Files
Jyotisha/frontend/tests/agent-reply.test.ts
T
jesse-ux e4e73f56c0
Independent Staging Quality Gate / publish (push) Canceled after 0s
Independent Staging Quality Gate / validate (push) Canceled after 9m33s
fix(web): 四个页面共用一份会话列表,空会话不入列
对话、星盘、星历、报告进同一 (app) 外壳,列表只拉一次。服务端不再列出空咨询;新建复用已有空会话。新标题改成「生时校正 · M月D日」,侧栏副标题用创建时间。
2026-09-17 21:27:40 +08:00

103 lines
3.9 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import { parseAgentReply, resolveSessionTitle } from "../src/lib/agent-reply.ts";
test("extracts a model-generated session title without exposing hidden metadata", () => {
// Given
const response = [
"你目前更适合先验证新的职业方向。",
'<!--AYANAM_SUGGESTIONS:["什么时候行动?","适合什么方向?","有哪些风险?"]-->',
"<!--AYANAM_TITLE:未来半年职业转型-->",
].join("\n");
// When
const reply = parseAgentReply(response);
// Then
assert.equal(reply.text, "你目前更适合先验证新的职业方向。");
assert.equal(reply.title, "未来半年职业转型");
});
test("rejects an overlong model-generated session title", () => {
// Given
const response = "回答正文\n<!--AYANAM_TITLE:这是一个明显超过合理长度并且不适合作为会话标题的模型输出标题-->";
// When
const reply = parseAgentReply(response);
// Then
assert.equal(reply.text, "回答正文");
assert.equal(reply.title, undefined);
});
test("accepts a concise English model-generated session title", () => {
// Given
const response = "Your next step is to test the market first.\n<!--AYANAM_TITLE:Career Change Timing-->";
// When
const reply = parseAgentReply(response);
// Then
assert.equal(reply.title, "Career Change Timing");
});
test("hides an incomplete metadata block while a reply is streaming", () => {
// Given
const response = "回答正文\n<!--AYANAM_TITLE:未来半年";
// When
const reply = parseAgentReply(response);
// Then
assert.equal(reply.text, "回答正文");
});
test("general no-birth-time replies keep a question-specific session title", () => {
assert.equal(resolveSessionTitle("工作变化的重点是什么?", "一般占星咨询"), "工作变化的重点是什么");
assert.equal(resolveSessionTitle("如何理解印度占星里的行星关系?"), "如何理解印度占星里的行星关系");
assert.equal(resolveSessionTitle("工作变化的重点是什么?", "事业方向与工作变化"), "事业方向与工作变化");
});
test("daily and topic consultations get distinct dated or domain titles", () => {
// 原值:8月22日 · 今日节奏;同名追加墙钟 08:36;8月22日 · 生时校正
// 新值:今日节奏 · 8月22日;同名不再加 HH:MM;生时校正 · 8月22日
// 原因:任务书 T4 类别在前,同名靠副标题区分
const at = new Date(Date.UTC(2026, 7, 22, 0, 36));
assert.equal(
resolveSessionTitle("深入看今日", undefined, { entrypoint: "daily_starlanguage", at }),
"今日节奏 · 8月22日",
);
assert.equal(
resolveSessionTitle("深入看今日", undefined, {
entrypoint: "daily_starlanguage",
at,
existingTitles: ["今日节奏 · 8月22日"],
}),
"今日节奏 · 8月22日",
);
assert.equal(
resolveSessionTitle("请帮我梳理目前的事业方向和下一步重点。", undefined, { theme: "career", at }),
"事业 · 请帮我梳理目前的事业…",
);
assert.equal(
resolveSessionTitle("请用刚才采用的代表性出生时间看盘。", undefined, {
entrypoint: "birth_time_rectification",
at,
}),
"生时校正 · 8月22日",
);
});
test("a stored legacy suggestion block is stripped and never becomes suggested questions", () => {
// Answers written before the follow-up chips were removed still carry this block, and
// parsing must neither surface it as text nor revive it as a suggestion field.
const reply = parseAgentReply([
"可以先采用 05:07 作为当前排盘时间。",
'<!--AYANAM_SUGGESTIONS:["问题一","问题二","问题三"]-->',
].join("\n"));
assert.deepEqual(reply, { text: "可以先采用 05:07 作为当前排盘时间。", title: undefined });
assert.deepEqual(Object.keys(reply), ["text", "title"]);
});