diff --git a/src/agents/scriptAgent/index.ts b/src/agents/scriptAgent/index.ts index 47b809a..acbe05a 100644 --- a/src/agents/scriptAgent/index.ts +++ b/src/agents/scriptAgent/index.ts @@ -67,7 +67,7 @@ export async function decisionAI(ctx: AgentContext) { ...skill.tools, ...memory.getTools(), run_sub_agent: runSubAgent(ctx), - ...useTools(ctx.resTool), + ...useTools({ resTool: ctx.resTool, msg: ctx.msg }), }, }); @@ -77,45 +77,50 @@ export async function decisionAI(ctx: AgentContext) { //====================== 执行层 ====================== export async function executionAI(ctx: AgentContext) { - const { isolationKey, text, abortSignal, resTool } = ctx; - const memory = new Memory("scriptAgent", isolationKey); - const [skill, mem] = await Promise.all([useSkill("script_agent_execution.md"), memory.get(text)]); + const { text, abortSignal } = ctx; + const skill = await useSkill("script_agent_execution.md"); - const systemPrompt = buildSystemPrompt(skill.prompt, mem); + const subMsg = ctx.resTool.newMessage("assistant", "编剧"); + + const prefixSystem = ` +你可以使用如下XML格式写入工作区: +故事骨架内容 +改编策略内容 +`; const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: systemPrompt, + system: prefixSystem + skill.prompt, messages: [{ role: "user", content: text }], abortSignal, tools: { ...skill.tools, - ...memory.getTools(), - ...useTools(ctx.resTool), + ...useTools({ resTool: ctx.resTool, msg: subMsg }), }, }); - return textStream; + return { textStream, subMsg }; } export async function supervisionAI(ctx: AgentContext) { - const { isolationKey, text, abortSignal, resTool } = ctx; + const { text, abortSignal } = ctx; - const memory = new Memory("scriptAgent", isolationKey); - const [skill, mem] = await Promise.all([useSkill("script_agent_supervision.md"), memory.get(text)]); - - const systemPrompt = buildSystemPrompt(skill.prompt, mem); + const skill = await useSkill("script_agent_supervision.md"); + const subMsg = ctx.resTool.newMessage("assistant", "编辑"); const { textStream } = await u.Ai.Text("scriptAgent").stream({ - system: systemPrompt, + system: skill.prompt, messages: [{ role: "user", content: text }], abortSignal, tools: { ...skill.tools, - ...useTools(ctx.resTool), + ...useTools({ + resTool: ctx.resTool, + msg: subMsg, + }), }, }); - return textStream; + return { textStream, subMsg }; } //工具函数 @@ -125,17 +130,15 @@ function runSubAgent(parentCtx: AgentContext) { description: "启动子Agent执行独立任务。可用子Agent:executionAI, decisionAI, supervisionAI", inputSchema: z.object({ agent: z.enum(["executionAI", "supervisionAI"]).describe("子Agent名称"), - prompt: z.string().max(100).describe("交给子Agent的任务简约描述"), + prompt: z.string().describe("交给子Agent的任务简约描述,100字以内"), }), execute: async ({ agent, prompt }) => { const fn = [executionAI, supervisionAI][subAgentList.indexOf(agent)]; - const subMsg = parentCtx.resTool.newMessage("assistant", agent == "executionAI" ? "编剧" : "编辑"); - // 先完成主Agent当前的消息 parentCtx.msg.complete(); // 子Agent用新消息回复 - const subTextStream = await fn({ ...parentCtx, text: prompt }); + const { textStream: subTextStream, subMsg } = await fn({ ...parentCtx, text: prompt }); let text = subMsg.text(); let fullResponse = ""; for await (const chunk of subTextStream) { diff --git a/src/agents/scriptAgent/tools.ts b/src/agents/scriptAgent/tools.ts index 03cbdbe..0c312f4 100644 --- a/src/agents/scriptAgent/tools.ts +++ b/src/agents/scriptAgent/tools.ts @@ -29,7 +29,14 @@ const planDataKeyLabels = Object.fromEntries( Object.entries(planData.shape).map(([key, schema]) => [key, (schema as z.ZodTypeAny).description ?? key]), ) as Record; -export default (resTool: ResTool, toolsNames?: string[]) => { +interface ToolConfig { + resTool: ResTool; + toolsNames?: string[]; + msg: ReturnType; +} + +export default (toolCpnfig: ToolConfig) => { + const { resTool, toolsNames, msg } = toolCpnfig; const { socket } = resTool; const tools: Record = { get_novel_events: tool({ @@ -38,14 +45,18 @@ export default (resTool: ResTool, toolsNames?: string[]) => { ids: z.array(z.number()).describe("章节id,注意区分"), }), execute: async ({ ids }) => { - resTool.newMessage('system').text(`正在获取章节事件,章节ID:${ids.join(",")}`).complete(); console.log("[tools] get_novel_events", ids); + const thinking = msg.thinking("正在查询章节事件..."); const data = await u .db("o_novel") .where("projectId", resTool.data.projectId) .select("id", "chapterIndex as index", "reel", "chapter", "chapterData", "event", "eventState") .whereIn("id", ids); + thinking.appendText("正在查询章节ID: " + ids.join(",")); const eventString = data.map((i: any) => [`第${i.index}章,标题:${i.chapter},事件:${i.event}`].join("\n")).join("\n"); + thinking.appendText("查询结果:\n" + eventString); + thinking.updateTitle("查询章节事件完成"); + thinking.complete(); return eventString; }, }), @@ -55,9 +66,12 @@ export default (resTool: ResTool, toolsNames?: string[]) => { key: keySchema.describe("数据key"), }), execute: async ({ key }) => { - resTool.newMessage('system').text(`正在阅读 ${planDataKeyLabels[key]} 数据...`).complete(); console.log("[tools] get_planData", key); + const thinking = msg.thinking(`正在获取${planDataKeyLabels[key]}工作区数据...`); const planData: planData = await new Promise((resolve) => socket.emit("getPlanData", { key }, (res: any) => resolve(res))); + thinking.appendText(`获取到${planDataKeyLabels[key]}:\n` + planData[key]); + thinking.updateTitle(`获取${planDataKeyLabels[key]}完成`); + thinking.complete(); return planData[key]; }, }), @@ -67,42 +81,27 @@ export default (resTool: ResTool, toolsNames?: string[]) => { id: z.string().describe("章节id"), }), execute: async ({ id }) => { - console.log(id); - return ""; - }, - }), - set_planData_storySkeleton: tool({ - description: "保存故事骨架到工作区", - inputSchema: z.object({ value: planData.shape.storySkeleton }), - execute: async ({ value }) => { - console.log("[tools] set_planData storySkeleton", value); - resTool.newMessage('system').text("正在保存 故事骨架 数据").complete(); - socket.emit("setPlanData", { key: "storySkeleton", value }); - return true; - }, - }), - set_planData_adaptationStrategy: tool({ - description: "保存改编策略到工作区", - inputSchema: z.object({ value: planData.shape.adaptationStrategy }), - execute: async ({ value }) => { - console.log("[tools] set_planData adaptationStrategy", value); - resTool.newMessage('system').text("正在保存 改编策略 数据").complete(); - socket.emit("setPlanData", { key: "adaptationStrategy", value }); - return true; + console.log("[tools] get_novel_text", id); + const thinking = msg.thinking(`正在获取小说章节原文...`); + const data = await u.db("o_novel").where({ id }).select("chapterData").first(); + const text = data && data?.chapterData ? data.chapterData : ""; + thinking.appendText(`获取到原文:\n` + text); + thinking.updateTitle(`获取小说章节原文完成`); + thinking.complete(); + return text; }, }), + //====================== update_script_to_sqlite: tool({ description: "更新剧本,修改数据库对应剧本,供后续业务使用", inputSchema: z.object({ script: ScriptSchema, }), execute: async ({ script }) => { - console.log("%c Line:103 🍷 script", "background:#42b983", script); await u.db("o_script").where({ id: script.id }).update({ name: script.name, content: script.content, }); - socket.emit("setPlanData", { key: "script", value: script.id }); return true; }, @@ -113,8 +112,6 @@ export default (resTool: ResTool, toolsNames?: string[]) => { script: ScriptSchema.omit({ id: true }), }), execute: async ({ script }) => { - console.log("%c Line:103 🍷 script", "background:#42b983", script); - const [scriptId] = await u.db("o_script").insert({ name: script.name, content: script.content,