@minded-ai/mindedjs 1.0.150 → 1.0.151-beta-1
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.
- package/dist/agent.js +2 -2
- package/dist/agent.js.map +1 -1
- package/dist/browserTask/README.md +419 -0
- package/dist/browserTask/browserAgent.py +632 -0
- package/dist/browserTask/captcha_isolated.png +0 -0
- package/dist/browserTask/executeBrowserTask.ts +79 -0
- package/dist/browserTask/requirements.txt +8 -0
- package/dist/browserTask/setup.sh +144 -0
- package/dist/internalTools/retell.d.ts +12 -0
- package/dist/internalTools/retell.d.ts.map +1 -0
- package/dist/internalTools/retell.js +54 -0
- package/dist/internalTools/retell.js.map +1 -0
- package/dist/internalTools/sendPlaceholderMessage.d.ts +14 -0
- package/dist/internalTools/sendPlaceholderMessage.d.ts.map +1 -0
- package/dist/internalTools/sendPlaceholderMessage.js +61 -0
- package/dist/internalTools/sendPlaceholderMessage.js.map +1 -0
- package/dist/nodes/addPromptNode.d.ts.map +1 -1
- package/dist/nodes/addPromptNode.js +262 -117
- package/dist/nodes/addPromptNode.js.map +1 -1
- package/package.json +1 -1
- package/src/agent.ts +2 -2
- package/src/nodes/addPromptNode.ts +300 -116
|
@@ -50,150 +50,334 @@ export const addPromptNode = async ({ graph, node, llm, tools, emit, agent }: Ad
|
|
|
50
50
|
const systemMessage = combinedPlaybooks + '\n\n' + currentPromptNode;
|
|
51
51
|
const compiledPrompt = compilePrompt(systemMessage, { memory: state.memory, system: { currentTime: new Date().toISOString() } });
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
53
|
+
// Check if we should use the agentic loop (only when humanInTheLoop is true)
|
|
54
|
+
const useAgenticLoop = node.humanInTheLoop === true;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* When humanInTheLoop is true: Run an agentic loop that continues invoking the LLM
|
|
58
|
+
* after tool calls until we get a final AI message without tool calls.
|
|
59
|
+
*
|
|
60
|
+
* When humanInTheLoop is false: Return immediately after tool execution without
|
|
61
|
+
* additional LLM invocations.
|
|
62
|
+
*/
|
|
63
|
+
let allMessages: any[] = [];
|
|
64
|
+
let allHistory: any[] = [];
|
|
65
|
+
let accumulatedStateUpdates = {};
|
|
66
|
+
let currentMessages = [...state.messages];
|
|
67
|
+
let finalAIMessage: AIMessage | null = null;
|
|
68
|
+
let loopCount = 0;
|
|
69
|
+
const MAX_LOOP_ITERATIONS = 10;
|
|
70
|
+
|
|
71
|
+
while (true) {
|
|
72
|
+
loopCount++;
|
|
73
|
+
|
|
74
|
+
// Break if we've reached the maximum number of iterations
|
|
75
|
+
if (loopCount > MAX_LOOP_ITERATIONS) {
|
|
76
|
+
logger.warn({
|
|
77
|
+
msg: '[Model] Reached maximum loop iterations, breaking agentic loop',
|
|
78
|
+
loopCount,
|
|
74
79
|
sessionId: state.sessionId,
|
|
75
80
|
node: node.displayName,
|
|
76
81
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
|
|
86
|
+
const result: AIMessage = await llmToUse.bindTools(scopedTools).invoke([new SystemMessage(compiledPrompt), ...currentMessages]);
|
|
87
|
+
|
|
88
|
+
// Always pass accumulated state to interrupt manager
|
|
89
|
+
// Pass the accumulated messages from this prompt node execution
|
|
90
|
+
// If empty, pass undefined to avoid empty state updates
|
|
91
|
+
const interruptState =
|
|
92
|
+
allMessages.length > 0 || allHistory.length > 0
|
|
93
|
+
? {
|
|
94
|
+
messages: allMessages,
|
|
95
|
+
history: allHistory,
|
|
96
|
+
}
|
|
97
|
+
: undefined;
|
|
98
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId, interruptState);
|
|
99
|
+
|
|
100
|
+
const endTime = Date.now();
|
|
101
|
+
|
|
102
|
+
logger.debug({
|
|
103
|
+
msg: '[Model] Model execution time',
|
|
104
|
+
executionTimeMs: endTime - startTime,
|
|
105
|
+
sessionId: state.sessionId,
|
|
106
|
+
node: node.displayName,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Check if the result contains tool calls
|
|
110
|
+
if (result.tool_calls && result.tool_calls.length > 0) {
|
|
111
|
+
// Add the tool call message
|
|
112
|
+
allMessages.push(result);
|
|
113
|
+
allHistory.push(
|
|
114
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
115
|
+
type: NodeType.TOOL,
|
|
116
|
+
nodeId: node.name,
|
|
117
|
+
nodeDisplayName: node.displayName,
|
|
118
|
+
raw: result,
|
|
119
|
+
messageIds: [result.id!],
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
// Execute the tools
|
|
124
|
+
// Track how many tool responses we've added for validation
|
|
125
|
+
const toolResponseStartIndex = allMessages.length;
|
|
126
|
+
|
|
127
|
+
// Ensure we process ALL tool calls, even if some fail
|
|
128
|
+
for (const toolCall of result.tool_calls) {
|
|
129
|
+
const matchedTool = scopedTools.find((t) => t.name === toolCall.name);
|
|
130
|
+
logger.info({
|
|
131
|
+
msg: `[Model] Calling tool inside prompt node`,
|
|
132
|
+
tool: matchedTool?.name || toolCall.name,
|
|
133
|
+
toolCallId: toolCall.id,
|
|
134
|
+
sessionId: state.sessionId,
|
|
135
|
+
node: node.displayName,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (matchedTool) {
|
|
139
|
+
try {
|
|
140
|
+
// Invoke the LangChain tool directly
|
|
141
|
+
const toolStartTime = Date.now();
|
|
142
|
+
const toolResult = await matchedTool.invoke(toolCall);
|
|
143
|
+
const toolEndTime = Date.now();
|
|
144
|
+
|
|
145
|
+
logger.debug({
|
|
146
|
+
msg: `[Tool] Tool result inside prompt node`,
|
|
147
|
+
tool: matchedTool?.name,
|
|
148
|
+
result: toolResult,
|
|
149
|
+
executionTimeMs: toolEndTime - toolStartTime,
|
|
150
|
+
sessionId: state.sessionId,
|
|
151
|
+
node: node.displayName,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Add the tool result directly to allMessages
|
|
155
|
+
allMessages.push(toolResult);
|
|
156
|
+
|
|
157
|
+
// Check for queue after tool call
|
|
158
|
+
const systemMessageId = uuidv4();
|
|
159
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId, {
|
|
160
|
+
messages: [
|
|
161
|
+
...allMessages,
|
|
162
|
+
new SystemMessage({
|
|
163
|
+
id: systemMessageId,
|
|
164
|
+
content:
|
|
165
|
+
'you called tool when the user send a new message, Consider calling the function again after user message is processed',
|
|
166
|
+
}),
|
|
167
|
+
],
|
|
168
|
+
history: [
|
|
169
|
+
...allHistory,
|
|
170
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
171
|
+
type: NodeType.TOOL,
|
|
172
|
+
nodeId: node.name,
|
|
173
|
+
nodeDisplayName: node.displayName,
|
|
174
|
+
raw: toolResult,
|
|
175
|
+
messageIds: [toolResult.id!, systemMessageId],
|
|
176
|
+
}),
|
|
177
|
+
],
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const toolStateUpdate = extractToolStateResponse(toolResult);
|
|
181
|
+
// Properly merge memory and other state updates
|
|
182
|
+
accumulatedStateUpdates = {
|
|
183
|
+
...accumulatedStateUpdates,
|
|
184
|
+
...toolStateUpdate,
|
|
185
|
+
memory: { ...(accumulatedStateUpdates as any).memory, ...(toolStateUpdate as any).memory },
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
allHistory.push(
|
|
105
189
|
createHistoryStep<HistoryStep>(state.history, {
|
|
106
190
|
type: NodeType.TOOL,
|
|
107
191
|
nodeId: node.name,
|
|
108
192
|
nodeDisplayName: node.displayName,
|
|
109
193
|
raw: toolResult,
|
|
110
|
-
messageIds: [toolResult.id
|
|
194
|
+
messageIds: [toolResult.id!],
|
|
111
195
|
}),
|
|
112
|
-
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
196
|
+
);
|
|
197
|
+
} catch (err: any) {
|
|
198
|
+
if (err?.name === 'GraphInterrupt') throw err;
|
|
199
|
+
logger.error({
|
|
200
|
+
msg: `[Tool] Error executing tool inside prompt node`,
|
|
201
|
+
tool: toolCall.name,
|
|
202
|
+
err,
|
|
203
|
+
sessionId: state.sessionId,
|
|
204
|
+
node: node.displayName,
|
|
205
|
+
});
|
|
206
|
+
const errorMessage = new ToolMessage({
|
|
207
|
+
content: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }),
|
|
208
|
+
tool_call_id: toolCall.id!,
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Add the error message directly to allMessages
|
|
212
|
+
allMessages.push(errorMessage);
|
|
213
|
+
|
|
214
|
+
// Check for queue after tool error
|
|
215
|
+
const errorSystemMessageId = uuidv4();
|
|
216
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId, {
|
|
217
|
+
messages: [
|
|
218
|
+
...allMessages,
|
|
219
|
+
new SystemMessage({
|
|
220
|
+
id: errorSystemMessageId,
|
|
221
|
+
content: 'Tool execution failed. Consider handling the error or calling another function if needed.',
|
|
222
|
+
}),
|
|
223
|
+
],
|
|
224
|
+
history: [
|
|
225
|
+
...allHistory,
|
|
226
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
227
|
+
type: NodeType.TOOL,
|
|
228
|
+
nodeId: node.name,
|
|
229
|
+
nodeDisplayName: node.displayName,
|
|
230
|
+
raw: errorMessage,
|
|
231
|
+
messageIds: [errorMessage.id!, errorSystemMessageId],
|
|
232
|
+
}),
|
|
233
|
+
],
|
|
234
|
+
});
|
|
235
|
+
allHistory.push(
|
|
236
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
237
|
+
type: NodeType.TOOL,
|
|
238
|
+
nodeId: node.name,
|
|
239
|
+
nodeDisplayName: node.displayName,
|
|
240
|
+
raw: errorMessage,
|
|
241
|
+
messageIds: [errorMessage.id!],
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
124
246
|
logger.error({
|
|
125
|
-
msg: `[Tool]
|
|
247
|
+
msg: `[Tool] Model called tool but it was not found inside prompt node`,
|
|
126
248
|
tool: toolCall.name,
|
|
127
|
-
|
|
249
|
+
toolCallId: toolCall.id,
|
|
128
250
|
sessionId: state.sessionId,
|
|
129
251
|
node: node.displayName,
|
|
130
252
|
});
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
253
|
+
|
|
254
|
+
// IMPORTANT: Create an error message for the missing tool with the correct tool_call_id
|
|
255
|
+
const missingToolMessage = new ToolMessage({
|
|
256
|
+
content: JSON.stringify({ error: `Tool '${toolCall.name}' not found` }),
|
|
257
|
+
tool_call_id: toolCall.id!, // This MUST match the tool_call_id from the AI message
|
|
258
|
+
name: toolCall.name,
|
|
134
259
|
});
|
|
135
|
-
|
|
260
|
+
|
|
261
|
+
allMessages.push(missingToolMessage);
|
|
262
|
+
allHistory.push(
|
|
263
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
264
|
+
type: NodeType.TOOL,
|
|
265
|
+
nodeId: node.name,
|
|
266
|
+
nodeDisplayName: node.displayName,
|
|
267
|
+
raw: missingToolMessage,
|
|
268
|
+
messageIds: [missingToolMessage.id!],
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
136
271
|
}
|
|
137
|
-
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Validate that we have responses for ALL tool calls
|
|
275
|
+
const toolResponseCount = allMessages.length - toolResponseStartIndex;
|
|
276
|
+
if (toolResponseCount !== result.tool_calls.length) {
|
|
138
277
|
logger.error({
|
|
139
|
-
msg:
|
|
140
|
-
|
|
278
|
+
msg: '[Model] Tool response count mismatch',
|
|
279
|
+
expectedCount: result.tool_calls.length,
|
|
280
|
+
actualCount: toolResponseCount,
|
|
281
|
+
toolCallIds: result.tool_calls.map((tc) => tc.id),
|
|
141
282
|
sessionId: state.sessionId,
|
|
142
283
|
node: node.displayName,
|
|
143
284
|
});
|
|
144
285
|
}
|
|
286
|
+
|
|
287
|
+
// If humanInTheLoop is false, return immediately after tool execution
|
|
288
|
+
if (!useAgenticLoop) {
|
|
289
|
+
return {
|
|
290
|
+
...accumulatedStateUpdates,
|
|
291
|
+
messages: allMessages,
|
|
292
|
+
history: allHistory,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Otherwise, prepare for next iteration
|
|
297
|
+
// allMessages now contains all the new messages from this iteration
|
|
298
|
+
currentMessages = [...state.messages, ...allMessages];
|
|
299
|
+
|
|
300
|
+
// Continue the loop to see what the model wants to do next
|
|
301
|
+
continue;
|
|
302
|
+
} else {
|
|
303
|
+
// We got an AI message without tool calls - this is our final response
|
|
304
|
+
finalAIMessage = result;
|
|
305
|
+
break;
|
|
145
306
|
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Process the final AI message if we have one
|
|
310
|
+
if (finalAIMessage) {
|
|
311
|
+
// Update state so AI_MESSAGE will get the latest state
|
|
312
|
+
const stateForAIMessage = structuredClone(state);
|
|
313
|
+
stateForAIMessage.goto = null;
|
|
314
|
+
stateForAIMessage.messages.push(...allMessages, finalAIMessage);
|
|
315
|
+
|
|
316
|
+
let aiMessageStateUpdate: any = { goto: null };
|
|
317
|
+
let messagesToReturn = [...allMessages, finalAIMessage];
|
|
318
|
+
|
|
319
|
+
if (finalAIMessage.getType() === 'ai') {
|
|
320
|
+
logger.info({
|
|
321
|
+
msg: `[Model] Response`,
|
|
322
|
+
content: finalAIMessage.content,
|
|
323
|
+
sessionId: state.sessionId,
|
|
324
|
+
node: node.displayName,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const results = await emit(AgentEvents.AI_MESSAGE, {
|
|
328
|
+
message: finalAIMessage.content as string,
|
|
329
|
+
state: stateForAIMessage,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const handlerResult = results.find((r) => r !== undefined);
|
|
333
|
+
if (handlerResult && handlerResult.state) {
|
|
334
|
+
aiMessageStateUpdate = { ...aiMessageStateUpdate, ...handlerResult.state };
|
|
146
335
|
|
|
147
|
-
|
|
336
|
+
// If the handler returned modified messages, use those instead
|
|
337
|
+
if (handlerResult.state.messages) {
|
|
338
|
+
messagesToReturn = [...allMessages, ...handlerResult.state.messages];
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
allHistory.push(
|
|
344
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
345
|
+
type: NodeType.PROMPT_NODE,
|
|
346
|
+
nodeId: node.name,
|
|
347
|
+
nodeDisplayName: node.displayName,
|
|
348
|
+
raw: finalAIMessage.content,
|
|
349
|
+
messageIds: [finalAIMessage.id!],
|
|
350
|
+
}),
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
// Return all accumulated state updates and messages
|
|
148
354
|
return {
|
|
149
|
-
...
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
type: NodeType.TOOL,
|
|
154
|
-
nodeId: node.name,
|
|
155
|
-
nodeDisplayName: node.displayName,
|
|
156
|
-
raw: result,
|
|
157
|
-
messageIds: [result.id!],
|
|
158
|
-
}),
|
|
159
|
-
...toolResults.map((toolResult) =>
|
|
160
|
-
createHistoryStep<HistoryStep>(state.history, {
|
|
161
|
-
type: NodeType.TOOL,
|
|
162
|
-
nodeId: node.name,
|
|
163
|
-
nodeDisplayName: node.displayName,
|
|
164
|
-
raw: toolResult,
|
|
165
|
-
messageIds: [toolResult.id!],
|
|
166
|
-
}),
|
|
167
|
-
),
|
|
168
|
-
],
|
|
355
|
+
...accumulatedStateUpdates,
|
|
356
|
+
...aiMessageStateUpdate,
|
|
357
|
+
messages: messagesToReturn,
|
|
358
|
+
history: allHistory,
|
|
169
359
|
};
|
|
170
360
|
}
|
|
171
361
|
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
362
|
+
// If we hit the loop limit without a final AI message, return what we have
|
|
363
|
+
if (loopCount > MAX_LOOP_ITERATIONS && allMessages.length > 0) {
|
|
364
|
+
logger.warn({
|
|
365
|
+
msg: '[Model] Returning accumulated messages after hitting loop limit',
|
|
366
|
+
messageCount: allMessages.length,
|
|
367
|
+
sessionId: state.sessionId,
|
|
368
|
+
node: node.displayName,
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
return {
|
|
372
|
+
...accumulatedStateUpdates,
|
|
373
|
+
goto: null,
|
|
374
|
+
messages: allMessages,
|
|
375
|
+
history: allHistory,
|
|
376
|
+
};
|
|
186
377
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
type: NodeType.PROMPT_NODE,
|
|
191
|
-
nodeId: node.name,
|
|
192
|
-
nodeDisplayName: node.displayName,
|
|
193
|
-
raw: result.content,
|
|
194
|
-
messageIds: [result.id!],
|
|
195
|
-
}),
|
|
196
|
-
};
|
|
378
|
+
|
|
379
|
+
// This should only be reached in unexpected cases
|
|
380
|
+
throw new Error('Unexpected state: no messages generated in prompt node');
|
|
197
381
|
};
|
|
198
382
|
graph.addNode(node.name, callback);
|
|
199
383
|
};
|