Files
writing-agent/tests/agent-view.test.ts
2026-07-10 08:31:27 +08:00

151 lines
5.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
classifyAgentMessage,
buildFocus,
buildSkillCatalog,
buildToolTrace,
inferLifecycleStage,
canEnterPlay,
} from "../src/server/agent-view.js";
import { createSession } from "../src/runtime/phase-machine.js";
describe("classifyAgentMessage", () => {
it("parses orchestrator decisions", () => {
const m = classifyAgentMessage("[总管] run_worker: 生成规则");
expect(m.kind).toBe("orchestrator_decision");
expect(m.body).toBe("生成规则");
});
it("parses agent tool calls", () => {
const m = classifyAgentMessage("[总管 tool] invoke_worker: write-rules");
expect(m.kind).toBe("agent_tool");
expect(m.title).toContain("invoke_worker");
expect(m.body).toBe("write-rules");
});
it("parses worker output", () => {
const m = classifyAgentMessage("[Worker] write-rules 已完成\n\n### rules\n\n1. foo");
expect(m.kind).toBe("worker_output");
expect(m.actor).toBe("write-rules");
expect(m.body).toContain("1. foo");
});
it("parses worker questions", () => {
const m = classifyAgentMessage(
"[Worker] setup-scenario 提问:\n- 请提供玩家人数",
);
expect(m.kind).toBe("worker_questions");
expect(m.actor).toBe("setup-scenario");
expect(m.body).toContain("请提供玩家人数");
});
it("falls back when worker question body is empty", () => {
const m = classifyAgentMessage("Worker 提问:\n");
expect(m.kind).toBe("worker_questions");
expect(m.body).toContain("请补充当前步骤");
});
});
describe("lifecycle", () => {
it("infers design before startup completed", () => {
const session = createSession();
expect(inferLifecycleStage(session)).toBe("design");
expect(canEnterPlay(session)).toBe(false);
});
it("infers play after startup completed", () => {
const session = {
...createSession(),
slots: { ...createSession().slots, startupCompleted: true },
};
expect(inferLifecycleStage(session)).toBe("play");
expect(canEnterPlay(session)).toBe(true);
});
it("respects uiLifecycleStage override", () => {
const session = {
...createSession(),
slots: { ...createSession().slots, uiLifecycleStage: "play" },
};
expect(inferLifecycleStage(session)).toBe("play");
});
});
describe("buildSkillCatalog", () => {
it("lists design skills for world-simulator", () => {
const session = createSession();
const catalog = buildSkillCatalog(session, "world-simulator", "design");
expect(catalog.length).toBeGreaterThan(0);
expect(catalog.every((s) => s.stage === "design")).toBe(true);
expect(catalog.some((s) => s.id === "interaction-paradigm")).toBe(true);
expect(catalog[0].purpose.length).toBeGreaterThan(0);
});
it("marks intake active during intake wait", () => {
const session = {
...createSession(),
waitingReason: { kind: "intake" as const, prompt: "请填写" },
};
const catalog = buildSkillCatalog(session, "basic", "design");
const intake = catalog.find((s) => s.id === "intake");
expect(intake?.status).toBe("active");
});
});
describe("buildToolTrace", () => {
it("collects agent_tool messages since last user input", () => {
const trace = buildToolTrace([
{
kind: "user_input",
text: "hello",
createdAt: "2026-01-01T00:00:00Z",
},
{
kind: "agent_tool",
text: "[总管 tool] read_blackboard: tags=3",
createdAt: "2026-01-01T00:00:01Z",
},
]);
expect(trace).toHaveLength(1);
expect(trace[0].name).toBe("read_blackboard");
});
});
describe("buildFocus", () => {
it("focuses user on input wait", () => {
const session = {
...createSession(),
phase: "waiting_user" as const,
waitingReason: { kind: "input" as const, message: "请描述场景" },
};
const focus = buildFocus(session, session.waitingReason);
expect(focus.actorType).toBe("user");
});
it("focuses user on worker questions", () => {
const session = {
...createSession(),
phase: "waiting_user" as const,
waitingReason: {
kind: "worker_questions" as const,
workerId: "setup-scenario",
questions: ["请提供玩家人数"],
},
};
const focus = buildFocus(session, session.waitingReason);
expect(focus.actorType).toBe("user");
expect(focus.action).toContain("setup-scenario");
expect(focus.detail).toContain("请提供玩家人数");
});
it("shows design burst when running in design lifecycle", () => {
const session = {
...createSession(),
phase: "running" as const,
};
const focus = buildFocus(session, undefined, undefined, "design");
expect(focus.actorLabel).toBe("Agent");
expect(focus.action).toContain("设计");
});
});