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

78 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from "vitest";
import {
createMockMainAgentResponse,
createMockToolCall,
MockLlmProvider,
} from "../src/llm/client.js";
import { buildIntakeProgress, readIntakeValues } from "../src/intake/intake.js";
import { PhaseRuntime } from "../src/runtime/phase-runtime.js";
describe("phase runtime", () => {
it("selects basic skill and shows startup inquiry", async () => {
const runtime = new PhaseRuntime();
await runtime.start();
expect(runtime.getSession().waitingReason?.kind).toBe("skill_selection");
await runtime.selectSkill("basic");
expect(runtime.getSession().waitingReason?.kind).toBe("intake");
expect(runtime.getActiveSkill()?.name).toBe("basic");
});
it("writes book.brief after intake confirm", async () => {
const runtime = new PhaseRuntime();
await runtime.start();
await runtime.selectSkill("basic");
await runtime.submitInput("科幻中篇,第三人称");
await runtime.confirmIntake();
expect(runtime.getSession().slots["book.brief"]).toContain("科幻");
expect(runtime.getSession().slots.startupCompleted).toBe(true);
});
it("syncs demand tag to blackboard after intake confirm", async () => {
const runtime = new PhaseRuntime();
await runtime.start();
await runtime.selectSkill("roleplay-game-theory");
const fields = runtime.getActiveSkill()?.intakeFields ?? [];
await runtime.submitInput("德州扑克,经典博弈情境");
await runtime.submitInput("玩家A算计型玩家B怕吃亏");
await runtime.submitInput("单轮定胜负,需要思考标签与场景描写");
const progress = buildIntakeProgress(
fields,
readIntakeValues(runtime.getSession().slots),
);
if (!progress.ready) {
const values = readIntakeValues(runtime.getSession().slots);
for (const f of fields.filter((x) => x.required && !values[x.id])) {
values[f.id] = "补充";
}
await runtime.dispatch({
type: "user_submitted_input",
payload: { text: "补充", intakeValues: values },
});
}
await runtime.confirmIntake();
const demand = runtime.getBlackboard().getContentByTag("用户.博弈需求") ?? "";
expect(demand).toContain("德州扑克");
expect(runtime.getSession().slots.startupCompleted).toBe(true);
});
it("mock main agent tool loop reads blackboard then proposes worker", async () => {
const runtime = new PhaseRuntime({
llm: new MockLlmProvider([
createMockToolCall("read_blackboard", { tags: ["book.brief"] }),
createMockToolCall("run_worker", {
workerId: "outline",
reason: "已读需求,生成大纲",
requiresApproval: true,
}),
]),
});
await runtime.start();
await runtime.selectSkill("basic");
await runtime.submitInput("科幻中篇,第三人称");
await runtime.confirmIntake();
expect(runtime.getSession().waitingReason?.kind).toBe("approve_step");
expect(runtime.getSession().pendingDecision?.workerId).toBe("outline");
});
});