feat(contracts,db): agent.plan / agent.propose_options, interaction events, proposeFirst replaces run mode

- agent_run_event gains plan_updated, options_proposed/resolved, approval_requested/resolved (migration 0040)
- AgentRunStartInput.proposeFirst; mode deprecated (plan_only maps to proposeFirst); mode dropped from AgentRun API
- POST /agent/runs/{id}/choice; agent.optionsTimeoutSec/optionsTimeoutAction/approvalTimeoutSec settings

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 21:07:01 +08:00
1 parent d931e75310
commit 74c2ed45aa
12 files changed
+379 -12

No files matched your search

+43
View File
@@ -1,4 +1,5 @@
import { z } from "zod";
import { 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";
@@ -252,6 +253,42 @@ export const AgentAwaitInput = z.object({
});
export const AgentAwaitOutput = z.object({ results: z.array(SubagentResult), allDone: z.boolean() });
// ── 会话交互(AG-2):步骤清单 / 方案选择 ──
export const AgentPlanInput = z.object({
/** 新增或更新的步骤(按 id 合并;title 缺省沿用已有步骤的标题) */
steps: z
.array(
z.object({
id: z.string().trim().min(1).max(40),
title: z.string().trim().min(1).max(200).optional(),
/** 缺省:新步骤 pending,已有步骤不变 */
status: AgentPlanStepStatus.optional(),
note: z.string().max(500).nullable().optional(),
}),
)
.min(1)
.max(20),
/** true:用这批步骤整体替换原计划 */
replace: z.boolean().default(false),
});
export const AgentPlanOutput = z.object({ steps: z.array(AgentPlanStep), revision: z.number().int().min(1) });
export const AgentProposeOptionsInput = z.object({
question: z.string().trim().min(1).max(500),
options: z.array(AgentOptionItem).min(2).max(4),
/** 推荐项 id(超时自动选择时用它) */
recommendedId: z.string().max(40).optional(),
});
export const AgentProposeOptionsOutput = z.object({
/** chosen = 选了 choice;rejected = 都不要(看 reason);stop = 超时按设置停止,简要汇报后结束 */
outcome: z.enum(["chosen", "rejected", "stop"]),
choice: z.string().nullable(),
option: AgentOptionItem.nullable(),
reason: z.string().nullable(),
by: z.enum(["user", "timeout"]),
});
// ── 站点能力(W10-pre2):输出只给状态与统计,不含凭证、Cookie、secret 引用、登录名与站点 config ──
/** 账号摘要:凭证只给"有没有" */
@@ -433,6 +470,8 @@ export const CAPABILITY_IO = {
"browser.navigate": { input: BrowserNavigateInput, output: BrowserNavigateOutput },
"browser.interact": { input: BrowserInteractInput, output: BrowserInteractOutput },
"browser.download": { input: BrowserDownloadInput, output: BrowserDownloadOutput },
"agent.plan": { input: AgentPlanInput, output: AgentPlanOutput },
"agent.propose_options": { input: AgentProposeOptionsInput, output: AgentProposeOptionsOutput },
} as const satisfies Record<KnownCapabilityId, { input: z.ZodType; output: z.ZodType }>;
type CapabilityIo = typeof CAPABILITY_IO;
@@ -487,6 +526,10 @@ export type AgentSpawnOutput = z.infer<typeof AgentSpawnOutput>;
export type AgentAwaitInput = z.infer<typeof AgentAwaitInput>;
export type AgentAwaitOutput = z.infer<typeof AgentAwaitOutput>;
export type SubagentResult = z.infer<typeof SubagentResult>;
export type AgentPlanInput = z.infer<typeof AgentPlanInput>;
export type AgentPlanOutput = z.infer<typeof AgentPlanOutput>;
export type AgentProposeOptionsInput = z.infer<typeof AgentProposeOptionsInput>;
export type AgentProposeOptionsOutput = z.infer<typeof AgentProposeOptionsOutput>;
export type SiteListInput = z.infer<typeof SiteListInput>;
export type SiteListOutput = z.infer<typeof SiteListOutput>;
export type SiteHealthCheckInput = z.infer<typeof SiteHealthCheckInput>;