Merge branch 'agui3'

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-29 22:43:07 +08:00
commit 0055db6cf9
35 files changed
+3034 -1912

No files matched your search

+36 -2
View File
@@ -20,7 +20,7 @@ import {
agentRunEventFromRow,
cursorPage,
} from "@umt/contracts";
import { MOCK_RUNS, mockCreateRun, mockDetail, mockEventsAfter } from "~/components/agent/mock.ts";
import { MOCK_RUNS, mockChoose, mockCreateRun, mockDetail, mockEventsAfter } from "~/components/agent/mock.ts";
import { TTL_SECOND } from "~/lib/api.ts";
import { useSession } from "./auth.ts";
import { apiMutate, apiParsed, cleanParams } from "./parse.ts";
@@ -254,7 +254,7 @@ export function useChooseOption() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (input: { runId: string; decisionId: string; optionId: string | null; reason?: string }) => {
if (agentMockEnabled()) return mockDetail(input.runId).run;
if (agentMockEnabled()) return mockChoose(input.runId, input.optionId).run;
return apiMutate(`${AGENT_BASE}/:id/choice`, {
pathParams: { id: input.runId },
body: { decisionId: input.decisionId, optionId: input.optionId, reason: input.reason },
@@ -264,6 +264,40 @@ export function useChooseOption() {
});
}
/** 需要按计划单次审批的能力:这类动作在会话里走审批卡,不另建持续授权 */
const PLAN_APPROVAL_CAPS = new Set(["download.submit", "organize.execute", "policy.apply"]);
/**
* 「批准并重试」(AGUI-3):被拒绝的调用由管理员批准一次后让智能体重试。
* 非计划类能力建一条只覆盖这个能力、今天只能成功一次、1 小时后过期的持续授权(服务端核对,不靠模型转述);
* 计划类能力只追加消息让智能体重试,重试时在步骤处照常出审批卡。
*/
export function useApproveAndRetry() {
const qc = useQueryClient();
return useMutation({
mutationFn: async (input: { runId: string; capabilityId: string; title: string }) => {
const text = PLAN_APPROVAL_CAPS.has(input.capabilityId)
? `重试「${input.title}」,需要审批时在步骤处等我批准。`
: `已批准「${input.title}」一次,重试这一步。`;
if (agentMockEnabled()) return mockDetail(input.runId, { append: text }).run;
if (!PLAN_APPROVAL_CAPS.has(input.capabilityId))
await apiMutate("/automation-grants", {
body: {
action: input.capabilityId,
scope: { capabilities: [input.capabilityId] },
budget: { maxInvocationsPerDay: 1 },
reason: `智能体会话 ${input.runId.slice(0, 8)} 里批准并重试`,
expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
},
});
return apiMutate(`${AGENT_BASE}/:id/messages`, { pathParams: { id: input.runId }, body: { text } }).then((d) =>
AgentRun.parse(d),
);
},
onSuccess: (_d, v) => qc.invalidateQueries({ queryKey: agentKeys.run(v.runId) }),
});
}
export const RUN_STATUS_LABEL: Record<AgentRunStatus, string> = {
queued: "排队中",
running: "运行中",