@minded-ai/mindedjs 1.0.128 → 1.0.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/agent.d.ts +7 -4
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +45 -72
  4. package/dist/agent.js.map +1 -1
  5. package/dist/browserTask/executeBrowserTask.d.ts +2 -13
  6. package/dist/browserTask/executeBrowserTask.d.ts.map +1 -1
  7. package/dist/browserTask/executeBrowserTask.js +9 -180
  8. package/dist/browserTask/executeBrowserTask.js.map +1 -1
  9. package/dist/debugging/index.d.ts +2 -0
  10. package/dist/debugging/index.d.ts.map +1 -0
  11. package/dist/debugging/index.js +6 -0
  12. package/dist/debugging/index.js.map +1 -0
  13. package/dist/debugging/llmCallbackHandler.d.ts +83 -0
  14. package/dist/debugging/llmCallbackHandler.d.ts.map +1 -0
  15. package/dist/debugging/llmCallbackHandler.js +102 -0
  16. package/dist/debugging/llmCallbackHandler.js.map +1 -0
  17. package/dist/nodes/addBrowserTaskNode.d.ts.map +1 -1
  18. package/dist/nodes/addBrowserTaskNode.js +2 -1
  19. package/dist/nodes/addBrowserTaskNode.js.map +1 -1
  20. package/dist/nodes/addBrowserTaskRunNode.d.ts +1 -1
  21. package/dist/nodes/addBrowserTaskRunNode.d.ts.map +1 -1
  22. package/dist/nodes/addBrowserTaskRunNode.js +10 -2
  23. package/dist/nodes/addBrowserTaskRunNode.js.map +1 -1
  24. package/dist/platform/mindedConnectionTypes.d.ts +28 -1
  25. package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
  26. package/dist/platform/mindedConnectionTypes.js +2 -0
  27. package/dist/platform/mindedConnectionTypes.js.map +1 -1
  28. package/dist/platform/toolExecutor.d.ts +29 -0
  29. package/dist/platform/toolExecutor.d.ts.map +1 -0
  30. package/dist/platform/toolExecutor.js +95 -0
  31. package/dist/platform/toolExecutor.js.map +1 -0
  32. package/dist/platform/utils/tools.d.ts +6 -0
  33. package/dist/platform/utils/tools.d.ts.map +1 -0
  34. package/dist/platform/utils/tools.js +57 -0
  35. package/dist/platform/utils/tools.js.map +1 -0
  36. package/dist/types/Flows.types.d.ts +1 -0
  37. package/dist/types/Flows.types.d.ts.map +1 -1
  38. package/dist/types/Flows.types.js.map +1 -1
  39. package/dist/types/LangGraph.types.d.ts +2 -0
  40. package/dist/types/LangGraph.types.d.ts.map +1 -1
  41. package/dist/types/LangGraph.types.js +5 -0
  42. package/dist/types/LangGraph.types.js.map +1 -1
  43. package/dist/types/Tools.types.d.ts +3 -2
  44. package/dist/types/Tools.types.d.ts.map +1 -1
  45. package/dist/utils/agentUtils.d.ts +5 -0
  46. package/dist/utils/agentUtils.d.ts.map +1 -0
  47. package/dist/utils/agentUtils.js +86 -0
  48. package/dist/utils/agentUtils.js.map +1 -0
  49. package/dist/utils/history.d.ts +1 -0
  50. package/dist/utils/history.d.ts.map +1 -1
  51. package/dist/utils/history.js +20 -0
  52. package/dist/utils/history.js.map +1 -1
  53. package/docs/SUMMARY.md +1 -0
  54. package/docs/sdk/agent-api.md +524 -0
  55. package/docs/sdk/debugging.md +42 -306
  56. package/package.json +2 -2
  57. package/src/agent.ts +53 -103
  58. package/src/browserTask/executeBrowserTask.ts +11 -215
  59. package/src/debugging/index.ts +1 -0
  60. package/src/debugging/llmCallbackHandler.ts +126 -0
  61. package/src/nodes/addBrowserTaskNode.ts +3 -2
  62. package/src/nodes/addBrowserTaskRunNode.ts +21 -2
  63. package/src/platform/mindedConnectionTypes.ts +33 -1
  64. package/src/platform/toolExecutor.ts +118 -0
  65. package/src/platform/utils/tools.ts +55 -0
  66. package/src/types/Flows.types.ts +1 -0
  67. package/src/types/LangGraph.types.ts +5 -0
  68. package/src/types/Tools.types.ts +2 -1
  69. package/src/utils/agentUtils.ts +68 -0
  70. package/src/utils/history.ts +29 -1
