Skip to content

本页是 OpenClaw 将低使用率、实验性的 Canvas 从核心代码中剥离为内置插件的重构审计清单。如果您在审计当前分支状态、准备实验性插件 PR 或检查 Canvas 所有权归属,请对照此清单:已验证的迁移项、核心仍未移走的 Canvas 表面、目标形状以及验证命令。完成重构的条件是所有核心 import 清空且插件清单检查通过。

OpenClaw Canvas 插件重构审计清单

Canvas 使用率低且处于实验状态。将其视为内置插件,而非核心特性。核心可保留通用的网关、节点、HTTP、认证、配置和原生客户端基础设施,但 Canvas 专属行为应归入 extensions/canvas

目标

将 Canvas 所有权迁移至 extensions/canvas,同时保留当前配对节点行为:

  • 由 Canvas 插件注册智能体用的 canvas 工具
  • Canvas 节点命令仅在 Canvas 插件注册时允许
  • A2UI 宿主/源代码文件归 Canvas 插件管理
  • Canvas 文档物化归 Canvas 插件管理
  • CLI 命令实现归 Canvas 插件管理,或通过插件自有运行时 barrel 委托
  • 文档和插件清单将 Canvas 描述为实验性、插件驱动的功能

非目标

  • 本重构不重新设计原生应用 Canvas UI。
  • 除非单独的产品决定删除 Canvas,否则不从 iOS、Android 或 macOS 中移除 Canvas 协议/客户端支持。
  • 除非至少另一个内置插件需要相同的接缝,否则不为 Canvas 构建宽泛的插件服务框架。

当前分支状态

已完成迁移项:

  • extensions/canvas 中添加了内置插件包。
  • 添加了 extensions/canvas/openclaw.plugin.json
  • 将智能体 canvas 工具从 src/agents/tools/canvas-tool.ts 迁移到 extensions/canvas/src/tool.ts
  • src/agents/openclaw-tools.ts 中移除了核心注册 createCanvasTool
  • 将 Canvas 宿主实现从 src/canvas-host 迁移到 extensions/canvas/src/host
  • 保留 extensions/canvas/runtime-api.ts 作为插件自有兼容性 barrel,供测试、打包和外部公共 Canvas 辅助函数使用。
  • 将 Canvas 文档物化从 src/gateway/canvas-documents.ts 迁移到 extensions/canvas/src/documents.ts
  • 将 Canvas CLI 实现和 A2UI JSONL 辅助函数迁移到 extensions/canvas/src/cli.ts
  • 将 Canvas 宿主 URL 和作用域能力辅助函数迁移到 extensions/canvas/src
  • 将 Canvas 节点命令默认值从硬编码的核心列表移动到插件 nodeInvokePolicies
  • 添加了插件自有的 Canvas 宿主配置 plugins.entries.canvas.config.host
  • 将 Canvas 和 A2UI HTTP 服务移至 Canvas 插件 HTTP 路由注册之后。
  • 添加了通用插件 WebSocket 升级分发,用于插件自有的 HTTP 路由。
  • 用通用托管插件表面和节点能力辅助函数替换了 Canvas 专属的网关宿主 URL 和节点能力认证。
  • 添加了插件自有的托管媒体解析器,使 Canvas 文档 URL 通过 Canvas 插件解析,而非核心导入 Canvas 文档内部实现。
  • 添加了 api.registerNodeCliFeature(...),使 Canvas 可以声明 openclaw nodes canvas 为插件自有节点功能,而无需手动拼写父命令路径。
  • 移除了生产环境 src/**extensions/canvas/runtime-api.js 的导入。
  • 将 A2UI 包源从 apps/shared/OpenClawKit/Tools/CanvasA2UI 迁移到 extensions/canvas/src/host/a2ui-app
  • 将 A2UI 构建/复制实现移至 extensions/canvas/scripts,并用通用内置插件资产钩子替换了根构建流程。
  • 移除了运行时的旧版顶层 canvasHost 配置别名。
  • 保留了 Canvas doctor 迁移,使 openclaw doctor --fix 将旧版 canvasHost 配置重写为 plugins.entries.canvas.config.host
  • 移除了网关协议 v4 之后的旧智能体 Canvas 协议兼容性。原生客户端和网关现在只使用 pluginSurfaceUrls.canvasnode.pluginSurface.refresh;废弃的 canvasHostUrlcanvasCapabilitynode.canvas.capability.refresh 路径在此实验性重构中不再支持。
  • 更新了生成的插件清单以包含 Canvas。
  • docs/plugins/reference/canvas.md 添加了插件参考文档。

已知核心仍持有的 Canvas 表面(有意保留):

  • apps/ 下的原生应用 Canvas 处理程序仍然消费 Canvas 插件表面
  • apps/ 下的原生应用 Canvas 协议/客户端处理程序
  • 发布的产物输出仍使用 dist/canvas-host/a2ui 以保持向后兼容的运行时查找,但复制步骤已归插件所有

目标形状

extensions/canvas 应拥有:

  • 插件清单和包元数据
  • 智能体工具注册
  • 节点调用命令策略
  • Canvas 宿主和 A2UI 运行时
  • Canvas A2UI 包源码和资产构建/复制脚本
  • Canvas 文档创建和资产解析
  • Canvas CLI 实现
  • Canvas 文档页面和插件清单条目

核心应仅拥有通用接缝:

  • 插件发现和注册
  • 通用智能体工具注册表
  • 通用节点调用策略注册表
  • 通用网关 HTTP/认证和 WebSocket 升级分发
  • 通用托管插件表面 URL 解析
  • 通用托管媒体解析器注册
  • 通用节点能力传输
  • 通用配置管道
  • 通用内置插件资产钩子发现

原生应用可保留 Canvas 命令处理程序作为协议的客户端,它们不是插件运行时的所有者。

迁移步骤

  1. plugins.entries.canvas.config.host 视为插件自有的配置表面。
  2. 更新文档,将 Canvas 描述为实验性内置插件。
  3. 运行针对性的 Canvas 测试、插件清单检查、插件 SDK API 检查和受运行时边界影响的构建/类型通道。

审计清单

在重构完成前检查以下项目:

  • rg "src/canvas-host|../canvas-host" 无实时源码导入。
  • rg "canvas-tool|createCanvasTool" src 找不到核心拥有的 Canvas 工具实现。
  • rg "canvas.present|canvas.snapshot|canvas.a2ui" src/gateway 在通用插件策略测试之外找不到硬编码的允许列表默认值。
  • rg "extensions/canvas/runtime-api" src --glob '!**/*.test.ts' 为空。
  • rg "canvas-documents" src 为空。
  • rg "registerNodesCanvasCommands|nodes-canvas" src 为空;Canvas 插件通过嵌套的插件 CLI 元数据注册 openclaw nodes canvas
  • rg "createCanvasHostHandler|handleA2uiHttpRequest" src/gateway 无网关运行时所有权。
  • rg "apps/shared/OpenClawKit/Tools/CanvasA2UI|canvas-a2ui-copy|extensions/canvas/src/host/a2ui" scripts .github package.json 仅找到兼容性包装或插件自有的路径。
  • pnpm plugins:inventory:check 通过。
  • pnpm plugin-sdk:api:check 通过,或生成的 API 基线已更新并经过审查。
  • 针对性的 Canvas 测试通过。
  • 变更通道测试对 Canvas 宿主/A2UI 路径通过。
  • PR 描述明确说明 Canvas 为实验性、插件支持的。

