// BUG-1306: an explicit request opens rectification directly. Fictional data only. import assert from "node:assert/strict"; import { readFileSync, readdirSync } from "node:fs"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import test from "node:test"; import { consultationAgentPublicEventSchema, createNdjsonParser, type AgentExecutionReceipt, type ConsultationAgentPublicEvent } from "../src/lib/consultation-agent-events.ts"; import { RECTIFICATION_OFFER_RULE } from "../src/lib/consultation-thinking-plan.ts"; import { RECTIFICATION_DIRECT_NEW_COPY, RECTIFICATION_DIRECT_NOT_SELF_COPY, RECTIFICATION_DIRECT_RESUME_COPY, RECTIFICATION_DIRECT_RESUME_ELSEWHERE_COPY, RECTIFICATION_DIRECT_UNAVAILABLE_COPY, RECTIFICATION_OFFER_TOOL_ID, attachOpenedOfferToFreeMessage, bindOfferToCase, offerForCase, sourceFromSessionRows, type RectificationOfferRecord, } from "../src/lib/rectification-in-chat.ts"; import { CONTRACT_DEGRADED_NOTE, streamAgentResponse } from "../src/lib/stream-agent-response.ts"; import type { Pass4Mode } from "../src/lib/timing-output-guard.ts"; import { consultationStepBudgetReceipt, createConsultationRuntimeState, createConsultationTools, publicConsultationRuntimeSteps, } from "../src/mastra/consultation-tools.ts"; const CASE_ID = "11111111-1111-4111-8111-111111111111"; const OTHER_CASE = "55555555-5555-4555-8555-555555555555"; const RECT_SESSION = "22222222-2222-4222-8222-222222222222"; const SOURCE_SESSION = "33333333-3333-4333-8333-333333333333"; const RESUME_SESSION = "44444444-4444-4444-8444-444444444444"; const REQUEST_ID = "66666666-6666-4666-8666-666666666666"; const DIRECT_SENTENCES = [ RECTIFICATION_DIRECT_NEW_COPY, RECTIFICATION_DIRECT_RESUME_COPY, RECTIFICATION_DIRECT_UNAVAILABLE_COPY, RECTIFICATION_DIRECT_NOT_SELF_COPY, RECTIFICATION_DIRECT_RESUME_ELSEWHERE_COPY, ] as const; const STOP_FINISH = { type: "finish", payload: { stepResult: { reason: "stop" }, output: { usage: {}, steps: [{}] } } }; type OfferDecision = | { ok: true; creditCost: number; questionEstimate: number } | { ok: false; reason: "not_self" | "product_disabled" | "case_in_progress" | "pricing_unavailable" }; function offer(status: RectificationOfferRecord["status"] = "offered", extra: Partial = {}): RectificationOfferRecord { return { status, creditCost: 3, questionEstimate: 8, sourceQuestion: "我和伴侣还能走下去吗", offeredAt: "2026-10-07T00:00:00.000Z", ...extra, }; } function offerTool(options: { alreadyOffered?: boolean; decide?: () => Promise; loadResumableSessionId?: () => Promise; } = {}) { const state = createConsultationRuntimeState(); let decisions = 0; let loads = 0; const tools = createConsultationTools({ userId: "user-fictional", sessionId: SOURCE_SESSION, requestId: REQUEST_ID, consultationMode: "verified_chart", serverChart: {} as never, state, rectificationOffer: { decide: async () => { decisions += 1; return options.decide ? options.decide() : { ok: true, creditCost: 3, questionEstimate: 8 }; }, alreadyOffered: options.alreadyOffered ?? false, revisitQuestion: "我和伴侣还能走下去吗", sourceSessionId: SOURCE_SESSION, loadResumableSessionId: async () => { loads += 1; return options.loadResumableSessionId ? options.loadResumableSessionId() : null; }, now: () => new Date("2026-10-07T00:00:00.000Z"), }, }) as Record Promise> }>; return { state, decisions: () => decisions, loads: () => loads, tool: tools[RECTIFICATION_OFFER_TOOL_ID]! }; } function src(relative: string) { return readFileSync(new URL(relative, import.meta.url), "utf8"); } function walkSources(dir: string): string[] { const out: string[] = []; for (const entry of readdirSync(dir, { withFileTypes: true })) { if (entry.name === "node_modules") continue; const full = join(dir, entry.name); if (entry.isDirectory()) out.push(...walkSources(full)); else if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) out.push(full); } return out; } test("direct-entry sentences stay within the free-completion length", () => { assert.deepEqual(DIRECT_SENTENCES.map((sentence) => Array.from(sentence).length), [13, 13, 14, 11, 11]); for (const sentence of DIRECT_SENTENCES) assert.ok(Array.from(sentence).length <= 20); assert.equal(RECTIFICATION_DIRECT_NEW_COPY, "好,我们开始核对出生时间。"); assert.equal(RECTIFICATION_DIRECT_RESUME_COPY, "核对还没做完,我们接着做。"); assert.equal(RECTIFICATION_DIRECT_UNAVAILABLE_COPY, "出生时间核对这会儿还做不了。"); assert.equal(RECTIFICATION_DIRECT_NOT_SELF_COPY, "给家人校正暂时还不支持"); assert.equal(RECTIFICATION_DIRECT_RESUME_ELSEWHERE_COPY, "可在历史对话里接着做。"); }); test("an opened offer with no case id binds, and a reload can find that case", () => { const opened = [{ role: "assistant", text: RECTIFICATION_DIRECT_NEW_COPY, responseKind: "smalltalk", rectificationOffer: offer("opened"), }]; assert.equal(sourceFromSessionRows([{ id: SOURCE_SESSION, messages: opened }], CASE_ID), null); const bound = bindOfferToCase(opened, { caseId: CASE_ID, rectificationSessionId: RECT_SESSION }); assert.ok(bound); assert.equal((bound![0]!.rectificationOffer as RectificationOfferRecord).status, "opened"); assert.equal((bound![0]!.rectificationOffer as RectificationOfferRecord).caseId, CASE_ID); assert.equal((bound![0]!.rectificationOffer as RectificationOfferRecord).rectificationSessionId, RECT_SESSION); assert.equal(bindOfferToCase(bound, { caseId: CASE_ID, rectificationSessionId: RECT_SESSION }), null); assert.ok(offerForCase(bound, CASE_ID)); assert.deepEqual(sourceFromSessionRows([{ id: SOURCE_SESSION, messages: bound }], CASE_ID), { sessionId: SOURCE_SESSION, question: "我和伴侣还能走下去吗", returned: null, }); }); test("binding leaves another case's opened record alone and still binds a later card", () => { const messages = [ { role: "assistant", text: "旧卡", rectificationOffer: offer("opened", { caseId: OTHER_CASE, rectificationSessionId: RECT_SESSION }) }, { role: "assistant", text: RECTIFICATION_DIRECT_NEW_COPY, responseKind: "smalltalk", rectificationOffer: offer("opened") }, ]; assert.equal(bindOfferToCase( [{ role: "assistant", rectificationOffer: offer("opened", { caseId: OTHER_CASE, rectificationSessionId: RECT_SESSION }) }], { caseId: CASE_ID, rectificationSessionId: RECT_SESSION }, ), null); const bound = bindOfferToCase(messages, { caseId: CASE_ID, rectificationSessionId: RECT_SESSION }); assert.ok(bound); assert.equal((bound![0]!.rectificationOffer as RectificationOfferRecord).caseId, OTHER_CASE); assert.equal((bound![1]!.rectificationOffer as RectificationOfferRecord).caseId, CASE_ID); assert.equal((bound![1]!.rectificationOffer as RectificationOfferRecord).status, "opened"); }); test("the free reply can carry the opened offer once, without clobbering a case id", () => { const sentence = RECTIFICATION_DIRECT_NEW_COPY; const card = offer("opened"); assert.equal(attachOpenedOfferToFreeMessage([], { sentence, offer: card }), "missing"); assert.equal(attachOpenedOfferToFreeMessage( [{ role: "assistant", text: sentence, responseKind: "consultation" }], { sentence, offer: card }, ), "missing"); const attached = attachOpenedOfferToFreeMessage( [{ role: "user", text: "请帮我核对出生时间" }, { role: "assistant", text: sentence, responseKind: "smalltalk" }], { sentence, offer: card }, ); assert.ok(Array.isArray(attached)); assert.deepEqual(attached[1]!.rectificationOffer, card); assert.equal(attachOpenedOfferToFreeMessage(attached, { sentence, offer: card }), "present"); const withCase = attachOpenedOfferToFreeMessage( [{ role: "assistant", text: sentence, responseKind: "smalltalk", rectificationOffer: offer("opened", { caseId: CASE_ID, rectificationSessionId: RECT_SESSION }) }], { sentence, offer: card }, ); assert.equal(withCase, "present"); }); test("explicit pass opens once, records an opened offer, and does not open again", async () => { const fresh = offerTool(); const result = await fresh.tool.execute({ explicitRequest: true, userAsked: true }); assert.equal(result.offered, true); assert.equal(result.directEntry, "new"); assert.match(String(result.note), /好,我们开始核对出生时间/); assert.deepEqual(fresh.state.rectificationOffer, offer("opened")); assert.equal(fresh.state.rectificationOffer?.caseId, undefined); assert.deepEqual(fresh.state.rectificationDirectEntry, { kind: "new", sentence: RECTIFICATION_DIRECT_NEW_COPY, sourceSessionId: SOURCE_SESSION, }); assert.equal(fresh.loads(), 0); assert.equal(fresh.decisions(), 1); const again = await fresh.tool.execute({ explicitRequest: true }); assert.equal(again.offered, false); assert.match(String(again.note), /已经在打开/); assert.match(String(again.note), /不要再写解读/); assert.equal(fresh.decisions(), 1); assert.deepEqual(fresh.state.rectificationOffer, offer("opened")); }); test("explicitRequest bypasses an earlier offer, and userAsked alone still only shows a card", async () => { const direct = offerTool({ alreadyOffered: true }); const opened = await direct.tool.execute({ explicitRequest: true }); assert.equal(opened.directEntry, "new"); assert.equal(direct.state.rectificationOffer?.status, "opened"); assert.equal(direct.state.rectificationDirectEntry?.kind, "new"); const card = offerTool({ alreadyOffered: true }); const asked = await card.tool.execute({ userAsked: true }); assert.equal(asked.offered, true); assert.equal(card.state.rectificationOffer?.status, "offered"); assert.equal(card.state.rectificationDirectEntry, undefined); const held = offerTool(); await held.tool.execute({}); const second = await held.tool.execute({ explicitRequest: true }); assert.match(String(second.note), /提议卡已经在了/); assert.equal(held.state.rectificationDirectEntry, undefined); assert.equal(held.state.rectificationOffer?.status, "offered"); assert.equal(held.decisions(), 1); }); test("an in-progress case resumes that session, or says to continue in history", async () => { const resume = offerTool({ decide: async () => ({ ok: false, reason: "case_in_progress" }), loadResumableSessionId: async () => RESUME_SESSION, }); const resumed = await resume.tool.execute({ explicitRequest: true }); assert.equal(resumed.offered, false); assert.equal(resumed.directEntry, "resume"); assert.equal(resume.state.rectificationOffer, undefined); assert.deepEqual(resume.state.rectificationDirectEntry, { kind: "resume", sentence: RECTIFICATION_DIRECT_RESUME_COPY, sourceSessionId: SOURCE_SESSION, resumeSessionId: RESUME_SESSION, }); assert.equal(resume.loads(), 1); const missing = offerTool({ decide: async () => ({ ok: false, reason: "case_in_progress" }) }); const refused = await missing.tool.execute({ explicitRequest: true }); assert.equal(refused.directEntry, undefined); assert.equal(missing.state.rectificationDirectEntry?.kind, "refused"); assert.equal(missing.state.rectificationDirectEntry?.sentence, RECTIFICATION_DIRECT_RESUME_ELSEWHERE_COPY); assert.equal(missing.state.rectificationOffer, undefined); assert.match(String(refused.note), /历史对话/); assert.doesNotMatch(String(refused.note), /不要提校正/); const thrown = offerTool({ decide: async () => ({ ok: false, reason: "case_in_progress" }), loadResumableSessionId: async () => { throw new Error("db down"); }, }); const fallback = await thrown.tool.execute({ explicitRequest: true }); assert.equal(thrown.state.rectificationDirectEntry?.kind, "refused"); assert.equal(thrown.state.rectificationDirectEntry?.sentence, RECTIFICATION_DIRECT_RESUME_ELSEWHERE_COPY); assert.match(String(fallback.note), /历史对话/); const quiet = offerTool({ decide: async () => ({ ok: false, reason: "case_in_progress" }) }); const ordinary = await quiet.tool.execute({}); assert.equal(quiet.loads(), 0); assert.equal(quiet.state.rectificationDirectEntry, undefined); assert.match(String(ordinary.note), /历史对话/); assert.doesNotMatch(String(ordinary.note), /不要提校正/); }); test("explicit refusals are one sentence, and none of the four notes says to hide rectification", async () => { const unavailable = offerTool({ decide: async () => ({ ok: false, reason: "product_disabled" }) }); const disabled = await unavailable.tool.execute({ explicitRequest: true }); assert.equal(unavailable.state.rectificationDirectEntry?.kind, "refused"); assert.equal(unavailable.state.rectificationDirectEntry?.sentence, RECTIFICATION_DIRECT_UNAVAILABLE_COPY); assert.equal(unavailable.state.rectificationOffer, undefined); assert.match(String(disabled.note), /出生时间核对这会儿还做不了/); assert.match(String(disabled.note), /不写内部原因/); assert.doesNotMatch(String(disabled.note), /不要提校正/); const unpriced = offerTool({ decide: async () => ({ ok: false, reason: "pricing_unavailable" }) }); const priced = await unpriced.tool.execute({ explicitRequest: true }); assert.equal(unpriced.state.rectificationDirectEntry?.sentence, RECTIFICATION_DIRECT_UNAVAILABLE_COPY); assert.match(String(priced.note), /出生时间核对这会儿还做不了/); assert.match(String(priced.note), /不写价格/); assert.doesNotMatch(String(priced.note), /不要提校正/); const family = offerTool({ decide: async () => ({ ok: false, reason: "not_self" }) }); const other = await family.tool.execute({ explicitRequest: true }); assert.equal(family.state.rectificationDirectEntry?.sentence, RECTIFICATION_DIRECT_NOT_SELF_COPY); assert.match(String(other.note), /给家人校正暂时还不支持/); assert.doesNotMatch(String(other.note), /不要提校正/); const plainFamily = offerTool({ decide: async () => ({ ok: false, reason: "not_self" }) }); const plain = await plainFamily.tool.execute({}); assert.equal(plainFamily.state.rectificationDirectEntry, undefined); assert.doesNotMatch(String(plain.note), /不要提校正/); const plainPrice = offerTool({ decide: async () => ({ ok: false, reason: "pricing_unavailable" }) }); assert.doesNotMatch(String((await plainPrice.tool.execute({})).note), /不要提校正/); const plainOff = offerTool({ decide: async () => ({ ok: false, reason: "product_disabled" }) }); assert.doesNotMatch(String((await plainOff.tool.execute({})).note), /不要提校正/); assert.equal(plainPrice.state.rectificationDirectEntry, undefined); assert.equal(plainOff.state.rectificationDirectEntry, undefined); }); function receipt(state: ReturnType): AgentExecutionReceipt { return { runId: "run-direct", runtime: "mastra-agentic", skill: { name: "jyotish-vedic-astrology", loaded: state.jyotishSkillBound, referenceReads: state.skillReferenceReadCount, methodologySections: state.methodologySectionCount, }, steps: publicConsultationRuntimeSteps(state), stepBudget: consultationStepBudgetReceipt(state), workflow: { route: "career", status: "ready", preciseTiming: "blocked", missingLayers: [] }, }; } function visibleAnswer(events: readonly ConsultationAgentPublicEvent[]) { let text = ""; for (const event of events) { if (event.type !== "answer.delta") continue; text = event.replace ? event.text : text + event.text; } return text; } async function readStream(response: Response) { const events: ConsultationAgentPublicEvent[] = []; const parser = createNdjsonParser((event) => events.push(event)); parser.finish(await response.text()); return events; } test("natal and window direct entry or explicit refusal skips the runtime-contract retry", async () => { const modes: Pass4Mode[] = ["verified_chart", "declared_birth_window"]; const kinds = ["new", "resume", "refused"] as const; for (const pass4Mode of modes) { for (const kind of kinds) { const state = createConsultationRuntimeState(); const sentence = kind === "new" ? RECTIFICATION_DIRECT_NEW_COPY : kind === "resume" ? RECTIFICATION_DIRECT_RESUME_COPY : RECTIFICATION_DIRECT_UNAVAILABLE_COPY; let contractRetries = 0; let answerRetries = 0; let warmupRan = false; let completedOutput = ""; const response = streamAgentResponse({ runId: "run-direct", requestId: REQUEST_ID, state, requireTool: true, pass4Mode, stepScopedAnswer: true, toolStatus: () => "ready", receipt: () => receipt(state), ...(pass4Mode === "declared_birth_window" ? { warmup: async (send: (event: ConsultationAgentPublicEvent) => void) => { warmupRan = true; send({ type: "activity", phase: "chart-calculation", label: "窗口预热" }); }, } : {}), stream: (async function* () { yield { type: "text-delta", payload: { text: "我先看看盘。" } }; yield { type: "tool-call", payload: { toolCallId: "offer-1", toolName: "offer-birth-time-rectification" } }; state.rectificationDirectEntry = { kind, sentence, sourceSessionId: SOURCE_SESSION, ...(kind === "resume" ? { resumeSessionId: RESUME_SESSION } : {}), }; if (kind === "new") state.rectificationOffer = offer("opened"); yield { type: "text-delta", payload: { text: "然后写一段解读。" } }; yield STOP_FINISH; })(), retry: async () => { contractRetries += 1; return (async function* () { yield STOP_FINISH; })(); }, retryForAnswer: async () => { answerRetries += 1; return (async function* () { yield STOP_FINISH; })(); }, onComplete: (output) => { completedOutput = output; }, }); const events = await readStream(response); assert.equal(contractRetries, 0, `${pass4Mode} ${kind} retried the contract`); assert.equal(answerRetries, 0, `${pass4Mode} ${kind} retried the answer`); assert.equal(state.consultationToolCompleted, false); assert.equal(visibleAnswer(events), sentence); assert.equal(visibleAnswer(events).includes("我先看看盘"), false); assert.equal(visibleAnswer(events).includes("然后写一段解读"), false); assert.equal(visibleAnswer(events).includes(CONTRACT_DEGRADED_NOTE), false); assert.equal(completedOutput, sentence); if (pass4Mode === "declared_birth_window") assert.equal(warmupRan, true); const completed = events.filter((event) => event.type === "run.completed"); assert.equal(completed.length, 1); const done = completed[0]!; assert.equal(done.type === "run.completed" && done.responseKind, "smalltalk"); assert.equal(done.type === "run.completed" && done.receipt, undefined); if (kind === "new") { assert.equal(done.type === "run.completed" && done.rectificationOffer?.status, "opened"); assert.equal(done.type === "run.completed" && done.rectificationOffer?.caseId, undefined); assert.deepEqual(done.type === "run.completed" ? done.rectificationDirectOpen : undefined, { sourceSessionId: SOURCE_SESSION, mode: "new", }); } else if (kind === "resume") { assert.equal(done.type === "run.completed" && done.rectificationOffer, undefined); assert.deepEqual(done.type === "run.completed" ? done.rectificationDirectOpen : undefined, { sourceSessionId: SOURCE_SESSION, mode: "resume", resumeSessionId: RESUME_SESSION, }); } else { assert.equal(done.type === "run.completed" && done.rectificationDirectOpen, undefined); assert.equal(done.type === "run.completed" && done.rectificationOffer, undefined); } assert.equal(events.some((event) => event.type === "activity" && event.label === "正在补齐方法与计算步骤"), false); } } }); test("a reading that already streamed is replaced by the direct-entry sentence", async () => { for (const pass4Mode of ["verified_chart", "declared_birth_window"] as const) { const state = createConsultationRuntimeState(); state.consultationToolCompleted = true; state.consultationToolSuccessCount = 1; let contractRetries = 0; const response = streamAgentResponse({ runId: "run-direct", requestId: REQUEST_ID, state, requireTool: true, pass4Mode, stepScopedAnswer: true, toolStatus: () => "ready", receipt: () => receipt(state), stream: (async function* () { yield { type: "text-delta", payload: { text: "事业方向的判断如下。" } }; yield { type: "step-finish", payload: { stepResult: { reason: "stop" } } }; state.rectificationDirectEntry = { kind: "new", sentence: RECTIFICATION_DIRECT_NEW_COPY, sourceSessionId: SOURCE_SESSION, }; state.rectificationOffer = offer("opened"); yield STOP_FINISH; })(), retry: async () => { contractRetries += 1; return (async function* () { yield STOP_FINISH; })(); }, }); const events = await readStream(response); assert.equal(contractRetries, 0); assert.equal(events.some((event) => event.type === "answer.delta" && event.text.includes("事业方向的判断如下")), true); assert.equal(events.some((event) => event.type === "answer.delta" && event.replace === true && event.text === RECTIFICATION_DIRECT_NEW_COPY), true); assert.equal(visibleAnswer(events), RECTIFICATION_DIRECT_NEW_COPY); } }); test("an ordinary consultation still retries once when the calculation never finished", async () => { const state = createConsultationRuntimeState(); let contractRetries = 0; let answerRetries = 0; const response = streamAgentResponse({ runId: "run-direct", requestId: REQUEST_ID, state, requireTool: true, pass4Mode: "verified_chart", stepScopedAnswer: true, toolStatus: () => "ready", receipt: () => receipt(state), stream: (async function* () { yield { type: "text-delta", payload: { text: "还没排盘。" } }; yield STOP_FINISH; })(), retry: async () => { contractRetries += 1; state.consultationToolCompleted = true; state.consultationToolSuccessCount = 1; return (async function* () { yield { type: "text-delta", payload: { text: "事业方向可以看。" } }; yield STOP_FINISH; })(); }, retryForAnswer: async () => { answerRetries += 1; return (async function* () { yield STOP_FINISH; })(); }, }); const events = await readStream(response); assert.equal(contractRetries, 1); assert.equal(answerRetries, 0); assert.equal(visibleAnswer(events), "事业方向可以看。"); assert.equal(visibleAnswer(events).includes(CONTRACT_DEGRADED_NOTE), false); assert.equal(visibleAnswer(events).includes("还没排盘"), false); const done = events.find((event) => event.type === "run.completed"); assert.equal(done?.type === "run.completed" && done.receipt !== undefined, true); assert.equal(done?.type === "run.completed" && done.responseKind, undefined); assert.equal(events.some((event) => event.type === "activity" && event.label === "正在补齐方法与计算步骤"), true); }); test("the offer rule is defined once, and direct entry settles with the free completion", () => { const definitions = walkSources(fileURLToPath(new URL("../src/", import.meta.url))).filter((file) => ( readFileSync(file, "utf8").includes("export const RECTIFICATION_OFFER_RULE") )); assert.equal(definitions.length, 1); assert.match(definitions[0]!, /consultation-thinking-plan\.ts$/); assert.match(RECTIFICATION_OFFER_RULE, /不承诺能收窄出生时间/); assert.match(RECTIFICATION_OFFER_RULE, /不在对话里收集经历做校正/); assert.match(RECTIFICATION_OFFER_RULE, /explicitRequest=true/); assert.match(RECTIFICATION_OFFER_RULE, /只写那一句过渡,不写解读/); assert.match(RECTIFICATION_OFFER_RULE, /只是不认同某个解释,按纠正规则认下、改读,不提校正/); assert.match(RECTIFICATION_OFFER_RULE, /userAsked=true/); const tools = src("../src/mastra/consultation-tools.ts"); assert.doesNotMatch(tools, /不承诺能收窄出生时间/); assert.doesNotMatch(tools, /不要提校正/); assert.match(tools, /explicitRequest/); assert.match(tools, /userAsked/); const route = src("../src/app/api/consult/route.ts"); assert.match(route, /大运、子运只说「在哪一段附近」,不写起止年月日/); assert.match(route, /这只是粗看。" \+ RECTIFICATION_OFFER_RULE;/); assert.doesNotMatch(route, /请你帮我进行生时纠正/); const direct = route.slice( route.indexOf("async function completeDirectRectificationTurn"), route.indexOf("let settlement:"), ); assert.match(direct, /complete_consultation_free/); assert.match(direct, /responseKind: "smalltalk"/); assert.match(direct, /persistOpenedDirectOffer/); assert.doesNotMatch(direct, /complete_consultation_response/); assert.doesNotMatch(direct, /consultation_requests/); const windowBlock = route.slice( route.indexOf("if (shouldRunDeclaredWindowWorkflow(consultationMode))"), route.indexOf("if (!prepared.serverChart)"), ); const natalBlock = route.slice( route.indexOf("if (!prepared.serverChart)"), route.indexOf("const history = storedHistory;"), ); assert.match(windowBlock, /settleAnswer/); assert.match(natalBlock, /settleAnswer/); assert.match(windowBlock, /warmup:/); assert.match(windowBlock, /precomputeWindowConsultation/); assert.match(windowBlock, /运行合同不完整/); assert.match(natalBlock, /运行合同不完整/); assert.match(route, /getRectificationEntrySummary\(accounting, userId\)/); assert.match(route, /\.from\("agentic_rectification_cases"\)/); assert.match(route, /\.select\("session_id"\)/); const stream = src("../src/lib/stream-agent-response.ts"); assert.match(stream, /if \(options\.state\.rectificationDirectEntry\) return true;/); assert.match(stream, /rectificationDirectRunCompleted\(options\.state\)/); assert.doesNotMatch(stream, /请你帮我进行生时纠正/); const hook = src("../src/hooks/use-consultation-run.ts"); assert.match(hook, /openRectificationFromChat\(rectificationDirectOpen\.sourceSessionId\)/); assert.match(hook, /openRectificationSession\(rectificationDirectOpen\.resumeSessionId\)/); assert.equal(hook.match(/openRectificationFromChat\(rectificationDirectOpen\.sourceSessionId\)/g)?.length, 1); assert.match(hook, /responseKind === "smalltalk" \? \{[\s\S]*?rectificationOffer/); const page = src("../src/app/(app)/page.tsx"); assert.match(page, /openAccountDialog, openRectificationSession, openRectificationFromChat,/); assert.doesNotMatch(page, /请你帮我进行生时纠正/); const server = src("../src/lib/rectification-in-chat-server.ts"); assert.match(server, /return sourceFromSessionRows/); assert.match(server, /attachOpenedOfferToFreeMessage/); const persist = server.slice(server.indexOf("export async function persistOpenedDirectOffer"), server.indexOf("export async function bindRectificationSource")); assert.doesNotMatch(persist, /consultation_requests/); consultationAgentPublicEventSchema.parse({ type: "run.completed", responseKind: "smalltalk", rectificationOffer: offer("opened"), rectificationDirectOpen: { sourceSessionId: SOURCE_SESSION, mode: "new" }, }); });