--- title: 清单参考 description: manifest 每个字段的含义、取值与校验规则。 section: dev order: 20 updated: 2026-11-09 --- # 清单参考 ## 描述 gem 本身、它的每个工具、每个 SOP、每个 agent 都必须写描述(`description`)。描述是给 AI 和用户看的,有字数上限: | 写在哪 | 上限 | 写什么 | | --- | --- | --- | | 清单顶层的 `description` | 200 个字符 | 一两句话:这个 gem 能做什么,主要的工具叫什么(只有 skill 的 gem 写它的 skill 讲什么)。 | | `tools[].description` | 512 个字符 | 这个工具做什么、什么时候用。 | | `workflows[].description`(SOP) | 200 个字符 | 这个 SOP 做什么、什么时候运行。 | | agent 文件头部的 `description` | 不限 | 一两句话:这个 agent 是做什么的,显示在 gem 的页面上。见 [agents](#agents)。 | | 对外提供的工具、SOP、agent 的 `description` | 200 个字符 | 标了 `expose: true` 的项进主聊天的系统提示,所以和 gem 的描述一样限 200。见[对外提供](#对外提供expose)。 | 上限按字符数算,一个汉字算一个字符。没写、写成空的、或者超过上限,清单校验不通过,包装不上(`E_PERM_INVALID`)。agent 的描述没有字数上限,Gem Studio 安装时没写会拒绝。 gem 的描述要写得短,因为它是 AI 认识这个 gem 的唯一依据:用户装的每个 gem 都以一行(名字、id、描述)列在 AI 面前,装了上百个也一起列出来。AI 只凭这一行决定要不要打开这个 gem,打开之后才看得到工具、SOP 和 skill(见 [Gem 是什么](/zh/dev/gem-overview.md#ai-怎么用到你的-gem))。所以 gem 的描述只写做什么和主要工具,用法和细节写进工具、SOP 自己的描述。gem 商店的介绍和搜索将来也用这一段。 ```json "description": "Summarizes and fully translates every new email and keeps both in an encrypted store. Main tools: summarize_email, translate_email, save_record, list_records." ``` Gem Studio 的草稿里,gem 的描述是 `manifest.json` 顶层的 `description`,每个工具、SOP 的描述写在 `exports[]` 各项的 `description` 里;只有一个工具、用顶层简写时,顶层的 `description` 同时是 gem 和这个工具的描述,所以也不能超过 200 个字符。agent 的描述写在它自己文件的头部。 ## tools gem 提供给 AI 和 SOP 调用的工具。 ```json "tools": [ { "name": "summarize_email", "entry": "tools/summarize_email.js", "description": "Distill one email into its key points and any action items. Returns { summary }.", "inputSchema": { "type": "object", "properties": { "text": { "type": "string" } }, "required": ["text"] }, "outputSchema": { "type": "object", "properties": { "summary": { "type": "string" } } } } ] ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `name` | 是 | 小写字母开头,只含小写字母、数字、下划线,最长 64 个字符。SOP 里用 `ctx.call('tool.<name>', …)` 调用它。 | | `entry` | 是 | 工具代码所在的文件。写法见[工具 API](/zh/dev/tools.md)。 | | `description` | 是 | 最多 512 个字符,见上面的「描述」。 | | `inputSchema` | 是 | 输入参数的 JSON Schema。文件和文件夹的路径就是普通字符串,工具用 `workspace:` 前缀在对话文件夹里读写,见[权限模型](/zh/dev/permissions.md#对话文件夹)。 | | `outputSchema` | 否 | 返回值的 JSON Schema,给将来调用这个工具的 gem 和 SOP 参考。现在不做检查。 | | `permissions` | 否 | 这个工具自己用到的权限,见[权限模型](/zh/dev/permissions.md)。gem 自己的存储不用写(见[存储不是权限](/zh/dev/permissions.md#存储不是权限))。 | | `sideEffect` | 否 | `read`(什么都不改:计划模式里只有这一类工具能运行)、`write`(不写时按它处理)或 `destructive`(删除、发送、付款这类难撤回的)。这是你的声明,运行时不检查:只在确实不改任何东西时写 `read`。 | | `expose` | 否 | `true`:对外提供,主聊天的 AI 看得到、能调用。不写就是 gem 自己用的,只有这个 gem 的 SOP、agent 和页面能调用,别的会话调用一律被拒绝。见[对外提供](#对外提供expose)。 | 工具没有单独的时间上限:用户可以随时停止,SOP 里的调用受 SOP 的 `limits.maxDurationMs` 约束。 ## 对外提供(expose) 装好的 gem 有两个方向的作用:靠自己的页面、SOP 和 agent 完成任务,以及作为一个有特长的队友,让主聊天的 AI(和 gem 以外的任何 agent)用上它的本事。后者靠 gem **对外提供**一小组明确的接口:标了 `expose: true` 的工具、SOP 和 agent。其余都是 gem 的内部实现,gem 以外的 agent 看不到也调不到(调用会被 Notochord 拒绝,不管它有什么权限)。 主聊天的 AI 看到的是:每个已安装的 gem 一行(它的 `description`),下面每个对外提供的项一行(它的 `description`)。AI 用 `read_skill` 打开 gem 以后,工具列表上出现的正是这些项;第一次调用时问用户一次,同意的是整个 gem。所以对外提供的项和它们的描述,就是这个 gem 在团队眼里的全部——用队友听得懂的话写(它替人做什么、什么时候用),不要写实现步骤。 提供什么: | 形态 | 什么时候 | 怎么写 | | --- | --- | --- | | 工具 | 一次调用就能做完、结果是一个值:查一个东西、转换、总结一封邮件、记一笔。不多花一次模型调用,输入格式让调用准确。 | `tools[]` 里那一项加 `"expose": true` | | agent | 要串好几个 gem 自己的工具、需要 gem 的判断(报税:收集、分类、计算、填表)。主聊天把任务用一段话交给它(`gem.<id>.<名字>({ task })`),它在自己的会话里、用自己的 `tools` 和 `platform_tools`、用用户给它选的模型完成,回复就是结果。它只看到这段任务,看不到对话的其余部分,所以任务要把需要的都带上。gem 的一堆内部工具留在里面。 | agent 文件头部加 `expose: true` | | SOP | 队友可以启动的固定流程(可能等审批、等定时,这时调用方先拿到运行编号)。 | `workflows[]` 里那一项加 `"expose": true` | | 什么都不提供 | 只给团队读知识的 gem(有 skill:主聊天照样能读 `skill/SKILL.md`),或者只靠自己的页面和定时 SOP 工作的 gem。 | 都不写 | 安装时和 Gem Studio 里都检查:每个 gem 最多 5 项对外提供;对外提供的项描述最多 200 个字符(它进系统提示)。为自己的页面和 SOP 生成了很多工具的 gem,对外提供其中一两个,或者一个 agent,而不是整张列表。对外提供的名字在 gem 的工具、SOP、agent 之间不能重复(它们共用 `gem.<id>.<名字>` 这一个名字空间,所以工具、SOP、agent 的名字本来就不能相同)。 ## skill skill 是写给 AI 看的说明:这个 gem 的事情怎么做——什么情况下用哪个工具、按什么顺序、要注意什么。它只是文字,不会被执行,也不需要权限。**一个 gem 最多一个 skill**,格式和 [Agent Skills](https://agentskills.io/specification) 一样:一份 `SKILL.md`,加上它提到的参考资料。 ``` skill/ SKILL.md references/ regions.md rules/ 2024.csv ``` - **`skill/SKILL.md`**:skill 本身。AI 一打开这个 gem 就会完整读它,所以要短(最多 64 KB,越短越好):这个 gem 能做什么、主要的做法,以及**什么时候读哪份参考资料**——写出从 gem 根目录开始的完整路径,例如 `skill/references/regions.md`。不需要头部(front matter),AI 选 gem 看的是清单顶层的 `description`。 - **`skill/references/`**:`SKILL.md` 提到的细节,子文件夹随意:步骤、例子、表格、数据。**只能是文本文件**:`.md`、`.txt`、`.json`、`.jsonl`、`.csv`、`.tsv`、`.yaml`、`.yml`、`.xml`,每个最多 64 KB。不能放可以运行的文件(代码、脚本);需要代码示例,写在 Markdown 文件里。 - `skill/` 里不能有别的文件,没有 `SKILL.md` 也不能有 `references/`。不满足的包装不上(`E_PERM_INVALID`)。 **清单里不用声明。** 包里有 `skill/SKILL.md`,这个 gem 就有 skill。 **`SKILL.md` 有没有写对参考资料的路径,Notochord 不检查。** 没被提到的参考资料,AI 不会去读;路径写错的,AI 读不到。写完自己核对一遍:`SKILL.md` 里提到的每个路径都在 `skill/references/` 下,每份参考资料都在 `SKILL.md` 里写明了什么时候读。在 Gem Studio 里可以请助手帮你检查。 **gem 可以只有 skill**:没有工具、SOP、agent,只有 `skill/`——比如一份公司的写作规范、一套业务流程说明。它照样出现在 AI 的 gem 列表里,AI 用 `read_skill` 读它就能看到这些文件。 **AI 怎么读到**:AI 用 `read_skill` 读你的 gem id,一次拿到: - `SKILL.md` 的**全文**; - `skill/references/` 下**每个文件的名字**(`<gem id>/skill/references/…`); - 你的 gem 的工具(含 SOP),从下一步起出现在 AI 的工具列表上。 之后 AI 需要哪份参考资料,就用 `read_skill` 加这个名字读全文。读 skill 不问用户。 **gem 自己的 agent 也这样读**:只要 gem 有 skill,它的每个 agent 都会拿到 `read_skill`,系统提示的末尾附上 skill 的全部文件名。agent 用 `read_skill` 读的只是文字,它能用的工具仍然只是它自己文件头部写的那些。 ### 怎么写 skill - **`SKILL.md` 放说明和索引**,细节放进 `references/`:`SKILL.md` 每次打开 gem 都会整份读进对话。 - **每次都要遵守的规则**写在 agent 自己的提示词里(`agents/<name>.md` 的正文)——那是 gem 的 agent 每一轮都看得到的。Chat agent 只有在打开你的 gem 时才会读到 skill。 - **参考资料别太多、别太碎**:每个文件都会以一行出现在列表里,几百个小文件会让列表本身就占掉不少上下文,小模型也更难选对。 ## permissions.knowledge 申请访问用户知识库。完整说明见[知识库 API](/zh/dev/knowledge.md)。 ```json "permissions": { "knowledge": { "permissions": ["facts.read:self:location.home.*", "collections.write:diary"], "predicates": [{ "predicate": "pref.food.cuisine", "cardinality": "many", "description": "喜欢的菜系", "aliases": ["菜系"] }], "reason": "显示给用户的一句话理由(可选)" } } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `permissions` | 是 | 权限字符串列表,格式和取值见[权限模型](/zh/dev/permissions.md)。安装时逐条校验,格式错误的清单无法安装。 | | `predicates` | 否 | 这个 gem 会写入的谓词。`predicate` 必须是「固定第一级 + 至少一级」,例如 `pref.food.cuisine`;`cardinality` 为 `one` 或 `many`。安装时写进全局词表,已存在的不覆盖。 | | `reason` | 否 | 显示在安装界面上。 | 需要 `ctx.knowledge` 的工具,在工具自己的 `permissions` 里写 `"knowledge": true`。它能访问什么由上面 gem 级的声明和用户的批准决定,工具级只是开关。Gem Studio 草稿里在 `manifest.json` 顶层写 `"knowledge": { ... }`,每个工具默认都能用;某个工具只要其中几项时,在它的那一项里写 `"permissions": ["network", "knowledge"]`(或在 Gem Studio 的工具页勾选),`side_effect` 也写在这里。 ## data gem 的数据要存成什么样:有哪些集合,每个集合有哪些字段、索引和版本。平台按这份声明存储、校验每一次写入,工具用 `ctx.data` 读写,见[数据与存储](/zh/dev/storage.md)。 ```json "data": { "collections": { "notes": { "kind": "table", "description": "用户记下的待办", "fields": { "title": { "type": "string", "required": true }, "status": { "type": "string", "enum": ["open", "done"] }, "due": { "type": "timestamp" }, "project": { "type": "ref", "to": "projects" }, "tags": { "type": "array", "items": "string" } }, "indexes": [["status", "due"], ["project"]] }, "projects": { "kind": "table", "fields": { "name": { "type": "string", "required": true, "unique": true } } }, "readings": { "kind": "log", "fields": { "value": { "type": "number" } }, "retention": { "days": 365 } } } } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `collections` | 否 | 集合,键是集合名,最多 64 个。 | | `eventRetentionDays` | 否 | 修改记录(每次写入留下的记录:谁改的、改了什么)保留多少天,1–3650,默认 180。Log 的条目不按它清理,按各自的 `retention`。 | 集合名和字段名:小写字母开头,只含小写字母、数字、下划线,最长 64 个字符。 ### 集合 每个集合是一个表(`table`:可以修改、可以查询的记录)或一个 Log(`log`:只追加、不修改的条目)。 | 字段 | 表 | Log | 说明 | | --- | --- | --- | --- | | `kind` | 必填 | 必填 | `table` 或 `log`。 | | `fields` | 必填 | 必填 | 1–128 个字段,见下面的「字段」。 | | `description` | 可选 | 可选 | 最多 500 个字符。 | | `version` | 可选 | 不能写 | 整数,默认 1,只能升不能降,见下面的「改字段的规则」。 | | `indexes` | 可选 | 不能写 | 最多 16 个,每个是 1–8 个字段名组成的数组,不能重复;只能用标量字段(见下表)。查询需要什么索引见[索引规则](/zh/dev/storage.md#索引规则)。 | | `migrations` | `version` 大于 1 时必填 | 不能写 | 迁移模块在包里的路径:`.js`、`.mjs` 或 `.ts`,不能有 `..`,包里必须有这个文件。它为每一步导出一个函数(`v1_to_v2(data, { id })`、`v2_to_v3`……),见[版本与迁移](/zh/dev/storage.md#版本与迁移)。 | | `retention` | 不能写 | 可选 | 旧条目保留多少:`{ "days": 1–36500, "maxEntries": 1–10000000 }`,至少写一项,由平台清理。不写就一直保留。 | ### 字段 | 字段 | 说明 | | --- | --- | | `type` | 必填。标量:`string`、`number`、`integer`、`boolean`、`timestamp`(整数毫秒)、`ref`(另一条记录的 id)、`blob`(Blob 的哈希),能查询、排序、建索引。另外三种:`array`(只能用 `array-contains` 查)、`object`、`any`(这两种不能查询)。 | | `required` | `true` 时每条记录都必须有这个字段。 | | `unique` | `true` 时这个字段的值在集合里不能重复。只能用在表的标量字段上。 | | `enum` | 允许的值,1–256 个,不能重复;只能用在 `string`、`number`、`integer` 上,值的类型要和字段一致。 | | `to` | `ref` 字段(或 `items` 为 `ref` 的数组)必填:它指向哪个集合,必须是同一份清单里的一个表。 | | `items` | 只能用在 `array` 上:元素的类型,七种标量之一。不写就不检查元素,也不能用 `array-contains`。 | | `description` | 最多 500 个字符。 | ### 改字段的规则 每次激活(安装、升级、Gem Studio 测试)时,Notochord 把清单里的声明和已经存下的数据对比: - **同一个 `version` 里只能放宽**:加可选字段、去掉 `required` 或 `unique`、扩大或去掉 `enum`、加删索引、改说明。加 `unique` 也可以,但已有的值有重复时激活失败。 - **下面这些要升 `version` 并写迁移**:删字段;改 `type`、`to` 或 `items`;给已有字段加 `required`;缩小 `enum`,或给原来没有 `enum` 的字段加上;新加必填字段。 - `version` 不能比已经存下的数据低。 - 集合的 `kind` 不能改。 - Log 没有版本,字段可以随时改,旧条目保持写入时的样子。 - 从清单里删掉的集合,数据还在(接口访问不到),卸载时删除。 违反这些规则,激活失败,报错是 `E_DATA_SCHEMA: …`(新加的 `unique` 遇到重复值是 `E_DATA_UNIQUE: …`);升级和同版本重装时外面包着 `E_ACTIVATION_FAILED`,升级回滚到旧版本(见[打包与发布](/zh/dev/publishing.md#安装时检查什么))。`data` 段本身写得不对,在 Gem Studio 测试、打包和安装时就报 `E_PERM_INVALID`。打包和安装时,形状上的错误(不认识的键、`type` 写错、说明超长)先被清单的 JSON Schema 拦下,消息是 `notochord.json failed schema validation: …`;其余规则(名字、数量上限、`to`、`version` 与 `migrations`、迁移文件不在包里)的消息以 `data:` 开头。Gem Studio 测试时都以 `data:` 开头。 Gem Studio 草稿里,`data` 同样写在 `manifest.json` 顶层,字段相同,直接编辑 `manifest.json`。测试数据怎么保留、迁移怎么测,见[在 Gem Studio 里测试](/zh/dev/storage.md#在-gem-studio-里测试)。 ## agents gem 自带的 agent。**每个 agent 是 `agents/` 下的一个文件**,`agents/<名字>.md`:文件名就是 agent 的名字,开头的 YAML 头部(front matter)写它是做什么的、能用哪些工具,后面的正文是它的系统提示词。 ```markdown --- description: 汇总并翻译新邮件,然后存档。 tools: [summarize_email, translate_email, save_record] platform_tools: [http.request] expose: true --- You are a calm, meticulous email assistant. … ``` **清单里不写 agent。** 打包时 Notochord 读 `agents/` 下的每个文件,生成安装包清单里的 `agents[]`;你自己写的 `notochord.json` 里有 `agents`,打包会报错。Gem Studio 的草稿也一样:`manifest.json` 里没有 agent,新建、改名、删除 agent 就是新建、改名、删除它的文件。 **名字**:文件名去掉 `.md`。小写字母开头,只含小写字母、数字、下划线,最长 64 个字符(`agents/mail_helper.md` 是 `mail_helper`)。文件必须直接放在 `agents/` 里,不能放在子文件夹。SOP 里用 `ctx.call('agent.<名字>', …)` 调用它,页面的助手气泡用 `data-agent="<名字>"` 指定它。 头部只能有下面五个键,写了别的打包会报错: | 键 | 必填 | 说明 | | --- | --- | --- | | `description` | 是 | 这个 agent 是做什么的,一两句话,显示在 gem 的页面上。里面有 `: ` 或 `#` 时整句加引号。 | | `tools` | 否 | 它可以调用的、这个 gem 自己的工具,写工具名。 | | `platform_tools` | 否 | 它可以调用的平台工具,写全名(`fs.cat`、`http.request`、`browser.navigate` 等)。这是一项权限申请,列在 gem 页面的「它能做什么」里。不能写 `tool_search`、`read_skill`、`agent.spawn_child`、`search_gem_catalog`,也不能写别的 gem 的工具(`gem.*`)。 | | `models` | 否 | 它的代码用到的模型,键是名字,`main` 是它对话时用的模型(不写也有)。每一项只有一个可选字段 `requires`:这个模型除了文字以外还必须会什么,见下面的[模型能力](#模型能力)。**用哪个模型由用户选**——在 gem 的页面上或「设置 › AI 设置 › Agent」里,选一个具体的模型,或者选用户的一个角色(内置的是 `chat`、`vision`、`deep`、`local`,`local` 给用户电脑上运行的模型用,界面上叫「本地」);没选时用用户的 `chat` 角色;这里不能指定。想建议用户用什么样的模型(比如处理邮件、个人资料的 agent 建议选「本地」),写在 gem 的介绍文档里(见 [docs](#docs))。 | | `expose` | 否 | `true`:对外提供,主聊天的 AI 把任务交给它(见[对外提供](#对外提供expose))。这时 `description` 限 200 个字符,并计入 gem 最多 5 项的上限。不写,只有这个 gem 的 SOP 和页面能用到它。 | 生成的 `agents[]` 每项是 `name`、`entry`(`agents/<名字>.md`)、`description`、`tools`、`platformTools`、`models`、`expose`。装好以后 Notochord 只按 `agents[]` 决定 agent 能用什么,文件的头部不再读,正文是系统提示词。 agent 只能调用 `tools` 和 `platform_tools` 列出的工具,别的一律用不了。唯一的例外是 `read_skill`:gem 有 skill 时,Notochord 自动给每个 agent 加上它,只用来读 skill(见 [skill](#skill)),不需要也不能写进 `platform_tools`。 ### 模型能力 agent 要模型看图片、听音频这类文字以外的事,在 `models` 的那一项里用 `requires` 写明: ```yaml models: { main: { requires: [image_input] } } ``` 只能写下面六个值,写别的,包**装不上**(报 `E_PERM_INVALID`): | 值 | 模型要能 | | --- | --- | | `image_input` | 看懂图片 | | `audio_input` | 听懂音频,包括语音转文字 | | `video_input` | 看懂视频 | | `image_output` | 生成图片 | | `audio_output` | 生成音频,包括语音合成 | | `video_output` | 生成视频 | 用户在 gem 的页面上给每个 agent 选模型(没选时用用户的 `chat` 角色),「设置 › AI 设置 › Agent」里也能换。Notochord 拿选中的模型对照一份常见模型的能力列表: - 列表说这个模型有你写的全部能力:不显示任何东西。 - 列表说它没有其中某项,或者列表里没有这个模型(比如用户自己起的模型名),或者这个角色还没有配模型:显示一行提示,由用户自己确认。 - 提示不会阻止安装,运行时也不检查。模型真的不支持时,出错的是你的 agent 对模型的那次调用,和没有写 `requires` 一样。 所以 `requires` 只写 agent 离了它就做不成事的能力。只是偶尔用得到的,不要写,免得用户每次都看到提示。 **清单里没有按 agent 设置的运行上限。** 一个 agent 一次运行最多走多少步、用多少 token,由用户在「设置 › 系统」里的「最大循环步数」和「每次运行的 token 上限」 决定,对所有 agent 相同。`maxTurns`、`maxCostUsd` 这两个字段已经删除:打包后的清单里写了它们,安装时会因为清单校验失败被拒绝。 ## docs `docs/` 是写给人看的:这个 gem 能做什么、怎么用。**它会成为 gem 在商店里的介绍页**。使用 gem 时不会用到这个文件夹里的任何内容——gem 的代码、它的 agent、AI 都不读它,所以不要把给 AI 的说明写在这里(那是 [skill](#skill))。 ``` docs/ README.en.md README.zh-CN.md prompts/ first-steps.en.md first-steps.zh-CN.md examples/ weekly-report.en.md ``` - **只能是 Markdown**(`.md`),子文件夹随意。别的文件 Gem Studio 打包时会去掉;自己打的包里有别的文件,打包和安装都会报错(`E_PERM_INVALID`)。图片放不进来。 - **每个文件按语言命名**,用标准的语言代码(BCP 47:`en`、`zh-CN`、`ja`、`de`……): - `README.<语言>.md`:介绍页的正文——这个 gem 做什么、给谁用、怎么设置、怎么用。**写了哪几种语言,商店介绍页的语言菜单里就有哪几种**。至少写一份(`README.en.md`)。 - `prompts/<名字>.<语言>.md`:可选,可以直接试的提示词,每条说明它做什么。商店介绍页上单独一个「提示词」标签页。 - `examples/<名字>.<语言>.md`:可选,使用这个 gem 的完整例子。商店介绍页上单独一个「例子」标签页。 - 商店按普通的 Markdown 渲染这些文件,每个标签页显示用户选的语言。同一条提示词或例子的各个语言版本用同一个 `<名字>`(`prompts/first-steps.en.md`、`prompts/first-steps.zh-CN.md`)。 清单里不用声明 `docs/`。在 Gem Studio 里,结构栏的「介绍文档」列出这个文件夹里的文件,可以在那里新建和编辑。 ## resources 太大、不适合放进安装包的文件(模型、词典、数据集)。在清单里写明地址、大小和校验值,由 Notochord 下载;工具用 [`ctx.resources`](/zh/dev/tools.md#ctxresources) 取得本地路径。 ```json "resources": [ { "id": "ocr-model", "url": "https://cdn.example.com/models/ocr-v3.onnx", "mirrors": ["https://mirror.example.org/models/ocr-v3.onnx"], "sha256": "9f2c…", "size": 412000000, "required": true, "description": "OCR 模型" } ] ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `id` | 是 | 工具里取这个文件时用的名字。同一份清单里不能重复,重复的清单无法安装。 | | `url` | 是 | 下载地址,必须以 `https://` 开头。 | | `mirrors` | 否 | 备用地址,同样必须是 `https://`。`url` 失败后按顺序逐个尝试。 | | `sha256` | 是 | 文件内容的 SHA-256,64 位小写十六进制。 | | `size` | 是 | 文件大小,单位是字节。 | | `required` | 否 | `true`:安装完成后就在后台开始下载;以后每次启动应用时,如果文件还不在,会再试一次。默认 `false`:工具第一次用到时才下载。 | | `description` | 否 | 显示在 gem 的页面上。不写就显示 `id`。 | 下载是这样进行的: - **由 Notochord 下载,不是 gem 的代码。** 下载地址不用写进 `network`,也不需要申请任何权限。gem 的页面上会列出每个文件的说明、大小、来自哪个主机、装完就下载还是用到时才下载。 - **只接受 `https`,不能指向本机或内网地址。** 重定向最多跟 5 次,每一跳都按同样的规则检查。 - **受用户的网络策略约束。** 用户在「设置 › 系统」的网络策略(白名单 / 黑名单模式)里没有放行的主机下载不了,镜像和重定向经过的主机也算在内。 - **大小和 SHA-256 都要与清单一致。** 服务器多发、少发、或者内容对不上的文件会被丢弃,然后换下一个地址。磁盘剩余空间不够时不会开始下载。 - **下载失败不影响安装。** `required` 的文件也一样:安装不会等它,也不会因为它失败。gem 照常可用,只有用到这个文件的那次调用会报错;下一次调用、或下次启动应用时会自动重试。 - **升级时不重复下载。** 新版本里 `sha256` 没变的文件直接沿用;新版本不再声明的文件,在升级成功后删除。卸载 gem 时全部删除。 - 不支持断点续传,失败后从头下载。目前没有下载进度的界面。 Gem Studio 的草稿里,`resources` 同样写在 `manifest.json` 顶层,字段相同;也可以在 Gem Studio 概览的「资源」里填,填好地址后点「自动填大小和 SHA-256」,Notochord 按下载资源的同一套规则把文件下载一遍、算出这两项(不保留文件)。草稿测试时 `ctx.resources` 和装好以后一样可用。
Notochord
简体中文English