Skip to content

✨ ctl: server 侧 agrctl 执行者与控制台作答工具审批,pin agentre 到 bd8519d3 - #26

Merged
CodFrm merged 17 commits into
mainfrom
2026-09-22-agrctl-resource-management
Sep 25, 2026
Merged

CodFrm merged 17 commits into
mainfrom
2026-09-22-agrctl-resource-management

Conversation

@CodFrm

@CodFrm CodFrm commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

变更说明 / Summary

agrctl 资源管理的 server 侧(桌面端:agentre-hub/agentre#67):

  • ctl 执行者:POST /v1/ctl/resources(设备 Bearer,protojson),五类资源按 id 读写、计算前后值,写入复用 workspace_svc / engine_svc 现有路径,照常推进同步版本并广播账号信号;?preview 只返回变更清单不写入(agentred 据此出卡);/v1/ctl/send 与 OpenClaw --token(非本机绑定)、桌面设备项目本机路径明确拒绝。
  • 控制台作答:answerToolApproval 端口接到新 relay 方法 toolApproval.answer,org 与 ctl 两类审批卡在控制台都能作答;wireview 透出 toolInput。
  • 修正轮 2:删 Agent 时同一事务里给它的执行目标与项目成员落墓碑、删后端时给引用它的执行目标落墓碑(web 与 agrctl 共用 workspace_svc.DeleteOrgObject / engine_svc.DeleteBackend,与桌面端 sync 级联一致);agrctl 一次写入涉及的多行并进一个事务(持账号锁),失败整体回滚,提交后只广播一次。
  • 修正轮 3:openclaw 后端写入(web 与 agrctl 共用)按桌面端同一规则校验——网关地址必填且 ws/wss、会话模式、不得携带 provider/model/env/推理强度/沙箱/审批等——agrctl 在预览即拒(不出卡),每种原因单独错误码(30905–30916,中英文),不再产生桌面端落不了地的同步行;ctl 路径的网关错误点名 --config openclawGatewayUrl。
  • CtlBackend 报 sync_id / device_fingerprint,OpenClaw token 状态报 unknown。
  • pin:pkg/wire、pkg/syncwire、@agentre-hub/agentre-ui、@agentre-hub/agentre-wire pin 到桌面分支 d5df824f(该分支已合入桌面 origin/main 2996e334);中继词表补 unsupported_request_notice。

合并顺序:先合桌面端 agentre-hub/agentre#67。桌面端若以 merge commit 合入,d5df824f 仍可达;若 squash,需要把本 PR 的 pin 改到桌面 main 上的新 SHA 再合。

验证 / Verification

门禁(coding.lan,HEAD 0a11a68):

make test-backend  → exit 0(84 包 ok)
golangci-lint      → 0 issues;eslint → exit 0
make test-frontend → exit 0(126 文件)

真机:本分支 server(e2e 的 pnpm serve,专用 e2e 库,收尾 no residue)+ 本轮 agentred + 隔离桌面端 + 真实 Claude Code。控制台对桌面端会话与 agentred 会话的 ctl 卡都能在待审批期间作答(V4 / V6 holds),写入后控制台组织页实时出现。修正轮 2/3 复验:web 删除 Agent / 后端的级联墓碑、agentred 会话里不合规 openclaw 出卡前被拒、合规的桌面端即时落地、删除后端新文案均 holds。完整结论见桌面端 PR。

已知限制(未在本 PR 修)

  • openclaw 规则是桌面端 agent_backend_entity 的逐条复刻,目前一致,但没有跨仓对齐守卫。
  • 已存在的不合规 openclaw 行在修好网关地址前无法改名(删除照常),与桌面端一致。

截图 / Screenshots

控制台审批卡截图在本地验证证据目录,未随 PR 上传。

自检 / Checklist

  • Fixes mentioned issues / 修复已提及的问题
  • Code reviewed by human / 代码通过人工检查
  • Changes tested / 已完成测试

- POST /v1/ctl/resources(protojson CtlRequest→CtlResponse,错误 {"error"},?preview=1 只算变更清单)只挂在 DeviceJWT 组;浏览器 engine 路由的会话 + CSRF 不变
- 读取同步组行:id 即 sync_objects.id,模型 id 由提供方同步标识 + ModelKey 派生;API key 只回掩码
- 写入经 workspace_svc / engine_svc 既有写路径,同步版本推进、账号信号广播照旧
- send、OpenClaw token、桌面设备的项目本机路径明确拒绝(422)
…op_ctl_token),镜像投影补 toolInput case

