@librechat/agents 2.4.41 → 2.4.43

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 (62) hide show
  1. package/dist/cjs/common/enum.cjs +4 -2
  2. package/dist/cjs/common/enum.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +5 -6
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/llm/google/index.cjs +73 -1
  6. package/dist/cjs/llm/google/index.cjs.map +1 -1
  7. package/dist/cjs/llm/google/utils/common.cjs +469 -0
  8. package/dist/cjs/llm/google/utils/common.cjs.map +1 -0
  9. package/dist/cjs/run.cjs +4 -3
  10. package/dist/cjs/run.cjs.map +1 -1
  11. package/dist/cjs/stream.cjs +5 -2
  12. package/dist/cjs/stream.cjs.map +1 -1
  13. package/dist/cjs/utils/title.cjs +25 -20
  14. package/dist/cjs/utils/title.cjs.map +1 -1
  15. package/dist/esm/common/enum.mjs +4 -2
  16. package/dist/esm/common/enum.mjs.map +1 -1
  17. package/dist/esm/graphs/Graph.mjs +5 -6
  18. package/dist/esm/graphs/Graph.mjs.map +1 -1
  19. package/dist/esm/llm/google/index.mjs +73 -1
  20. package/dist/esm/llm/google/index.mjs.map +1 -1
  21. package/dist/esm/llm/google/utils/common.mjs +463 -0
  22. package/dist/esm/llm/google/utils/common.mjs.map +1 -0
  23. package/dist/esm/run.mjs +4 -3
  24. package/dist/esm/run.mjs.map +1 -1
  25. package/dist/esm/stream.mjs +5 -2
  26. package/dist/esm/stream.mjs.map +1 -1
  27. package/dist/esm/utils/title.mjs +25 -20
  28. package/dist/esm/utils/title.mjs.map +1 -1
  29. package/dist/types/common/enum.d.ts +5 -3
  30. package/dist/types/graphs/Graph.d.ts +3 -2
  31. package/dist/types/llm/google/index.d.ts +10 -5
  32. package/dist/types/llm/google/types.d.ts +32 -0
  33. package/dist/types/llm/google/utils/common.d.ts +19 -0
  34. package/dist/types/llm/google/utils/tools.d.ts +10 -0
  35. package/dist/types/llm/google/utils/zod_to_genai_parameters.d.ts +14 -0
  36. package/dist/types/run.d.ts +1 -1
  37. package/dist/types/scripts/args.d.ts +2 -1
  38. package/dist/types/types/llm.d.ts +2 -0
  39. package/dist/types/types/run.d.ts +1 -0
  40. package/dist/types/types/stream.d.ts +5 -0
  41. package/package.json +1 -1
  42. package/src/common/enum.ts +4 -2
  43. package/src/graphs/Graph.ts +16 -11
  44. package/src/llm/google/index.ts +118 -8
  45. package/src/llm/google/types.ts +43 -0
  46. package/src/llm/google/utils/common.ts +632 -0
  47. package/src/llm/google/utils/tools.ts +160 -0
  48. package/src/llm/google/utils/zod_to_genai_parameters.ts +88 -0
  49. package/src/run.ts +4 -2
  50. package/src/scripts/args.ts +12 -8
  51. package/src/scripts/code_exec.ts +49 -18
  52. package/src/scripts/code_exec_files.ts +48 -17
  53. package/src/scripts/image.ts +52 -20
  54. package/src/scripts/simple.ts +1 -0
  55. package/src/specs/anthropic.simple.test.ts +88 -31
  56. package/src/specs/openai.simple.test.ts +88 -31
  57. package/src/stream.ts +5 -2
  58. package/src/types/llm.ts +2 -0
  59. package/src/types/run.ts +1 -0
  60. package/src/types/stream.ts +6 -0
  61. package/src/utils/llmConfig.ts +2 -2
  62. package/src/utils/title.ts +44 -27
@@ -5,14 +5,17 @@ import { HumanMessage, AIMessage, BaseMessage } from '@langchain/core/messages';
5
5
  import type { RunnableConfig } from '@langchain/core/runnables';
6
6
  import type * as t from '@/types';
7
7
  import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
8
- import { ToolEndHandler, ModelEndHandler, createMetadataAggregator } from '@/events';
8
+ import {
9
+ ToolEndHandler,
10
+ ModelEndHandler,
11
+ createMetadataAggregator,
12
+ } from '@/events';
9
13
  import { fetchRandomImageTool, fetchRandomImageURL } from '@/tools/example';