验证命令

迭代时使用以下本地检查命令:

sh
pnpm test extensions/canvas/src/host/server.test.ts extensions/canvas/src/host/server.state-dir.test.ts extensions/canvas/src/host/file-resolver.test.ts
pnpm test src/gateway/server.plugin-node-capability-auth.test.ts src/gateway/server-import-boundary.test.ts
pnpm test extensions/canvas/src/config-migration.test.ts src/commands/doctor-legacy-config.migrations.test.ts
pnpm test test/scripts/changed-lanes.test.ts test/scripts/build-all.test.ts extensions/canvas/scripts/bundle-a2ui.test.ts test/scripts/bundled-plugin-assets.test.ts extensions/canvas/scripts/copy-a2ui.test.ts src/infra/run-node.test.ts
pnpm tsgo:extensions
pnpm plugins:inventory:check
pnpm plugin-sdk:api:check

在修改运行时 barrel、惰性导入、打包或发布的插件表面之前,务必运行 pnpm build

常见问题

如何确认当前 OpenClaw 分支的 Canvas 是否已完全移出核心?

运行审计清单中的 rg 命令,特别关注 rg "src/canvas-host|../canvas-host" 是否返回空。同时执行 pnpm plugins:inventory:check 确保插件清单包含 Canvas 且无报错。

Canvas 配置从 canvasHost 迁移到 plugins.entries.canvas.config.host 后如何重写?

运行 openclaw doctor --fix,doctor 工具会自动将旧版 canvasHost 配置重写为新格式。重构文档中保留了此迁移逻辑。

打包或发布时遇到 Canvas 相关导入报错怎么办?

先运行 pnpm build,再执行 pnpm plugins:inventory:checkpnpm plugin-sdk:api:check。如果报错指向未被迁移的核心导入,请对照本页“审计清单”中的 rg 检查项,找到残留的核心导入并移入 extensions/canvas