运行时与打包
支持的运行时
manifest.json 的 runtime 字段:
| 值 | 入口 | 说明 |
|---|---|---|
java | .jar | 需要系统有 Java 8+,用 -jar 启动 |
python | .py | 需要 python3 或 python 在 PATH |
node | .js | 需要 node 在 PATH |
c / cpp | 可执行文件 | 编译好的原生程序 |
go | 可执行文件 | go build 产物,静态链接最省事 |
rust | 可执行文件 | cargo build --release 产物 |
zig | 可执行文件 | zig build-exe 产物 |
native | 可执行文件 | 兜底,等同上面几个原生项 |
原生运行时不需要目标机器装解释器,代价是要按平台分别编译:
| 平台 | 产物 |
|---|---|
| Windows x64 | .exe |
| Linux x64 / arm64 | 无扩展名,带执行位 |
| macOS arm64 / x64 | 无扩展名,需要签名 |
一个包只放当前平台的二进制;要覆盖多平台就发多个包,或在 manifest.json 里用 entry 指向不同文件。
manifest.json
最小可用:
json
{
"id": "hello-go",
"name": "Hello Go",
"version": "1.0.0",
"runtime": "go",
"entry": "bin/hello-go.exe",
"author": "you",
"description": "示例拓展"
}完整字段:
| 字段 | 必填 | 说明 |
|---|---|---|
id | 是 | 唯一标识,[a-z0-9-],装上后不能改 |
name | 是 | 显示名 |
version | 是 | 语义化版本 |
runtime | 是 | 见上表 |
entry | 是 | 入口文件,包内相对路径 |
author | 否 | 作者 |
description | 否 | 一句话说明 |
homepage | 否 | 主页 |
permissions | 否 | 权限数组 |
minHost | 否 | 要求的最低启动器版本 |
args | 否 | 启动参数数组(原生运行时用) |
env | 否 | 环境变量对象 |
entry 的坑:
- 路径分隔符统一用
/。 - 不能出现
..,不能是绝对路径。 - 原生运行时的
entry就是包里的二进制本身,不要写解释器。
打包
仓库自带 extensions/pack.py:
bash
python extensions/pack.py extensions/examples/hello-go -o dist/hello-go.zip它会:
校验
manifest.json(字段、类型、路径安全)。原生运行时自动编译:
textgo → go build -ldflags "-s -w" rust → cargo build --release统一文件权限:zip 内一律
0644,解压后由宿主给入口补0755。检查体积上限。
输出 zip。
手工打包也可以,但要注意:
- zip 内不要带可执行位,某些解压实现会拒绝。
- 不要把
target/、node_modules/整个塞进去,只留运行需要的。 - Windows 下用
Compress-Archive打包时确认目录层级正确(zip 根就是拓展根)。
示例
仓库里的三个示例:
| 目录 | 运行时 | 演示什么 |
|---|---|---|
extensions/examples/hello-java | java | 最小可运行 + 收消息 |
extensions/examples/hello-go | go | 原生二进制 + 宿主 API |
extensions/examples/hello-rust | rust | 零依赖 JSON + 原生二进制 |
SDK:
| 语言 | 位置 | 说明 |
|---|---|---|
| Go | extensions/sdk/go | package tmlext,只用标准库 |
| Rust | extensions/sdk/rust | crate tml-ext,零第三方依赖 |
SDK 与模板仓库
协议只有一个来源:本仓库的 extensions/schema。SDK 分两种给法——Go / Rust 从本仓库的 extensions/sdk 用依赖引用(不复制);Java / Python / Node / C 的模板各自带一份零依赖的协议实现, 直接用模板里的那份就行:
| 语言 | 模板仓库 | 引用方式 |
|---|---|---|
| Java | https://github.com/TYWStudio/template-tml-extension-java | 模板自带 Json.java,无外部依赖 |
| Python | https://github.com/TYWStudio/template-tml-extension-python | 模板自带 tml.py |
| Node.js | https://github.com/TYWStudio/template-tml-extension-node | 模板自带 tml.js |
| C | https://github.com/TYWStudio/template-tml-extension-c | 模板自带零依赖协议实现 |
| Rust | https://github.com/TYWStudio/template-tml-extension-rust | tml-ext = { git = "https://github.com/TYWStudio/TML", tag = "sdk-rust-v1.0.0" } |
| Go | https://github.com/TYWStudio/template-tml-extension-go | require github.com/TYWStudio/TML/extensions/sdk/go v1.0.0 |
逐个语言的 clone / 构建 / 导入步骤见 语言模板。
改了协议怎么发:先改本仓库的 extensions/sdk/* 和 schema/,再打新 tag (Go 用 extensions/sdk/go/vX.Y.Z,Rust 用 sdk-rust-vX.Y.Z),最后升级模板的依赖版本。 顺序反过来(先改模板)就会分叉成两套实现。
调试
bash
# 直接跑入口,宿主协议走 stdio
cd extensions/my-ext
./bin/hello-go启动器的「设置 → 拓展」里有「刷新」,改完点一下即可,不用重启。日志在数据目录 logs/ext-*.log。导入、启用与卸载见 导入与管理拓展。
常见失败原因:
| 现象 | 原因 |
|---|---|
| 列表里不出现 | manifest.json JSON 语法错误,或 id 重复 |
| 显示「已被修改」 | 包内容改过但没重新信任(删掉 trusted.json 里对应项再加载) |
| 「运行时不可用」 | 非原生运行时缺少解释器;原生运行时缺执行位或架构不符 |
| 启动后立即退出 | 入口没按协议读 stdin,或异常退出,看 ext-*.log |
