feat(agent): 选定方案即批准,服务端绑定计划(AGUI-3)

- agent.propose_options 的方案可带 action(capabilityId + planId)。提出方案时服务端按计划当前的
  payload hash + revision 绑定,并用计划本身生成动作要点(对象、大小 / 文件数)发给界面,不用模型的说法。
- 控制台管理员会话选定绑定了计划的方案时,建一份 scope.via=option 的已批准单次审批(审计 approval.approved);
  执行时授权器 optionApproval 核对能力、计划类型 + ID、payload hash、revision、有效期后放行,用后 consumed,
  不再出第二张审批卡。API Key 作答、超时自动选、计划已变化都不算批准;移动 / 替换文件的整理与发布策略
  (删除、覆盖类)选定后仍单独确认。会话停止时撤销没用掉的这类审批。
- contracts:CAPABILITY_ACTIVITY 给每个能力加 verb / noun(会话进度行的人话计数);agent.plan /
  agent.propose_options 标为 hidden。
- e12 补测试:管理员选定 → 无 approval_requested、审批绑定同一计划并 consumed、换 hash 不放行;
  API Key 选定 → 仍出审批卡。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 22:40:57 +08:00
1 parent c9c6505d71
commit 4e0e6712da
8 files changed
+507 -33

No files matched your search

+3 -1
View File
@@ -1,6 +1,6 @@
import { z } from "zod";
import { DecisionKind, DecisionOption, DecisionStatus, Severity } from "./agent.ts";
import { AgentOptionItem, AgentPlanStep, AgentPlanStepStatus } from "./agent-events.ts";
import { AgentOptionAction, AgentOptionItem, AgentPlanStep, AgentPlanStepStatus } from "./agent-events.ts";
import { MediaAsset } from "./assets.ts";
import { BrowserController, BrowserDownloadVerification, BrowserSnapshot } from "./browser.ts";
import { CAPABILITY_CATALOG, type CapabilitySpec, type KnownCapabilityId } from "./capability.ts";
@@ -404,6 +404,8 @@ export const AgentProposeOptionsOutput = z.object({
outcome: z.enum(["chosen", "rejected", "stop"]),
choice: z.string().nullable(),
option: AgentOptionItem.nullable(),
/** 选定即批准(AGUI-3):用户在管理员会话里选定的方案绑定了这份计划,可直接执行;null = 没有随选定批准的动作 */
approvedAction: AgentOptionAction.nullable().optional(),
reason: z.string().nullable(),
by: z.enum(["user", "timeout"]),
});