@@ -5,222 +5,11 @@ import {
5
5
  CreateBrowserSessionResponse,
6
6
  InvokeBrowserTaskResponse,
7
7
  CreateBrowserSessionRequest,
8
+ InvokeBrowserTaskRequest,
8
9
  } from '../platform/mindedConnectionTypes';
9
10
 
10
- // Browser Use Cloud API configuration
11
- const BROWSER_USE_API_BASE_URL = 'https://api.browser-use.com/api/v1';
12
-
13
- // Types for Browser Use Cloud API
14
- export interface CloudTaskResponse {
15
- id: string;
16
- status: string;
17
- live_url?: string;
18
- steps?: any[];
19
- output?: string;
20
- }
21
-
22
- // Browser Use Cloud API methods
23
- export const createCloudTask = async (prompt: string, model?: string): Promise<string> => {
24
- const apiKey = process.env.BROWSER_USE_API_KEY;
25
- if (!apiKey) {
26
- throw new Error('BROWSER_USE_API_KEY environment variable is required');
27
- }
28
-
29
- logger.debug({ msg: 'Creating cloud browser task', prompt: prompt.substring(0, 100) + '...' });
30
-
31
- const response = await fetch(`${BROWSER_USE_API_BASE_URL}/run-task`, {
32
- method: 'POST',
33
- headers: {
34
- Authorization: `Bearer ${apiKey}`,
35
- 'Content-Type': 'application/json',
36
- },
37
- body: JSON.stringify({
38
- task: prompt,
39
- use_proxy: false,
40
- llm_model: model || 'gpt-4o',
41
- }),
42
- });
43
-
44
- if (!response.ok) {
45
- logger.error({ msg: 'Failed to create cloud browser task', status: response.status, statusText: response.statusText });
46
- throw new Error(`Failed to create browser task: ${response.statusText}`);
47
- }
48
-
49
- const data = await response.json();
50
- logger.debug({ msg: 'Cloud browser task created', taskId: data.id });
51
- return data.id;
52
- };
53
-
54
- export const getTaskDetails = async (taskId: string): Promise<CloudTaskResponse> => {
55
- const apiKey = process.env.BROWSER_USE_API_KEY;
56
- if (!apiKey) {
57
- throw new Error('BROWSER_USE_API_KEY environment variable is required');
58
- }
59
-
60
- const response = await fetch(`${BROWSER_USE_API_BASE_URL}/task/${taskId}`, {
61
- headers: {
62
- Authorization: `Bearer ${apiKey}`,
63
- },
64
- });
65
-
66
- if (!response.ok) {
67
- logger.error({ msg: 'Failed to get task details', taskId, status: response.status, statusText: response.statusText });
68
- throw new Error(`Failed to get task details: ${response.statusText}`);
69
- }
70
-
71
- return response.json();
72
- };
73
-
74
- export const waitForLiveUrl = async (taskId: string, maxWaitTime: number = 30000): Promise<CloudTaskResponse> => {
75
- const startTime = Date.now();
76
- const pollInterval = 2000; // 2 seconds
77
- let pollCount = 0;
78
-
79
- logger.debug({ msg: 'Starting to poll for live_url', taskId, maxWaitTime, pollInterval });
80
-
81
- while (Date.now() - startTime < maxWaitTime) {
82
- pollCount++;
83
- const elapsedTime = Date.now() - startTime;
84
-
85
- logger.trace({
86
- msg: 'Polling for live_url',
87
- taskId,
88
- pollCount,
89
- elapsedTime,
90
- remainingTime: maxWaitTime - elapsedTime,
91
- });
92
-
93
- const taskDetails = await getTaskDetails(taskId);
94
-
95
- logger.trace({
96
- msg: 'Task details received',
97
- taskId,
98
- status: taskDetails.status,
99
- hasLiveUrl: !!taskDetails.live_url,
100
- pollCount,
101
- });
102
-
103
- if (taskDetails.live_url) {
104
- logger.debug({
105
- msg: 'Live URL available',
106
- taskId,
107
- liveUrl: taskDetails.live_url,
108
- pollCount,
109
- totalTime: elapsedTime,
110
- });
111
- return taskDetails;
112
- }
113
-
114
- if (taskDetails.status === 'failed' || taskDetails.status === 'stopped') {
115
- logger.error({
116
- msg: 'Task failed while waiting for live_url',
117
- taskId,
118
- status: taskDetails.status,
119
- pollCount,
120
- elapsedTime,
121
- });
122
- throw new Error(`Task failed with status: ${taskDetails.status}`);
123
- }
124
-
125
- logger.trace({
126
- msg: 'Live URL not yet available, continuing to poll',
127
- taskId,
128
- status: taskDetails.status,
129
- pollCount,
130
- nextPollIn: pollInterval,
131
- });
132
-
133
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
134
- }
135
-
136
- logger.error({
137
- msg: 'Timeout waiting for live_url',
138
- taskId,
139
- pollCount,
140
- totalTime: Date.now() - startTime,
141
- maxWaitTime,
142
- });
143
- throw new Error('Timeout waiting for live_url to become available');
144
- };
145
-
146
- export const waitForCompletion = async (taskId: string, maxWaitTime: number = 300000): Promise<CloudTaskResponse> => {
147
- const startTime = Date.now();
148
- const pollInterval = 3000; // 3 seconds for completion polling
149
- let pollCount = 0;
150
-
151
- logger.debug({ msg: 'Starting to poll for task completion', taskId, maxWaitTime, pollInterval });
152
-
153
- while (Date.now() - startTime < maxWaitTime) {
154
- pollCount++;
155
- const elapsedTime = Date.now() - startTime;
156
-
157
- logger.trace({
158
- msg: 'Polling for task completion',
159
- taskId,
160
- pollCount,
161
- elapsedTime,
162
- remainingTime: maxWaitTime - elapsedTime,
163
- });
164
-
165
- const taskDetails = await getTaskDetails(taskId);
166
-
167
- logger.trace({
168
- msg: 'Task completion status received',
169
- taskId,
170
- status: taskDetails.status,
171
- pollCount,
172
- hasOutput: !!taskDetails.output,
173
- stepCount: taskDetails.steps?.length || 0,
174
- });
175
-
176
- if (taskDetails.status === 'finished') {
177
- logger.debug({
178
- msg: 'Task completed successfully',
179
- taskId,
180
- pollCount,
181
- totalTime: elapsedTime,
182
- stepCount: taskDetails.steps?.length || 0,
183
- hasOutput: !!taskDetails.output,
184
- });
185
- return taskDetails;
186
- }
187
-
188
- if (taskDetails.status === 'failed' || taskDetails.status === 'stopped') {
189
- logger.error({
190
- msg: 'Task failed during completion polling',
191
- taskId,
192
- status: taskDetails.status,
193
- pollCount,
194
- elapsedTime,
195
- stepCount: taskDetails.steps?.length || 0,
196
- });
197
- throw new Error(`Task failed with status: ${taskDetails.status}`);
198
- }
199
-
200
- logger.trace({
201
- msg: 'Task still in progress, continuing to poll',
202
- taskId,
203
- status: taskDetails.status,
204
- pollCount,
205
- stepCount: taskDetails.steps?.length || 0,
206
- nextPollIn: pollInterval,
207
- });
208
-
209
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
210
- }
211
-
212
- logger.error({
213
- msg: 'Timeout waiting for task completion',
214
- taskId,
215
- pollCount,
216
- totalTime: Date.now() - startTime,
217
- maxWaitTime,
218
- });
219
- throw new Error('Timeout waiting for task completion');
220
- };
221
-
222
11
  // Socket-based browser task functions
