148 lines
4.8 KiB
TypeScript
148 lines
4.8 KiB
TypeScript
import {
|
||
isAwaitingUserConfirmationWorkflow,
|
||
type AgentWorkflowState,
|
||
type AgentWorkflowStatus,
|
||
type AgentWorkflowType,
|
||
} from "@/lib/ai/runtime/agent-workflow-state";
|
||
import type { AgentThreadState } from "@/lib/ai/runtime/agent-thread-state";
|
||
import { interpretStoryboardCommand } from "@/lib/video-agent/storyboard-command-interpreter";
|
||
|
||
export type HumanConfirmationIntent =
|
||
| "none"
|
||
| "confirm"
|
||
| "revise"
|
||
| "cancel"
|
||
| "unclear";
|
||
|
||
export type HumanConfirmationGateAction =
|
||
| "pass"
|
||
| "awaiting_confirmation"
|
||
| "confirmed"
|
||
| "revision_requested"
|
||
| "cancel_requested";
|
||
|
||
export interface HumanConfirmationGateDecision {
|
||
action: HumanConfirmationGateAction;
|
||
confirmationIntent: HumanConfirmationIntent;
|
||
workflowId?: string;
|
||
workflowType?: AgentWorkflowType;
|
||
nextWorkflowStatus?: AgentWorkflowStatus;
|
||
allowWorkflowExecution: boolean;
|
||
shouldBypassPlanner: boolean;
|
||
friendlyMessage?: string;
|
||
}
|
||
|
||
function buildAwaitingConfirmationMessage(workflowState: AgentWorkflowState): string {
|
||
const title = workflowState.title || "当前工作流";
|
||
const summary = workflowState.summary
|
||
? `\n当前待确认内容:${workflowState.summary}`
|
||
: "";
|
||
const pendingItemsPreview = workflowState.pendingItems
|
||
.slice(0, 3)
|
||
.map((item) => {
|
||
const indexText = item.index ? `镜头${item.index}` : item.title || "待确认项";
|
||
const summaryText = item.summary ? `:${item.summary}` : "";
|
||
return `- ${indexText}${summaryText}`;
|
||
})
|
||
.join("\n");
|
||
const previewBlock = pendingItemsPreview ? `\n${pendingItemsPreview}` : "";
|
||
const confirmExample = workflowState.confirmPhrases[0] || "确认开始生成视频";
|
||
const reviseExample = workflowState.revisionHints[0] || "修改第3镜头";
|
||
|
||
return [
|
||
`当前有一个待确认流程:${title}。`,
|
||
summary ? summary.trim() : "",
|
||
previewBlock.trim(),
|
||
`如果确认无误,请回复“${confirmExample}”。`,
|
||
`如果需要修改,请直接回复类似“${reviseExample}”。`,
|
||
]
|
||
.filter(Boolean)
|
||
.join("\n");
|
||
}
|
||
|
||
function buildConfirmMessage(workflowState: AgentWorkflowState): string {
|
||
const title = workflowState.title || "当前流程";
|
||
return `已收到确认:${title} 可以进入下一步执行。我会按已确认内容继续处理。`;
|
||
}
|
||
|
||
function buildRevisionMessage(workflowState: AgentWorkflowState): string {
|
||
const title = workflowState.title || "当前流程";
|
||
return `收到修改意见。我会先更新 ${title} 的草案内容,并在重新确认前暂停执行。`;
|
||
}
|
||
|
||
function buildCancelMessage(workflowState: AgentWorkflowState): string {
|
||
const title = workflowState.title || "当前流程";
|
||
return `已收到取消指令。${title} 会继续停留在人工确认前状态,不会继续自动执行。`;
|
||
}
|
||
|
||
export async function runHumanConfirmationGate(params: {
|
||
text: string;
|
||
threadState?: AgentThreadState | null;
|
||
}): Promise<HumanConfirmationGateDecision> {
|
||
const workflowState = params.threadState?.workflowState;
|
||
if (!workflowState || !isAwaitingUserConfirmationWorkflow(workflowState)) {
|
||
return {
|
||
action: "pass",
|
||
confirmationIntent: "none",
|
||
allowWorkflowExecution: true,
|
||
shouldBypassPlanner: false,
|
||
};
|
||
}
|
||
|
||
const interpreted = await interpretStoryboardCommand({
|
||
text: params.text,
|
||
totalShots: workflowState.pendingItems.length || undefined,
|
||
items: workflowState.pendingItems.map((item) => ({
|
||
index: item.index || 0,
|
||
title: item.title,
|
||
summary: item.summary,
|
||
})),
|
||
});
|
||
const confirmationIntent = interpreted.intent;
|
||
const baseDecision = {
|
||
workflowId: workflowState.workflowId,
|
||
workflowType: workflowState.type,
|
||
shouldBypassPlanner: true,
|
||
};
|
||
|
||
switch (confirmationIntent) {
|
||
case "confirm":
|
||
return {
|
||
...baseDecision,
|
||
action: "confirmed",
|
||
confirmationIntent,
|
||
nextWorkflowStatus: "confirmed",
|
||
allowWorkflowExecution: true,
|
||
friendlyMessage: buildConfirmMessage(workflowState),
|
||
};
|
||
case "revise":
|
||
return {
|
||
...baseDecision,
|
||
action: "revision_requested",
|
||
confirmationIntent,
|
||
nextWorkflowStatus: "draft",
|
||
allowWorkflowExecution: false,
|
||
friendlyMessage: buildRevisionMessage(workflowState),
|
||
};
|
||
case "cancel":
|
||
return {
|
||
...baseDecision,
|
||
action: "cancel_requested",
|
||
confirmationIntent,
|
||
nextWorkflowStatus: "cancelled",
|
||
allowWorkflowExecution: false,
|
||
friendlyMessage: buildCancelMessage(workflowState),
|
||
};
|
||
case "unclear":
|
||
default:
|
||
return {
|
||
...baseDecision,
|
||
action: "awaiting_confirmation",
|
||
confirmationIntent: "unclear",
|
||
nextWorkflowStatus: workflowState.status,
|
||
allowWorkflowExecution: false,
|
||
friendlyMessage: buildAwaitingConfirmationMessage(workflowState),
|
||
};
|
||
}
|
||
}
|