# 插件契约 v2 状态:**实施中(2026-10-01)**;owner:weichen;主任务:Dev 仓 `feature/base-extension-roadmap`。 撰写日期:2026-10-01。配套:[路线图](2026-10-01-base-extension-roadmap.md)、[兼容规则](2026-10-01-extension-compat-policy.md)。 ## 1. 四种形态 下游按需要选一种或组合。基座对四种形态使用同一份 manifest 与同一套 fail-closed:任一资产解析失败则整包拒绝,保留上一状态。 | 形态 | 下游交付 | 基座职责 | |---|---|---| | 声明 | `plugin.json` + 资产目录 | 注册 tools/skills/mcp/knowledge/parsers/agents/channels/pages/commands/… | | 进程内编译 | 下游 `main` import `pkg/extension` 并 `RegisterCompiled` | `link` + builder 模式产出**下游自己的**单二进制 | | sidecar | 原生进程,manifest `backend.mode=sidecar` | 拉起、健康(进程存活)、停止;环境变量注入 Host API | | 前端 ESM | `pages/*.json` 指向模块 | UI SDK 只暴露命令、SSE 与 `@ui` 组件;页面不得另起设计令牌 | 进程内编译适合要事务一致性的领域逻辑。sidecar 适合异构语言或强隔离。声明式 HTTP 工具仍然只描述调用,不携带任意代码。 ## 2. manifest 增补 `apiVersion` 用 `2.0-experimental` 才强制网络白名单。字段见 `modules/core/plugin_v2.go`。 - `provides.skills`:`skills/.md`,宿主写入 `/skills/plugin-/`。 - `provides.mcpServers`:并入小队 MCP 配置(与 `tools.mcp.servers` 合并)。 - `provides.knowledge|parsers|agents|channels|pages`:声明登记,供清单 API 与前端加载。 - `scope.tenants/projects`:空 = 全部可见。 - `backend.command`:sidecar 可执行文件(相对插件目录或 PATH)。`schemaVersion` 记入 `plugin_schema`。 密钥查找顺序:`secrets..`(按工具执行时的 `OwnerID`),再回落同名全局设置。不再在绑定期固定读 `OwnerDefault`。 ## 3. Host API(sidecar 与外部进程) 监听由基座在本机拉起,令牌随进程环境变量 `AGENT_HOST_API`、`AGENT_HOST_TOKEN` 下发。 | 方法 | 路径 | 作用 | |---|---|---| | PUT/GET | `/host/v1/kv/{key}` | 插件隔离 KV(带 owner 与 plugin id) | | POST | `/host/v1/audit` | 写通用审计 | | POST | `/host/v1/commands/{id}` | 走命令总线 | | POST | `/host/v1/llm` | 代理聊天补全;未配置模型返回 503,不静默伪造 | | GET | `/host/v1/knowledge/search` | 混合检索(引擎在基座) | 插件故障不拖垮基座:sidecar 退出只记日志与审计,不退出主进程。 ## 4. 进程内注册 ```go func init() { extension.RegisterCompiled(extension.InProc{ ID: "rdm", Register: func(reg extension.Registry) error { return reg.AddSkill("rdm-note", "# …") }, }) } ``` 下游 main: ```go import _ "agent-system-backend/pkg/extension/link" func main() { extension.Main(extension.Options{Addr: "127.0.0.1:8787"}) } ``` ## 5. 前端 `@ui` 导出 `createPluginBridge`:`execCommand` 与 `subscribeEvents`。插件页面模块默认导出 `mount(el, bridge)` / `unmount()`。宿主按 `pages[].module` 动态 `import()`。插件 TSX 与基座一样受 design-guard 约束(令牌、无私人 keyframes、无行内字号)。 ## 6. 生命周期 - 启用:`POST /api/plugins/{id}/enabled`,按租户记 `plugin_grants`。 - 升级:`backend.schemaVersion` 大于已记录版本时调用宿主迁移钩子(KV 命名空间不清空;钩子由进程内扩展提供)。版本只升不降,降级拒绝装载。 - 管理面:`GET /api/plugins` 返回 manifest(含 v2 provides)以及技能/页面/渠道声明。既有设置页「插件」分组继续承担热重载。 ## 7. 开发体验 - `make plugin-new NAME=` 在 `examples/plugins/` 生成声明式骨架。 - `examples/plugins/decl-demo`、`examples/downstream-rdm`、`examples/sidecar-demo`、`examples/page-demo` 各覆盖一种形态。 - 验收:`examples/downstream-rdm` 的测试不导入 `internal`,并由 `make test-boundaries` 卡住。