1
- import Anthropic from "@anthropic-ai/sdk" ;
2
1
import { Tool } from "../../core/types.js" ;
3
2
import { z } from "zod" ;
4
3
import { zodToJsonSchema } from "zod-to-json-schema" ;
5
- import { subAgentStates } from "./subAgentState.js" ;
4
+ import { subAgentStates , SubAgentState } from "./subAgentState.js" ;
6
5
import { v4 as uuidv4 } from "uuid" ;
6
+ import { toolAgent } from "../../core/toolAgent.js" ;
7
+ import { getTools } from "../getTools.js" ;
7
8
8
9
const parameterSchema = z . object ( {
9
- prompt : z
10
- . string ( )
11
- . describe ( "The prompt/task for the sub-agent" ) ,
10
+ prompt : z . string ( ) . describe ( "The prompt/task for the sub-agent" ) ,
12
11
description : z
13
12
. string ( )
14
13
. max ( 80 )
@@ -17,7 +16,9 @@ const parameterSchema = z.object({
17
16
18
17
const returnSchema = z
19
18
. object ( {
20
- instanceId : z . string ( ) . describe ( "Unique identifier for the sub-agent instance" ) ,
19
+ instanceId : z
20
+ . string ( )
21
+ . describe ( "Unique identifier for the sub-agent instance" ) ,
21
22
response : z . string ( ) . describe ( "Initial response from the sub-agent" ) ,
22
23
} )
23
24
. describe ( "Result containing sub-agent instance ID and initial response" ) ;
@@ -27,65 +28,77 @@ type ReturnType = z.infer<typeof returnSchema>;
27
28
28
29
export const subAgentStartTool : Tool < Parameters , ReturnType > = {
29
30
name : "subAgentStart" ,
30
- description : "Creates a sub-agent that has access to all tools to solve a specific task" ,
31
+ description :
32
+ "Creates a sub-agent that has access to all tools to solve a specific task" ,
31
33
parameters : zodToJsonSchema ( parameterSchema ) ,
32
34
returns : zodToJsonSchema ( returnSchema ) ,
33
35
34
- execute : async (
35
- params ,
36
- { logger } ,
37
- ) : Promise < ReturnType > => {
38
- if ( ! process . env . ANTHROPIC_API_KEY ) {
39
- throw new Error ( "ANTHROPIC_API_KEY environment variable is not set" ) ;
40
- }
41
-
42
- const anthropic = new Anthropic ( {
43
- apiKey : process . env . ANTHROPIC_API_KEY ,
44
- } ) ;
45
-
46
- // Create new instance ID
36
+ execute : async ( params , { logger } ) : Promise < ReturnType > => {
47
37
const instanceId = uuidv4 ( ) ;
48
38
logger . verbose ( `Creating new sub-agent with instance ID: ${ instanceId } ` ) ;
49
39
50
- // Initialize sub-agent state
51
- subAgentStates . set ( instanceId , {
52
- prompt : params . prompt ,
53
- messages : [ ] ,
54
- aborted : false ,
55
- } ) ;
56
-
57
- // Get initial response
58
- logger . verbose ( `Getting initial response from Anthropic API` ) ;
59
- const response = await anthropic . messages . create ( {
60
- model : "claude-3-opus-20240229" ,
61
- max_tokens : 4096 ,
62
- messages : [
63
- {
64
- role : "user" ,
65
- content : params . prompt ,
66
- } ,
67
- ] ,
68
- } ) ;
69
-
70
- // Check if response content exists and has the expected structure
71
- if ( ! response . content ?. [ 0 ] ?. text ) {
72
- throw new Error ( "Invalid response from Anthropic API" ) ;
73
- }
40
+ try {
41
+ const tools = ( await getTools ( ) ) . filter (
42
+ ( tool ) => tool . name !== "userPrompt"
43
+ ) ;
44
+
45
+ // Initialize toolAgent
46
+ const toolAgentState = toolAgent ( params . prompt , tools , logger ) ;
74
47
75
- const responseText = response . content [ 0 ] . text ;
76
- logger . verbose ( `Received response from sub-agent` ) ;
48
+ // Initialize sub-agent state
49
+ const state : SubAgentState = {
50
+ prompt : params . prompt ,
51
+ messages : [ ] ,
52
+ aborted : false ,
53
+ toolAgentState,
54
+ } ;
55
+ subAgentStates . set ( instanceId , state ) ;
77
56
78
- // Store the interaction
79
- const state = subAgentStates . get ( instanceId ) ! ;
80
- state . messages . push (
81
- { role : "user" , content : params . prompt } ,
82
- { role : "assistant" , content : responseText } ,
83
- ) ;
57
+ // Set up message handling
58
+ return new Promise ( ( resolve , reject ) => {
59
+ let messageReceived = false ;
84
60
85
- return {
86
- instanceId,
87
- response : responseText ,
88
- } ;
61
+ const messageHandler = ( message : any ) => {
62
+ if ( message . type === "assistant" && ! messageReceived ) {
63
+ messageReceived = true ;
64
+ const initialResponse = message . content ;
65
+
66
+ // Store the interaction
67
+ state . messages . push (
68
+ { role : "user" , content : params . prompt } ,
69
+ { role : "assistant" , content : initialResponse }
70
+ ) ;
71
+
72
+ resolve ( {
73
+ instanceId,
74
+ response : initialResponse ,
75
+ } ) ;
76
+ }
77
+ } ;
78
+
79
+ const errorHandler = ( error : Error ) => {
80
+ state . aborted = true ;
81
+ reject ( error ) ;
82
+ } ;
83
+
84
+ const endHandler = ( ) => {
85
+ if ( ! messageReceived ) {
86
+ state . aborted = true ;
87
+ reject (
88
+ new Error ( "Stream ended without receiving assistant message" )
89
+ ) ;
90
+ }
91
+ } ;
92
+
93
+ toolAgentState . outMessages
94
+ . on ( "data" , messageHandler )
95
+ . on ( "error" , errorHandler )
96
+ . on ( "end" , endHandler ) ;
97
+ } ) ;
98
+ } catch ( error ) {
99
+ logger . error ( `Failed to start sub-agent: ${ error } ` ) ;
100
+ throw error ;
101
+ }
89
102
} ,
90
103
91
104
logParameters : ( input , { logger } ) => {
0 commit comments