Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

迁移到类型化插件配置

类型化实例配置对于所有读取操作器配置的 1.0 之前插件都是一项破坏性变更。本页面是面向插件作者和运维人员的迁移文档:哪些内容会中断、原因,以及修复软件包的确切步骤。

此处所述行为会根据 crates/zeroclaw-plugins/src/config.rscrates/zeroclaw-plugins/src/instance.rs 以及 crates/zeroclaw-plugins/src/host.rs 中的准入路径进行检查。

发布决策

强制执行机制与此功能一同发布。没有兼容性垫片、宽限期或选择退出标志。插件在 1.0 之前属于实验性接口,因此项目选择接受这一破坏性变更,而不是永久保留一个更弱的配置路径:无类型回退机制必须将宿主无法确定类型、命名或设置边界的值交给 guest,而这正是此功能要堵住的漏洞。

未迁移的软件包将不再被发现。不会发生静默降级,也不会有不完整的配置传递给来宾代码。

会出现什么问题

三件彼此独立的事情:

  1. 请求 config_read 但未包含 config_schema 的清单不再被发现或安装。 二者互为必要条件:没有该权限的架构同样无效。
  2. **不再读取以包名或绑定名称为键的配置项。**现在,运算符值存储在由包、能力和绑定派生的完整实例键下。
  3. 来宾接收的是类型化的 JSON,而不是字符串映射。 曾经自行解析字符串的来宾现在可以直接获得真正的布尔值、数字、数组和对象。

为什么宿主需要模式

操作员值以带有 secret 标记的字符串映射形式存储,并在静态存储时加密,而来宾是不受信任的第三方代码。在来宾启动之前,主机必须能够回答两个问题,但如果没有声明式契约,主机无法回答:此软件包获准接收哪些键,以及每个值的类型是什么。WIT world 是固定的,并由所有插件共享,因此每个软件包的配置类型无法放入 ABI。manifest 是唯一可以声明该契约的地方,而 additionalProperties = false 加上显式的 properties 映射,才使 config_read 授权具有可枚举的含义。

编写步骤

1. 声明架构

添加一个封闭的 Draft 2020-12 对象,准确涵盖插件读取的键。每个顶级属性都必须解析为一种明确的类型:stringbooleanintegernumberarrayobject

name = "my-plugin"
version = "0.2.0"
wasm_path = "my_plugin.wasm"
capabilities = ["channel"]
permissions = ["config_read"]

[config_schema]
"$schema" = "https://json-schema.org/draft/2020-12/schema"
type = "object"
required = ["bot_token"]
additionalProperties = false

[config_schema.properties.bot_token]
type = "string"
minLength = 1

[config_schema.properties.poll_interval_secs]
type = "integer"
minimum = 1

[config_schema.properties.allowed_chats]
type = "array"

宿主会对架构本身强制实施以下限制:序列化后大小不得超过 64 KiB,嵌套层级最多 32 层,不得包含 $id,且 $ref 目标必须是本地 JSON 指针。远程引用会被拒绝,因此架构永远不会触发网络获取。

动态键关键字不属于此方言:patternPropertiespropertyNamesunevaluatedProperties 在根级会被拒绝,因为宿主只会为根 properties 映射中列出的键具体化值,因此通过模式匹配允许的键永远不会传递到插件。嵌套属性模式不受影响。

pattern 使用线性时间正则表达式方言

宿主会在每次调用时通过重新编译并重新验证你的架构来解析配置,而这项工作在宿主上执行,不计入组件的燃料预算。因此,pattern 仅限于开销可由宿主预测的正则表达式:

  • 反向引用和环视断言会被拒绝。 (\w+)\s\1(?=...)(?<=...) 及其类似形式需要回溯匹配器。模式会改用线性时间的 regex 方言进行编译,无论模式如何编写,匹配所需的时间都与值的长度成正比。
  • 单个模式编译后的程序大小不得超过 256 KiB。 大的重复次数会触发此限制:^[\s\S]{0,200}$ 没问题,^[\s\S]{0,1000}$ 则不行。请使用 maxLength 设置长度限制;检查它无需额外开销,而且能准确表达你的意图。

这两次拒绝都发生在安装时,并显示指明架构的 InvalidManifest 错误,因此,对于主机无法限定其 pattern 的插件,根本不会运行。结构化模式的行为符合预期:slug、UUID、电子邮件地址、URL 以及长度受限的简短自由文本都可以编译。

