引入游玩呈现壳与旁观维护槽,完善结算合并、十分制自评与技能产物 UI。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-12 02:03:29 +08:00
parent 94f67fa744
commit 120d67ee82
46 changed files with 2513 additions and 236 deletions

View File

@@ -0,0 +1,91 @@
import { describe, expect, it } from "vitest";
import {
isPresentLikeObject,
parsePresentPacket,
parseShellAdaptationFromReplyFormat,
presentFromPlainText,
shellDefaultRegions,
} from "../src/skills/present-packet.js";
describe("present.v1", () => {
it("parses present packet with blocks", () => {
const view = parsePresentPacket(
JSON.stringify({
schema: "present.v1",
shell: "chat_monitor",
blocks: {
monitor: { : "暖络" },
body: "她回了一句短谢。",
},
meta: { suggested_actions: ["回一句关心"] },
}),
);
expect(view.ok).toBe(true);
expect(view.fallbackPlain).toBe(false);
expect(view.packet.shell).toBe("chat_monitor");
expect(view.packet.blocks.body).toContain("短谢");
expect(view.packet.meta?.suggested_actions?.[0]).toBe("回一句关心");
});
it("falls back plain text to prose body", () => {
const view = parsePresentPacket("林晚点头收下了画册。");
expect(view.fallbackPlain).toBe(true);
expect(view.packet.shell).toBe("prose");
expect(view.packet.blocks.body).toContain("画册");
});
it("does not treat settlement as present", () => {
const view = parsePresentPacket(
JSON.stringify({
schema: "settlement.v1",
visible_now: "场面",
player_action: "送礼",
}),
);
expect(view.fallbackPlain).toBe(true);
expect(isPresentLikeObject({ schema: "settlement.v1" })).toBe(false);
});
it("presentFromPlainText helper", () => {
const p = presentFromPlainText("hello", "chapter_reader");
expect(p.shell).toBe("chapter_reader");
expect(p.blocks.body).toBe("hello");
});
});
describe("shell adaptation from reply-format", () => {
it("reads 呈现壳 from context-fragment", () => {
const adapt = parseShellAdaptationFromReplyFormat(
JSON.stringify({
schema: "context-fragment.v1",
: "正文组成",
: {
: {
shell_id: "turn_panel",
: "机制重",
: {
tone_chrome: "terminal",
show_suggested_actions: true,
block_labels: { body: "场面" },
},
},
: [{ id: "body", : "body" }],
},
}),
);
expect(adapt?.shell_id).toBe("turn_panel");
expect(adapt?.tweaks.tone_chrome).toBe("terminal");
expect(adapt?.tweaks.block_labels?.body).toBe("场面");
expect(shellDefaultRegions("turn_panel")).toContain("footer");
});
it("defaults missing shell to prose", () => {
const adapt = parseShellAdaptationFromReplyFormat(
JSON.stringify({
schema: "context-fragment.v1",
: { : [{ id: "body" }] },
}),
);
expect(adapt?.shell_id).toBe("prose");
});
});