feat(agent): W4-E2 in-grant auto recovery for decisions with verified outcome
- settings.agent.autoInvestigateMode investigate|recover, investigateMaxAttempts, recoverVerifySec - new capability download.recheck (execute, replay never): qB force recheck / resume, no source swap/delete - autoInvestigate moves to agent/investigate.ts: recover mode runs execute with a recovery allowlist only when an active grant (published policy if bound) covers the recovery actions; otherwise degrades to read-only investigation and leaves suggestion + recheck option on the decision - runAgent verifies recovery against business facts (download_task/task/source_release) before finalize; verified -> decision resolved by system:auto-recover, run summary '已恢复(系统核实)'; otherwise stays awaiting_user; per-root-cause attempt cap - e2e E6: missingFiles -> download_failed -> recheck -> verified; no grant degrades; swap rejected; dedupe; attempts exhausted; budget exceeded keeps attention Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
23309042dc
commit
86af723b2a
13 files changed
+1072
-15
No files matched your search
@@ -3,7 +3,7 @@ import { MediaAsset } from "./assets.ts";
|
||||
import { CAPABILITY_CATALOG, type CapabilitySpec, type KnownCapabilityId } from "./capability.ts";
|
||||
import { Id, JsonObject, NonNegInt } from "./common.ts";
|
||||
import { MediaEntity, MediaKind } from "./content.ts";
|
||||
import { AcquisitionPlan, DownloadTask, Task, TaskStatus } from "./execution.ts";
|
||||
import { AcquisitionPlan, DownloadStatus, DownloadTask, Task, TaskStatus } from "./execution.ts";
|
||||
import { ExternalEntityType, ExternalIdentity } from "./identity.ts";
|
||||
import { ServerMapping } from "./ops.ts";
|
||||
import { OrganizationAction, OrganizationRecord } from "./organization.ts";
|
||||
@@ -121,6 +121,22 @@ export const OrganizePlanOutput = z.object({
|
||||
export const OrganizeExecuteInput = z.object({ planId: Id, payloadHash: z.string().min(1), approvalId: Id.optional() });
|
||||
export const OrganizeExecuteOutput = Accepted.extend({ record: OrganizationRecord.nullable() });
|
||||
|
||||
/** 授权内恢复:强制重新校验(missingFiles / error 之后)或恢复暂停;换源、删除、清理不在此能力内 */
|
||||
export const DownloadRecheckAction = z.enum(["recheck", "resume"]);
|
||||
export const DownloadRecheckInput = z.object({
|
||||
downloadTaskId: Id,
|
||||
action: DownloadRecheckAction.default("recheck"),
|
||||
reason: z.string().max(500).optional(),
|
||||
});
|
||||
export const DownloadRecheckOutput = z.object({
|
||||
downloadTaskId: Id,
|
||||
action: DownloadRecheckAction,
|
||||
statusBefore: DownloadStatus,
|
||||
rawStateBefore: z.string().nullable(),
|
||||
/** 已向下载器发出请求;是否恢复以后续同步到的 download_task 状态为准 */
|
||||
requested: z.boolean(),
|
||||
});
|
||||
|
||||
export const TaskInspectInput = z.object({ taskId: Id });
|
||||
export const TaskInspectOutput = z.object({
|
||||
task: Task,
|
||||
@@ -178,6 +194,7 @@ export const CAPABILITY_IO = {
|
||||
"identity.resolve": { input: IdentityResolveInput, output: IdentityResolveOutput },
|
||||
"download.plan": { input: DownloadPlanInput, output: DownloadPlanOutput },
|
||||
"download.submit": { input: DownloadSubmitInput, output: DownloadSubmitOutput },
|
||||
"download.recheck": { input: DownloadRecheckInput, output: DownloadRecheckOutput },
|
||||
"organize.plan": { input: OrganizePlanInput, output: OrganizePlanOutput },
|
||||
"organize.execute": { input: OrganizeExecuteInput, output: OrganizeExecuteOutput },
|
||||
"task.inspect": { input: TaskInspectInput, output: TaskInspectOutput },
|
||||
@@ -223,6 +240,8 @@ export type OrganizeExecuteInput = z.infer<typeof OrganizeExecuteInput>;
|
||||
export type OrganizeExecuteOutput = z.infer<typeof OrganizeExecuteOutput>;
|
||||
export type TaskInspectInput = z.infer<typeof TaskInspectInput>;
|
||||
export type TaskInspectOutput = z.infer<typeof TaskInspectOutput>;
|
||||
export type DownloadRecheckInput = z.infer<typeof DownloadRecheckInput>;
|
||||
export type DownloadRecheckOutput = z.infer<typeof DownloadRecheckOutput>;
|
||||
export type TaskRetryInput = z.infer<typeof TaskRetryInput>;
|
||||
export type TaskRetryOutput = z.infer<typeof TaskRetryOutput>;
|
||||
export type TaskCancelInput = z.infer<typeof TaskCancelInput>;
|
||||
|
||||
@@ -57,6 +57,7 @@ export const CAPABILITY_IDS = [
|
||||
"identity.resolve",
|
||||
"download.plan",
|
||||
"download.submit",
|
||||
"download.recheck",
|
||||
"organize.plan",
|
||||
"organize.execute",
|
||||
"task.inspect",
|
||||
@@ -171,6 +172,17 @@ export const CAPABILITY_CATALOG: Record<KnownCapabilityId, CapabilityDescriptor>
|
||||
true,
|
||||
false,
|
||||
),
|
||||
"download.recheck": d(
|
||||
"download.recheck",
|
||||
"重新校验/恢复下载",
|
||||
"对已纳管的下载任务发起强制重新校验(action=recheck)或恢复非阈值、非人工的暂停(action=resume);不换源、不删除、不改保存路径",
|
||||
"execute",
|
||||
"DownloadRecheck",
|
||||
"organize.execute",
|
||||
"medium",
|
||||
true,
|
||||
false,
|
||||
),
|
||||
"organize.plan": d(
|
||||
"organize.plan",
|
||||
"生成整理计划",
|
||||
|
||||
@@ -73,8 +73,22 @@ export type PiSettings = z.infer<typeof PiSettings>;
|
||||
* 上游/模型/思考档位在 pi 分组;pi.provider = "fake" 时使用脚本化假模型(不联网,演示与 e2e 用)。
|
||||
*/
|
||||
export const AgentRuntimeSettings = z.object({
|
||||
/** 识别歧义 / 下载失败诊断等待处理事项创建时,自动发起有界只读调查 */
|
||||
/** 识别歧义 / 下载失败诊断等待处理事项创建时,自动发起有界调查 */
|
||||
autoInvestigate: z.boolean(),
|
||||
/**
|
||||
* 自动调查的模式:investigate = 只读调查,结论交还人工;
|
||||
* recover = 在已发布策略 / 持续授权范围内可执行恢复类能力(task.retry、download.recheck、identity.resolve),
|
||||
* 换源、删除、清理始终排除;没有覆盖的授权时自动降级为 investigate。
|
||||
*/
|
||||
autoInvestigateMode: z.enum(["investigate", "recover"]),
|
||||
/** 同一根因(decision 去重键)最多自动恢复几次;用尽后只交还人工,不再唤醒模型 */
|
||||
investigateMaxAttempts: z.number().int().min(1).max(10),
|
||||
/** 恢复动作后等待业务事实(下载状态 / 任务状态)核实的最长时间(秒) */
|
||||
recoverVerifySec: z
|
||||
.number()
|
||||
.int()
|
||||
.min(5)
|
||||
.max(24 * 3600),
|
||||
/** 单次运行:工具调用次数上限 */
|
||||
maxToolCalls: z.number().int().min(1).max(500),
|
||||
/** 单次运行:时长上限(秒) */
|
||||
@@ -165,6 +179,9 @@ export const DEFAULT_SETTINGS: GlobalSettings = {
|
||||
},
|
||||
agent: {
|
||||
autoInvestigate: false,
|
||||
autoInvestigateMode: "investigate",
|
||||
investigateMaxAttempts: 2,
|
||||
recoverVerifySec: 600,
|
||||
maxToolCalls: 40,
|
||||
maxDurationSec: 900,
|
||||
maxTokensPerRun: null,
|
||||
|
||||
Reference in new issue
Block a user