import assert from "node:assert/strict"; import test from "node:test"; import { finalizeRectificationSpokenAndThinking, nextStableChannelDelta, splitRectificationSpokenAndThinking, } from "../src/lib/rectification-agentic/v9/spoken-answer.ts"; test("a plain spoken follow-up stays on the answer channel", () => { const spoken = [ "记下了,大约六岁入学小学。", "接下来你大概哪一年上的初中?说个大概年份或范围就行。", ].join("\n\n"); assert.deepEqual(splitRectificationSpokenAndThinking(spoken), { thinking: "", spoken, }); }); test("process self-talk leaves the spoken conclusion on the answer channel", () => { const processTalk = [ "用户提到先给了一个很晚的年份,后又改口说六岁入学。这里有个明显的内部矛盾。", "但按 skill 规则,日期精度真实保留,不得猜补。datePrecision 用 year,occurredFrom 只能按用户原话来。", "我决定先按六岁入学记下来,再在正文里确认那句晚年份是不是口误。", "让我调用 batch 写入 education_start。", ].join("\n\n"); const spoken = [ "入学小学这条先按大约六岁记下。你第一句提到的那个很晚的年份,我理解是口误对吗?", "接下来你大概哪一年上的初中?说个大概年份或范围就行。", ].join("\n\n"); assert.deepEqual(splitRectificationSpokenAndThinking(`${processTalk}\n\n${spoken}`), { thinking: processTalk, spoken, }); }); test("English process talk is classified as thinking, not the spoken answer", () => { const split = splitRectificationSpokenAndThinking([ "The proposedKind value was rejected. Retrying with education_start.", "记下了,那年九月上大学。", ].join("\n\n")); assert.match(split.thinking, /proposedKind/); assert.equal(split.spoken, "记下了,那年九月上大学。"); }); test("stable channel deltas only emit the newly classified suffix", () => { assert.equal(nextStableChannelDelta("", "先核对升学年份。"), "先核对升学年份。"); assert.equal( nextStableChannelDelta("先核对升学年份。", "先核对升学年份。\n\n再问初中。"), "\n\n再问初中。", ); assert.equal(nextStableChannelDelta("先核对升学年份。", "另一段"), ""); }); test("a lone process paragraph stays in thinking until a spoken conclusion arrives", () => { const processTalk = "用户提到先给了一个很晚的年份。这里有个明显的内部矛盾。"; assert.deepEqual(splitRectificationSpokenAndThinking(`${processTalk}\n\n`), { thinking: processTalk, spoken: "", }); }); test("all-process text keeps a spoken fallback only when the turn is finalized", () => { const first = "用户提到先给了一个很晚的年份。这里有个明显的内部矛盾。"; const last = "但按 skill 规则,日期精度真实保留,不得猜补。"; assert.deepEqual(finalizeRectificationSpokenAndThinking(`${first}\n\n${last}`), { thinking: first, spoken: last, }); });