Explorar el Código

feat(core): extend SubAgentParams with architect/writer/reviser/exporter fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fanghanjun hace 6 meses
padre
commit
2ac2d6df77

+ 44 - 0
packages/core/src/__tests__/agent-tools-params.test.ts

@@ -0,0 +1,44 @@
+import { describe, it, expect } from "vitest";
+import { createSubAgentTool } from "../agent/agent-tools.js";
+
+describe("SubAgentParams schema", () => {
+  const mockPipeline = {} as any;
+  const tool = createSubAgentTool(mockPipeline, null);
+  const schema = tool.parameters;
+  const props = (schema as any).properties;
+
+  it("has architect params: title, genre, platform, language, targetChapters", () => {
+    expect(props.title).toBeDefined();
+    expect(props.genre).toBeDefined();
+    expect(props.platform).toBeDefined();
+    expect(props.language).toBeDefined();
+    expect(props.targetChapters).toBeDefined();
+  });
+
+  it("has writer/architect param: chapterWordCount", () => {
+    expect(props.chapterWordCount).toBeDefined();
+  });
+
+  it("has reviser param: mode", () => {
+    expect(props.mode).toBeDefined();
+  });
+
+  it("has exporter params: format, approvedOnly", () => {
+    expect(props.format).toBeDefined();
+    expect(props.approvedOnly).toBeDefined();
+  });
+
+  it("has existing params: agent, instruction, bookId, chapterNumber", () => {
+    expect(props.agent).toBeDefined();
+    expect(props.instruction).toBeDefined();
+    expect(props.bookId).toBeDefined();
+    expect(props.chapterNumber).toBeDefined();
+  });
+
+  it("all new params have description with agent scope", () => {
+    expect(props.title.description).toMatch(/architect/i);
+    expect(props.genre.description).toMatch(/architect/i);
+    expect(props.mode.description).toMatch(/reviser/i);
+    expect(props.format.description).toMatch(/exporter/i);
+  });
+});

+ 33 - 3
packages/core/src/agent/agent-tools.ts

@@ -37,9 +37,39 @@ const SubAgentParams = Type.Object({
     Type.Literal("reviser"),
     Type.Literal("reviser"),
     Type.Literal("exporter"),
     Type.Literal("exporter"),
   ]),
   ]),
-  instruction: Type.String({ description: "Natural language instruction from the main Agent" }),
+  instruction: Type.String({ description: "Natural language instruction for the sub-agent" }),
   bookId: Type.Optional(Type.String({ description: "Book ID — required for all agents except architect" })),
   bookId: Type.Optional(Type.String({ description: "Book ID — required for all agents except architect" })),
-  chapterNumber: Type.Optional(Type.Number({ description: "Target chapter number for auditor/reviser. Omit to use the latest chapter." })),
+  chapterNumber: Type.Optional(Type.Number({ description: "auditor/reviser: target chapter number. Omit to use the latest chapter." })),
+  // -- architect params --
+  title: Type.Optional(Type.String({ description: "architect only: book title" })),
+  genre: Type.Optional(Type.String({ description: "architect only: genre (xuanhuan, urban, mystery, romance, scifi, fantasy, wuxia, general, etc.)" })),
+  platform: Type.Optional(Type.Union([
+    Type.Literal("tomato"),
+    Type.Literal("qidian"),
+    Type.Literal("feilu"),
+    Type.Literal("other"),
+  ], { description: "architect only: target platform. Default: other" })),
+  language: Type.Optional(Type.Union([
+    Type.Literal("zh"),
+    Type.Literal("en"),
+  ], { description: "architect only: writing language. Default: zh" })),
+  targetChapters: Type.Optional(Type.Number({ description: "architect only: total chapter count. Default: 200" })),
+  chapterWordCount: Type.Optional(Type.Number({ description: "architect/writer: words per chapter. Default: 3000" })),
+  // -- reviser params --
+  mode: Type.Optional(Type.Union([
+    Type.Literal("spot-fix"),
+    Type.Literal("polish"),
+    Type.Literal("rewrite"),
+    Type.Literal("rework"),
+    Type.Literal("anti-detect"),
+  ], { description: "reviser only: revision mode. Default: spot-fix" })),
+  // -- exporter params --
+  format: Type.Optional(Type.Union([
+    Type.Literal("txt"),
+    Type.Literal("md"),
+    Type.Literal("epub"),
+  ], { description: "exporter only: export format. Default: txt" })),
+  approvedOnly: Type.Optional(Type.Boolean({ description: "exporter only: export only approved chapters. Default: false" })),
 });
 });
 
 
 export function createSubAgentTool(pipeline: PipelineRunner, activeBookId: string | null): AgentTool<typeof SubAgentParams> {
 export function createSubAgentTool(pipeline: PipelineRunner, activeBookId: string | null): AgentTool<typeof SubAgentParams> {
@@ -57,7 +87,7 @@ export function createSubAgentTool(pipeline: PipelineRunner, activeBookId: strin
       _signal?: AbortSignal,
       _signal?: AbortSignal,
       onUpdate?: AgentToolUpdateCallback,
       onUpdate?: AgentToolUpdateCallback,
     ): Promise<AgentToolResult<undefined>> {
     ): Promise<AgentToolResult<undefined>> {
-      const { agent, instruction, bookId, chapterNumber } = params;
+      const { agent, instruction, bookId, chapterNumber, title, genre, platform, language, targetChapters, chapterWordCount, mode, format, approvedOnly } = params;
 
 
       const progress = (msg: string) => {
       const progress = (msg: string) => {
         onUpdate?.(textResult(msg));
         onUpdate?.(textResult(msg));