Files
UHD_Media_Tool/packages/agent/test/system-prompt.test.ts
T
rootandClaude Opus 5.5 0508f3418f feat(agent): require Chinese thinking and reports in subagent prompts (AG-4)
Subagent / vision subflow prompts (audience=agent) get a dedicated section:
report goes to the parent session, and thinking, step notes and reports stay
in Chinese even when the goal, tool results or web pages are in English.
Prompt regression test covers both the shared hard rule and the new section.

Child reports reaching the user are already humanized: the child session page
uses the same FIX-7 report-humanize path, and the parent's final report resolves
child run IDs to their goal titles; agent.spawn/await tool rows show no raw summary.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 17:58:08 +08:00

103 lines
4.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { buildSystemPrompt, interactionRules, REPORT_FORMAT } from "../src/index.ts";
// AGUI-3 prompt 回归:用户在会话里看到的汇报就是模型写的文字,格式约束靠这里守住。
// 改提示词时先想清楚是否放宽了这些约束,再同步改断言。
const userPrompt = () =>
buildSystemPrompt({
role: "媒体库自动化智能体",
goal: "看看有哪些新 4K",
interaction: { plan: true, options: true, approvals: true },
});
/** 取提示词里的一节(## 标题到下一个 ## 之前) */
function section(p: string, title: string): string {
const start = p.indexOf(`## ${title}`);
if (start < 0) return "";
const rest = p.slice(start);
const next = rest.indexOf("\n## ", 3);
return next < 0 ? rest : rest.slice(0, next);
}
describe("汇报格式(AGUI-3)", () => {
it("关键约束句:结论先行、用名字不用函数名 / 字段名 / UUID、不超过 10 行、多个资源才用表格", () => {
const f = section(userPrompt(), "汇报格式");
expect(f).toMatchInlineSnapshot(`
"## 汇报格式
- 第一句写结论:做成了什么、没做成什么、为什么。
- 对象用名字:作品名、站点名、资源标题、文件名;不写函数名、工具名、字段名、参数、UUID 或 hash。
- 数量以工具返回为准:派出几个子会话、提交几个下载,只数成功的调用,失败或被拒绝的不算。
- 不超过 10 行;不复述过程,不写下一步打算,除非需要用户做什么。
- 只有列举多个资源(3 个以上的资源、任务或文件)时才用表格,其余用短句或列表。
- 可以用 Markdown 列表、表格和粗体,不写标题,不写 HTML。
"
`);
});
it("汇报格式与已有硬规则不冲突:证据写名称和数值,不再要求引用对象 ID", () => {
const p = userPrompt();
expect(p).not.toContain("对象 ID");
expect(p).toContain("写出查到的对象名称和关键数值");
// 旧的"最后用简短中文汇报…可以用 Markdown(标题…)"已换成汇报格式一节
expect(p).not.toContain("最后用简短中文汇报");
expect(REPORT_FORMAT.length).toBe(6);
});
it("子会话 / 视觉子流程汇报给父会话:不加用户汇报格式", () => {
const p = buildSystemPrompt({ role: "网页挑战处理员", goal: "过验证", audience: "agent" });
expect(p).not.toContain("## 汇报格式");
});
it("子会话与父会话一样要求思考、步骤说明和汇报都用中文(AG-4)", () => {
const child = buildSystemPrompt({
role: "媒体库自动化智能体",
goal: "Check the torrent list on the site",
audience: "agent",
});
// 与父会话同一条硬规则
expect(child).toContain("思考、步骤说明和汇报都用中文");
expect(userPrompt()).toContain("思考、步骤说明和汇报都用中文");
// 子会话专有的一节:目标 / 工具结果是英文也用中文
expect(section(child, "汇报对象")).toMatchInlineSnapshot(`
"## 汇报对象
- 你的汇报交给父会话汇总,不直接给用户看,可以带对象 ID。
- 思考、步骤说明和汇报一律用中文,即使目标、工具结果或网页是英文;引用文件名、原站标题时保持原文。"
`);
expect(section(userPrompt(), "汇报对象")).toBe("");
});
});
describe("工作方式(AGUI-3)", () => {
it("只在真有分歧时给方案;查询、盘点不给方案", () => {
const rules = interactionRules({ options: true }).join("\n");
expect(rules).toContain("只有真的存在分歧时");
expect(rules).toContain("只是查询、盘点或结论明确时不要给方案");
});
it("选定即批准:方案绑定计划,approvedAction 直接执行;删除、覆盖类仍单独确认;只在能审批的会话里说", () => {
const rules = interactionRules({ options: true, approvals: true }).join("\n");
expect(rules).toContain("把计划 ID 填进这个方案的 action");
expect(rules).toContain("用户选定即批准这份计划");
expect(rules).toContain("删除、覆盖类动作选定后仍会单独确认");
expect(interactionRules({ options: true }).join("\n")).not.toContain("approvedAction");
});
it("步骤标题写要做的事,不写工具名", () => {
expect(interactionRules({ plan: true }).join("\n")).toContain("不写工具名");
});
it("先看方案(/先给方案)只对本会话生效的约束句保留", () => {
expect(interactionRules({ options: true, proposeFirst: true }).join("\n")).toContain("本会话要求先看方案再执行");
});
});
describe("站点类型(IA-2)", () => {
it("RSS 属于站点,没有单独的 RSS 页;按获取方式判断能不能搜索 / 登录", () => {
const p = userPrompt();
expect(p).toContain("RSS 属于站点");
expect(p).toContain("没有单独的 RSS 页");
expect(p).toContain("自定义 RSS 源");
});
});