import type { AgentActivityTraceItem } from "./agent-activity-trace.ts"; import { activityCompletedTrail } from "./chat-message-view.ts"; import type { PublicActivityPhase } from "./consultation-agent-events.ts"; import type { CompletedActivityReceiptView } from "./rectification-activity-receipt.ts"; import type { PublicRectificationActivity, PublicRectificationTool, } from "./rectification-agentic/v9/public-receipt.ts"; import type { RectificationTurnProgressStage } from "./rectification-agentic/v9/turn-progress.ts"; import { RECTIFICATION_AGENT_ATTEMPT_TIMEOUT_MS as ATTEMPT_TIMEOUT_MS } from "./rectification-run-budget.ts"; export { RECTIFICATION_AGENT_ATTEMPT_TIMEOUT_MS } from "./rectification-run-budget.ts"; export const RECTIFICATION_TOOL_DONE_LABELS: Readonly> = { "rectification-read-case": "看了你的资料", "rectification-set-focus": "准备好下一个问题", "rectification-resolve-focus": "记下你对这一问的回答", "rectification-record-evidence-batch": "记下你说的事", "rectification-propose-evidence": "记下你说的事", "rectification-confirm-evidence": "核对好这件事", "rectification-revise-evidence": "改好这件事", "rectification-compare-candidates": "重新对照了盘面", "rectification-read-diagnostics": "看了结果稳不稳", "rectification-offer-candidates": "整理好可能的时间", "rectification-accept-candidate": "用上你选的时间", "rectification-confirm-birth-time": "确认好出生时间", "rectification-stop-and-review": "先停下不再问", "rectification-close-case": "结束这次校正", }; export const RECTIFICATION_ACTIVITY_PROGRESS_LABELS: Readonly> = { reading_case: "正在看你的资料…", recording_answer: "正在记下你的选择…", updating_candidates: "正在重新对照盘面…", checking_stability: "正在看结果稳不稳…", preparing_question: "正在准备下一个问题…", preparing_result: "正在准备结果…", }; /** * Stage lines for a typed answer (BUG-1047 D3). The first one shows the moment * the reader sends; the server's `turn.progress` events move it forward. They * live only on the live row and are never part of the saved reply. */ export const RECTIFICATION_TURN_PROGRESS_LABELS: Readonly> = { received: "收到,正在对照你的档案…", recording: "正在记下这件事…", rescoring: "正在重新对照盘面…", preparing_question: "正在准备下一个问题…", }; export function rectificationTurnProgressPhase(stage: RectificationTurnProgressStage): PublicActivityPhase { if (stage === "received") return "loading-method"; if (stage === "rescoring") return "chart-calculation"; return "evidence-validation"; } /** Live label between a completed tool and the next tool or spoken answer. */ export const RECTIFICATION_ANALYZING_LIVE_LABEL = "正在分析…"; export const RECTIFICATION_SLOW_STEP_MS = 45_000; export const RECTIFICATION_TIMEOUT_WARN_BEFORE_MS = 20_000; export function rectificationSlowProgressLabel(tool: PublicRectificationTool | string | null | undefined): string { if (typeof tool === "string" && RECTIFICATION_TOOL_PROGRESS_LABELS[tool as PublicRectificationTool]) { const doing = RECTIFICATION_TOOL_PROGRESS_LABELS[tool as PublicRectificationTool] .replace(/^正在/, "") .replace(/…$/, ""); return `还在${doing},可能需要一两分钟`; } return "这一步还在进行,可能需要一两分钟"; } export function rectificationLiveProgressLabel(input: { tool?: string | null; baseLabel: string; stepStartedAt: number; runStartedAt: number; now?: number; }): string { const now = input.now ?? Date.now(); if (now - input.runStartedAt >= ATTEMPT_TIMEOUT_MS - RECTIFICATION_TIMEOUT_WARN_BEFORE_MS) { return "即将超时,会自动重试或提示"; } if (now - input.stepStartedAt >= RECTIFICATION_SLOW_STEP_MS) { return rectificationSlowProgressLabel(input.tool); } return input.baseLabel; } export const RECTIFICATION_TOOL_PROGRESS_LABELS: Readonly> = { "rectification-read-case": "正在看你的资料…", "rectification-set-focus": "正在准备下一个问题…", "rectification-resolve-focus": "正在记下你对这一问的回答…", "rectification-record-evidence-batch": "正在记下这件事…", "rectification-propose-evidence": "正在记下这件事…", "rectification-confirm-evidence": "正在核对这件事…", "rectification-revise-evidence": "正在改这件事…", "rectification-compare-candidates": "正在重新对照盘面…", "rectification-read-diagnostics": "正在看结果稳不稳…", "rectification-offer-candidates": "正在整理可能的时间…", "rectification-accept-candidate": "正在用上你选的时间…", "rectification-confirm-birth-time": "正在确认出生时间…", "rectification-stop-and-review": "正在停下提问…", "rectification-close-case": "正在结束这次校正…", }; const COMPARE_TOOLS = new Set([ "rectification-compare-candidates", "rectification-read-diagnostics", "rectification-offer-candidates", ]); const LOAD_TOOLS = new Set([ "rectification-read-case", "rectification-set-focus", "rectification-resolve-focus", ]); /** Several tools share a plain label (BUG-1050); the trail names each once. */ export function rectificationCompletedTrail(steps: readonly PublicRectificationTool[]): string | undefined { return activityCompletedTrail([...new Set(steps.map((tool) => RECTIFICATION_TOOL_DONE_LABELS[tool]))]); } export function activityTraceFromReceipt( receipt: CompletedActivityReceiptView | null | undefined, ): readonly AgentActivityTraceItem[] { if (!receipt?.steps.length) return []; return receipt.steps.map((tool) => ({ id: `persisted-${tool}`, kind: "activity" as const, status: "done" as const, label: RECTIFICATION_TOOL_DONE_LABELS[tool], tool, })); } export function rectificationToolActivityPhase(tool: PublicRectificationTool): PublicActivityPhase { if (LOAD_TOOLS.has(tool)) return "loading-method"; if (COMPARE_TOOLS.has(tool)) return "chart-calculation"; if ( tool === "rectification-accept-candidate" || tool === "rectification-confirm-birth-time" || tool === "rectification-stop-and-review" || tool === "rectification-close-case" ) { return "answer-composition"; } return "evidence-validation"; }