Files
writing-agent/tests/worker-set-sanitize.test.ts
moranzhi ec474cb946 完善创作节点循环与等待态交互,并大幅打磨 Web 壳与会话运行时。
- 节点循环:配方开局直坐 DAG 第一步;验收后先问下一步意向,再确认开干并可钉编排参数;「按意见修改」只重跑当前节点。
- 询问分流:能力 opening 走说话面引导,可跳过追问按题干去重;追问与产物同轮挂载,避免拆成两段历史。
- 运行时:补强 revision 重跑、创作流程合并/进度指针、工具循环与 worker 执行;新增运行日志与 web:watch。
- 前端:统一等待态文案与底栏主按钮,完善询问卡/产物验收/呈现壳样式与交互。
- 同步世界模拟器模块提示、编排文档与相关测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 01:28:12 +08:00

233 lines
8.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import {
extractJsonObjectText,
isUsableWorkerSet,
looksLikeProseNotSpec,
parseWorkerSetYaml,
} from "../src/skills/worker-set-parse.js";
import {
parseWorkerResponseForTest,
sanitizeWorkerSetOutputs,
} from "../src/worker/executor.js";
describe("worker-set prose rejection", () => {
it("does not YAML-crash on Chinese prose; returns clear parseError", () => {
const prose =
"我们被要求输出 JSON。首先根据用户输入和 SKILL进行实例设计。用户需求是扮演一个坠机的幸存者…";
expect(looksLikeProseNotSpec(prose)).toBe(true);
const parsed = parseWorkerSetYaml(prose);
expect(parsed?.parseError).toMatch(/不是 JSON 规格|askUser/);
expect(parsed?.parseError).not.toMatch(/Implicit keys/);
});
it("extracts JSON object from surrounding prose", () => {
const raw = `说明如下:\n\`\`\`json\n{"version":1,"workers":[{"ref":"narrator","duty":"转述","acceptance":"review"}]}\n\`\`\``;
const extracted = extractJsonObjectText(raw);
expect(extracted?.startsWith("{")).toBe(true);
expect(isUsableWorkerSet(parseWorkerSetYaml(extracted!))).toBe(true);
});
});
describe("sanitizeWorkerSetOutputs", () => {
it("converts prose-in-draft to askUser and clears bad tag", () => {
const result = sanitizeWorkerSetOutputs({
outputs: {
"设计.worker集.草稿":
"坠机后伤势如何?\n请描述你的初始状态轻伤还是重伤\n也可以让我随机生成。",
},
summary: "提问",
preview: "…",
});
expect(result.outputs["设计.worker集.草稿"]).toBeUndefined();
expect(result.askUser?.length).toBeGreaterThan(0);
});
it("keeps valid JSON draft", () => {
const json = JSON.stringify({
version: 1,
workers: [{ ref: "world-simulator", duty: "世界", acceptance: "continue" }],
});
const result = sanitizeWorkerSetOutputs({
outputs: { "设计.worker集.草稿": json },
summary: "草案",
preview: json,
});
expect(result.outputs["设计.worker集.草稿"]).toContain("world-simulator");
expect(result.askUser).toBeUndefined();
});
it("parseWorkerResponse does not dump raw prose into worker-set tags", () => {
const raw =
"我们被要求输出 JSON。请描述你的初始状态伤势如何";
const result = parseWorkerResponseForTest(raw, [
"设计.worker集.草稿",
"设计.worker集",
"用户.需求",
]);
expect(result.outputs["设计.worker集.草稿"]).toBeUndefined();
expect(result.askUser?.length).toBeGreaterThan(0);
});
it("accepts nested object outputs for worker set", () => {
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: {
"设计.worker集.草稿": {
version: 1,
workers: [{ ref: "narrator", duty: "转述", acceptance: "review" }],
},
},
summary: "ok",
askUser: null,
}),
["设计.worker集.草稿"],
);
expect(result.outputs["设计.worker集.草稿"]).toContain("narrator");
expect(result.askUser).toBeUndefined();
});
it("lifts fragment 追问/自评 into askUser + askAssessment", () => {
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: {
"设计.美学纲领与交互范式": {
schema: "context-fragment.v1",
brief: "孤立免疫",
: { : { : "特权与惊惶" } },
: {
: [{ : "美学纲领", 分数: 6, : "边界未锁" }],
: "尺度",
},
: {
: "还需确认:",
: [
{
: "血腥如何用?",
: ["少而锋利", "常态压抑"],
: "锈迹即可",
},
],
},
},
},
summary: "美学纲领 · 孤立免疫",
}),
["设计.美学纲领与交互范式"],
);
expect(result.askUser?.length).toBe(1);
expect(result.askUser?.[0]?.options?.length).toBe(2);
expect(result.askAssessment).toContain("美学纲领 6/10");
expect(result.askAssessment).toContain("还需确认");
});
it("drops askUser copies of fragment 追问 and keeps the 示例 prompt", () => {
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: {
"设计.美学纲领与交互范式": {
schema: "context-fragment.v1",
brief: "孤立免疫",
: { : { : "特权与惊惶" } },
: {
: "还需确认:",
: [
{
: "你最想反复感受到的是哪一种?",
: ["日常从容", "揭示翻转"],
: "袖口唐纹",
},
],
},
},
},
summary: "美学纲领 · 孤立免疫",
askUser: [
{
prompt: "为贴近你要的质感:你最想反复感受到的是哪一种?",
options: ["日常从容", "揭示翻转"],
},
],
}),
["设计.美学纲领与交互范式"],
);
expect(result.askUser).toHaveLength(1);
expect(result.askUser?.[0]?.prompt).toContain("示例:袖口唐纹");
expect(result.askUser?.[0]?.prompt).not.toContain("为贴近你要的质感");
});
it("recovers a root-level context-fragment into the artifact tag", () => {
const frag = {
schema: "context-fragment.v1",
: "美学纲领与交互范式",
brief: "孤立免疫",
: {
: { : { : "丧尸", : "唯我免疫" } },
: { : "完全" },
: { : "人人录我" },
},
};
const result = parseWorkerResponseForTest(JSON.stringify(frag), [
"设计.美学纲领与交互范式",
]);
expect(result.outputs["设计.美学纲领与交互范式"]).toContain("人人录我");
expect(result.askUser).toBeUndefined();
});
it("moves a fragment written to 创作.当前步骤 onto the artifact tag", () => {
const frag = {
schema: "context-fragment.v1",
: "美学纲领与交互范式",
brief: "孤立免疫",
: { : { : "特权与惊惶" } },
};
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: { "创作.当前步骤": frag },
summary: "误写入指针",
}),
["设计.美学纲领与交互范式", "创作.当前步骤"],
);
expect(result.outputs["创作.当前步骤"]).toBeUndefined();
expect(result.outputs["设计.美学纲领与交互范式"]).toContain("特权与惊惶");
});
it("does not accept a fragment without 正文; keeps 追问 for the LLM loop", () => {
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: {
"设计.美学纲领与交互范式": {
schema: "context-fragment.v1",
: "美学纲领与交互范式",
brief: "在唯一免疫的末日联接中体验绝望掌控感",
mount: "world-simulator",
: {
: "还差站位",
: [{ : "你代入吗?", : ["完全代入", "旁观"] }],
},
},
},
summary: "半残",
}),
["设计.美学纲领与交互范式"],
);
expect(result.outputs["设计.美学纲领与交互范式"]).toBeUndefined();
expect(result.askUser?.length).toBeGreaterThan(0);
expect(result.askUser?.[0]?.prompt).toContain("你代入吗");
});
it("asks to continue the loop when fragment JSON is unusable", () => {
const result = parseWorkerResponseForTest(
JSON.stringify({
outputs: {
"设计.美学纲领与交互范式":
'{"schema":"context-fragment.v1","brief":"孤立免疫","mount":"world-simulator"',
},
summary: "截断",
}),
["设计.美学纲领与交互范式"],
);
expect(result.outputs["设计.美学纲领与交互范式"]).toBeUndefined();
expect(result.askUser?.[0]?.prompt).toContain("还没写出可验收的产物");
});
});