接通主角绑定、开场封印与游玩辅助,让世界模拟器从创作连续落到本局。
直聘插入按模块回馈,并记录请求骨架便于排查。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
parseOpeningSealPayload,
|
||||
openingVariablesToTableDoc,
|
||||
reopenCreationFlowRaw,
|
||||
splitOpeningDocument,
|
||||
} from "../src/skills/opening-seal.js";
|
||||
|
||||
const fragment = JSON.stringify({
|
||||
@@ -63,6 +64,117 @@ describe("opening-seal", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("reads 用户角色 from candidate meta and 正文", () => {
|
||||
const raw = JSON.stringify({
|
||||
schema: "context-fragment.v1",
|
||||
技能: "开场白与开场变量",
|
||||
正文: {
|
||||
开场白全文: "@玩家站在债契前。",
|
||||
开场白候选: [
|
||||
{
|
||||
meta: {
|
||||
用户角色: { 名字: "沈聿", 简介: "本地放贷人;与这对母女相识但不熟。" },
|
||||
},
|
||||
正文: "@玩家站在债契前。",
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
用户角色: { 名字: "阿泽", 简介: "刚穿进来的社畜。" },
|
||||
},
|
||||
正文: "门外有人喊 @玩家 的名字。",
|
||||
},
|
||||
],
|
||||
开场变量: [{ 名: "债额", 值: 3 }],
|
||||
},
|
||||
});
|
||||
const first = parseOpeningSealPayload(raw, 0);
|
||||
expect(first?.persona).toEqual({
|
||||
name: "沈聿",
|
||||
description: "本地放贷人;与这对母女相识但不熟。",
|
||||
});
|
||||
const second = parseOpeningSealPayload(raw, 1);
|
||||
expect(second?.selectedText).toContain("门外");
|
||||
expect(second?.persona).toEqual({
|
||||
name: "阿泽",
|
||||
description: "刚穿进来的社畜。",
|
||||
});
|
||||
});
|
||||
|
||||
it("serializes present.v1 正文 and per-candidate 开场变量", () => {
|
||||
const packet = {
|
||||
schema: "present.v1",
|
||||
shell: "chat_monitor",
|
||||
blocks: {
|
||||
monitor: { 债额: "三两" },
|
||||
body: "@玩家站在债契前。",
|
||||
},
|
||||
meta: { suggested_actions: ["问债"] },
|
||||
};
|
||||
const raw = JSON.stringify({
|
||||
schema: "context-fragment.v1",
|
||||
技能: "开场白与开场变量",
|
||||
正文: {
|
||||
开场白全文: packet,
|
||||
开场白候选: [
|
||||
{
|
||||
meta: {
|
||||
用户角色: { 名字: "沈聿", 简介: "放贷人" },
|
||||
开场变量: [{ 名: "债额", 值: 3, 依据: "桌上债契" }],
|
||||
},
|
||||
正文: packet,
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
用户角色: { 名字: "阿泽", 简介: "社畜" },
|
||||
开场变量: [{ 名: "口粮", 值: 1 }],
|
||||
},
|
||||
正文: {
|
||||
schema: "present.v1",
|
||||
shell: "chat_monitor",
|
||||
blocks: { body: "门外有人喊 @玩家。" },
|
||||
},
|
||||
},
|
||||
],
|
||||
开场变量: [{ 名: "债额", 值: 3, 依据: "桌上债契" }],
|
||||
},
|
||||
});
|
||||
const first = parseOpeningSealPayload(raw, 0);
|
||||
expect(first?.candidates).toHaveLength(2);
|
||||
const selected = JSON.parse(first!.selectedText);
|
||||
expect(selected.schema).toBe("present.v1");
|
||||
expect(selected.shell).toBe("chat_monitor");
|
||||
expect(selected.blocks.body).toContain("@玩家");
|
||||
expect(first?.persona).toEqual({ name: "沈聿", description: "放贷人" });
|
||||
expect(first?.variables).toEqual([
|
||||
{ name: "债额", value: 3, note: "桌上债契" },
|
||||
]);
|
||||
const second = parseOpeningSealPayload(raw, 1);
|
||||
expect(second?.persona?.name).toBe("阿泽");
|
||||
expect(second?.variables).toEqual([{ name: "口粮", value: 1 }]);
|
||||
expect(JSON.parse(second!.selectedText).blocks.body).toContain("门外");
|
||||
});
|
||||
|
||||
it("splits YAML frontmatter meta from opening 正文", () => {
|
||||
const nested = splitOpeningDocument(`---
|
||||
用户角色:
|
||||
名字: 沈聿
|
||||
简介: 本地放贷人
|
||||
---
|
||||
清晨,@玩家推开堂屋门。
|
||||
`);
|
||||
expect(nested.persona).toEqual({ name: "沈聿", description: "本地放贷人" });
|
||||
expect(nested.text).toBe("清晨,@玩家推开堂屋门。");
|
||||
|
||||
const dotted = splitOpeningDocument(`---
|
||||
用户角色.名字: 阿泽
|
||||
用户角色.简介: 刚穿进来的社畜
|
||||
---
|
||||
门外有人喊 @玩家。
|
||||
`);
|
||||
expect(dotted.persona).toEqual({ name: "阿泽", description: "刚穿进来的社畜" });
|
||||
expect(dotted.text).toBe("门外有人喊 @玩家。");
|
||||
});
|
||||
|
||||
it("builds table rows from opening variables", () => {
|
||||
const payload = parseOpeningSealPayload(fragment, 0);
|
||||
const doc = openingVariablesToTableDoc(payload!.variables);
|
||||
|
||||
Reference in New Issue
Block a user