223
- export const createBrowserSession = async (proxy?: string): Promise<CreateBrowserSessionResponse> => {
12
+ export const createBrowserSession = async (proxy?: string, onPrem?: boolean): Promise<CreateBrowserSessionResponse> => {
224
13
  logger.debug({ msg: 'Creating browser session via socket', proxy });
225
14
 
226
15
  try {
@@ -229,6 +18,7 @@ export const createBrowserSession = async (proxy?: string): Promise<CreateBrowse
229
18
  {
230
19
  type: mindedConnectionSocketMessageType.CREATE_BROWSER_SESSION,
231
20
  proxy,
21
+ onPrem: onPrem,
232
22
  },
233
23
  60000, // 60 seconds timeout
234
24
  );
@@ -257,6 +47,8 @@ export const invokeBrowserTask = async (
257
47
  task: string,
258
48
  keepAlive?: boolean,
259
49
  hooks?: { name: string }[],
50
+ onPrem?: boolean,
51
+ toolSchemas?: any[],
260
52
  outputSchema?: {
261
53
  name: string;
262
54
  type: 'string' | 'number';
@@ -270,18 +62,22 @@ export const invokeBrowserTask = async (
270
62
  taskLength: task.length,
271
63
  keepAlive,
272
64
  hooksCount: hooks?.length || 0,
65
+ onPrem,
273
66
  outputSchemaFields: outputSchema?.length || 0,
274
67
  });
275
68
 
276
69
  try {
277
- const response = await mindedConnection.awaitEmit<any, InvokeBrowserTaskResponse>(
70
+ const response = await mindedConnection.awaitEmit<InvokeBrowserTaskRequest, InvokeBrowserTaskResponse>(
278
71
  mindedConnectionSocketMessageType.INVOKE_BROWSER_TASK,
279
72
  {
280
- sessionId,
73
+ type: mindedConnectionSocketMessageType.INVOKE_BROWSER_TASK,
281
74
  cdpUrl,
282
75
  task,
76
+ sessionId,
283
77
  keepAlive,
284
78
  hooks,
79
+ onPrem,
80
+ toolSchemas,
285
81
  outputSchema,
286
82
  },
287
83
  900000, // 15 minutes timeout
@@ -0,0 +1 @@
1
+ export { LLMDebugCallbackHandler } from './llmCallbackHandler';
@@ -0,0 +1,126 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ /* eslint-disable no-debugger */
3
+
4
+ import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
5
+ import { Serialized } from '@langchain/core/load/serializable';
6
+ import { LLMResult } from '@langchain/core/outputs';
7
+ import { BaseMessage } from '@langchain/core/messages';
8
+
9
+ /**
10
+ * A callback handler for debugging LLM interactions in MindedJS agents.
11
+ * This handler allows you to inspect messages before they are sent to the LLM
12
+ * and see the responses received.
13
+ *
14
+ * This class extends BaseCallbackHandler from LangChain and provides several
15
+ * callback methods. You can override additional methods for more comprehensive debugging:
16
+ *
17
+ * Available LangChain Callback Methods:
18
+ * - handleChatModelStart - For chat model requests (receives BaseMessage arrays)
19
+ * - handleLLMStart - For standard LLM requests (receives string prompts)
20
+ * - handleLLMNewToken - For streaming tokens as they're generated
21
+ * - handleLLMEnd - When LLM finishes generating
22
+ * - handleLLMError - When LLM encounters an error
23
+ * - handleChainStart - When a LangChain chain starts execution
24
+ * - handleChainEnd - When a chain completes execution
25
+ * - handleChainError - When a chain encounters an error
26
+ * - handleToolStart - When a tool/function starts execution
27
+ * - handleToolEnd - When a tool completes execution
28
+ * - handleToolError - When a tool encounters an error
29
+ * - handleAgentAction - When an agent takes an action
30
+ * - handleAgentFinish - When an agent completes its task
31
+ *
32
+ * For more details on all available callbacks and their signatures, see the LangChain documentation:
33
+ * https://js.langchain.com/docs/modules/callbacks/
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * import { Agent, LLMDebugCallbackHandler } from '@minded-ai/mindedjs';
38
+ *
39
+ * const debugHandler = new LLMDebugCallbackHandler();
40
+ *
41
+ * const agent = new Agent({
42
+ * config: {
43
+ * ...config,
44
+ * llm: {
45
+ * ...config.llm,
46
+ * properties: {
47
+ * ...config.llm.properties,
48
+ * callbacks: [debugHandler],
49
+ * },
50
+ * },
51
+ * },
52
+ * // ... other agent configuration
53
+ * });
54
+ * ```
55
+ */
56
+ export class LLMDebugCallbackHandler extends BaseCallbackHandler {
57
+ name = 'LLMDebugCallbackHandler';
58
+
59
+ constructor() {
60
+ super();
61
+ }
62
+
63
+ /**
64
+ * Called when a chat model (like GPT-4) starts processing.
65
+ * This is triggered before the messages are sent to the LLM.
66
+ * The messages parameter contains the full conversation history.
67
+ */
68
+ async handleChatModelStart(
69
+ llm: Serialized,
70
+ messages: BaseMessage[][],
71
+ runId: string,
72
+ parentRunId?: string,
73
+ extraParams?: Record<string, unknown>,
74
+ tags?: string[],
75
+ metadata?: Record<string, unknown>,
76
+ name?: string,
77
+ ): Promise<void> {
78
+ console.log('handleChatModelStart called with messages:', messages);
79
+ // Set a breakpoint here to inspect messages
80
+ debugger;
81
+ }
82
+
83
+ /**
84
+ * Called when any LLM starts processing (including non-chat models).
85
+ * For chat models, the messages are available in extraParams.messages.
86
+ * This is a more general callback that works with all LLM types.
87
+ */
88
+ async handleLLMStart(
89
+ llm: Serialized,
90
+ prompts: string[],
91
+ runId: string,
92
+ parentRunId?: string,
93
+ extraParams?: Record<string, unknown>,
94
+ tags?: string[],
95
+ metadata?: Record<string, unknown>,
96
+ name?: string,
97
+ ): Promise<void> {
98
+ console.log('handleLLMStart called with extraParams.messages:', extraParams?.messages);
99
+ // Set a breakpoint here to inspect messages
100
+ debugger;
101
+ }
102
+
103
+ /**
104
+ * Called when a chat model finishes processing and returns a response.
105
+ * The output contains the generated message and metadata.
106
+ */
107
+ async handleChatModelEnd(output: LLMResult, runId: string, parentRunId?: string): Promise<void> {
108
+ console.log('handleChatModelEnd called with output:', output);
109
+ }
110
+
111
+ /**
112
+ * Called when any LLM finishes processing and returns a response.
113
+ * This is called for all LLM types, including chat models.
114
+ */
115
+ async handleLLMEnd(output: LLMResult, runId: string, parentRunId?: string): Promise<void> {
116
+ console.log('handleLLMEnd called with output:', output);
117
+ }
118
+
119
+ /**
120
+ * Called when an error occurs during LLM processing.
121
+ * This captures any errors that happen during the LLM call.
122
+ */
123
+ async handleLLMError(err: Error, runId: string, parentRunId?: string): Promise<void> {
124
+ console.log('handleLLMError called with error:', err);
125
+ }
126
+ }
@@ -54,7 +54,7 @@ export const addBrowserTaskNode = async ({ graph, node, agent, llm }: AddBrowser
54
54
  const zodSchema = z.object(schemaFields);
55
55
 
56
56
  // Create langchain tool
57
- const tool = langchainTool(() => { }, {
57
+ const tool = langchainTool(() => {}, {
58
58
  name: 'browser-task',
59
59
  description: node.prompt,
60
60
  schema: zodSchema,
@@ -98,7 +98,7 @@ ${compiledPrompt}
98
98
  ${Object.keys(inputParams).length > 0 ? `# Input parameters:\n${JSON.stringify(inputParams, null, 2)}\n\n` : ''}`;
99
99
 
100
100
  // Create browser session using socket
101
- const session = await createBrowserSession(node.proxy);
101
+ const session = await createBrowserSession(node.proxy, node.onPrem);
102
102
 
103
103
  if (!session.sessionId || !session.cdpUrl) {
104
104
  throw new Error('Failed to create browser session: missing session details');
@@ -137,6 +137,7 @@ ${Object.keys(inputParams).length > 0 ? `# Input parameters:\n${JSON.stringify(i
137
137
  liveUrl: session.liveViewUrl,
138
138
  keepAlive,
139
139
  hooks: node.hooks || [],
140
+ onPrem: node.onPrem,
140
141
  outputSchema: node.outputSchema,
141
142
  },
142
143
  },
@@ -8,6 +8,7 @@ import { createHistoryStep } from '../utils/history';
8
8
  import { HistoryStep } from '../types/Agent.types';
9
9
  import { v4 as uuidv4 } from 'uuid';
10
10
  import { invokeBrowserTask } from '../browserTask/executeBrowserTask';
11
+ import { zodSchemaToParams } from '../platform/utils/tools';
11
12
 
12
13
  type AddBrowserTaskRunNodeParams = {
13
14
  graph: PreCompiledGraph;
@@ -18,7 +19,7 @@ type AddBrowserTaskRunNodeParams = {
18
19
 
19
20
  export const buildBrowserTaskRunNodeName = (nodeName: string) => `${nodeName}${internalNodesSuffix.BROWSER_TASK_RUN}`;
20
21
 
21
- export const addBrowserTaskRunNode = async ({ graph, browserTaskNode, attachedToNodeName }: AddBrowserTaskRunNodeParams) => {
22
+ export const addBrowserTaskRunNode = async ({ graph, browserTaskNode, attachedToNodeName, agent }: AddBrowserTaskRunNodeParams) => {
22
23
  const callback: RunnableLike = async (state: typeof stateAnnotation.State) => {
23
24
  logger.info(`Executing browser task run node for ${browserTaskNode.displayName}`);
24
25
 
@@ -30,13 +31,31 @@ export const addBrowserTaskRunNode = async ({ graph, browserTaskNode, attachedTo
30
31
  const toolCall = toolCallObj.tool_calls[0];
31
32
  const { prompt, ...inputParams } = toolCall.args;
32
33
  const { sessionId, cdpUrl, keepAlive, hooks, outputSchema } = toolCallMindedMetadata;
34
+
33
35
  try {
34
36
  if (!sessionId || !cdpUrl || !prompt) {
35
37
  throw new Error('Missing required parameters: sessionId, cdpUrl, or prompt');
36
38
  }
37
39
 
40
+ const toolSchemas = agent.tools
41
+ .filter((tool) => tool.allowExecutionRequests === true)
42
+ .map((tool) => ({
43
+ name: tool.name,
44
+ description: tool.description,
45
+ inputParams: zodSchemaToParams(tool.input),
46
+ }));
47
+
38
48
  // Invoke browser task via socket
39
- const result = await invokeBrowserTask(sessionId, cdpUrl, prompt, keepAlive, hooks, outputSchema);
49
+ const result = await invokeBrowserTask(
50
+ sessionId,
51
+ cdpUrl,
52
+ prompt,
53
+ keepAlive,
54
+ hooks,
55
+ browserTaskNode.onPrem,
56
+ toolSchemas,
57
+ outputSchema,
58
+ );
40
59
 
41
60
  logger.debug({
42
61
  msg: 'Browser task completed',
@@ -51,6 +51,8 @@ export enum mindedConnectionSocketMessageType {
51
51
  INTERRUPT_SESSION_DEQUEUE = 'interrupt-session-dequeue',
52
52
  INTERRUPT_SESSION_HAS_MESSAGES = 'interrupt-session-has-messages',
53
53
  INTERRUPT_SESSION_GET_MESSAGES = 'interrupt-session-get-messages',
54
+ // Tool execution
55
+ EXECUTE_TOOL = 'execute-tool',
54
56
  }
55
57
 
56
58
  export type mindedConnectionSocketMessageTypeMap = {
@@ -91,6 +93,7 @@ export type mindedConnectionSocketMessageTypeMap = {
91
93
  [mindedConnectionSocketMessageType.INTERRUPT_SESSION_DEQUEUE]: InterruptSessionDequeueRequest;
92
94
  [mindedConnectionSocketMessageType.INTERRUPT_SESSION_HAS_MESSAGES]: InterruptSessionHasMessagesRequest;
93
95
  [mindedConnectionSocketMessageType.INTERRUPT_SESSION_GET_MESSAGES]: InterruptSessionGetMessagesRequest;
96
+ [mindedConnectionSocketMessageType.EXECUTE_TOOL]: ExecuteToolRequest;
94
97
  };
95
98
 
96
99
  export interface BasemindedConnectionSocketMessage {
@@ -441,6 +444,7 @@ export interface UpdateStateRequest extends BasemindedConnectionSocketMessage {
441
444
  export interface CreateBrowserSessionRequest extends BasemindedConnectionSocketMessage {
442
445
  type: mindedConnectionSocketMessageType.CREATE_BROWSER_SESSION;
443
446
  proxy?: string; // 2-digit country code like 'IL'
447
+ onPrem?: boolean;
444
448
  }
445
449
 
446
450
  export interface CreateBrowserSessionResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
@@ -455,7 +459,19 @@ export interface InvokeBrowserTaskRequest extends BasemindedConnectionSocketMess
455
459
  task: string;
456
460
  sessionId: string;
457
461
  keepAlive?: boolean;
458
- hooks?: { name: string }[]; // Array of hooks to be passed to the browser-use lambda
462
+ hooks?: {
463
+ name: string;
464
+ lifecycle_phases?: string[];
465
+ config?: Record<string, any>;
466
+ }[]; // Array of hooks to be passed to the browser-use lambda
467
+ onPrem?: boolean;
468
+ toolSchemas?: any[];
469
+ outputSchema?: {
470
+ name: string;
471
+ type: 'string' | 'number';
472
+ description?: string;
473
+ required?: boolean;
474
+ }[];
459
475
  }
460
476
 
461
477
  export interface InvokeBrowserTaskResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
@@ -463,3 +479,19 @@ export interface InvokeBrowserTaskResponse extends BaseSdkConnectionSocketMessag
463
479
  steps?: any[];
464
480
  recordings?: any[];
465
481
  }
482
+
483
+ export interface ExecuteToolRequest extends BasemindedConnectionSocketMessage {
484
+ type: mindedConnectionSocketMessageType.EXECUTE_TOOL;
485
+ toolName: string;
486
+ toolParams: any;
487
+ sessionId: string;
488
+ requestId: string;
489
+ error?: string;
490
+ cdpUrl?: string; // Optional CDP URL for browser context
491
+ }
492
+
493
+ export interface ExecuteToolResponse extends BaseSdkConnectionSocketMessageResponseCallbackAck {
494
+ requestId: string;
495
+ result?: any;
496
+ state?: any;
497
+ }
@@ -0,0 +1,118 @@
1
+ import { Tool } from '../types/Tools.types';
2
+ import { Agent } from '../agent';
3
+ import { logger } from '../utils/logger';
4
+ import extractToolStateResponse from '../utils/extractStateMemoryResponse';
5
+ import { ToolMessage } from '@langchain/core/messages';
6
+
7
+ export interface ToolExecutionRequest {
8
+ toolName: string;
9
+ toolParams: any;
10
+ sessionId: string;
11
+ requestId: string;
12
+ cdpUrl?: string;
13
+ }
14
+
15
+ export interface ToolExecutionResponse {
16
+ result?: any;
17
+ state?: any;
18
+ error?: string;
19
+ }
20
+
21
+ export class ToolExecutor {
22
+ private tools: Map<string, Tool<any, any>> = new Map();
23
+
24
+ constructor(private agent: Agent) {}
25
+
26
+ /**
27
+ * Register tools for standalone execution
28
+ */
29
+ registerTools(tools: Tool<any, any>[]) {
30
+ tools.forEach((tool) => {
31
+ if (tool.allowExecutionRequests === true) {
32
+ this.tools.set(tool.name, tool);
33
+ }
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Execute a tool by name with given parameters
39
+ * This is called when browser-use requests tool execution via socket
40
+ */
41
+ async executeTool(request: ToolExecutionRequest): Promise<ToolExecutionResponse> {
42
+ const { toolName, toolParams, sessionId, cdpUrl } = request;
43
+
44
+ try {
45
+ // Find the tool
46
+ const tool = this.tools.get(toolName);
47
+ if (!tool) {
48
+ throw new Error(`Tool not found: ${toolName}`);
49
+ }
50
+
51
+ // We only allow to execute tools that are marked as allowed to be executed
52
+
53
+ logger.debug({
54
+ msg: '[ToolExecutor] Executing tool',
55
+ toolName,
56
+ sessionId,
57
+ hasCdpUrl: !!cdpUrl,
58
+ });
59
+
60
+ // Get the current state for the session
61
+ const state = await this.agent.getState(sessionId);
62
+ if (!state) {
63
+ throw new Error(`Session state not found: ${sessionId}`);
64
+ }
65
+
66
+ // Execute the tool
67
+ const startTime = Date.now();
68
+
69
+ if (cdpUrl) {
70
+ state.cdpUrl = cdpUrl;
71
+ }
72
+
73
+ const response = await tool.execute({
74
+ input: toolParams,
75
+ state,
76
+ agent: this.agent,
77
+ });
78
+ const endTime = Date.now();
79
+
80
+ logger.debug({
81
+ msg: '[ToolExecutor] Tool execution completed',
82
+ toolName,
83
+ executionTimeMs: endTime - startTime,
84
+ });
85
+
86
+ // Extract state updates from the response
87
+ let stateUpdate = {};
88
+ let result = response;
89
+
90
+ // If the response is a ToolMessage, extract state updates
91
+ if (response && typeof response === 'object' && 'content' in response) {
92
+ const toolMessage = response as ToolMessage;
93
+ stateUpdate = extractToolStateResponse(toolMessage);
94
+ // Extract the content as the result
95
+ result = { result: toolMessage.content };
96
+ }
97
+
98
+ // Update the session state if there are state changes
99
+ if (Object.keys(stateUpdate).length > 0) {
100
+ await this.agent.updateState({ sessionId, state: stateUpdate });
101
+ }
102
+
103
+ return {
104
+ result,
105
+ };
106
+ } catch (error) {
107
+ logger.error({
108
+ msg: '[ToolExecutor] Error executing tool',
109
+ toolName,
110
+ error: error instanceof Error ? error.message : String(error),
111
+ });
112
+
113
+ return {
114
+ error: error instanceof Error ? error.message : String(error),
115
+ };
116
+ }
117
+ }
118
+ }