@minded-ai/mindedjs 3.1.43 → 3.1.44
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/cli/cliUtils.d.ts +4 -2
- package/dist/cli/cliUtils.d.ts.map +1 -1
- package/dist/cli/cliUtils.js +12 -5
- package/dist/cli/cliUtils.js.map +1 -1
- package/dist/nodes/addAppToolNode.d.ts.map +1 -1
- package/dist/nodes/addAppToolNode.js +59 -13
- package/dist/nodes/addAppToolNode.js.map +1 -1
- package/dist/nodes/addBrowserTaskNode.d.ts.map +1 -1
- package/dist/nodes/addBrowserTaskNode.js +13 -3
- package/dist/nodes/addBrowserTaskNode.js.map +1 -1
- package/dist/nodes/addToolNode.d.ts.map +1 -1
- package/dist/nodes/addToolNode.js +22 -40
- package/dist/nodes/addToolNode.js.map +1 -1
- package/dist/nodes/addToolRunNode.d.ts.map +1 -1
- package/dist/nodes/addToolRunNode.js +93 -82
- package/dist/nodes/addToolRunNode.js.map +1 -1
- package/dist/nodes/utils/getSchemaForToolInference.d.ts +13 -0
- package/dist/nodes/utils/getSchemaForToolInference.d.ts.map +1 -0
- package/dist/nodes/utils/getSchemaForToolInference.js +34 -0
- package/dist/nodes/utils/getSchemaForToolInference.js.map +1 -0
- package/dist/nodes/utils/inferToolCallWithRetry.d.ts +18 -0
- package/dist/nodes/utils/inferToolCallWithRetry.d.ts.map +1 -0
- package/dist/nodes/utils/inferToolCallWithRetry.js +58 -0
- package/dist/nodes/utils/inferToolCallWithRetry.js.map +1 -0
- package/dist/types/Flows.types.d.ts +1 -0
- package/dist/types/Flows.types.d.ts.map +1 -1
- package/dist/types/Flows.types.js +1 -0
- package/dist/types/Flows.types.js.map +1 -1
- package/dist/utils/flowSchema.d.ts.map +1 -1
- package/dist/utils/flowSchema.js +20 -4
- package/dist/utils/flowSchema.js.map +1 -1
- package/dist/utils/schemaUtils.d.ts.map +1 -1
- package/dist/utils/schemaUtils.js +2 -0
- package/dist/utils/schemaUtils.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/cliUtils.ts +12 -5
- package/src/nodes/addAppToolNode.ts +61 -15
- package/src/nodes/addBrowserTaskNode.ts +13 -3
- package/src/nodes/addToolNode.ts +24 -46
- package/src/nodes/addToolRunNode.ts +114 -97
- package/src/nodes/utils/getSchemaForToolInference.ts +48 -0
- package/src/nodes/utils/inferToolCallWithRetry.ts +89 -0
- package/src/types/Flows.types.ts +1 -0
- package/src/utils/flowSchema.ts +21 -4
- package/src/utils/schemaUtils.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemaUtils.js","sourceRoot":"","sources":["../../src/utils/schemaUtils.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"schemaUtils.js","sourceRoot":"","sources":["../../src/utils/schemaUtils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli/cliUtils.ts
CHANGED
|
@@ -4,12 +4,19 @@ import * as path from 'path';
|
|
|
4
4
|
import { Agent } from '../agent';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Registers TypeScript loader (tsx or ts-node) to enable requiring .ts files
|
|
7
|
+
* Registers TypeScript loader (tsx or ts-node) to enable requiring .ts files.
|
|
8
|
+
* Resolves loaders from the agent's project directory so that devDependencies
|
|
9
|
+
* installed there (not in mindedjs itself) are found correctly.
|
|
8
10
|
*/
|
|
9
|
-
export function registerTypeScriptLoader(): void {
|
|
10
|
-
// Try tsx first (faster), then fall back to ts-node
|
|
11
|
+
export function registerTypeScriptLoader(projectDir: string): void {
|
|
11
12
|
const loaders = [
|
|
12
|
-
{
|
|
13
|
+
{
|
|
14
|
+
name: 'tsx',
|
|
15
|
+
register: () => {
|
|
16
|
+
const tsxPath = require.resolve('tsx/cjs', { paths: [projectDir] });
|
|
17
|
+
require(tsxPath);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
13
20
|
];
|
|
14
21
|
|
|
15
22
|
for (const loader of loaders) {
|
|
@@ -44,7 +51,7 @@ export function loadAgentFromConfig(projectDir: string, agentFilePath: string):
|
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
// Register TypeScript loader before requiring .ts files
|
|
47
|
-
registerTypeScriptLoader();
|
|
54
|
+
registerTypeScriptLoader(projectDir);
|
|
48
55
|
|
|
49
56
|
// Clear require cache to ensure fresh load
|
|
50
57
|
const resolvedPath = require.resolve(modulePath);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AppToolNode, AppToolNodeMindedMetadata, NodeType } from '../types/Flows.types';
|
|
2
2
|
import { tool as langchainTool } from '@langchain/core/tools';
|
|
3
3
|
import { PreCompiledGraph, stateAnnotation } from '../types/LangGraph.types';
|
|
4
|
-
import { SystemMessage } from '@langchain/core/messages';
|
|
4
|
+
import { AIMessage, SystemMessage } from '@langchain/core/messages';
|
|
5
5
|
import { RunnableLike } from '@langchain/core/runnables';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { LLMProviders } from '../types/LLM.types';
|
|
@@ -15,6 +15,8 @@ import { compileParameter, compilePrompt } from './compilePrompt';
|
|
|
15
15
|
import { ToolMessage } from '@langchain/core/messages';
|
|
16
16
|
import { AnalyticsEventName } from '../types/Analytics.types';
|
|
17
17
|
import { trackAnalyticsEvent } from '../internalTools/analytics';
|
|
18
|
+
import { inferToolCallWithRetry } from './utils/inferToolCallWithRetry';
|
|
19
|
+
import { getSchemaForToolInference } from './utils/getSchemaForToolInference';
|
|
18
20
|
|
|
19
21
|
export const addAppToolNode = async ({
|
|
20
22
|
graph,
|
|
@@ -82,6 +84,12 @@ export const addAppToolNode = async ({
|
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
}
|
|
87
|
+
const overriddenKeys = Object.keys(compiledParameters);
|
|
88
|
+
const { schemaForLLM, skipLLMCall } = getSchemaForToolInference({
|
|
89
|
+
inputSchema: appRunnerTool.input,
|
|
90
|
+
overriddenKeys,
|
|
91
|
+
toolName: appRunnerTool.name,
|
|
92
|
+
});
|
|
85
93
|
|
|
86
94
|
const executeWrapper = async (input: z.infer<typeof appRunnerTool.input>) => {
|
|
87
95
|
try {
|
|
@@ -92,10 +100,15 @@ export const addAppToolNode = async ({
|
|
|
92
100
|
throw err;
|
|
93
101
|
}
|
|
94
102
|
};
|
|
95
|
-
const
|
|
103
|
+
const inferenceTool = langchainTool(() => ({}), {
|
|
104
|
+
name: appRunnerTool.name,
|
|
105
|
+
description: appRunnerTool.description,
|
|
106
|
+
schema: schemaForLLM as any,
|
|
107
|
+
});
|
|
108
|
+
const executionTool = langchainTool(executeWrapper, {
|
|
96
109
|
name: appRunnerTool.name,
|
|
97
110
|
description: appRunnerTool.description,
|
|
98
|
-
schema: appRunnerTool.input,
|
|
111
|
+
schema: appRunnerTool.input as any,
|
|
99
112
|
});
|
|
100
113
|
|
|
101
114
|
const combinedPlaybooks = combinePlaybooks(agent.playbooks) || '';
|
|
@@ -143,19 +156,52 @@ export const addAppToolNode = async ({
|
|
|
143
156
|
${compiledNodePrompt ? compiledNodePrompt : 'no instructions set by the user'}`;
|
|
144
157
|
|
|
145
158
|
// const compiledPrompt = compilePrompt(message, { state: state, memory: state.memory, env: process.env });
|
|
146
|
-
|
|
147
|
-
if (
|
|
148
|
-
|
|
159
|
+
let AIToolCallMessage: AIMessage;
|
|
160
|
+
if (skipLLMCall) {
|
|
161
|
+
AIToolCallMessage = new AIMessage({
|
|
162
|
+
content: '',
|
|
163
|
+
tool_calls: [
|
|
164
|
+
{
|
|
165
|
+
name: appRunnerTool.name,
|
|
166
|
+
args: compiledParameters,
|
|
167
|
+
id: `call_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
|
|
168
|
+
type: 'tool_call',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
});
|
|
149
172
|
} else {
|
|
150
|
-
|
|
173
|
+
const systemMessage = new SystemMessage(message);
|
|
174
|
+
if (state.messages.length === 0 || state.messages[0].getType() === 'system') {
|
|
175
|
+
state.messages[0] = systemMessage;
|
|
176
|
+
} else {
|
|
177
|
+
state.messages.unshift(systemMessage);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
AIToolCallMessage = await inferToolCallWithRetry({
|
|
181
|
+
llm,
|
|
182
|
+
tool: inferenceTool,
|
|
183
|
+
inputSchema: appRunnerTool.input,
|
|
184
|
+
messages: state.messages,
|
|
185
|
+
sessionId: state.sessionId,
|
|
186
|
+
mergeArgs: (args) => ({
|
|
187
|
+
...args,
|
|
188
|
+
...compiledParameters, // user-set parameters have priority over AI-generated parameters
|
|
189
|
+
}),
|
|
190
|
+
onAfterAttempt: async () => {
|
|
191
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
|
|
192
|
+
},
|
|
193
|
+
toolNameForLogs: appRunnerTool.name,
|
|
194
|
+
});
|
|
195
|
+
if (!AIToolCallMessage.tool_calls || AIToolCallMessage.tool_calls.length === 0) {
|
|
196
|
+
throw new Error('No tool calls generated by LLM');
|
|
197
|
+
}
|
|
151
198
|
}
|
|
152
199
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const toolCallMessage = await tool.invoke(AIToolCallMessage.tool_calls[0]);
|
|
200
|
+
if (!AIToolCallMessage.tool_calls || AIToolCallMessage.tool_calls.length === 0) {
|
|
201
|
+
throw new Error('No tool calls generated by LLM');
|
|
202
|
+
}
|
|
203
|
+
const firstToolCall = AIToolCallMessage.tool_calls[0];
|
|
204
|
+
const toolCallMessage = await executionTool.invoke(firstToolCall);
|
|
159
205
|
AIToolCallMessage.additional_kwargs = {
|
|
160
206
|
mindedMetadata: {
|
|
161
207
|
nodeType: NodeType.APP_TOOL,
|
|
@@ -190,11 +236,11 @@ export const addAppToolNode = async ({
|
|
|
190
236
|
nodeId: node.name,
|
|
191
237
|
nodeDisplayName: node.displayName!,
|
|
192
238
|
raw: {
|
|
193
|
-
...
|
|
239
|
+
...firstToolCall,
|
|
194
240
|
result: parsedContent,
|
|
195
241
|
},
|
|
196
242
|
appName: node.appName,
|
|
197
|
-
messageIds: [
|
|
243
|
+
messageIds: [firstToolCall.id!],
|
|
198
244
|
}),
|
|
199
245
|
);
|
|
200
246
|
return state;
|
|
@@ -17,6 +17,7 @@ import { getConfig } from '../platform/config';
|
|
|
17
17
|
import { createZodSchemaFromFields } from '../utils/schemaUtils';
|
|
18
18
|
import { AnalyticsEventName } from '../types/Analytics.types';
|
|
19
19
|
import { trackAnalyticsEvent } from '../internalTools/analytics';
|
|
20
|
+
import { inferToolCallWithRetry } from './utils/inferToolCallWithRetry';
|
|
20
21
|
|
|
21
22
|
type AddBrowserTaskNodeParams = {
|
|
22
23
|
graph: PreCompiledGraph;
|
|
@@ -61,9 +62,18 @@ export const addBrowserTaskNode = async ({ graph, node, agent, llm }: AddBrowser
|
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
try {
|
|
64
|
-
// Use LLM to generate tool call
|
|
65
|
-
const AIToolCallMessage: AIMessage = await
|
|
66
|
-
|
|
65
|
+
// Use LLM to generate tool call, with retry when inferred args are schema-invalid
|
|
66
|
+
const AIToolCallMessage: AIMessage = await inferToolCallWithRetry({
|
|
67
|
+
llm,
|
|
68
|
+
tool,
|
|
69
|
+
inputSchema: zodSchema as any,
|
|
70
|
+
messages: state.messages,
|
|
71
|
+
sessionId: state.sessionId,
|
|
72
|
+
onAfterAttempt: async () => {
|
|
73
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
|
|
74
|
+
},
|
|
75
|
+
toolNameForLogs: 'browser-task',
|
|
76
|
+
});
|
|
67
77
|
if (!AIToolCallMessage.tool_calls || AIToolCallMessage.tool_calls.length === 0) {
|
|
68
78
|
throw new Error('No tool calls generated by LLM');
|
|
69
79
|
}
|
package/src/nodes/addToolNode.ts
CHANGED
|
@@ -13,7 +13,8 @@ import { combinePlaybooks } from '../playbooks/playbooks';
|
|
|
13
13
|
import { compileParameter, compilePrompt } from './compilePrompt';
|
|
14
14
|
import { AnalyticsEventName } from '../types/Analytics.types';
|
|
15
15
|
import { trackAnalyticsEvent } from '../internalTools/analytics';
|
|
16
|
-
import {
|
|
16
|
+
import { inferToolCallWithRetry } from './utils/inferToolCallWithRetry';
|
|
17
|
+
import { getSchemaForToolInference } from './utils/getSchemaForToolInference';
|
|
17
18
|
|
|
18
19
|
export const addToolNode = async ({
|
|
19
20
|
graph,
|
|
@@ -65,38 +66,14 @@ export const addToolNode = async ({
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
// Create a filtered schema for the LLM (exclude overridden parameters)
|
|
69
|
-
let schemaForLLM = matchedTool.input;
|
|
70
69
|
const overriddenKeys = Object.keys(compiledParameters);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (matchedTool.input instanceof z.ZodObject) {
|
|
77
|
-
// Create omit map: { key1: true, key2: true, ... }
|
|
78
|
-
const omitMap = overriddenKeys.reduce((acc, key) => {
|
|
79
|
-
acc[key] = true;
|
|
80
|
-
return acc;
|
|
81
|
-
}, {} as Record<string, true>);
|
|
82
|
-
|
|
83
|
-
schemaForLLM = matchedTool.input.omit(omitMap);
|
|
84
|
-
|
|
85
|
-
// Check if all parameters are overridden
|
|
86
|
-
const remainingKeys = Object.keys(schemaForLLM.shape);
|
|
87
|
-
skipLLMCall = remainingKeys.length === 0;
|
|
88
|
-
}
|
|
89
|
-
} catch (err) {
|
|
90
|
-
logger.warn({
|
|
91
|
-
msg: '[Tool] Failed to filter schema, using original',
|
|
92
|
-
tool: matchedTool.name,
|
|
93
|
-
err,
|
|
94
|
-
});
|
|
95
|
-
// Fall back to original schema on error
|
|
96
|
-
}
|
|
97
|
-
}
|
|
70
|
+
const { schemaForLLM, skipLLMCall } = getSchemaForToolInference({
|
|
71
|
+
inputSchema: matchedTool.input,
|
|
72
|
+
overriddenKeys,
|
|
73
|
+
toolName: matchedTool.name,
|
|
74
|
+
});
|
|
98
75
|
|
|
99
|
-
let AIToolCallMessage: AIMessage;
|
|
76
|
+
let AIToolCallMessage: AIMessage = new AIMessage({ content: '', tool_calls: [] });
|
|
100
77
|
|
|
101
78
|
if (skipLLMCall) {
|
|
102
79
|
// All parameters are overridden - create synthetic tool call without LLM
|
|
@@ -112,10 +89,10 @@ export const addToolNode = async ({
|
|
|
112
89
|
});
|
|
113
90
|
} else {
|
|
114
91
|
// Need LLM to infer remaining parameters
|
|
115
|
-
const tool = langchainTool(() => {}, {
|
|
92
|
+
const tool = langchainTool(() => { }, {
|
|
116
93
|
name: matchedTool.name,
|
|
117
94
|
description: matchedTool.description,
|
|
118
|
-
schema: schemaForLLM, // Use filtered schema
|
|
95
|
+
schema: schemaForLLM as any, // Use filtered schema
|
|
119
96
|
});
|
|
120
97
|
|
|
121
98
|
const combinedPlaybooks = combinePlaybooks(agent.playbooks) || '';
|
|
@@ -172,20 +149,21 @@ export const addToolNode = async ({
|
|
|
172
149
|
state.messages.unshift(systemMessage);
|
|
173
150
|
}
|
|
174
151
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (AIToolCallMessage.tool_calls && AIToolCallMessage.tool_calls.length > 0) {
|
|
184
|
-
AIToolCallMessage.tool_calls[0].args = {
|
|
185
|
-
...AIToolCallMessage.tool_calls[0].args,
|
|
152
|
+
AIToolCallMessage = await inferToolCallWithRetry({
|
|
153
|
+
llm,
|
|
154
|
+
tool,
|
|
155
|
+
inputSchema: matchedTool.input,
|
|
156
|
+
messages: state.messages,
|
|
157
|
+
sessionId: state.sessionId,
|
|
158
|
+
mergeArgs: (args) => ({
|
|
159
|
+
...args,
|
|
186
160
|
...compiledParameters, // User-set parameters have priority over AI-generated parameters
|
|
187
|
-
}
|
|
188
|
-
|
|
161
|
+
}),
|
|
162
|
+
onAfterAttempt: async () => {
|
|
163
|
+
await agent.interruptSessionManager.checkQueueAndInterrupt(state.sessionId);
|
|
164
|
+
},
|
|
165
|
+
toolNameForLogs: matchedTool.name,
|
|
166
|
+
});
|
|
189
167
|
}
|
|
190
168
|
|
|
191
169
|
state.goto = null;
|
|
@@ -35,55 +35,50 @@ export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeNam
|
|
|
35
35
|
const { env, browserTaskMode } = getConfig();
|
|
36
36
|
|
|
37
37
|
const executeWrapper = async (input: z.infer<typeof matchedTool.input>) => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return { breakpointHit: true, breakpointInfo } as unknown as ToolMessage;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return result as ToolMessage;
|
|
76
|
-
} else {
|
|
77
|
-
// Non-RPA tool - execute normally
|
|
78
|
-
const response = await matchedTool.execute({ input, state, agent });
|
|
79
|
-
const endTime = Date.now();
|
|
80
|
-
logger.debug({ msg: '[Tool] Tool execution time', tool: matchedTool.name, executionTimeMs: endTime - startTime });
|
|
81
|
-
return response as ToolMessage;
|
|
38
|
+
const startTime = Date.now();
|
|
39
|
+
|
|
40
|
+
// Check if this is an RPA tool
|
|
41
|
+
if (matchedTool.type === 'rpa') {
|
|
42
|
+
// Wrap with browser session and screenshot capture
|
|
43
|
+
const { result, breakpointHit, breakpointInfo } = await withBrowserSession(
|
|
44
|
+
{
|
|
45
|
+
sessionId: state.sessionId,
|
|
46
|
+
browserTaskMode: matchedTool.browserTaskMode ?? browserTaskMode,
|
|
47
|
+
toolCallId: toolCallObj.tool_calls[0].id,
|
|
48
|
+
proxyConfig: matchedTool.proxyConfig,
|
|
49
|
+
toolName: matchedTool.name,
|
|
50
|
+
persistSession: matchedTool.persistSession,
|
|
51
|
+
checkBreakpoints: env === Environment.DEVELOPMENT,
|
|
52
|
+
},
|
|
53
|
+
async (page) => {
|
|
54
|
+
// Pass page directly to RPA tool execution
|
|
55
|
+
const toolResult = await matchedTool.execute({
|
|
56
|
+
input,
|
|
57
|
+
state,
|
|
58
|
+
agent,
|
|
59
|
+
page,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return toolResult;
|
|
63
|
+
},
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const endTime = Date.now();
|
|
67
|
+
logger.debug({ msg: '[Tool] RPA tool execution time', tool: matchedTool.name, executionTimeMs: endTime - startTime });
|
|
68
|
+
|
|
69
|
+
// Check if breakpoint was hit - return special result
|
|
70
|
+
if (breakpointHit && breakpointInfo) {
|
|
71
|
+
return { breakpointHit: true, breakpointInfo } as unknown as ToolMessage;
|
|
82
72
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
throw err;
|
|
73
|
+
|
|
74
|
+
return result as ToolMessage;
|
|
86
75
|
}
|
|
76
|
+
|
|
77
|
+
// Non-RPA tool - execute normally
|
|
78
|
+
const response = await matchedTool.execute({ input, state, agent });
|
|
79
|
+
const endTime = Date.now();
|
|
80
|
+
logger.debug({ msg: '[Tool] Tool execution time', tool: matchedTool.name, executionTimeMs: endTime - startTime });
|
|
81
|
+
return response as ToolMessage;
|
|
87
82
|
};
|
|
88
83
|
|
|
89
84
|
const toolCallObj = state.messages[state.messages.length - 1] as any;
|
|
@@ -95,72 +90,94 @@ export const addToolRunNode = async ({ graph, tools, toolNode, attachedToNodeNam
|
|
|
95
90
|
const toolCall = toolCallObj.tool_calls[0];
|
|
96
91
|
const parsedArgs = matchedTool.input.parse(toolCall.args);
|
|
97
92
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
// Check if breakpoint was hit - handle gracefully by ending the flow
|
|
102
|
-
const resultObj = result as unknown as { breakpointHit?: boolean; breakpointInfo?: BreakpointHitResult };
|
|
103
|
-
if (resultObj?.breakpointHit && resultObj?.breakpointInfo) {
|
|
104
|
-
logger.info({
|
|
105
|
-
msg: '[Tool] RPA breakpoint hit - ending flow gracefully',
|
|
106
|
-
toolName: matchedTool.name,
|
|
107
|
-
stepNumber: resultObj.breakpointInfo.stepNumber,
|
|
108
|
-
});
|
|
93
|
+
try {
|
|
94
|
+
// Execute the tool with validated args
|
|
95
|
+
const result = await executeWrapper(parsedArgs);
|
|
109
96
|
|
|
110
|
-
//
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
toolName:
|
|
97
|
+
// Check if breakpoint was hit - handle gracefully by ending the flow
|
|
98
|
+
const resultObj = result as unknown as { breakpointHit?: boolean; breakpointInfo?: BreakpointHitResult };
|
|
99
|
+
if (resultObj?.breakpointHit && resultObj?.breakpointInfo) {
|
|
100
|
+
logger.info({
|
|
101
|
+
msg: '[Tool] RPA breakpoint hit - ending flow gracefully',
|
|
102
|
+
toolName: matchedTool.name,
|
|
116
103
|
stepNumber: resultObj.breakpointInfo.stepNumber,
|
|
117
|
-
})
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Create a ToolMessage indicating breakpoint was hit
|
|
107
|
+
const breakpointMessage = new ToolMessage({
|
|
108
|
+
content: JSON.stringify({
|
|
109
|
+
breakpointHit: true,
|
|
110
|
+
message: `RPA breakpoint reached at step ${resultObj.breakpointInfo.stepNumber + 1}`,
|
|
111
|
+
toolName: resultObj.breakpointInfo.toolName,
|
|
112
|
+
stepNumber: resultObj.breakpointInfo.stepNumber,
|
|
113
|
+
}),
|
|
114
|
+
tool_call_id: toolCall.id,
|
|
115
|
+
name: matchedTool.name,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
state.messages.push(breakpointMessage);
|
|
119
|
+
state.history.push(
|
|
120
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
121
|
+
type: NodeType.TOOL,
|
|
122
|
+
nodeId: toolNode.name,
|
|
123
|
+
nodeDisplayName: toolNode.displayName,
|
|
124
|
+
raw: breakpointMessage,
|
|
125
|
+
messageIds: [toolCall.id],
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Set goto to __end__ to stop the flow gracefully
|
|
130
|
+
state.goto = '__end__';
|
|
131
|
+
return state;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Create a ToolMessage with the result
|
|
135
|
+
const toolCallMessage = new ToolMessage({
|
|
136
|
+
content: typeof result === 'string' ? result : JSON.stringify(result),
|
|
118
137
|
tool_call_id: toolCall.id,
|
|
119
138
|
name: matchedTool.name,
|
|
120
139
|
});
|
|
121
140
|
|
|
122
|
-
state
|
|
141
|
+
// Add the tool message to the state
|
|
142
|
+
state.messages.push(toolCallMessage);
|
|
143
|
+
|
|
144
|
+
// Add history step
|
|
123
145
|
state.history.push(
|
|
124
146
|
createHistoryStep<HistoryStep>(state.history, {
|
|
125
147
|
type: NodeType.TOOL,
|
|
126
148
|
nodeId: toolNode.name,
|
|
127
149
|
nodeDisplayName: toolNode.displayName,
|
|
128
|
-
raw:
|
|
129
|
-
messageIds: [
|
|
150
|
+
raw: toolCallMessage,
|
|
151
|
+
messageIds: [toolCall.id],
|
|
130
152
|
}),
|
|
131
153
|
);
|
|
132
154
|
|
|
133
|
-
//
|
|
134
|
-
state.goto =
|
|
155
|
+
// Clear goto if it was set
|
|
156
|
+
state.goto = null;
|
|
157
|
+
|
|
158
|
+
// Return the entire modified state
|
|
135
159
|
return state;
|
|
136
|
-
}
|
|
160
|
+
} catch (err) {
|
|
161
|
+
logger.error({ message: '[Tool] Error executing tool', err, node: toolNode.displayName });
|
|
162
|
+
|
|
163
|
+
const errorMessage = err instanceof Error ? err.message : JSON.stringify(err);
|
|
164
|
+
const toolErrorMessage = new ToolMessage({
|
|
165
|
+
content: JSON.stringify({ error: errorMessage }),
|
|
166
|
+
tool_call_id: toolCall.id,
|
|
167
|
+
name: matchedTool.name,
|
|
168
|
+
});
|
|
137
169
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
state.history.push(
|
|
150
|
-
createHistoryStep<HistoryStep>(state.history, {
|
|
151
|
-
type: NodeType.TOOL,
|
|
152
|
-
nodeId: toolNode.name,
|
|
153
|
-
nodeDisplayName: toolNode.displayName,
|
|
154
|
-
raw: toolCallMessage,
|
|
155
|
-
messageIds: [toolCallObj.tool_calls[0].id],
|
|
156
|
-
}),
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Clear goto if it was set
|
|
160
|
-
state.goto = null;
|
|
161
|
-
|
|
162
|
-
// Return the entire modified state
|
|
163
|
-
return state;
|
|
170
|
+
state.messages.push(toolErrorMessage);
|
|
171
|
+
state.history.push(
|
|
172
|
+
createHistoryStep<HistoryStep>(state.history, {
|
|
173
|
+
type: NodeType.TOOL,
|
|
174
|
+
nodeId: toolNode.name,
|
|
175
|
+
nodeDisplayName: toolNode.displayName,
|
|
176
|
+
raw: toolErrorMessage,
|
|
177
|
+
messageIds: [toolCall.id],
|
|
178
|
+
}),
|
|
179
|
+
);
|
|
180
|
+
}
|
|
164
181
|
};
|
|
165
182
|
|
|
166
183
|
graph.addNode(buildToolRunNodeName(attachedToNodeName), callback);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { logger } from '../../utils/logger';
|
|
3
|
+
|
|
4
|
+
interface GetSchemaForToolInferenceParams {
|
|
5
|
+
inputSchema: z.ZodTypeAny;
|
|
6
|
+
overriddenKeys: string[];
|
|
7
|
+
toolName: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface GetSchemaForToolInferenceResult {
|
|
11
|
+
schemaForLLM: z.ZodTypeAny;
|
|
12
|
+
skipLLMCall: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const getSchemaForToolInference = ({
|
|
16
|
+
inputSchema,
|
|
17
|
+
overriddenKeys,
|
|
18
|
+
toolName,
|
|
19
|
+
}: GetSchemaForToolInferenceParams): GetSchemaForToolInferenceResult => {
|
|
20
|
+
let schemaForLLM = inputSchema;
|
|
21
|
+
let skipLLMCall = false;
|
|
22
|
+
|
|
23
|
+
if (overriddenKeys.length === 0) {
|
|
24
|
+
return { schemaForLLM, skipLLMCall };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
if (inputSchema instanceof z.ZodObject) {
|
|
29
|
+
const omitMap = overriddenKeys.reduce((acc, key) => {
|
|
30
|
+
acc[key] = true;
|
|
31
|
+
return acc;
|
|
32
|
+
}, {} as Record<string, true>);
|
|
33
|
+
|
|
34
|
+
const filteredSchema = inputSchema.omit(omitMap);
|
|
35
|
+
schemaForLLM = filteredSchema;
|
|
36
|
+
const remainingKeys = Object.keys(filteredSchema.shape);
|
|
37
|
+
skipLLMCall = remainingKeys.length === 0;
|
|
38
|
+
}
|
|
39
|
+
} catch (err) {
|
|
40
|
+
logger.warn({
|
|
41
|
+
msg: '[Tool] Failed to filter schema, using original',
|
|
42
|
+
tool: toolName,
|
|
43
|
+
err,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { schemaForLLM, skipLLMCall };
|
|
48
|
+
};
|