id: ADR-009 title: WIT 组件和直接 wasmtime 替代 Extism 插件桥 date: 2026-07-04 status: accepted relates-to:
- ADR-003
- crates/zeroclaw-plugins
- wit/v0
- docs/book/src/foundations/fnd-001-intentional-architecture.md
ADR-009:WIT 组件和直接 Wasmtime 替换 Extism 插件桥接
此 ADR 取代 ADR-003。ADR-003 记录了最初的 Extism 桥接。当前已接受的架构是一个由 WIT 定义、由 wasmtime 直接承载的 WASM 组件模型接口。
上下文
Extism 对于证明外部 WASM 插件可以作为 ZeroClaw 工具出现很有帮助。它也为该项目提供了一个简单的 JSON 协议和一个由权限门控的主机函数模型。
随着微内核架构逐渐成熟,插件层需要更强的兼容性边界:
- 插件契约需要明确、版本化并可审查;
- 工具、通道和内存后端需要独立的类型化世界;
- 宿主需要特定于 release target 的执行后端;
- 需要主机导入,以便在链接时附加到权限;
- 插件作者需要一个持久的 ABI,而不是临时的 JSON 导出;
- 存储限制和 WASI 主机接口需要由 ZeroClaw 拥有。
WASM 组件模型和 WIT 提供了这一边界。直接集成 wasmtime 让宿主有足够的控制能力来选择后端、附加 WASI Preview 2 接口、强制资源限制,并将 guest 世界桥接到 ZeroClaw 的 Rust traits。
决策
ZeroClaw 的插件 ABI 基于 wit/v0 下由 WIT 接口描述的 WASM components。宿主在 crates/zeroclaw-plugins 中使用直接的 wasmtime 组件模型对接,为工具、通道和内存后端提供按 world 划分的桥接。
执行模型是:
wit/v0/tool.wit、channel.wit和memory.wit定义了 guest 合约。crates/zeroclaw-plugins/src/component.rs负责共享的组件宿主管线、存储状态、资源限制、WIT 绑定以及 WASI 连接。wasm_tool.rs、wasm_channel.rs和wasm_memory.rs将这些世界重新桥接回 Rust 的Tool、Channel和Memorytrait。- 插件
manifest.toml声明插件名称、版本、能力类型、权限、配置和签名材料。 - Ed25519 清单验证仍然是插件宿主的一部分。
执行后端选择是显式的:
plugins-wasm可在主工作区中启用插件宿主表面。plugins-wasm-runtime-only启用最小的仅运行时主机。plugins-wasm-cranelift在受支持的平台上启用 Cranelift 编译。plugins-wasm-pulley为 Cranelift 不可用或不适用的目标启用 Pulley 解释器。
主机表面受到权限门控:
HttpClient是用于附加出站 HTTP 状态并链接 WASI HTTP 的权限。ConfigRead是必需的,主机随后才能将解析后的值注入工具的__config,或提供通道的config.get。工具或通道使用者可以将顶层字符串属性标记为x-secret = true;这些值不会进入公开对象,而是通过实例作用域的secrets导入读取。工具在execute期间获得机密访问权限。通道在configure和运行调用期间获得config.get和secrets.get;两次读取在每次调用中共享同一个规范配置解析结果。实例化和静态元数据发现仍不可用。主机会丢弃每次调用的具体化视图;符合要求的通道 guest 必须在使用点解析配置,且不得保留返回的配置或明文,而主机在交付后无法强制执行这一点。静态身份和能力导出会在加载时读取,因此更改这些值需要重建通道生命周期。- 主机不提供原始环境变量读取函数。
- 在构建 store 之前,会解析 store limits、fuel、table limits、instance limits 和 memory ceilings。
后果
正数:
- 插件与 Rust 宿主共享一个类型化的契约接口,而不是针对每种插件类型使用临时的 JSON 约定。
- WIT 文件成为可以冻结并审查的兼容性边界。
- Tool、channel 和 memory 插件对于运行时来说可以表现为原生 trait 实现。
- 执行后端现在按发布目标选择,而不是隐藏在一个通用功能标志中。
- 权限检查附加在宿主导入上,而不仅仅记录在清单中。
负值:
- 直接的
wasmtime组件集成比原始的 Extism 桥接更复杂。 - 发布构建必须为每个目标选择正确的执行后端。
- 插件作者需要构建 WASI Preview 2 组件,并遵循 WIT 接口,而不是导出 JSON 函数。
- WIT 接口现在需要保持兼容性纪律。修改它是一个跨插件架构决策,而不是一次本地 crate 编辑。
后续:
- WIT 版本控制和兼容性规则请参见 WIT 文档。如果兼容性策略发生变化,请编写新的 ADR,而不是悄悄修改这一份。
- 新的 guest worlds 应作为带版本的 WIT 接口添加,并配套相应的 host bridge 代码和权限审查。
参考文献
- ADR-003: WASM plugins use Extism 作为初始执行桥接
- FND-001: Intentional architecture
- 插件协议
wit/v0/wit/VERSIONING.mdcrates/zeroclaw-plugins/src/component.rscrates/zeroclaw-plugins/src/wasm_tool.rscrates/zeroclaw-plugins/src/wasm_channel.rscrates/zeroclaw-plugins/src/wasm_memory.rscrates/zeroclaw-plugins/src/host.rscrates/zeroclaw-plugins/src/signature.rscrates/zeroclaw-infra/src/net_guard.rs