- BUG-1049 (recurrence of BUG-504): the opening stem carries six examples and an example answer again and is server-owned on the zero-evidence opening; the body is two plain sentences (no 大运/盘面/代表分钟/精确到秒, no year, no question). Stem de-dup compares whole sentences / near-equality instead of a 12-char prefix, which had deleted the body's examples sentence sinceaa7ccb30(BUG-604) +dd8f35f7(BUG-648). - BUG-1050: plain step labels; a finished step label shows once and 「已完成 N 步」counts shown rows; failed rows read 「…未完成」 from the in-progress wording. - Skill 10.0.30 -> 10.0.31 (OpeningPolicy); 10.0.30 kept as deprecated. - VOICE / DESIGN / CHANGELOG / BUG_HISTORY / PROGRESS / real-device checklist and screenshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
151 lines
6.5 KiB
TypeScript
151 lines
6.5 KiB
TypeScript
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<Record<PublicRectificationTool, string>> = {
|
|
"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<Record<PublicRectificationActivity, string>> = {
|
|
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<Record<RectificationTurnProgressStage, string>> = {
|
|
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<Record<PublicRectificationTool, string>> = {
|
|
"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<PublicRectificationTool>([
|
|
"rectification-compare-candidates",
|
|
"rectification-read-diagnostics",
|
|
"rectification-offer-candidates",
|
|
]);
|
|
|
|
const LOAD_TOOLS = new Set<PublicRectificationTool>([
|
|
"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";
|
|
}
|