|
|
@@ -516,4 +516,193 @@ describe("ArchitectAgent", () => {
|
|
|
|
|
|
await expect(agent.generateFoundation(book)).rejects.toThrow(/book_rules/i);
|
|
|
});
|
|
|
+
|
|
|
+ it("passes maxTokens 16384 when generating foundation", async () => {
|
|
|
+ const agent = new ArchitectAgent({
|
|
|
+ client: {
|
|
|
+ provider: "openai",
|
|
|
+ apiFormat: "chat",
|
|
|
+ stream: false,
|
|
|
+ defaults: {
|
|
|
+ temperature: 0.7,
|
|
|
+ maxTokens: 4096,
|
|
|
+ thinkingBudget: 0, maxTokensCap: null,
|
|
|
+ extra: {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ model: "test-model",
|
|
|
+ projectRoot: process.cwd(),
|
|
|
+ });
|
|
|
+
|
|
|
+ const book: BookConfig = {
|
|
|
+ id: "max-tokens-book",
|
|
|
+ title: "Max Tokens Book",
|
|
|
+ platform: "other",
|
|
|
+ genre: "other",
|
|
|
+ status: "active",
|
|
|
+ targetChapters: 20,
|
|
|
+ chapterWordCount: 2200,
|
|
|
+ language: "zh",
|
|
|
+ createdAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ updatedAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ };
|
|
|
+
|
|
|
+ const chatSpy = vi.spyOn(agent as unknown as { chat: (...args: unknown[]) => Promise<unknown> }, "chat")
|
|
|
+ .mockResolvedValue({
|
|
|
+ content: [
|
|
|
+ "=== SECTION: story_bible ===",
|
|
|
+ "# 故事圣经",
|
|
|
+ "",
|
|
|
+ "=== SECTION: volume_outline ===",
|
|
|
+ "# 卷纲",
|
|
|
+ "",
|
|
|
+ "=== SECTION: book_rules ===",
|
|
|
+ "---",
|
|
|
+ "version: \"1.0\"",
|
|
|
+ "---",
|
|
|
+ "",
|
|
|
+ "=== SECTION: current_state ===",
|
|
|
+ "# 当前状态",
|
|
|
+ "",
|
|
|
+ "=== SECTION: pending_hooks ===",
|
|
|
+ "| hook_id | 起始章节 | 类型 | 状态 | 最近推进 | 预期回收 | 备注 |",
|
|
|
+ "| --- | --- | --- | --- | --- | --- | --- |",
|
|
|
+ "| H01 | 1 | mystery | open | 0 | 10章 | 初始钩子 |",
|
|
|
+ ].join("\n"),
|
|
|
+ usage: ZERO_USAGE,
|
|
|
+ });
|
|
|
+
|
|
|
+ await agent.generateFoundation(book);
|
|
|
+
|
|
|
+ expect(chatSpy).toHaveBeenCalledWith(
|
|
|
+ expect.any(Array),
|
|
|
+ expect.objectContaining({ temperature: 0.8, maxTokens: 16384 }),
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it("passes maxTokens 16384 when generating foundation from import", async () => {
|
|
|
+ const agent = new ArchitectAgent({
|
|
|
+ client: {
|
|
|
+ provider: "openai",
|
|
|
+ apiFormat: "chat",
|
|
|
+ stream: false,
|
|
|
+ defaults: {
|
|
|
+ temperature: 0.7,
|
|
|
+ maxTokens: 4096,
|
|
|
+ thinkingBudget: 0, maxTokensCap: null,
|
|
|
+ extra: {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ model: "test-model",
|
|
|
+ projectRoot: process.cwd(),
|
|
|
+ });
|
|
|
+
|
|
|
+ const book: BookConfig = {
|
|
|
+ id: "import-max-tokens-book",
|
|
|
+ title: "Import Max Tokens Book",
|
|
|
+ platform: "other",
|
|
|
+ genre: "other",
|
|
|
+ status: "active",
|
|
|
+ targetChapters: 20,
|
|
|
+ chapterWordCount: 2200,
|
|
|
+ language: "zh",
|
|
|
+ createdAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ updatedAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ };
|
|
|
+
|
|
|
+ const chatSpy = vi.spyOn(agent as unknown as { chat: (...args: unknown[]) => Promise<unknown> }, "chat")
|
|
|
+ .mockResolvedValue({
|
|
|
+ content: [
|
|
|
+ "=== SECTION: story_bible ===",
|
|
|
+ "# 故事圣经",
|
|
|
+ "",
|
|
|
+ "=== SECTION: volume_outline ===",
|
|
|
+ "# 卷纲",
|
|
|
+ "",
|
|
|
+ "=== SECTION: book_rules ===",
|
|
|
+ "---",
|
|
|
+ "version: \"1.0\"",
|
|
|
+ "---",
|
|
|
+ "",
|
|
|
+ "=== SECTION: current_state ===",
|
|
|
+ "# 当前状态",
|
|
|
+ "",
|
|
|
+ "=== SECTION: pending_hooks ===",
|
|
|
+ "| hook_id | 起始章节 | 类型 | 状态 | 最近推进 | 预期回收 | 备注 |",
|
|
|
+ "| --- | --- | --- | --- | --- | --- | --- |",
|
|
|
+ "| H01 | 1 | mystery | open | 0 | 10章 | 初始钩子 |",
|
|
|
+ ].join("\n"),
|
|
|
+ usage: ZERO_USAGE,
|
|
|
+ });
|
|
|
+
|
|
|
+ await agent.generateFoundationFromImport(book, "第一章正文");
|
|
|
+
|
|
|
+ expect(chatSpy).toHaveBeenCalledWith(
|
|
|
+ expect.any(Array),
|
|
|
+ expect.objectContaining({ temperature: 0.5, maxTokens: 16384 }),
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
+ it("passes maxTokens 16384 when generating fanfic foundation", async () => {
|
|
|
+ const agent = new ArchitectAgent({
|
|
|
+ client: {
|
|
|
+ provider: "openai",
|
|
|
+ apiFormat: "chat",
|
|
|
+ stream: false,
|
|
|
+ defaults: {
|
|
|
+ temperature: 0.7,
|
|
|
+ maxTokens: 4096,
|
|
|
+ thinkingBudget: 0, maxTokensCap: null,
|
|
|
+ extra: {},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ model: "test-model",
|
|
|
+ projectRoot: process.cwd(),
|
|
|
+ });
|
|
|
+
|
|
|
+ const book: BookConfig = {
|
|
|
+ id: "fanfic-max-tokens-book",
|
|
|
+ title: "Fanfic Max Tokens Book",
|
|
|
+ platform: "other",
|
|
|
+ genre: "fanfic",
|
|
|
+ status: "active",
|
|
|
+ targetChapters: 20,
|
|
|
+ chapterWordCount: 2200,
|
|
|
+ language: "zh",
|
|
|
+ createdAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ updatedAt: "2026-03-29T00:00:00.000Z",
|
|
|
+ };
|
|
|
+
|
|
|
+ const chatSpy = vi.spyOn(agent as unknown as { chat: (...args: unknown[]) => Promise<unknown> }, "chat")
|
|
|
+ .mockResolvedValue({
|
|
|
+ content: [
|
|
|
+ "=== SECTION: story_bible ===",
|
|
|
+ "# 故事圣经",
|
|
|
+ "",
|
|
|
+ "=== SECTION: volume_outline ===",
|
|
|
+ "# 卷纲",
|
|
|
+ "",
|
|
|
+ "=== SECTION: book_rules ===",
|
|
|
+ "---",
|
|
|
+ "version: \"1.0\"",
|
|
|
+ "---",
|
|
|
+ "",
|
|
|
+ "=== SECTION: current_state ===",
|
|
|
+ "# 当前状态",
|
|
|
+ "",
|
|
|
+ "=== SECTION: pending_hooks ===",
|
|
|
+ "| hook_id | 起始章节 | 类型 | 状态 | 最近推进 | 预期回收 | 备注 |",
|
|
|
+ "| --- | --- | --- | --- | --- | --- | --- |",
|
|
|
+ "| H01 | 1 | mystery | open | 0 | 10章 | 初始钩子 |",
|
|
|
+ ].join("\n"),
|
|
|
+ usage: ZERO_USAGE,
|
|
|
+ });
|
|
|
+
|
|
|
+ await agent.generateFanficFoundation(book, "正典文本", "canon");
|
|
|
+
|
|
|
+ expect(chatSpy).toHaveBeenCalledWith(
|
|
|
+ expect.any(Array),
|
|
|
+ expect.objectContaining({ temperature: 0.7, maxTokens: 16384 }),
|
|
|
+ );
|
|
|
+ });
|
|
|
});
|