Why: deploy needs a reviewed design for compiling selected plugins into the base binary before that behavior is treated as approved. Evidence: the proposal records the throwaway compose build; implementation status stays unreviewed. Impact: adds a pending proposal and an index link. Inclusion does not approve the design. Refs: Dev .task/feature-svc-plugin-compose.md Co-authored-by: Cursor <cursoragent@cursor.com>
5.4 KiB
5.4 KiB
svc 插件组合部署(--with)方案 r1
状态:待评审。日期:2026-10-14。负责人:weichen。
任务卡:Dev .task/feature-svc-plugin-compose.md。
需求来源:部署时用交互或参数选择把哪些插件与基座编译成同一个二进制服务,并在服务中激活这些插件。
1. 范围
做:
- 每次
svc.sh的 agent deploy 可以选择零个或多个已登记插件。 - 被选中的插件与
--from指定的 Dev 基座编译成一个仍名为agent-system的二进制。 - 部署后校验这些插件已注册且命令面处于启用;失败走现有 release 回退。
- 插件清单来自 Dev 仓
plugins/registry.json,不自动发现。
不做:
- 不做 sidecar,不把插件部署成独立服务。
- 不让插件自带基座 pin。基座就是本次
--from的 Dev 提交;对不上就构建失败并报原因。 - 第一版最多一个带静态工作台(
web)的插件。 - 不删除旧的
--from rdm。它仍用 RDM 仓自己的pins/构建,与--with互斥。
2. 步骤 0 试验结论(不留代码)
2026-10-14 在 /tmp/svc-compose-spike 复制当前 Dev 的 backend 模块,空白导入
agent-system-rdm/plugins/rdm(指向 ~/.cache/agent-system-svc/rdm-src),
go mod edit -require/-replace 后执行 CGO_ENABLED=0 go build -mod=mod。
- 构建成功。产物约 40MB,
version仍是基座的agent-system 0.1.0-dev。 go version -m显示主模块agent-system-backend,依赖agent-system-rdm v0.0.0。- 二进制内可见
rdm.project.create与rdm.ping。 - 聚焦依赖(
golang.org/x/*、github.com/jackc/*、modernc.org/sqlite、gopkg.in/yaml)版本无变化。 - 新增模块只有
agent-system-rdm、github.com/kr/text、github.com/rogpeppe/go-internal。 - 默认
-mod=readonly会拒绝更新go.mod/go.sum,组合构建必须使用-mod=mod。 - 依赖模块自己的
replace不生效,插件按主模块(Dev 基座)解析agent-system-backend。这正是“基座以 Dev 提交为准”所要的结果。
试验目录是一次性的,不进入任何仓库。
3. 行为
3.1 选择
--with rdm,foo选择插件;--with rdm@<sha>钉住单个插件提交;--with none明确不带插件。- 标准输入是终端且没有
--with时,按登记表给出编号勾选。默认勾选上次svc.env的plugins=;第一次默认不选。回车接受默认,none清空。 - 非交互且没有
--with:沿用上次选择,没有则不带插件。已有脚本和 CI 的行为不变。 --dry-run打印基座提交和每个插件的提交,不构建。--from rdm与--with(除none)互斥。--from release不能再注入插件。
3.2 构建
- 物化 Dev 提交的隔离 worktree,并完成前端构建,使嵌入资源就绪。
--from local不改主检出的go.mod:把 backend 模块复制到runtime/.worktrees/再构建。 - 每个插件使用独立源仓缓存(
~/.cache/agent-system-svc/plugin-<id>,repoEnv可覆盖克隆地址)并物化 worktree。 - 在这份一次性 backend 副本里生成
cmd/agent-system/zz_plugins_gen.go(空白导入entryPackage),并用go mod edit增加require与replace。 go build -mod=mod产出agent-system。基座的version、身份和user等子命令保持不变。- 测试可设
SVC_COMPOSE_STUB=1,跳过真实go build,只记录插件选择。这不是生产路径。
3.3 激活与记录
GET /api/plugins与GET /api/registry的compiled列表必须包含每个所选插件。GET /api/commands中该插件commandPrefix下至少有一条enabled命令。- 插件在而命令全部禁用时,用与设置播种相同的临时管理员 key 调用
POST /api/plugins/{id}/enabled,再复查。失败则svc_rollback_deploy。 svc.env写plugins=id@sha,id@sha。source形如dev@<sha>+rdm@<sha>。release 目录的release.json带同一plugins字段。update把基座升到远端最新,并原样带上已记录的--with,不再询问。recover只拉起已有二进制,不重新选择。- 插件 id 集合变化(含从无到有、从有到无)与源种类变化一样,需要
--allow-source-switch。只改提交不需要。
3.4 工作台
登记表里 web 非空的插件,沿用现有伴生 static 服务(<name>web)。多于一个带 web 的插件直接拒绝。
4. 跨仓
- Backend:
extension.InProc增加可选HostOptions与CLI。布尔默认按“任一为 true”合并,不覆盖显式 serve 旗标。GET /api/registry增加compiled。 - RDM:
plugins/rdm在InProc上声明HostOptions(含关闭上传自动索引、会话卡镜像、执行原语)和-bootstrap-admin钩子。RDM 自己的main.go继续可用,旧--from rdm不依赖这次钩子。 - Dev:
scripts/svc.sh、plugins/registry.json、docs/svc.md、help plugins、tests/test_svc_plugins.py,并推进 backend 与 documents 的 gitlink。
5. 验收
- 登记、选择、换源门禁、dry-run、stub 部署与激活走
tests/test_svc_plugins.py。 - Backend 的合并与 CLI 钩子走
go test ./pkg/extension/。 - 真实
go build组合(Dev 提交 + RDM 提交)在步骤 0 已证实可编译。带网络的完整svc deploy --with rdm与make test-lifecycle不在本增量的 stub 套件里,未在本机再跑时标 NOT_RUN。