10
14
  import { getLLMConfig } from '@/utils/llmConfig';
11
15
  import { getArgs } from '@/scripts/args';
12
16
  import { GraphEvents } from '@/common';
13
17
  import { Run } from '@/run';
14
18
 
15
-
16
19
  const conversationHistory: BaseMessage[] = [];
17
20
 
18
21
  async function testCodeExecution(): Promise<void> {
@@ -23,38 +26,57 @@ async function testCodeExecution(): Promise<void> {
23
26
  [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(),
24
27
  [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
25
28
  [GraphEvents.ON_RUN_STEP_COMPLETED]: {
26
- handle: (event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData): void => {
29
+ handle: (
30
+ event: GraphEvents.ON_RUN_STEP_COMPLETED,
31
+ data: t.StreamEventData
32
+ ): void => {
27
33
  console.log('====== ON_RUN_STEP_COMPLETED ======');
28
34
  console.dir(data, { depth: null });
29
- aggregateContent({ event, data: data as unknown as { result: t.ToolEndEvent } });
30
- }
35
+ aggregateContent({
36
+ event,
37
+ data: data as unknown as { result: t.ToolEndEvent },
38
+ });
39
+ },
31
40
  },
32
41
  [GraphEvents.ON_RUN_STEP]: {
33
- handle: (event: GraphEvents.ON_RUN_STEP, data: t.StreamEventData): void => {
42
+ handle: (
43
+ event: GraphEvents.ON_RUN_STEP,
44
+ data: t.StreamEventData
45
+ ): void => {
34
46
  console.log('====== ON_RUN_STEP ======');
35
47
  console.dir(data, { depth: null });
36
48
  aggregateContent({ event, data: data as t.RunStep });
37
- }
49
+ },
38
50
  },
39
51
  [GraphEvents.ON_RUN_STEP_DELTA]: {
40
- handle: (event: GraphEvents.ON_RUN_STEP_DELTA, data: t.StreamEventData): void => {
52
+ handle: (
53
+ event: GraphEvents.ON_RUN_STEP_DELTA,
54
+ data: t.StreamEventData
55
+ ): void => {
41
56
  console.log('====== ON_RUN_STEP_DELTA ======');
42
57
  console.dir(data, { depth: null });
43
58
  aggregateContent({ event, data: data as t.RunStepDeltaEvent });
44
- }
59
+ },
45
60
  },
46
61
  [GraphEvents.ON_MESSAGE_DELTA]: {
47
- handle: (event: GraphEvents.ON_MESSAGE_DELTA, data: t.StreamEventData): void => {
62
+ handle: (
63
+ event: GraphEvents.ON_MESSAGE_DELTA,
64
+ data: t.StreamEventData
65
+ ): void => {
48
66
  console.log('====== ON_MESSAGE_DELTA ======');
49
67
  console.dir(data, { depth: null });
50
68
  aggregateContent({ event, data: data as t.MessageDeltaEvent });
51
- }
69
+ },
52
70
  },
53
71
  [GraphEvents.TOOL_START]: {
54
- handle: (_event: string, data: t.StreamEventData, metadata?: Record<string, unknown>): void => {
72
+ handle: (
73
+ _event: string,
74
+ data: t.StreamEventData,
75
+ metadata?: Record<string, unknown>
76
+ ): void => {
55
77
  console.log('====== TOOL_START ======');
56
78
  console.dir(data, { depth: null });
57
- }
79
+ },
58
80
  },
59
81
  };
60
82
 
@@ -67,14 +89,19 @@ async function testCodeExecution(): Promise<void> {
67
89
  llmConfig,
68
90
  tools: [fetchRandomImageTool],
69
91
  // tools: [fetchRandomImageURL],
70
- instructions: 'You are a friendly AI assistant with internet capabilities. Always address the user by their name.',
92
+ instructions:
93
+ 'You are a friendly AI assistant with internet capabilities. Always address the user by their name.',
71
94
  additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
72
95
  },
73
96
  returnContent: true,
74
97
  customHandlers,
75
98
  });
76
99
 
77
- const config: Partial<RunnableConfig> & { version: 'v1' | 'v2'; run_id?: string; streamMode: string } = {
100
+ const config: Partial<RunnableConfig> & {
101
+ version: 'v1' | 'v2';
102
+ run_id?: string;
103
+ streamMode: string;
104
+ } = {
78
105
  configurable: {
79
106
  provider,
80
107
  thread_id: 'conversation-num-1',
@@ -109,7 +136,9 @@ async function testCodeExecution(): Promise<void> {
109
136
  inputs = {
110
137
  messages: conversationHistory,
111
138
  };
112
- const finalContentParts2 = await run.processStream(inputs, config, { keepContent: true });
139
+ const finalContentParts2 = await run.processStream(inputs, config, {
140
+ keepContent: true,
141
+ });
113
142
  const finalMessages2 = run.getRunMessages();
114
143
  if (finalMessages2) {
115
144
  conversationHistory.push(...finalMessages2);
@@ -119,12 +148,15 @@ async function testCodeExecution(): Promise<void> {
119
148
 
120
149
  const { handleLLMEnd, collected } = createMetadataAggregator();
121
150
  const titleResult = await run.generateTitle({
151
+ provider,
122
152
  inputText: userMessage2,
123
153
  contentParts,
124
154
  chainOptions: {
125
- callbacks: [{
126
- handleLLMEnd,
127
- }],
155
+ callbacks: [
156
+ {
157
+ handleLLMEnd,
158
+ },
159
+ ],
128
160
  },
129
161
  });
130
162
  console.log('Generated Title:', titleResult);
@@ -143,4 +175,4 @@ testCodeExecution().catch((err) => {
143
175
  console.log('Conversation history:');
144
176
  console.dir(conversationHistory, { depth: null });
145
177
  process.exit(1);
146
- });
178
+ });
@@ -160,6 +160,7 @@ async function testStandardStreaming(): Promise<void> {
160
160
  console.dir(contentParts, { depth: null });
161
161
  const { handleLLMEnd, collected } = createMetadataAggregator();
162
162
  const titleOptions: t.RunTitleOptions = {
163
+ provider,
163
164
  inputText: userMessage,
164
165
  contentParts,
165
166
  chainOptions: {
@@ -4,10 +4,18 @@
4
4
  import { config } from 'dotenv';
5
5
  config();
6
6
  import { Calculator } from '@langchain/community/tools/calculator';
7
- import { HumanMessage, BaseMessage, UsageMetadata } from '@langchain/core/messages';
7
+ import {
8
+ HumanMessage,
9
+ BaseMessage,
10
+ UsageMetadata,
11
+ } from '@langchain/core/messages';
8
12
  import type { StandardGraph } from '@/graphs';
9
13
  import type * as t from '@/types';
10
- import { ToolEndHandler, ModelEndHandler, createMetadataAggregator } from '@/events';
14
+ import {
15
+ ToolEndHandler,
16
+ ModelEndHandler,
17
+ createMetadataAggregator,
18
+ } from '@/events';
11
19
  import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
12
20
  import { ContentTypes, GraphEvents, Providers } from '@/common';
13
21
  import { capitalizeFirstLetter } from './spec.utils';
@@ -36,7 +44,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
36
44
  beforeEach(async () => {
37
45
  conversationHistory = [];
38
46
  collectedUsage = [];
39
- const { contentParts: cp, aggregateContent: ac } = createContentAggregator();
47
+ const { contentParts: cp, aggregateContent: ac } =
48
+ createContentAggregator();
40
49
  contentParts = cp as t.MessageContentComplex[];
41
50
  aggregateContent = ac;
42
51
  });
@@ -49,36 +58,62 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
49
58
  onRunStepSpy.mockReset();
50
59
  });
51
60
 
52
- const setupCustomHandlers = (): Record<string | GraphEvents, t.EventHandler> => ({
61
+ const setupCustomHandlers = (): Record<
62
+ string | GraphEvents,
63
+ t.EventHandler
64
+ > => ({
53
65
  [GraphEvents.TOOL_END]: new ToolEndHandler(),
54
66
  [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(collectedUsage),
55
67
  [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
56
68
  [GraphEvents.ON_RUN_STEP_COMPLETED]: {
57
- handle: (event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData): void => {
58
- aggregateContent({ event, data: data as unknown as { result: t.ToolEndEvent; } });
59
- }
69
+ handle: (
70
+ event: GraphEvents.ON_RUN_STEP_COMPLETED,
71
+ data: t.StreamEventData
72
+ ): void => {
73
+ aggregateContent({
74
+ event,
75
+ data: data as unknown as { result: t.ToolEndEvent },
76
+ });
77
+ },
60
78
  },
61
79
  [GraphEvents.ON_RUN_STEP]: {
62
- handle: (event: GraphEvents.ON_RUN_STEP, data: t.StreamEventData, metadata, graph): void => {
80
+ handle: (
81
+ event: GraphEvents.ON_RUN_STEP,
82
+ data: t.StreamEventData,
83
+ metadata,
84
+ graph
85
+ ): void => {
63
86
  onRunStepSpy(event, data, metadata, graph);
64
87
  aggregateContent({ event, data: data as t.RunStep });
65
- }
88
+ },
66
89
  },
67
90
  [GraphEvents.ON_RUN_STEP_DELTA]: {
68
- handle: (event: GraphEvents.ON_RUN_STEP_DELTA, data: t.StreamEventData): void => {
91
+ handle: (
92
+ event: GraphEvents.ON_RUN_STEP_DELTA,
93
+ data: t.StreamEventData
94
+ ): void => {
69
95
  aggregateContent({ event, data: data as t.RunStepDeltaEvent });
70
- }
96
+ },
71
97
  },
72
98
  [GraphEvents.ON_MESSAGE_DELTA]: {
73
- handle: (event: GraphEvents.ON_MESSAGE_DELTA, data: t.StreamEventData, metadata, graph): void => {
99
+ handle: (
100
+ event: GraphEvents.ON_MESSAGE_DELTA,
101
+ data: t.StreamEventData,
102
+ metadata,
103
+ graph
104
+ ): void => {
74
105
  onMessageDeltaSpy(event, data, metadata, graph);
75
106
  aggregateContent({ event, data: data as t.MessageDeltaEvent });
76
- }
107
+ },
77
108
  },
78
109
  [GraphEvents.TOOL_START]: {
79
- handle: (_event: string, _data: t.StreamEventData, _metadata?: Record<string, unknown>): void => {
110
+ handle: (
111
+ _event: string,
112
+ _data: t.StreamEventData,
113
+ _metadata?: Record<string, unknown>
114
+ ): void => {
80
115
  // Handle tool start
81
- }
116
+ },
82
117
  },
83
118
  });
84
119
 
@@ -93,7 +128,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
93
128
  type: 'standard',
94
129
  llmConfig,
95
130
  tools: [new Calculator()],
96
- instructions: 'You are a friendly AI assistant. Always address the user by their name.',
131
+ instructions:
132
+ 'You are a friendly AI assistant. Always address the user by their name.',
97
133
  additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
98
134
  },
99
135
  returnContent: true,
@@ -109,7 +145,9 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
109
145
 
110
146
  const finalContentParts = await run.processStream(inputs, config);
111
147
  expect(finalContentParts).toBeDefined();
112
- const allTextParts = finalContentParts?.every((part) => part.type === ContentTypes.TEXT);
148
+ const allTextParts = finalContentParts?.every(
149
+ (part) => part.type === ContentTypes.TEXT
150
+ );
113
151
  expect(allTextParts).toBe(true);
114
152
  expect(collectedUsage.length).toBeGreaterThan(0);
115
153
  expect(collectedUsage[0].input_tokens).toBeGreaterThan(0);
@@ -117,26 +155,33 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
117
155
 
118
156
  const finalMessages = run.getRunMessages();
119
157
  expect(finalMessages).toBeDefined();
120
- conversationHistory.push(...finalMessages ?? []);
158
+ conversationHistory.push(...(finalMessages ?? []));
121
159
  expect(conversationHistory.length).toBeGreaterThan(1);
122
160
  runningHistory = conversationHistory.slice();
123
161
 
124
162
  expect(onMessageDeltaSpy).toHaveBeenCalled();
125
163
  expect(onMessageDeltaSpy.mock.calls.length).toBeGreaterThan(1);
126
- expect((onMessageDeltaSpy.mock.calls[0][3] as StandardGraph).provider).toBeDefined();
164
+ expect(
165
+ (onMessageDeltaSpy.mock.calls[0][3] as StandardGraph).provider
166
+ ).toBeDefined();
127
167
 
128
168
  expect(onRunStepSpy).toHaveBeenCalled();
129
169
  expect(onRunStepSpy.mock.calls.length).toBeGreaterThan(0);
130
- expect((onRunStepSpy.mock.calls[0][3] as StandardGraph).provider).toBeDefined();
170
+ expect(
171
+ (onRunStepSpy.mock.calls[0][3] as StandardGraph).provider
172
+ ).toBeDefined();
131
173
 
132
174
  const { handleLLMEnd, collected } = createMetadataAggregator();
133
175
  const titleResult = await run.generateTitle({
176
+ provider,
134
177
  inputText: userMessage,
135
178
  contentParts,
136
179
  chainOptions: {
137
- callbacks: [{
138
- handleLLMEnd,
139
- }],
180
+ callbacks: [
181
+ {
182
+ handleLLMEnd,
183
+ },
184
+ ],
140
185
  },
141
186
  });
142
187
 
@@ -148,7 +193,10 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
148
193
 
149
194
  test(`${capitalizeFirstLetter(provider)}: should follow-up`, async () => {
150
195
  console.log('Previous conversation length:', runningHistory.length);
151
- console.log('Last message:', runningHistory[runningHistory.length - 1].content);
196
+ console.log(
197
+ 'Last message:',
198
+ runningHistory[runningHistory.length - 1].content
199
+ );
152
200
  const { userName, location } = await getArgs();
153
201
  const llmConfig = getLLMConfig(provider);
154
202
  const customHandlers = setupCustomHandlers();
@@ -159,7 +207,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
159
207
  type: 'standard',
160
208
  llmConfig,
161
209
  tools: [new Calculator()],
162
- instructions: 'You are a friendly AI assistant. Always address the user by their name.',
210
+ instructions:
211
+ 'You are a friendly AI assistant. Always address the user by their name.',
163
212
  additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
164
213
  },
165
214
  returnContent: true,
@@ -175,7 +224,9 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
175
224
 
176
225
  const finalContentParts = await run.processStream(inputs, config);
177
226
  expect(finalContentParts).toBeDefined();
178
- const allTextParts = finalContentParts?.every((part) => part.type === ContentTypes.TEXT);
227
+ const allTextParts = finalContentParts?.every(
228
+ (part) => part.type === ContentTypes.TEXT
229
+ );
179
230
  expect(allTextParts).toBe(true);
180
231
  expect(collectedUsage.length).toBeGreaterThan(0);
181
232
  expect(collectedUsage[0].input_tokens).toBeGreaterThan(0);
@@ -184,7 +235,10 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
184
235
  const finalMessages = run.getRunMessages();
185
236
  expect(finalMessages).toBeDefined();
186
237
  expect(finalMessages?.length).toBeGreaterThan(0);
187
- console.log(`${capitalizeFirstLetter(provider)} follow-up message:`, finalMessages?.[finalMessages.length - 1]?.content);
238
+ console.log(
239
+ `${capitalizeFirstLetter(provider)} follow-up message:`,
240
+ finalMessages?.[finalMessages.length - 1]?.content
241
+ );
188
242
 
189
243
  expect(onMessageDeltaSpy).toHaveBeenCalled();
190
244
  expect(onMessageDeltaSpy.mock.calls.length).toBeGreaterThan(1);
@@ -196,9 +250,12 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
196
250
  test('should handle errors appropriately', async () => {
197
251
  // Test error scenarios
198
252
  await expect(async () => {
199
- await run.processStream({
200
- messages: [],
201
- }, {} as any);
253
+ await run.processStream(
254
+ {
255
+ messages: [],
256
+ },
257
+ {} as any
258
+ );
202
259
  }).rejects.toThrow();
203
260
  });
204
- });
261
+ });
@@ -4,10 +4,18 @@
4
4
  import { config } from 'dotenv';
5
5
  config();
6
6
  import { Calculator } from '@langchain/community/tools/calculator';
7
- import { HumanMessage, BaseMessage, UsageMetadata } from '@langchain/core/messages';
7
+ import {
8
+ HumanMessage,
9
+ BaseMessage,
10
+ UsageMetadata,
11
+ } from '@langchain/core/messages';
8
12
  import type { StandardGraph } from '@/graphs';
9
13
  import type * as t from '@/types';
10
- import { ToolEndHandler, ModelEndHandler, createMetadataAggregator } from '@/events';
14
+ import {
15
+ ToolEndHandler,
16
+ ModelEndHandler,
17
+ createMetadataAggregator,
18
+ } from '@/events';
11
19
  import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
12
20
  import { ContentTypes, GraphEvents, Providers } from '@/common';
13
21
  import { capitalizeFirstLetter } from './spec.utils';
@@ -36,7 +44,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
36
44
  beforeEach(async () => {
37
45
  conversationHistory = [];
38
46
  collectedUsage = [];
39
- const { contentParts: cp, aggregateContent: ac } = createContentAggregator();
47
+ const { contentParts: cp, aggregateContent: ac } =
48
+ createContentAggregator();
40
49
  contentParts = cp as t.MessageContentComplex[];
41
50
  aggregateContent = ac;
42
51
  });
@@ -49,36 +58,62 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
49
58
  onRunStepSpy.mockReset();
50
59
  });
51
60
 
52
- const setupCustomHandlers = (): Record<string | GraphEvents, t.EventHandler> => ({
61
+ const setupCustomHandlers = (): Record<
62
+ string | GraphEvents,
63
+ t.EventHandler
64
+ > => ({
53
65
  [GraphEvents.TOOL_END]: new ToolEndHandler(),
54
66
  [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(collectedUsage),
55
67
  [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
56
68
  [GraphEvents.ON_RUN_STEP_COMPLETED]: {
57
- handle: (event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData): void => {
58
- aggregateContent({ event, data: data as unknown as { result: t.ToolEndEvent; } });
59
- }
69
+ handle: (
70
+ event: GraphEvents.ON_RUN_STEP_COMPLETED,
71
+ data: t.StreamEventData
72
+ ): void => {
73
+ aggregateContent({
74
+ event,
75
+ data: data as unknown as { result: t.ToolEndEvent },
76
+ });
77
+ },
60
78
  },
61
79
  [GraphEvents.ON_RUN_STEP]: {
62
- handle: (event: GraphEvents.ON_RUN_STEP, data: t.StreamEventData, metadata, graph): void => {
80
+ handle: (
81
+ event: GraphEvents.ON_RUN_STEP,
82
+ data: t.StreamEventData,
83
+ metadata,
84
+ graph
85
+ ): void => {
63
86
  onRunStepSpy(event, data, metadata, graph);
64
87
  aggregateContent({ event, data: data as t.RunStep });
65
- }
88
+ },
66
89
  },
67
90
  [GraphEvents.ON_RUN_STEP_DELTA]: {
68
- handle: (event: GraphEvents.ON_RUN_STEP_DELTA, data: t.StreamEventData): void => {
91
+ handle: (
92
+ event: GraphEvents.ON_RUN_STEP_DELTA,
93
+ data: t.StreamEventData
94
+ ): void => {
69
95
  aggregateContent({ event, data: data as t.RunStepDeltaEvent });
70
- }
96
+ },
71
97
  },
72
98
  [GraphEvents.ON_MESSAGE_DELTA]: {
73
- handle: (event: GraphEvents.ON_MESSAGE_DELTA, data: t.StreamEventData, metadata, graph): void => {
99
+ handle: (
100
+ event: GraphEvents.ON_MESSAGE_DELTA,
101
+ data: t.StreamEventData,
102
+ metadata,
103
+ graph
104
+ ): void => {
74
105
  onMessageDeltaSpy(event, data, metadata, graph);
75
106
  aggregateContent({ event, data: data as t.MessageDeltaEvent });
76
- }
107
+ },
77
108
  },
78
109
  [GraphEvents.TOOL_START]: {
79
- handle: (_event: string, _data: t.StreamEventData, _metadata?: Record<string, unknown>): void => {
110
+ handle: (
111
+ _event: string,
112
+ _data: t.StreamEventData,
113
+ _metadata?: Record<string, unknown>
114
+ ): void => {
80
115
  // Handle tool start
81
- }
116
+ },
82
117
  },
83
118
  });
84
119
 
@@ -93,7 +128,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
93
128
  type: 'standard',
94
129
  llmConfig,
95
130
  tools: [new Calculator()],
96
- instructions: 'You are a friendly AI assistant. Always address the user by their name.',
131
+ instructions:
132
+ 'You are a friendly AI assistant. Always address the user by their name.',
97
133
  additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
98
134
  },
99
135
  returnContent: true,
@@ -109,7 +145,9 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
109
145
 
110
146
  const finalContentParts = await run.processStream(inputs, config);
111
147
  expect(finalContentParts).toBeDefined();
112
- const allTextParts = finalContentParts?.every((part) => part.type === ContentTypes.TEXT);
148
+ const allTextParts = finalContentParts?.every(
149
+ (part) => part.type === ContentTypes.TEXT
150
+ );
113
151
  expect(allTextParts).toBe(true);
114
152
  expect(collectedUsage.length).toBeGreaterThan(0);
115
153
  expect(collectedUsage[0].input_tokens).toBeGreaterThan(0);
@@ -117,26 +155,33 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
117
155
 
118
156
  const finalMessages = run.getRunMessages();
119
157
  expect(finalMessages).toBeDefined();
120
- conversationHistory.push(...finalMessages ?? []);
158
+ conversationHistory.push(...(finalMessages ?? []));
121
159
  expect(conversationHistory.length).toBeGreaterThan(1);
122
160
  runningHistory = conversationHistory.slice();
123
161
 
124
162
  expect(onMessageDeltaSpy).toHaveBeenCalled();
125
163
  expect(onMessageDeltaSpy.mock.calls.length).toBeGreaterThan(1);
126
- expect((onMessageDeltaSpy.mock.calls[0][3] as StandardGraph).provider).toBeDefined();
164
+ expect(
165
+ (onMessageDeltaSpy.mock.calls[0][3] as StandardGraph).provider
166
+ ).toBeDefined();
127
167
 
128
168
  expect(onRunStepSpy).toHaveBeenCalled();
129
169
  expect(onRunStepSpy.mock.calls.length).toBeGreaterThan(0);
130
- expect((onRunStepSpy.mock.calls[0][3] as StandardGraph).provider).toBeDefined();
170
+ expect(
171
+ (onRunStepSpy.mock.calls[0][3] as StandardGraph).provider
172
+ ).toBeDefined();
131
173
 
132
174
  const { handleLLMEnd, collected } = createMetadataAggregator();
133
175
  const titleResult = await run.generateTitle({
176
+ provider,
134
177
  inputText: userMessage,
135
178
  contentParts,
136
179
  chainOptions: {
137
- callbacks: [{
138
- handleLLMEnd,
139
- }],
180
+ callbacks: [
181
+ {
182
+ handleLLMEnd,
183
+ },
184
+ ],
140
185
  },
141
186
  });
142
187
 
@@ -148,7 +193,10 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
148
193
 
149
194
  test(`${capitalizeFirstLetter(provider)}: should follow-up`, async () => {
150
195
  console.log('Previous conversation length:', runningHistory.length);
151
- console.log('Last message:', runningHistory[runningHistory.length - 1].content);
196
+ console.log(
197
+ 'Last message:',
198
+ runningHistory[runningHistory.length - 1].content
199
+ );
152
200
  const { userName, location } = await getArgs();
153
201
  const llmConfig = getLLMConfig(provider);
154
202
  const customHandlers = setupCustomHandlers();
@@ -159,7 +207,8 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
159
207
  type: 'standard',
160
208
  llmConfig,
161
209
  tools: [new Calculator()],
162
- instructions: 'You are a friendly AI assistant. Always address the user by their name.',
210
+ instructions:
211
+ 'You are a friendly AI assistant. Always address the user by their name.',
163
212
  additional_instructions: `The user's name is ${userName} and they are located in ${location}.`,
164
213
  },
165
214
  returnContent: true,
@@ -175,7 +224,9 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
175
224
 
176
225
  const finalContentParts = await run.processStream(inputs, config);
177
226
  expect(finalContentParts).toBeDefined();
178
- const allTextParts = finalContentParts?.every((part) => part.type === ContentTypes.TEXT);
227
+ const allTextParts = finalContentParts?.every(
228
+ (part) => part.type === ContentTypes.TEXT
229
+ );
179
230
  expect(allTextParts).toBe(true);
180
231
  expect(collectedUsage.length).toBeGreaterThan(0);
181
232
  expect(collectedUsage[0].input_tokens).toBeGreaterThan(0);
@@ -184,7 +235,10 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
184
235
  const finalMessages = run.getRunMessages();
185
236
  expect(finalMessages).toBeDefined();
186
237
  expect(finalMessages?.length).toBeGreaterThan(0);
187
- console.log(`${capitalizeFirstLetter(provider)} follow-up message:`, finalMessages?.[finalMessages.length - 1]?.content);
238
+ console.log(
239
+ `${capitalizeFirstLetter(provider)} follow-up message:`,
240
+ finalMessages?.[finalMessages.length - 1]?.content
241
+ );
188
242
 
189
243
  expect(onMessageDeltaSpy).toHaveBeenCalled();
190
244
  expect(onMessageDeltaSpy.mock.calls.length).toBeGreaterThan(1);
@@ -196,9 +250,12 @@ describe(`${capitalizeFirstLetter(provider)} Streaming Tests`, () => {
196
250
  test('should handle errors appropriately', async () => {
197
251
  // Test error scenarios
198
252
  await expect(async () => {
199
- await run.processStream({
200
- messages: [],
201
- }, {} as any);
253
+ await run.processStream(
254
+ {
255
+ messages: [],
256
+ },
257
+ {} as any
258
+ );
202
259
  }).rejects.toThrow();
203
260
  });
204
- });
261
+ });
package/src/stream.ts CHANGED
@@ -244,6 +244,7 @@ hasToolCallChunks: ${hasToolCallChunks}
244
244
  content.every(
245
245
  (c) =>
246
246
  (c.type?.startsWith(ContentTypes.THINKING) ?? false) ||
247
+ (c.type?.startsWith(ContentTypes.REASONING) ?? false) ||
247
248
  (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false)
248
249
  )
249
250
  ) {
@@ -252,6 +253,7 @@ hasToolCallChunks: ${hasToolCallChunks}
252
253
  type: ContentTypes.THINK,
253
254
  think:
254
255
  (c as t.ThinkingContentText).thinking ??
256
+ (c as Partial<t.GoogleReasoningContentText>).reasoning ??
255
257
  (c as Partial<t.BedrockReasoningContentText>).reasoningText?.text ??
256
258
  '',
257
259
  })),
@@ -264,8 +266,9 @@ hasToolCallChunks: ${hasToolCallChunks}
264
266
  | undefined;
265
267
  if (
266
268
  Array.isArray(chunk.content) &&
267
- (chunk.content[0]?.type === 'thinking' ||
268
- chunk.content[0]?.type === 'reasoning_content')
269
+ (chunk.content[0]?.type === ContentTypes.THINKING ||
270
+ chunk.content[0]?.type === ContentTypes.REASONING ||
271
+ chunk.content[0]?.type === ContentTypes.REASONING_CONTENT)
269
272
  ) {
270
273
  reasoning_content = 'valid';
271
274
  }
package/src/types/llm.ts CHANGED
@@ -17,6 +17,7 @@ import type {
17
17
  } from '@langchain/openai';
18
18
  import type { BedrockChatFields } from '@langchain/community/chat_models/bedrock/web';
19
19
  import type { GoogleGenerativeAIChatInput } from '@langchain/google-genai';
20
+ import type { GeminiGenerationConfig } from '@langchain/google-common';
20
21
  import type { ChatVertexAIInput } from '@langchain/google-vertexai';
21
22
  import type { ChatDeepSeekCallOptions } from '@langchain/deepseek';
22
23
  import type { ChatOpenRouterCallOptions } from '@/llm/openrouter';
@@ -70,6 +71,7 @@ export type BedrockAnthropicInput = ChatBedrockConverseInput & {
70
71
  export type BedrockConverseClientOptions = ChatBedrockConverseInput;
71
72
  export type GoogleClientOptions = GoogleGenerativeAIChatInput & {
72
73
  customHeaders?: RequestOptions['customHeaders'];
74
+ thinkingConfig?: GeminiGenerationConfig['thinkingConfig'];
73
75
  };
74
76
  export type DeepSeekClientOptions = ChatDeepSeekCallOptions;
75
77
  export type XAIClientOptions = ChatXAIInput;
package/src/types/run.ts CHANGED
@@ -26,6 +26,7 @@ export type StandardGraphConfig = BaseGraphConfig &
26
26
 
27
27
  export type RunTitleOptions = {
28
28
  inputText: string;
29
+ provider: e.Providers;
29
30
  contentParts: (s.MessageContentComplex | undefined)[];
30
31
  titlePrompt?: string;
31
32
  skipLanguage?: boolean;
@@ -251,6 +251,12 @@ export type ReasoningContentText = {
251
251
  think: string;
252
252
  };
253
253
 
254
+ /** Vertex AI / Google Common - Reasoning Content Block Format */
255
+ export type GoogleReasoningContentText = {
256
+ type: ContentTypes.REASONING;
257
+ reasoning: string;
258
+ };
259
+
254
260
  /** Anthropic's Reasoning Content Block Format */
255
261
  export type ThinkingContentText = {
256
262
  type: ContentTypes.THINKING;