把创作产物收敛为可挂载片段与 play_slots/context_order,同步修订世界模拟器模块与运行时拼装。 Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
4.3 KiB
TypeScript
141 lines
4.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
appendDialogueHistoryTurn,
|
|
projectDialogueHistory,
|
|
buildHistoryFallback,
|
|
isDialogueHistoryRef,
|
|
} from "../src/skills/dialogue-history.js";
|
|
import { assembleWorkerContext } from "../src/skills/context-segments.js";
|
|
import { Blackboard } from "../src/blackboard/blackboard.js";
|
|
import {
|
|
contextOrderToSegments,
|
|
parseContextOrder,
|
|
applyContextOrderEdit,
|
|
synthesizeContextOrderFromWorkers,
|
|
} from "../src/skills/context-order.js";
|
|
|
|
describe("dialogue history projection", () => {
|
|
it("recognizes history refs and projects by level", () => {
|
|
expect(isDialogueHistoryRef("对话.历史")).toBe(true);
|
|
expect(isDialogueHistoryRef("history")).toBe(true);
|
|
const long = Array.from({ length: 30 }, (_, i) => `## 用户\n\n第${i}句`).join(
|
|
"\n\n",
|
|
);
|
|
const summary = projectDialogueHistory(long, "summary");
|
|
expect(summary).toContain("仅最近");
|
|
expect(projectDialogueHistory(long, "fixed")).toContain("不注入");
|
|
});
|
|
|
|
it("assembles history tag in flat segment order", () => {
|
|
const bb = new Blackboard();
|
|
bb.write({
|
|
tag: "对话.历史",
|
|
content: appendDialogueHistoryTurn("", { role: "用户", text: "推门" }),
|
|
source: "test",
|
|
});
|
|
bb.write({ tag: "用户.最新输入", content: "再看一眼", source: "test" });
|
|
const text = assembleWorkerContext({
|
|
inputs: {},
|
|
segments: [
|
|
{
|
|
id: "p",
|
|
tier: "static",
|
|
tags: [],
|
|
label: "## persona",
|
|
inline: "GM",
|
|
projection: "fixed",
|
|
},
|
|
{
|
|
id: "h",
|
|
tier: "static",
|
|
tags: ["对话.历史"],
|
|
label: "## 对话.历史",
|
|
projection: "full",
|
|
},
|
|
{
|
|
id: "u",
|
|
tier: "dynamic",
|
|
tags: ["用户.最新输入"],
|
|
label: "## 用户.最新输入",
|
|
projection: "full",
|
|
},
|
|
],
|
|
blackboard: bb,
|
|
workerId: "world-simulator",
|
|
workerName: "主世界层",
|
|
outputTags: [],
|
|
});
|
|
const iPersona = text.indexOf("GM");
|
|
const iHist = text.indexOf("推门");
|
|
const iUser = text.indexOf("再看一眼");
|
|
expect(iPersona).toBeGreaterThanOrEqual(0);
|
|
expect(iHist).toBeGreaterThan(iPersona);
|
|
expect(iUser).toBeGreaterThan(iHist);
|
|
});
|
|
|
|
it("falls back to event stream when history empty", () => {
|
|
expect(
|
|
buildHistoryFallback({
|
|
eventStream: "门开了",
|
|
latestUser: "走进去",
|
|
}),
|
|
).toContain("门开了");
|
|
});
|
|
});
|
|
|
|
describe("flat context order", () => {
|
|
it("synthesizes history tag and moves across it", () => {
|
|
const doc = synthesizeContextOrderFromWorkers(
|
|
[
|
|
{
|
|
ref: "narrator",
|
|
name: "叙事转述",
|
|
context: {
|
|
static: ["设计.叙事指南"],
|
|
dynamic: ["运行.本轮.裁决", "用户.最新输入"],
|
|
},
|
|
},
|
|
],
|
|
{ gm: true, narrator: true, perspective: false },
|
|
)!;
|
|
expect(doc.slots[0]!.inserts.some((i) => i.ref === "对话.历史")).toBe(true);
|
|
|
|
const histIdx = doc.slots[0]!.inserts.findIndex((i) => i.ref === "对话.历史");
|
|
const moved = applyContextOrderEdit(doc, {
|
|
action: "set_anchor",
|
|
slotRef: "narrator",
|
|
index: doc.slots[0]!.inserts.length - 1,
|
|
anchor: "pre_history",
|
|
});
|
|
const newHist = moved.slots[0]!.inserts.findIndex((i) => i.ref === "对话.历史");
|
|
const lastUser = moved.slots[0]!.inserts.findIndex(
|
|
(i) => i.ref === "用户.最新输入",
|
|
);
|
|
expect(lastUser).toBeLessThan(newHist);
|
|
expect(histIdx).toBeGreaterThanOrEqual(0);
|
|
});
|
|
|
|
it("maps to segments in list order including history", () => {
|
|
const doc = parseContextOrder({
|
|
schema: "context-order.v1",
|
|
slots: [
|
|
{
|
|
ref: "world-simulator",
|
|
inserts: [
|
|
{ order: 0, ref: "worker.persona", projection: "fixed" },
|
|
{ order: 1, ref: "对话.历史", projection: "summary" },
|
|
{ order: 2, ref: "用户.最新输入", projection: "full" },
|
|
],
|
|
},
|
|
],
|
|
})!;
|
|
const segs = contextOrderToSegments({
|
|
slot: doc.slots[0]!,
|
|
personaText: "裁决",
|
|
});
|
|
expect(segs[0]!.inline).toContain("裁决");
|
|
expect(segs[1]!.tags).toEqual(["对话.历史"]);
|
|
expect(segs[2]!.tags).toEqual(["用户.最新输入"]);
|
|
});
|
|
});
|