Move-only (TASK-rectification-code-split-20260926 T3/T4). No behavior, receipt, billing, Skill or scoring change. - agent-run.ts: 1400 -> 135 lines; runV9AgentTurn 1046 -> 25 lines, no nested functions. It keeps the public types, the budget constants and the phase order: agent-run-prepare.ts (reliability, session, year re-ask, Skill identity, delivered guard, reserve, turn row / replay), agent-run-retry.ts (attempt loop), agent-run-attempt.ts (the old nested streamAttempt), agent-run-finish.ts (billing settle, receipts, interview, finalize), agent-run-support.ts (outcome types, retry classification, turn receipt writers), agent-run-messages.ts (buildAgentMessages / buildOpeningBrief, re-exported). - One token changed with the move: the attempt passes its own `previousErrorCode` argument to buildAgentMessages instead of reading the enclosing `lastAttemptError`; the loop passes that same value (clears the old unused-parameter warning). - Tests: whole-source contracts read tests/rectification-agent-run-surface.ts; behavioral runV9AgentTurn tests unchanged. agent-run growth caps added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
34 lines
2.3 KiB
TypeScript
34 lines
2.3 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import test from "node:test";
|
||
import { rectificationChatSurface } from "./rectification-chat-surface.ts";
|
||
import { rectificationAgentRunSurface } from "./rectification-agent-run-surface.ts";
|
||
|
||
// 原值: 读 rectification-agentic-chat.tsx 单文件。新值: rectificationChatSurface(容器 + 拆出的 hook / 参数函数 / 块,见 rectification-chat-surface.ts)。原因: TASK-rectification-code-split-20260926 只搬不改,整文件断言跟着代码走;切片断言另行改为调用函数。
|
||
const chat = rectificationChatSurface;
|
||
// 原值: 读 lib/rectification-agentic/v9/agent-run.ts 单文件。新值: rectificationAgentRunSurface(agent-run.ts + 拆出的 agent-run-*.ts,见 rectification-agent-run-surface.ts)。原因: TASK-rectification-code-split-20260926 只搬不改,整文件断言跟着代码走;切片断言另行改写。
|
||
const agentRun = rectificationAgentRunSurface;
|
||
|
||
test("live and persisted assistant text stay verbatim after spoken-answer removal", () => {
|
||
assert.match(chat, /const raw = failed \? "" : turn\.text \?\? ""/);
|
||
assert.match(chat, /text: raw,/);
|
||
assert.doesNotMatch(chat, /spoken-answer/);
|
||
assert.doesNotMatch(chat, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/);
|
||
assert.match(agentRun, /answerText = visible;/);
|
||
assert.doesNotMatch(agentRun, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/);
|
||
});
|
||
|
||
test("structured current_question, not model prose, owns the visible question on the turn", () => {
|
||
assert.match(chat, /current_question\?: unknown/);
|
||
assert.match(chat, /setCurrentQuestion\(nextQuestion\)/);
|
||
assert.doesNotMatch(chat, /className="rectification-question-slot"/);
|
||
assert.match(chat, /currentQuestion\?\.kind === "collect_spoken"/);
|
||
assert.match(chat, /<RectificationChoiceCard/);
|
||
assert.doesNotMatch(chat, /message\.text\.(?:includes|match|search)\(/);
|
||
});
|
||
|
||
test("answer deltas expose the model text without a parser or regex cleanup", () => {
|
||
assert.match(chat, /raw = event\.replace === true \? event\.text : raw \+ event\.text/);
|
||
assert.match(chat, /text: raw,/);
|
||
assert.doesNotMatch(chat, /splitRectificationSpokenAndThinking|settleRectificationSpokenAndThinking|finalizeRectificationSpokenAndThinking/);
|
||
});
|