引入上下文片段、固定槽与投影排序,并完善机遇裁定与游玩期 UI。
把创作产物收敛为可挂载片段与 play_slots/context_order,同步修订世界模拟器模块与运行时拼装。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
140
tests/dialogue-history.test.ts
Normal file
140
tests/dialogue-history.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
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(["用户.最新输入"]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user