T10/T11 在桌面仓推送了 tool_approval_requested/resolved 事件对与
RuntimeRunRequest.desktop_ctl_token/desktop_session_id(协议仍是 0.4.0,方法集
未变,wireversion 不用跟着抬)。go.mod 的 pkg/wire、pkg/syncwire 与
frontend/package.json 的 agentre-ui、agentre-wire 一起挂到该 SHA。

wireview.go 里 RuntimeEvent 少了 ToolApprovalRequested 分支:ToolInput 是
bytes 装的 JSON(ctl 变更清单),不补 putRawJSON 就会走 BytesKind 的默认投射
变成 base64 字符串,agentre-ui 的 frames.ts 用 record(ev,"toolInput") 直接当
对象取字段,喂给它一个字符串等于卡片拿到空对象。TestProjectableNotifications
CarryNoUnknownBinaryField 那条守卫先红了(新 bytes 字段不在白名单),补上
case 与白名单项即绿。

relay-event-vocabulary.test.ts 的 SAMPLES 是按 RuntimeEventCase 穷尽的表,
两个新分支一上线就让 pnpm typecheck 先红;补上样本、词表与一条端到端用例,
钉住 ctl 审批卡的请求帧经真实协议解码后合成带解析后变更清单的卡、终态帧
回填 status/result —— 批准调 toolApproval.answer 已由 74d8565 接好
(session-decision-ports.test.tsx、transcript-ports.test.tsx 覆盖)。

server 不解 RuntimeRunRequest(grep 全仓无命中),relay 路径只按 channel/
peer/stream 打日志,desktop_ctl_token 因此原样不落日志、不落库。
…fingerprint)

T14 把桌面仓 CtlBackend.token_set 换成 CtlTokenState token_state(UNSPECIFIED/
SET/UNSET/UNKNOWN),并加了 sync_id、device_fingerprint(协议仍是 0.4.0,方法集
未变)。go.mod 的 pkg/wire、pkg/syncwire 与 frontend/package.json 的 agentre-ui、
agentre-wire 一起挂到该 SHA。

server 执行者的 backendDoc 补上这三个只读字段:sync_id/device_fingerprint 原样
取自同步行的 SyncID/AgentredFingerprint;token_state 恒报 UNKNOWN(OpenClaw 类型)
或 UNSPECIFIED(没有 token 概念的类型)——server 只有同步过来的文档,够不到后端
绑定设备的钥匙串,没法像桌面端那样问出 SET/UNSET。OpenClaw token 写入仍然
422(checkSupported 不看类型,任何后端的 token 字段都拒),未受此次改动影响。

TDD:先在 ctl_test.go 补上三个字段与 UNKNOWN 状态的断言(对着旧 GetTokenSet
编译先红,换成新断言后运行时红),再在 state.go 实现 backendTokenState 与字段
填充转绿。
…住 0/1/多

- ctl_ctr:?preview=true / ?preview 等写法不再落成一次没经审批的真写入(fail closed);日志前缀改成 writeServiceErr
- ctl_svc:与桌面端 agent_svc 归属规则同口径,create 不给部门、update 把部门清空都在预览时 400
- 级联删除附注对 0 / 1 / 多个数量都与 agentred 的 ParseCtlCascadeNote 正则对得上
…otice

桌面轮次分支合入 main(bd8519d3)后推到 GitHub origin:main 带来
ClaudeCodeRateLimits.model_weekly(Sonnet/Opus 分列周配额弃用)、新事件
unsupported_request_notice(oneof 32)与 ExecApprovalRequested 字段 11–23;
本轮的 tool_approval_requested/resolved 随之挪到 33/34(协议仍是 0.4.0,方法集
未变)。go.mod 的 pkg/wire、pkg/syncwire 与 frontend/package.json 的
agentre-ui、agentre-wire 一起挂到该 SHA。

server 只经生成代码引用这些字段(全仓无裸字段号、无 Sonnet/Opus 周配额读取),
Go 侧 wireview/镜像守卫直接绿:新事件只有一个 string 字段,不涉及 bytes 白名单。

relay-event-vocabulary.test.ts 的 SAMPLES 按 RuntimeEventCase 穷尽,pnpm
typecheck 先红(TS2741 缺 unsupportedRequestNotice);补上样本与词表项,并加一条
端到端用例钉住该提示帧穿真实协议后归约成结构化 notice(noticeKind +
noticePurpose),而不是 default 分支的 JSON notice。
@CodFrm
CodFrm merged commit 02d31f7 into main Sep 25, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant