diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..41cbc83 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": false +} diff --git a/gadget-drone/src/services/agent.ts b/gadget-drone/src/services/agent.ts index a1b48de..aef5149 100644 --- a/gadget-drone/src/services/agent.ts +++ b/gadget-drone/src/services/agent.ts @@ -16,7 +16,6 @@ import { import { IChatSession, IChatTurn, - IProject, IUser, ServerToClientEvents, ClientToServerEvents, @@ -26,15 +25,7 @@ import { import AiService from "./ai.ts"; import { GadgetService } from "../lib/service.ts"; -import { AiToolbox } from "../../../packages/ai/dist/toolbox.js"; - -export interface IToolCall { - name: string; - params: string; - call_id?: string; - response?: string; - error?: Error; -} +import { AiToolbox } from "@gadget/ai"; export interface IAgentWorkOrder { createdAt: Date; @@ -50,8 +41,6 @@ interface IAgentWorkflow { type DroneSocket = Socket; class AgentService extends GadgetService { - private toolbox: AiToolbox | undefined; - get name(): string { return "AgentService"; } @@ -60,7 +49,6 @@ class AgentService extends GadgetService { } async start(): Promise { - this.createAgentToolbox(); this.log.info("started"); } @@ -72,18 +60,12 @@ class AgentService extends GadgetService { workOrder: IAgentWorkOrder, socket: DroneSocket, ): Promise { - assert(this.toolbox, "service uninitialized"); - const { turn } = workOrder; const task: IAgentWorkflow = { chatOptions: {}, context: [], }; - async function aiCallTool(name: string, args: string) { - return "[all tool calls are stubbed out]"; - } - const onStreamChunk = async (chunk: IAiStreamChunk): Promise => { this.log.debug("stream chunk received", { chunk }); }; @@ -94,7 +76,7 @@ class AgentService extends GadgetService { systemPrompt: turn.prompts.system, context: task.context, userPrompt: turn.prompts.user, - tools: Array.from(this.toolbox.getModeSet(turn.mode) || []), + tools: this.getToolsForMode(turn.mode), }; } catch (cause) { socket.emit( @@ -108,56 +90,43 @@ class AgentService extends GadgetService { } try { - let keepProcessing = true; - do { - const response = await AiService.chat( - turn.provider, - { - modelId: turn.llm, - params: { - reasoning: false, - temperature: 0.8, - topP: 0.9, - topK: 40, - }, + const response = await AiService.chat( + turn.provider, + { + modelId: turn.llm, + params: { + reasoning: false, + temperature: 0.8, + topP: 0.9, + topK: 40, }, - task.chatOptions, - onStreamChunk, - ); + }, + task.chatOptions, + onStreamChunk, + ); - // Emit thinking content if present - if (response.thinking) { - socket.emit("thinking", response.thinking); - } + // Emit thinking content if present + if (response.thinking) { + socket.emit("thinking", response.thinking); + } - // Emit response content if present - if (response.response) { - socket.emit("response", response.response); - } + // Emit response content if present + if (response.response) { + socket.emit("response", response.response); + } - keepProcessing = (response.toolCalls?.length ?? 0) > 0; - for (const toolCall of response.toolCalls ?? []) { - const result = await aiCallTool( - toolCall.function.name, - toolCall.function.arguments, - ); - task.context.push({ - createdAt: new Date(), - role: "tool", - callId: toolCall.callId, - content: result, - }); - - // Emit tool call event + // Emit tool calls if present + if (response.toolCalls && response.toolCalls.length > 0) { + for (const toolCall of response.toolCalls) { socket.emit( "toolCall", toolCall.callId, toolCall.function.name, toolCall.function.arguments, - result, + response.toolCallResults?.find(r => r.callId === toolCall.callId)?.result || "", ); } - } while (keepProcessing); + } } catch (cause) { socket.emit( "workOrderComplete", @@ -248,7 +217,7 @@ class AgentService extends GadgetService { // TODO } - createAgentToolbox(): void { + private getToolsForMode(mode: ChatSessionMode): any[] { const aiEnv: IAiEnvironment = { NODE_ENV: env.NODE_ENV || "develop", services: { @@ -260,16 +229,16 @@ class AgentService extends GadgetService { }, }, }; - this.toolbox = new AiToolbox(aiEnv); - - let tool = new GoogleSearchTool(this.toolbox); - this.toolbox.register(tool, [ + const toolbox = new AiToolbox(aiEnv); + const googleSearchTool = new GoogleSearchTool(toolbox); + toolbox.register(googleSearchTool, [ ChatSessionMode.Plan, ChatSessionMode.Build, ChatSessionMode.Test, ChatSessionMode.Ship, ChatSessionMode.Develop, ]); + return Array.from(toolbox.getModeSet(mode) || []); } } diff --git a/packages/ai/.gitignore b/packages/ai/.gitignore index 53c37a1..5c62e6e 100644 --- a/packages/ai/.gitignore +++ b/packages/ai/.gitignore @@ -1 +1,5 @@ -dist \ No newline at end of file +dist +*.js +*.js.map +*.d.ts +*.d.ts.map \ No newline at end of file diff --git a/packages/ai/src/index.ts b/packages/ai/src/index.ts index cb0dac0..18c260c 100644 --- a/packages/ai/src/index.ts +++ b/packages/ai/src/index.ts @@ -24,6 +24,7 @@ export { } from "./api.js"; export * from "./tools/search/google.ts"; +export { AiToolbox } from "./toolbox.js"; export { OllamaAiApi } from "./ollama.js"; export { OpenAiApi } from "./openai.js";