2. 匹配值编码

Operator 存储仍为字符串映射。架构会告诉宿主如何读取每个存储的字符串:

声明的类型运算符存储的内容访客收到的内容
stringsecret-value"secret-value"
booleantruetrue
integer44
number0.50.5
array["a","b"]["a","b"]
object{"k":"v"}{"k":"v"}

任何无法解析为声明类型的内容,都会在代码运行前被拒绝。

3. 确定每个键是必需项还是可选项

最终授予的权限会与清单请求分开检查。当请求 config_read 但未获授予时,宿主会根据你的架构验证一个空对象:

  • 全可选架构会接收 {},因此请为每个字段提供来宾端默认值。
  • required 字段采用失败即关闭策略,这正是凭据所需要的行为。无法进行身份验证的通道应拒绝启动,而不是在配置不完整的情况下运行。

4. 在来宾端反序列化类型化 JSON

将字符串解析替换为对注入对象的一次反序列化。工具插件读取保留的 __config 键,主机删除模型提供的任何同名值后,将其合并到调用参数中。

5. 重新构建并重新签名

config_schema包含在清单签名中,因此添加该字段后,已签名的软件包必须重新签名。有关签名流程,请参阅分发插件

操作步骤

现有的以软件包或绑定命名的 [[plugins.entries]] 块不会被读取。可用的迁移路径取决于插件能力。

工具实例

Install 和 info 命令可以从软件包的默认工具绑定中派生工具实例。要将工具值迁移到新键上:

  1. 运行 zeroclaw plugin info <package> 可打印完整实例密钥,其格式类似 zpi1_...
  2. 将现有条目的 name 重命名为该键,或重新安装插件以初始化该条目,然后使用 zeroclaw config set plugins.entries.<instance-key>.config.<key> 设置值。
  3. 保存配置。值在静态存储时保持加密。

该密钥是软件包、能力和绑定的带版本可逆编码,因此两个软件包可以同时使用名为 main 的绑定,而无需共享凭据。全新安装会自动生成并输出此工具密钥。

通道实例

渠道键包含已配置的渠道别名。zeroclaw plugin installzeroclaw plugin info 知道包,但不拥有该别名,因此无法推导、打印或预置渠道键,也不得臆造包级替代项。支持别名的渠道构造和运行时配置解析已在 zeroclaw#10146 中落地:守护进程会构造一个显式声明的渠道实例,并根据实际配置的别名,从 zpi1(package, channel, alias) 解析其类型化配置。

频道实例的自动 plugin info 密钥显示和安装时预置,在 zeroclaw#9584 中的授权流程完成之前仍需手动进行。在该流程落地之前,运维人员需要手动使用 zeroclaw config set 写入频道密钥,而不是由安装或 info 为其打印并写入,因此,依赖自动安装和 info 密钥流程的仅频道软件包目前尚未完成。

诊断遭拒#+#+#+#+

消息原因
请求 config_read,但未声明 config_schema第 1 步未完成
声明了 config_schema,但未请求 config_read移除架构或添加权限
config_schema 必须设置 additionalProperties = false根对象已打开
config_schema 不得在根级别声明 <keyword>根对象使用了 dynamic-key 关键字;请改为为 properties 中的每个键命名
属性使用了不受支持的类型属性没有显式支持的类型,或本地 $ref 无法解析
config 中包含 config_schema 中不存在的属性运算符键未声明,通常是拼写错误
配置属性必须是 JSON 整数存储的字符串无法解析为声明的类型
config 在 <path> 处不符合 config_schema某个约束(例如 minimumrequired)未通过

第一方软件包

zeroclaw-labs/zeroclaw-plugins 中发布的每个包都会请求 config_read,而在此变更落地时没有任何包声明 config_schema,因此它们全部需要执行第 1 步和第 5 步。迁移在该仓库中而不是此处跟踪,因为这些包的版本独立于宿主。工具包现在可以完成操作员密钥步骤。仅频道包必须等待上文支持别名的密钥路径,之后跟踪器才会根据此契约将其标记为已迁移或发布为已迁移。

内存插件

Memory 插件目前尚未支持配置导出,在该 ABI 存在之前不得请求 config_read