illuma-agents 1.0.8 → 1.0.9
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/LICENSE +1 -5
- package/dist/cjs/common/enum.cjs +1 -2
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -2
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +99 -0
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -0
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/providers.cjs +13 -16
- package/dist/cjs/llm/providers.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +14 -14
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/ids.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +10 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/splitStream.cjs.map +1 -1
- package/dist/cjs/stream.cjs +4 -1
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +10 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +29 -25
- package/dist/cjs/tools/handlers.cjs.map +1 -1
- package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
- package/dist/cjs/tools/search/content.cjs.map +1 -1
- package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
- package/dist/cjs/tools/search/format.cjs.map +1 -1
- package/dist/cjs/tools/search/highlights.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
- package/dist/cjs/tools/search/schema.cjs +25 -25
- package/dist/cjs/tools/search/schema.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +6 -1
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +162 -35
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/cjs/utils/graph.cjs.map +1 -1
- package/dist/cjs/utils/llm.cjs +0 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/misc.cjs.map +1 -1
- package/dist/cjs/utils/run.cjs.map +1 -1
- package/dist/cjs/utils/title.cjs +7 -7
- package/dist/cjs/utils/title.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +1 -2
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -2
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +97 -0
- package/dist/esm/llm/bedrock/index.mjs.map +1 -0
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/providers.mjs +2 -5
- package/dist/esm/llm/providers.mjs.map +1 -1
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +14 -14
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/ids.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +10 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/splitStream.mjs.map +1 -1
- package/dist/esm/stream.mjs +4 -1
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +10 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +30 -26
- package/dist/esm/tools/handlers.mjs.map +1 -1
- package/dist/esm/tools/search/anthropic.mjs.map +1 -1
- package/dist/esm/tools/search/content.mjs.map +1 -1
- package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
- package/dist/esm/tools/search/format.mjs.map +1 -1
- package/dist/esm/tools/search/highlights.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs.map +1 -1
- package/dist/esm/tools/search/schema.mjs +25 -25
- package/dist/esm/tools/search/schema.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +6 -1
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +162 -35
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/esm/utils/graph.mjs.map +1 -1
- package/dist/esm/utils/llm.mjs +0 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/misc.mjs.map +1 -1
- package/dist/esm/utils/run.mjs.map +1 -1
- package/dist/esm/utils/title.mjs +7 -7
- package/dist/esm/utils/title.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +1 -2
- package/dist/types/llm/bedrock/index.d.ts +36 -0
- package/dist/types/tools/search/types.d.ts +2 -0
- package/dist/types/types/llm.d.ts +3 -8
- package/package.json +15 -11
- package/src/common/enum.ts +1 -2
- package/src/common/index.ts +1 -1
- package/src/instrumentation.ts +22 -22
- package/src/llm/anthropic/llm.spec.ts +1442 -1442
- package/src/llm/anthropic/types.ts +140 -140
- package/src/llm/anthropic/utils/message_inputs.ts +757 -660
- package/src/llm/anthropic/utils/output_parsers.ts +133 -133
- package/src/llm/anthropic/utils/tools.ts +29 -29
- package/src/llm/bedrock/index.ts +128 -0
- package/src/llm/fake.ts +133 -133
- package/src/llm/google/utils/tools.ts +160 -160
- package/src/llm/openai/types.ts +24 -24
- package/src/llm/openai/utils/isReasoningModel.test.ts +90 -90
- package/src/llm/providers.ts +2 -7
- package/src/llm/text.ts +94 -94
- package/src/messages/core.ts +463 -463
- package/src/messages/formatAgentMessages.tools.test.ts +400 -400
- package/src/messages/formatMessage.test.ts +693 -693
- package/src/messages/ids.ts +26 -26
- package/src/messages/prune.ts +567 -567
- package/src/messages/shiftIndexTokenCountMap.test.ts +81 -81
- package/src/mockStream.ts +98 -98
- package/src/prompts/collab.ts +5 -5
- package/src/prompts/index.ts +1 -1
- package/src/prompts/taskmanager.ts +61 -61
- package/src/run.ts +13 -4
- package/src/scripts/ant_web_search_edge_case.ts +162 -0
- package/src/scripts/ant_web_search_error_edge_case.ts +148 -0
- package/src/scripts/args.ts +48 -48
- package/src/scripts/caching.ts +123 -123
- package/src/scripts/code_exec_files.ts +193 -193
- package/src/scripts/empty_input.ts +137 -137
- package/src/scripts/image.ts +178 -178
- package/src/scripts/memory.ts +97 -97
- package/src/scripts/thinking.ts +149 -149
- package/src/specs/anthropic.simple.test.ts +67 -0
- package/src/specs/spec.utils.ts +3 -3
- package/src/specs/token-distribution-edge-case.test.ts +316 -316
- package/src/specs/tool-error.test.ts +193 -193
- package/src/splitStream.test.ts +691 -691
- package/src/splitStream.ts +234 -234
- package/src/stream.test.ts +94 -94
- package/src/stream.ts +4 -1
- package/src/tools/ToolNode.ts +12 -1
- package/src/tools/handlers.ts +32 -28
- package/src/tools/search/anthropic.ts +51 -51
- package/src/tools/search/content.test.ts +173 -173
- package/src/tools/search/content.ts +147 -147
- package/src/tools/search/direct-url.test.ts +530 -0
- package/src/tools/search/firecrawl.ts +210 -210
- package/src/tools/search/format.ts +250 -250
- package/src/tools/search/highlights.ts +320 -320
- package/src/tools/search/index.ts +2 -2
- package/src/tools/search/jina-reranker.test.ts +126 -126
- package/src/tools/search/output.md +2775 -2775
- package/src/tools/search/rerankers.ts +242 -242
- package/src/tools/search/schema.ts +63 -63
- package/src/tools/search/search.ts +766 -759
- package/src/tools/search/serper-scraper.ts +155 -155
- package/src/tools/search/test.html +883 -883
- package/src/tools/search/test.md +642 -642
- package/src/tools/search/test.ts +159 -159
- package/src/tools/search/tool.ts +619 -471
- package/src/tools/search/types.ts +689 -687
- package/src/tools/search/utils.ts +79 -79
- package/src/types/index.ts +6 -6
- package/src/types/llm.ts +2 -8
- package/src/utils/graph.ts +10 -10
- package/src/utils/llm.ts +26 -27
- package/src/utils/llmConfig.ts +5 -3
- package/src/utils/logging.ts +48 -48
- package/src/utils/misc.ts +57 -57
- package/src/utils/run.ts +100 -100
- package/src/utils/title.ts +165 -165
- package/dist/cjs/llm/ollama/index.cjs +0 -70
- package/dist/cjs/llm/ollama/index.cjs.map +0 -1
- package/dist/cjs/llm/ollama/utils.cjs +0 -158
- package/dist/cjs/llm/ollama/utils.cjs.map +0 -1
- package/dist/esm/llm/ollama/index.mjs +0 -68
- package/dist/esm/llm/ollama/index.mjs.map +0 -1
- package/dist/esm/llm/ollama/utils.mjs +0 -155
- package/dist/esm/llm/ollama/utils.mjs.map +0 -1
- package/dist/types/llm/ollama/index.d.ts +0 -8
- package/dist/types/llm/ollama/utils.d.ts +0 -7
- package/src/llm/ollama/index.ts +0 -92
- package/src/llm/ollama/utils.ts +0 -193
- package/src/proto/CollabGraph.ts +0 -269
- package/src/proto/TaskManager.ts +0 -243
- package/src/proto/collab.ts +0 -200
- package/src/proto/collab_design.ts +0 -184
- package/src/proto/collab_design_v2.ts +0 -224
- package/src/proto/collab_design_v3.ts +0 -255
- package/src/proto/collab_design_v4.ts +0 -220
- package/src/proto/collab_design_v5.ts +0 -251
- package/src/proto/collab_graph.ts +0 -181
- package/src/proto/collab_original.ts +0 -123
- package/src/proto/example.ts +0 -93
- package/src/proto/example_new.ts +0 -68
- package/src/proto/example_old.ts +0 -201
- package/src/proto/example_test.ts +0 -152
- package/src/proto/example_test_anthropic.ts +0 -100
- package/src/proto/log_stream.ts +0 -202
- package/src/proto/main_collab_community_event.ts +0 -133
- package/src/proto/main_collab_design_v2.ts +0 -96
- package/src/proto/main_collab_design_v4.ts +0 -100
- package/src/proto/main_collab_design_v5.ts +0 -135
- package/src/proto/main_collab_global_analysis.ts +0 -122
- package/src/proto/main_collab_hackathon_event.ts +0 -153
- package/src/proto/main_collab_space_mission.ts +0 -153
- package/src/proto/main_philosophy.ts +0 -210
- package/src/proto/original_script.ts +0 -126
- package/src/proto/standard.ts +0 -100
- package/src/proto/stream.ts +0 -56
- package/src/proto/tasks.ts +0 -118
- package/src/proto/tools/global_analysis_tools.ts +0 -86
- package/src/proto/tools/space_mission_tools.ts +0 -60
- package/src/proto/vertexai.ts +0 -54
|
@@ -1,193 +1,193 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { config } from 'dotenv';
|
|
3
|
-
config();
|
|
4
|
-
import { tool } from '@langchain/core/tools';
|
|
5
|
-
import { ToolCall } from '@langchain/core/messages/tool';
|
|
6
|
-
import { HumanMessage, BaseMessage } from '@langchain/core/messages';
|
|
7
|
-
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
8
|
-
import type * as t from '@/types';
|
|
9
|
-
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
10
|
-
import { ToolEndHandler, ModelEndHandler } from '@/events';
|
|
11
|
-
import { GraphEvents, Providers } from '@/common';
|
|
12
|
-
import { getLLMConfig } from '@/utils/llmConfig';
|
|
13
|
-
import { getArgs } from '@/scripts/args';
|
|
14
|
-
import { StandardGraph } from '@/graphs';
|
|
15
|
-
import { Run } from '@/run';
|
|
16
|
-
|
|
17
|
-
const errorTool = tool(
|
|
18
|
-
async () => {
|
|
19
|
-
throw new Error('this is a test error I threw on purpose');
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
name: 'errorTool',
|
|
23
|
-
description: 'A tool that always throws an error',
|
|
24
|
-
schema: z.object({ input: z.string().optional() }),
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
describe('Tool Error Handling Tests', () => {
|
|
29
|
-
jest.setTimeout(30000);
|
|
30
|
-
let run: Run<t.IState>;
|
|
31
|
-
let contentParts: t.MessageContentComplex[];
|
|
32
|
-
let conversationHistory: BaseMessage[];
|
|
33
|
-
let aggregateContent: t.ContentAggregator;
|
|
34
|
-
let handleToolCallErrorSpy: jest.SpyInstance;
|
|
35
|
-
|
|
36
|
-
const config: Partial<RunnableConfig> & {
|
|
37
|
-
version: 'v1' | 'v2';
|
|
38
|
-
run_id?: string;
|
|
39
|
-
streamMode: string;
|
|
40
|
-
} = {
|
|
41
|
-
configurable: {
|
|
42
|
-
thread_id: 'conversation-num-1',
|
|
43
|
-
},
|
|
44
|
-
streamMode: 'values',
|
|
45
|
-
version: 'v2' as const,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
beforeEach(async () => {
|
|
49
|
-
conversationHistory = [];
|
|
50
|
-
const { contentParts: parts, aggregateContent: ac } =
|
|
51
|
-
createContentAggregator();
|
|
52
|
-
aggregateContent = ac;
|
|
53
|
-
contentParts = parts as t.MessageContentComplex[];
|
|
54
|
-
// Spy on the static method instead of the instance method
|
|
55
|
-
handleToolCallErrorSpy = jest.spyOn(
|
|
56
|
-
StandardGraph,
|
|
57
|
-
'handleToolCallErrorStatic'
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
afterEach(() => {
|
|
62
|
-
handleToolCallErrorSpy.mockRestore();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const onMessageDeltaSpy = jest.fn();
|
|
66
|
-
const onRunStepSpy = jest.fn();
|
|
67
|
-
const onRunStepCompletedSpy = jest.fn();
|
|
68
|
-
|
|
69
|
-
afterAll(() => {
|
|
70
|
-
onMessageDeltaSpy.mockReset();
|
|
71
|
-
onRunStepSpy.mockReset();
|
|
72
|
-
onRunStepCompletedSpy.mockReset();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const setupCustomHandlers = (): Record<
|
|
76
|
-
string | GraphEvents,
|
|
77
|
-
t.EventHandler
|
|
78
|
-
> => ({
|
|
79
|
-
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
80
|
-
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
81
|
-
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
82
|
-
[GraphEvents.ON_RUN_STEP_COMPLETED]: {
|
|
83
|
-
handle: (
|
|
84
|
-
event: GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
85
|
-
data: t.StreamEventData
|
|
86
|
-
): void => {
|
|
87
|
-
if ((data.result as t.MessageContentComplex)['type'] === 'tool_call') {
|
|
88
|
-
run.Graph?.overrideTestModel(
|
|
89
|
-
['Looks like there was an error calling the tool.'],
|
|
90
|
-
5
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
onRunStepCompletedSpy(event, data);
|
|
94
|
-
aggregateContent({
|
|
95
|
-
event,
|
|
96
|
-
data: data as unknown as { result: t.ToolEndEvent },
|
|
97
|
-
});
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
[GraphEvents.ON_RUN_STEP]: {
|
|
101
|
-
handle: (
|
|
102
|
-
event: GraphEvents.ON_RUN_STEP,
|
|
103
|
-
data: t.StreamEventData,
|
|
104
|
-
metadata,
|
|
105
|
-
graph
|
|
106
|
-
): void => {
|
|
107
|
-
const runStepData = data as t.RunStep;
|
|
108
|
-
onRunStepSpy(event, runStepData, metadata, graph);
|
|
109
|
-
aggregateContent({ event, data: runStepData });
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
[GraphEvents.ON_RUN_STEP_DELTA]: {
|
|
113
|
-
handle: (
|
|
114
|
-
event: GraphEvents.ON_RUN_STEP_DELTA,
|
|
115
|
-
data: t.StreamEventData
|
|
116
|
-
): void => {
|
|
117
|
-
aggregateContent({ event, data: data as t.RunStepDeltaEvent });
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
121
|
-
handle: (
|
|
122
|
-
event: GraphEvents.ON_MESSAGE_DELTA,
|
|
123
|
-
data: t.StreamEventData,
|
|
124
|
-
metadata,
|
|
125
|
-
graph
|
|
126
|
-
): void => {
|
|
127
|
-
onMessageDeltaSpy(event, data, metadata, graph);
|
|
128
|
-
aggregateContent({ event, data: data as t.MessageDeltaEvent });
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
test('should handle tool call errors correctly', async () => {
|
|
134
|
-
const { userName, location } = await getArgs();
|
|
135
|
-
const llmConfig = getLLMConfig(Providers.OPENAI);
|
|
136
|
-
const customHandlers = setupCustomHandlers();
|
|
137
|
-
|
|
138
|
-
// Create the run instance
|
|
139
|
-
run = await Run.create<t.IState>({
|
|
140
|
-
runId: 'test-run-id',
|
|
141
|
-
graphConfig: {
|
|
142
|
-
type: 'standard',
|
|
143
|
-
llmConfig,
|
|
144
|
-
tools: [errorTool],
|
|
145
|
-
instructions: 'You are a helpful AI assistant.',
|
|
146
|
-
additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
|
|
147
|
-
},
|
|
148
|
-
returnContent: true,
|
|
149
|
-
customHandlers,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const toolCalls: ToolCall[] = [
|
|
153
|
-
{
|
|
154
|
-
name: 'errorTool',
|
|
155
|
-
args: {
|
|
156
|
-
input: 'test input',
|
|
157
|
-
},
|
|
158
|
-
id: 'call_test123',
|
|
159
|
-
type: 'tool_call',
|
|
160
|
-
},
|
|
161
|
-
];
|
|
162
|
-
|
|
163
|
-
const firstResponse = 'Let me try calling the tool';
|
|
164
|
-
run.Graph?.overrideTestModel([firstResponse], 5, toolCalls);
|
|
165
|
-
|
|
166
|
-
const userMessage = 'Use the error tool';
|
|
167
|
-
conversationHistory.push(new HumanMessage(userMessage));
|
|
168
|
-
|
|
169
|
-
const inputs = {
|
|
170
|
-
messages: conversationHistory,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
await run.processStream(inputs, config);
|
|
174
|
-
|
|
175
|
-
// Verify handleToolCallError was called
|
|
176
|
-
expect(handleToolCallErrorSpy).toHaveBeenCalled();
|
|
177
|
-
|
|
178
|
-
// Find the tool call content part
|
|
179
|
-
const toolCallPart = contentParts.find(
|
|
180
|
-
(part) => part.type === 'tool_call'
|
|
181
|
-
) as t.ToolCallContent | undefined;
|
|
182
|
-
|
|
183
|
-
// Verify the error message in contentParts
|
|
184
|
-
expect(toolCallPart).toBeDefined();
|
|
185
|
-
expect(toolCallPart?.tool_call?.args).toEqual(
|
|
186
|
-
JSON.stringify(toolCalls[0].args)
|
|
187
|
-
);
|
|
188
|
-
expect(toolCallPart?.tool_call?.output).toContain('Error processing tool');
|
|
189
|
-
expect(toolCallPart?.tool_call?.output).toContain(
|
|
190
|
-
'this is a test error I threw on purpose'
|
|
191
|
-
);
|
|
192
|
-
});
|
|
193
|
-
});
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { config } from 'dotenv';
|
|
3
|
+
config();
|
|
4
|
+
import { tool } from '@langchain/core/tools';
|
|
5
|
+
import { ToolCall } from '@langchain/core/messages/tool';
|
|
6
|
+
import { HumanMessage, BaseMessage } from '@langchain/core/messages';
|
|
7
|
+
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
8
|
+
import type * as t from '@/types';
|
|
9
|
+
import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
|
|
10
|
+
import { ToolEndHandler, ModelEndHandler } from '@/events';
|
|
11
|
+
import { GraphEvents, Providers } from '@/common';
|
|
12
|
+
import { getLLMConfig } from '@/utils/llmConfig';
|
|
13
|
+
import { getArgs } from '@/scripts/args';
|
|
14
|
+
import { StandardGraph } from '@/graphs';
|
|
15
|
+
import { Run } from '@/run';
|
|
16
|
+
|
|
17
|
+
const errorTool = tool(
|
|
18
|
+
async () => {
|
|
19
|
+
throw new Error('this is a test error I threw on purpose');
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'errorTool',
|
|
23
|
+
description: 'A tool that always throws an error',
|
|
24
|
+
schema: z.object({ input: z.string().optional() }),
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
describe('Tool Error Handling Tests', () => {
|
|
29
|
+
jest.setTimeout(30000);
|
|
30
|
+
let run: Run<t.IState>;
|
|
31
|
+
let contentParts: t.MessageContentComplex[];
|
|
32
|
+
let conversationHistory: BaseMessage[];
|
|
33
|
+
let aggregateContent: t.ContentAggregator;
|
|
34
|
+
let handleToolCallErrorSpy: jest.SpyInstance;
|
|
35
|
+
|
|
36
|
+
const config: Partial<RunnableConfig> & {
|
|
37
|
+
version: 'v1' | 'v2';
|
|
38
|
+
run_id?: string;
|
|
39
|
+
streamMode: string;
|
|
40
|
+
} = {
|
|
41
|
+
configurable: {
|
|
42
|
+
thread_id: 'conversation-num-1',
|
|
43
|
+
},
|
|
44
|
+
streamMode: 'values',
|
|
45
|
+
version: 'v2' as const,
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
beforeEach(async () => {
|
|
49
|
+
conversationHistory = [];
|
|
50
|
+
const { contentParts: parts, aggregateContent: ac } =
|
|
51
|
+
createContentAggregator();
|
|
52
|
+
aggregateContent = ac;
|
|
53
|
+
contentParts = parts as t.MessageContentComplex[];
|
|
54
|
+
// Spy on the static method instead of the instance method
|
|
55
|
+
handleToolCallErrorSpy = jest.spyOn(
|
|
56
|
+
StandardGraph,
|
|
57
|
+
'handleToolCallErrorStatic'
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
afterEach(() => {
|
|
62
|
+
handleToolCallErrorSpy.mockRestore();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const onMessageDeltaSpy = jest.fn();
|
|
66
|
+
const onRunStepSpy = jest.fn();
|
|
67
|
+
const onRunStepCompletedSpy = jest.fn();
|
|
68
|
+
|
|
69
|
+
afterAll(() => {
|
|
70
|
+
onMessageDeltaSpy.mockReset();
|
|
71
|
+
onRunStepSpy.mockReset();
|
|
72
|
+
onRunStepCompletedSpy.mockReset();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const setupCustomHandlers = (): Record<
|
|
76
|
+
string | GraphEvents,
|
|
77
|
+
t.EventHandler
|
|
78
|
+
> => ({
|
|
79
|
+
[GraphEvents.TOOL_END]: new ToolEndHandler(),
|
|
80
|
+
[GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
|
|
81
|
+
[GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
|
|
82
|
+
[GraphEvents.ON_RUN_STEP_COMPLETED]: {
|
|
83
|
+
handle: (
|
|
84
|
+
event: GraphEvents.ON_RUN_STEP_COMPLETED,
|
|
85
|
+
data: t.StreamEventData
|
|
86
|
+
): void => {
|
|
87
|
+
if ((data.result as t.MessageContentComplex)['type'] === 'tool_call') {
|
|
88
|
+
run.Graph?.overrideTestModel(
|
|
89
|
+
['Looks like there was an error calling the tool.'],
|
|
90
|
+
5
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
onRunStepCompletedSpy(event, data);
|
|
94
|
+
aggregateContent({
|
|
95
|
+
event,
|
|
96
|
+
data: data as unknown as { result: t.ToolEndEvent },
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
[GraphEvents.ON_RUN_STEP]: {
|
|
101
|
+
handle: (
|
|
102
|
+
event: GraphEvents.ON_RUN_STEP,
|
|
103
|
+
data: t.StreamEventData,
|
|
104
|
+
metadata,
|
|
105
|
+
graph
|
|
106
|
+
): void => {
|
|
107
|
+
const runStepData = data as t.RunStep;
|
|
108
|
+
onRunStepSpy(event, runStepData, metadata, graph);
|
|
109
|
+
aggregateContent({ event, data: runStepData });
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
[GraphEvents.ON_RUN_STEP_DELTA]: {
|
|
113
|
+
handle: (
|
|
114
|
+
event: GraphEvents.ON_RUN_STEP_DELTA,
|
|
115
|
+
data: t.StreamEventData
|
|
116
|
+
): void => {
|
|
117
|
+
aggregateContent({ event, data: data as t.RunStepDeltaEvent });
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
[GraphEvents.ON_MESSAGE_DELTA]: {
|
|
121
|
+
handle: (
|
|
122
|
+
event: GraphEvents.ON_MESSAGE_DELTA,
|
|
123
|
+
data: t.StreamEventData,
|
|
124
|
+
metadata,
|
|
125
|
+
graph
|
|
126
|
+
): void => {
|
|
127
|
+
onMessageDeltaSpy(event, data, metadata, graph);
|
|
128
|
+
aggregateContent({ event, data: data as t.MessageDeltaEvent });
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('should handle tool call errors correctly', async () => {
|
|
134
|
+
const { userName, location } = await getArgs();
|
|
135
|
+
const llmConfig = getLLMConfig(Providers.OPENAI);
|
|
136
|
+
const customHandlers = setupCustomHandlers();
|
|
137
|
+
|
|
138
|
+
// Create the run instance
|
|
139
|
+
run = await Run.create<t.IState>({
|
|
140
|
+
runId: 'test-run-id',
|
|
141
|
+
graphConfig: {
|
|
142
|
+
type: 'standard',
|
|
143
|
+
llmConfig,
|
|
144
|
+
tools: [errorTool],
|
|
145
|
+
instructions: 'You are a helpful AI assistant.',
|
|
146
|
+
additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
|
|
147
|
+
},
|
|
148
|
+
returnContent: true,
|
|
149
|
+
customHandlers,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const toolCalls: ToolCall[] = [
|
|
153
|
+
{
|
|
154
|
+
name: 'errorTool',
|
|
155
|
+
args: {
|
|
156
|
+
input: 'test input',
|
|
157
|
+
},
|
|
158
|
+
id: 'call_test123',
|
|
159
|
+
type: 'tool_call',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const firstResponse = 'Let me try calling the tool';
|
|
164
|
+
run.Graph?.overrideTestModel([firstResponse], 5, toolCalls);
|
|
165
|
+
|
|
166
|
+
const userMessage = 'Use the error tool';
|
|
167
|
+
conversationHistory.push(new HumanMessage(userMessage));
|
|
168
|
+
|
|
169
|
+
const inputs = {
|
|
170
|
+
messages: conversationHistory,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
await run.processStream(inputs, config);
|
|
174
|
+
|
|
175
|
+
// Verify handleToolCallError was called
|
|
176
|
+
expect(handleToolCallErrorSpy).toHaveBeenCalled();
|
|
177
|
+
|
|
178
|
+
// Find the tool call content part
|
|
179
|
+
const toolCallPart = contentParts.find(
|
|
180
|
+
(part) => part.type === 'tool_call'
|
|
181
|
+
) as t.ToolCallContent | undefined;
|
|
182
|
+
|
|
183
|
+
// Verify the error message in contentParts
|
|
184
|
+
expect(toolCallPart).toBeDefined();
|
|
185
|
+
expect(toolCallPart?.tool_call?.args).toEqual(
|
|
186
|
+
JSON.stringify(toolCalls[0].args)
|
|
187
|
+
);
|
|
188
|
+
expect(toolCallPart?.tool_call?.output).toContain('Error processing tool');
|
|
189
|
+
expect(toolCallPart?.tool_call?.output).toContain(
|
|
190
|
+
'this is a test error I threw on purpose'
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
});
|