From 79adc5fffbd07c900604a79fa3d4413f507e896b Mon Sep 17 00:00:00 2001 From: Avraham Sakal Date: Wed, 7 May 2025 08:02:54 -0400 Subject: [PATCH] begin work on `delegate`'s ability to have a multi-step conversation --- server/tools.ts | 69 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/server/tools.ts b/server/tools.ts index e601dba..ca9d201 100644 --- a/server/tools.ts +++ b/server/tools.ts @@ -1,4 +1,10 @@ -import { streamText } from "ai"; +import { + streamText, + generateText, + generateObject, + type Message, + jsonSchema, +} from "ai"; import { getAgentById, openrouter } from "./agentRegistry.js"; // Define the tools with explicit type @@ -33,26 +39,59 @@ const tools: ToolFunctions = { } try { - // Generate a response from the agent using the prompt - const result = streamText({ - model: openrouter(agent.modelName), + const conversation: { messages: Array> } = { messages: [ { role: "system", content: agent.systemMessage }, { role: "user", content: prompt }, ], - tools: agent.tools, - }); - - // Collect the response text - let responseText = ""; - - // The textStream is already an AsyncIterable, no need to call it as a function - for await (const chunk of result.textStream) { - responseText += chunk; + }; + let isConversationDone = false; + while (!isConversationDone) { + // Generate a response from the agent using the prompt + const result = await generateText({ + model: openrouter(agent.modelName), + messages: conversation.messages, + tools: agent.tools, + }); + conversation.messages.push({ role: "assistant", content: result.text }); + const sentimentIsConversationDone = await generateObject<{ + isConversationDone: boolean; + }>({ + model: openrouter("mistralai/mistral-nemo"), + messages: [ + { + role: "system", + content: + "You are a tool to determine whether a conversation is done or should continue with another reply.", + }, + { + role: "user", + content: conversation.messages + .map((message) => `${message.role}: ${message.content}`) + .join("\n"), + }, + ], + schema: jsonSchema({ + type: "object", + properties: { + isConversationDone: { + type: "boolean", + description: + "Whether the conversation is done or should continue and requires a reply.", + }, + }, + }), + }); + isConversationDone = + sentimentIsConversationDone.object.isConversationDone; } - // Return the agent's response - return responseText; + // const summaryText = await generateSummary(); + // // Return the agent's response + // return summaryText; + return conversation.messages + .map((message) => `${message.role}: ${message.content}`) + .join("\n"); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error";