35e5781e66
Public can_adopt follows session_outcome; reverse_verify reuses the persisted question id; offer cards settle on the owning message with a status-bar handoff. Co-authored-by: Cursor <cursoragent@cursor.com>
145 lines
5.7 KiB
TypeScript
145 lines
5.7 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import test from "node:test";
|
||
|
||
import { parseAgentChoiceCopy } from "../src/lib/rectification-agentic/v9/choice-card.ts";
|
||
import { validateSpokenPrompt, withSpokenPrompt } from "../src/lib/rectification-agentic/v9/spoken-prompt.ts";
|
||
import { MACHINE_VOICE_LEXICON } from "../src/lib/rectification-agentic/v9/agent-voice-lexicon.ts";
|
||
import type { MethodFollowup } from "../src/lib/rectification-agentic/v9/method-followup.ts";
|
||
|
||
function followup(overrides: Partial<MethodFollowup> = {}): MethodFollowup {
|
||
return {
|
||
method_id: "d9_relationship",
|
||
intent: "distinguish_candidates",
|
||
ask_theme: "relationship_style",
|
||
domain: "relationship",
|
||
kind_hint: "relationship_change",
|
||
user_prompt_hint: "probe",
|
||
must_not_label: false,
|
||
choice_frame: {
|
||
question_id: "d9:relationship:2023",
|
||
method_id: "d9_relationship",
|
||
period: "2023 年前后",
|
||
prompt: "2023 年前后,你有没有一段认真开始或结束的关系?",
|
||
varga: "D9",
|
||
why: "区分",
|
||
option_a_hint: "明确发生且时间吻合",
|
||
option_b_hint: "发生过但时间偏了",
|
||
neither_label: "没有这回事",
|
||
unsure_label: "记不清",
|
||
option_a_answer_class: "yes",
|
||
option_b_answer_class: "weak_yes",
|
||
option_c_answer_class: "no",
|
||
option_d_answer_class: "unsure",
|
||
choice_mode: "A/B/C/D",
|
||
stop_label: "先这样,先看当前范围",
|
||
stop_message: "先这样",
|
||
scoring: true,
|
||
},
|
||
source: "event_probe",
|
||
probe_year: 2023,
|
||
...overrides,
|
||
};
|
||
}
|
||
|
||
test("spokenPrompt rejects length, option literals, unique-minute claims, and machine voice", () => {
|
||
assert.equal(validateSpokenPrompt({ spokenPrompt: "太短了" }).ok, false);
|
||
const optionLiteral = validateSpokenPrompt({
|
||
spokenPrompt: "2023 年这段感情,选项怎么选你还记得吗?",
|
||
});
|
||
assert.equal(optionLiteral.ok, false);
|
||
assert.equal(optionLiteral.ok ? null : optionLiteral.reason, "option_literal");
|
||
const uniqueMinute = validateSpokenPrompt({
|
||
spokenPrompt: "这能定下唯一的出生分钟吗,你还记得医院的钟点?",
|
||
});
|
||
assert.equal(uniqueMinute.ok, false);
|
||
assert.equal(uniqueMinute.ok ? null : uniqueMinute.reason, "unique_minute");
|
||
assert.equal(validateSpokenPrompt({
|
||
spokenPrompt: MACHINE_VOICE_LEXICON[3],
|
||
}).ok, false);
|
||
});
|
||
|
||
test("spokenPrompt rejects a different year or domain than the server probe", () => {
|
||
const probe = followup();
|
||
const yearMismatch = validateSpokenPrompt({
|
||
spokenPrompt: "2018 年前后,你有没有一段认真开始或结束的关系?",
|
||
followup: probe,
|
||
targetDomain: "relationship",
|
||
questionId: "d9_relationship:relationship:2023",
|
||
});
|
||
assert.equal(yearMismatch.ok ? null : yearMismatch.reason, "year_mismatch");
|
||
const yearMissing = validateSpokenPrompt({
|
||
spokenPrompt: "你有没有一段认真开始或结束的关系?",
|
||
followup: probe,
|
||
targetDomain: "relationship",
|
||
questionId: "d9_relationship:relationship:2023",
|
||
});
|
||
assert.equal(yearMissing.ok ? null : yearMissing.reason, "year_missing");
|
||
const domainMismatch = validateSpokenPrompt({
|
||
spokenPrompt: "2023 年前后,你有没有换过工作?",
|
||
followup: probe,
|
||
targetDomain: "career",
|
||
questionId: "d9_relationship:relationship:2023",
|
||
});
|
||
assert.equal(domainMismatch.ok ? null : domainMismatch.reason, "domain_mismatch");
|
||
assert.equal(validateSpokenPrompt({
|
||
spokenPrompt: "工作记下了。2023 年前后,有没有一段认真开始或结束的关系?",
|
||
followup: probe,
|
||
targetDomain: "relationship",
|
||
questionId: "d9_relationship:relationship:2023",
|
||
}).ok, true);
|
||
});
|
||
|
||
test("spokenPrompt requires each year in a period when probe_year is empty", () => {
|
||
const ranged = followup({
|
||
probe_year: undefined,
|
||
choice_frame: {
|
||
...followup().choice_frame!,
|
||
period: "2014–2016 年前后",
|
||
},
|
||
});
|
||
const questionId = "d9:relationship:2023";
|
||
const missing = validateSpokenPrompt({
|
||
spokenPrompt: "你有没有升学或换过学习环境?",
|
||
followup: ranged,
|
||
questionId,
|
||
});
|
||
assert.equal(missing.ok ? null : missing.reason, "year_missing");
|
||
assert.equal(validateSpokenPrompt({
|
||
spokenPrompt: "2014 到 2016 年前后,有没有升学或换过学习环境?",
|
||
followup: ranged,
|
||
questionId,
|
||
}).ok, true);
|
||
const collect = followup({ choice_frame: null, probe_year: 2023 });
|
||
assert.equal(validateSpokenPrompt({
|
||
spokenPrompt: "你还记得哪年入的职吗?",
|
||
followup: collect,
|
||
targetDomain: "relationship",
|
||
}).ok, true);
|
||
});
|
||
|
||
test("withSpokenPrompt keeps a parseable choice prompt when spoken copy includes a clock time", () => {
|
||
const schema = {
|
||
choice: {
|
||
prompt: "2016 年前后,升学结果或学习环境有没有明显变化?",
|
||
option_a: "明确发生且时间吻合",
|
||
option_b: "发生过但程度较弱",
|
||
option_c: "明确没有发生",
|
||
option_d: "这段记不清楚",
|
||
options: [
|
||
{ key: "A", label: "明确发生且时间吻合", answer_class: "yes" },
|
||
{ key: "B", label: "发生过但程度较弱", answer_class: "weak_yes" },
|
||
{ key: "C", label: "明确没有发生", answer_class: "no" },
|
||
{ key: "D", label: "这段记不清楚", answer_class: "unsure" },
|
||
],
|
||
},
|
||
};
|
||
const next = withSpokenPrompt(
|
||
schema,
|
||
"已按 05:06 采用。现在核对:2016 年前后升学或学习环境有没有明显变化?",
|
||
);
|
||
const copy = parseAgentChoiceCopy(next);
|
||
assert.equal(copy?.options.length, 4);
|
||
assert.equal(copy?.prompt, "2016 年前后,升学结果或学习环境有没有明显变化?");
|
||
assert.equal(next.prompt, "已按 05:06 采用。现在核对:2016 年前后升学或学习环境有没有明显变化?");
|
||
});
|