Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help


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.witchannel.witmemory.wit 定义了 guest 合约。
  • crates/zeroclaw-plugins/src/component.rs 负责共享的组件宿主管线、存储状态、资源限制、WIT 绑定以及 WASI 连接。
  • wasm_tool.rswasm_channel.rswasm_memory.rs 将这些世界重新桥接回 Rust 的 ToolChannelMemory trait。
  • 插件 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.getsecrets.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 代码和权限审查。

参考文献