@librechat/agents 3.0.80 → 3.0.771

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 (49) hide show
  1. package/dist/cjs/graphs/Graph.cjs +5 -19
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/llm/bedrock/index.cjs +25 -98
  4. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  5. package/dist/cjs/messages/cache.cjs +123 -32
  6. package/dist/cjs/messages/cache.cjs.map +1 -1
  7. package/dist/cjs/messages/core.cjs +1 -1
  8. package/dist/cjs/messages/core.cjs.map +1 -1
  9. package/dist/cjs/stream.cjs +2 -4
  10. package/dist/cjs/stream.cjs.map +1 -1
  11. package/dist/cjs/tools/ToolNode.cjs +5 -9
  12. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  13. package/dist/esm/graphs/Graph.mjs +5 -19
  14. package/dist/esm/graphs/Graph.mjs.map +1 -1
  15. package/dist/esm/llm/bedrock/index.mjs +24 -97
  16. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  17. package/dist/esm/messages/cache.mjs +123 -32
  18. package/dist/esm/messages/cache.mjs.map +1 -1
  19. package/dist/esm/messages/core.mjs +1 -1
  20. package/dist/esm/messages/core.mjs.map +1 -1
  21. package/dist/esm/stream.mjs +2 -4
  22. package/dist/esm/stream.mjs.map +1 -1
  23. package/dist/esm/tools/ToolNode.mjs +5 -9
  24. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  25. package/dist/types/llm/bedrock/index.d.ts +7 -86
  26. package/dist/types/messages/cache.d.ts +6 -2
  27. package/dist/types/types/tools.d.ts +0 -2
  28. package/package.json +3 -6
  29. package/src/graphs/Graph.ts +5 -23
  30. package/src/llm/bedrock/index.ts +43 -180
  31. package/src/messages/cache.test.ts +215 -0
  32. package/src/messages/cache.ts +172 -43
  33. package/src/messages/core.ts +1 -1
  34. package/src/scripts/thinking.ts +18 -39
  35. package/src/scripts/tools.ts +3 -7
  36. package/src/stream.ts +2 -4
  37. package/src/tools/ToolNode.ts +5 -9
  38. package/src/types/tools.ts +0 -2
  39. package/dist/types/llm/bedrock/types.d.ts +0 -27
  40. package/dist/types/llm/bedrock/utils/index.d.ts +0 -5
  41. package/dist/types/llm/bedrock/utils/message_inputs.d.ts +0 -31
  42. package/dist/types/llm/bedrock/utils/message_outputs.d.ts +0 -33
  43. package/src/llm/bedrock/llm.spec.ts +0 -616
  44. package/src/llm/bedrock/types.ts +0 -51
  45. package/src/llm/bedrock/utils/index.ts +0 -18
  46. package/src/llm/bedrock/utils/message_inputs.ts +0 -563
  47. package/src/llm/bedrock/utils/message_outputs.ts +0 -310
  48. package/src/scripts/code_exec_multi_session.ts +0 -241
  49. package/src/scripts/thinking-bedrock.ts +0 -159
@@ -7,13 +7,57 @@ type MessageWithContent = {
7
7
  content?: string | MessageContentComplex[];
8
8
  };
9
9
 
10
+ /**
11
+ * Deep clones a message's content to prevent mutation of the original.
12
+ * Handles both string and array content types.
13
+ */
14
+ function deepCloneContent<T extends string | MessageContentComplex[]>(
15
+ content: T
16
+ ): T {
17
+ if (typeof content === 'string') {
18
+ return content;
19
+ }
20
+ if (Array.isArray(content)) {
21
+ return content.map((block) => ({ ...block })) as T;
22
+ }
23
+ return content;
24
+ }
25
+
26
+ /**
27
+ * Creates a shallow clone of a message with deep-cloned content.
28
+ * This ensures modifications to content don't affect the original message.
29
+ */
30
+ function cloneMessageWithContent<T extends MessageWithContent>(message: T): T {
31
+ if (message.content === undefined) {
32
+ return { ...message };
33
+ }
34
+ return {
35
+ ...message,
36
+ content: deepCloneContent(message.content),
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Checks if a message's content needs cache control stripping.
42
+ * Returns true if content has cachePoint blocks or cache_control fields.
43
+ */
44
+ function needsCacheStripping(content: MessageContentComplex[]): boolean {
45
+ for (let i = 0; i < content.length; i++) {
46
+ const block = content[i];
47
+ if (isCachePoint(block)) return true;
48
+ if ('cache_control' in block) return true;
49
+ }
50
+ return false;
51
+ }
52
+
10
53
  /**
11
54
  * Anthropic API: Adds cache control to the appropriate user messages in the payload.
12
55
  * Strips ALL existing cache control (both Anthropic and Bedrock formats) from all messages,
13
56
  * then adds fresh cache control to the last 2 user messages in a single backward pass.
14
57
  * This ensures we don't accumulate stale cache points across multiple turns.
58
+ * Returns a new array - only clones messages that require modification.
15
59
  * @param messages - The array of message objects.
16
- * @returns - The updated array of message objects with cache control added.
60
+ * @returns - A new array of message objects with cache control added.
17
61
  */
18
62
  export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
19
63
  messages: T[]
@@ -22,22 +66,47 @@ export function addCacheControl<T extends AnthropicMessage | BaseMessage>(
22
66
  return messages;
23
67
  }
24
68
 
25
- const updatedMessages = [...messages];
69
+ const updatedMessages: T[] = [...messages];
26
70
  let userMessagesModified = 0;
27
71
 
28
72
  for (let i = updatedMessages.length - 1; i >= 0; i--) {
29
- const message = updatedMessages[i];
73
+ const originalMessage = updatedMessages[i];
30
74
  const isUserMessage =
31
- ('getType' in message && message.getType() === 'human') ||
32
- ('role' in message && message.role === 'user');
75
+ ('getType' in originalMessage && originalMessage.getType() === 'human') ||
76
+ ('role' in originalMessage && originalMessage.role === 'user');
77
+
78
+ const hasArrayContent = Array.isArray(originalMessage.content);
79
+ const needsStripping =
80
+ hasArrayContent &&
81
+ needsCacheStripping(originalMessage.content as MessageContentComplex[]);
82
+ const needsCacheAdd =
83
+ userMessagesModified < 2 &&
84
+ isUserMessage &&
85
+ (typeof originalMessage.content === 'string' || hasArrayContent);
86
+
87
+ if (!needsStripping && !needsCacheAdd) {
88
+ continue;
89
+ }
33
90
 
34
- if (Array.isArray(message.content)) {
35
- message.content = message.content.filter(
91
+ const message = cloneMessageWithContent(
92
+ originalMessage as MessageWithContent
93
+ ) as T;
94
+ updatedMessages[i] = message;
95
+
96
+ if (hasArrayContent) {
97
+ message.content = (message.content as MessageContentComplex[]).filter(
36
98
  (block) => !isCachePoint(block as MessageContentComplex)
37
99
  ) as typeof message.content;
38
100
 
39
- for (let j = 0; j < message.content.length; j++) {
40
- const block = message.content[j] as Record<string, unknown>;
101
+ for (
102
+ let j = 0;
103
+ j < (message.content as MessageContentComplex[]).length;
104
+ j++
105
+ ) {
106
+ const block = (message.content as MessageContentComplex[])[j] as Record<
107
+ string,
108
+ unknown
109
+ >;
41
110
  if ('cache_control' in block) {
42
111
  delete block.cache_control;
43
112
  }
@@ -81,9 +150,20 @@ function isCachePoint(block: MessageContentComplex): boolean {
81
150
  return 'cachePoint' in block && !('type' in block);
82
151
  }
83
152
 
153
+ /**
154
+ * Checks if a message's content has Anthropic cache_control fields.
155
+ */
156
+ function hasAnthropicCacheControl(content: MessageContentComplex[]): boolean {
157
+ for (let i = 0; i < content.length; i++) {
158
+ if ('cache_control' in content[i]) return true;
159
+ }
160
+ return false;
161
+ }
162
+
84
163
  /**
85
164
  * Removes all Anthropic cache_control fields from messages
86
165
  * Used when switching from Anthropic to Bedrock provider
166
+ * Returns a new array - only clones messages that require modification.
87
167
  */
88
168
  export function stripAnthropicCacheControl<T extends MessageWithContent>(
89
169
  messages: T[]
@@ -92,18 +172,30 @@ export function stripAnthropicCacheControl<T extends MessageWithContent>(
92
172
  return messages;
93
173
  }
94
174
 
95
- const updatedMessages = [...messages];
175
+ const updatedMessages: T[] = [...messages];
96
176
 
97
177
  for (let i = 0; i < updatedMessages.length; i++) {
98
- const message = updatedMessages[i];
99
- const content = message.content;
178
+ const originalMessage = updatedMessages[i];
179
+ const content = originalMessage.content;
100
180
 
101
- if (Array.isArray(content)) {
102
- for (let j = 0; j < content.length; j++) {
103
- const block = content[j] as Record<string, unknown>;
104
- if ('cache_control' in block) {
105
- delete block.cache_control;
106
- }
181
+ if (!Array.isArray(content) || !hasAnthropicCacheControl(content)) {
182
+ continue;
183
+ }
184
+
185
+ const message = cloneMessageWithContent(originalMessage);
186
+ updatedMessages[i] = message;
187
+
188
+ for (
189
+ let j = 0;
190
+ j < (message.content as MessageContentComplex[]).length;
191
+ j++
192
+ ) {
193
+ const block = (message.content as MessageContentComplex[])[j] as Record<
194
+ string,
195
+ unknown
196
+ >;
197
+ if ('cache_control' in block) {
198
+ delete block.cache_control;
107
199
  }
108
200
  }
109
201
  }
@@ -111,9 +203,20 @@ export function stripAnthropicCacheControl<T extends MessageWithContent>(
111
203
  return updatedMessages;
112
204
  }
113
205
 
206
+ /**
207
+ * Checks if a message's content has Bedrock cachePoint blocks.
208
+ */
209
+ function hasBedrockCachePoint(content: MessageContentComplex[]): boolean {
210
+ for (let i = 0; i < content.length; i++) {
211
+ if (isCachePoint(content[i])) return true;
212
+ }
213
+ return false;
214
+ }
215
+
114
216
  /**
115
217
  * Removes all Bedrock cachePoint blocks from messages
116
218
  * Used when switching from Bedrock to Anthropic provider
219
+ * Returns a new array - only clones messages that require modification.
117
220
  */
118
221
  export function stripBedrockCacheControl<T extends MessageWithContent>(
119
222
  messages: T[]
@@ -122,17 +225,22 @@ export function stripBedrockCacheControl<T extends MessageWithContent>(
122
225
  return messages;
123
226
  }
124
227
 
125
- const updatedMessages = [...messages];
228
+ const updatedMessages: T[] = [...messages];
126
229
 
127
230
  for (let i = 0; i < updatedMessages.length; i++) {
128
- const message = updatedMessages[i];
129
- const content = message.content;
231
+ const originalMessage = updatedMessages[i];
232
+ const content = originalMessage.content;
130
233
 
131
- if (Array.isArray(content)) {
132
- message.content = content.filter(
133
- (block) => !isCachePoint(block as MessageContentComplex)
134
- ) as typeof content;
234
+ if (!Array.isArray(content) || !hasBedrockCachePoint(content)) {
235
+ continue;
135
236
  }
237
+
238
+ const message = cloneMessageWithContent(originalMessage);
239
+ updatedMessages[i] = message;
240
+
241
+ message.content = (message.content as MessageContentComplex[]).filter(
242
+ (block) => !isCachePoint(block as MessageContentComplex)
243
+ ) as typeof content;
136
244
  }
137
245
 
138
246
  return updatedMessages;
@@ -145,8 +253,9 @@ export function stripBedrockCacheControl<T extends MessageWithContent>(
145
253
  * Strips ALL existing cache control (both Bedrock and Anthropic formats) from all messages,
146
254
  * then adds fresh cache points to the last 2 messages in a single backward pass.
147
255
  * This ensures we don't accumulate stale cache points across multiple turns.
256
+ * Returns a new array - only clones messages that require modification.
148
257
  * @param messages - The array of message objects.
149
- * @returns - The updated array of message objects with cache points added.
258
+ * @returns - A new array of message objects with cache points added.
150
259
  */
151
260
  export function addBedrockCacheControl<
152
261
  T extends Partial<BaseMessage> & MessageWithContent,
@@ -155,42 +264,62 @@ export function addBedrockCacheControl<
155
264
  return messages;
156
265
  }
157
266
 
158
- const updatedMessages: T[] = messages.slice();
267
+ const updatedMessages: T[] = [...messages];
159
268
  let messagesModified = 0;
160
269
 
161
270
  for (let i = updatedMessages.length - 1; i >= 0; i--) {
162
- const message = updatedMessages[i];
271
+ const originalMessage = updatedMessages[i];
163
272
  const isToolMessage =
164
- 'getType' in message &&
165
- typeof message.getType === 'function' &&
166
- message.getType() === 'tool';
273
+ 'getType' in originalMessage &&
274
+ typeof originalMessage.getType === 'function' &&
275
+ originalMessage.getType() === 'tool';
276
+
277
+ const content = originalMessage.content;
278
+ const hasArrayContent = Array.isArray(content);
279
+ const needsStripping =
280
+ hasArrayContent &&
281
+ needsCacheStripping(content as MessageContentComplex[]);
282
+ const isEmptyString = typeof content === 'string' && content === '';
283
+ const needsCacheAdd =
284
+ messagesModified < 2 &&
285
+ !isToolMessage &&
286
+ !isEmptyString &&
287
+ (typeof content === 'string' || hasArrayContent);
288
+
289
+ if (!needsStripping && !needsCacheAdd) {
290
+ continue;
291
+ }
167
292
 
168
- const content = message.content;
293
+ const message = cloneMessageWithContent(originalMessage);
294
+ updatedMessages[i] = message;
169
295
 
170
- if (Array.isArray(content)) {
171
- message.content = content.filter(
296
+ if (hasArrayContent) {
297
+ message.content = (message.content as MessageContentComplex[]).filter(
172
298
  (block) => !isCachePoint(block)
173
299
  ) as typeof content;
174
300
 
175
- for (let j = 0; j < message.content.length; j++) {
176
- const block = message.content[j] as Record<string, unknown>;
301
+ for (
302
+ let j = 0;
303
+ j < (message.content as MessageContentComplex[]).length;
304
+ j++
305
+ ) {
306
+ const block = (message.content as MessageContentComplex[])[j] as Record<
307
+ string,
308
+ unknown
309
+ >;
177
310
  if ('cache_control' in block) {
178
311
  delete block.cache_control;
179
312
  }
180
313
  }
181
314
  }
182
315
 
183
- if (messagesModified >= 2 || isToolMessage) {
316
+ if (messagesModified >= 2 || isToolMessage || isEmptyString) {
184
317
  continue;
185
318
  }
186
319
 
187
- if (typeof content === 'string' && content === '') {
188
- continue;
189
- }
190
-
191
- if (typeof content === 'string') {
320
+ if (typeof message.content === 'string') {
192
321
  message.content = [
193
- { type: ContentTypes.TEXT, text: content },
322
+ { type: ContentTypes.TEXT, text: message.content },
194
323
  { cachePoint: { type: 'default' } },
195
324
  ] as MessageContentComplex[];
196
325
  messagesModified++;
@@ -41,7 +41,7 @@ User: ${userMessage[1]}
41
41
  const _allowedTypes = ['image_url', 'text', 'tool_use', 'tool_result'];
42
42
  const allowedTypesByProvider: Record<string, string[]> = {
43
43
  default: _allowedTypes,
44
- [Providers.ANTHROPIC]: [..._allowedTypes, 'thinking', 'redacted_thinking'],
44
+ [Providers.ANTHROPIC]: [..._allowedTypes, 'thinking'],
45
45
  [Providers.BEDROCK]: [..._allowedTypes, 'reasoning_content'],
46
46
  [Providers.OPENAI]: _allowedTypes,
47
47
  };
@@ -1,11 +1,7 @@
1
1
  // src/scripts/test-thinking.ts
2
2
  import { config } from 'dotenv';
3
3
  config();
4
- import {
5
- HumanMessage,
6
- SystemMessage,
7
- BaseMessage,
8
- } from '@langchain/core/messages';
4
+ import { HumanMessage, SystemMessage, BaseMessage } from '@langchain/core/messages';
9
5
  import type { UsageMetadata } from '@langchain/core/messages';
10
6
  import * as t from '@/types';
11
7
  import { ChatModelStreamHandler, createContentAggregator } from '@/stream';
@@ -25,23 +21,17 @@ async function testThinking(): Promise<void> {
25
21
  const instructions = `You are a helpful AI assistant for ${userName}. When answering questions, be thorough in your reasoning.`;
26
22
  const { contentParts, aggregateContent } = createContentAggregator();
27
23
  _contentParts = contentParts as t.MessageContentComplex[];
28
-
24
+
29
25
  // Set up event handlers
30
26
  const customHandlers = {
31
27
  [GraphEvents.TOOL_END]: new ToolEndHandler(),
32
28
  [GraphEvents.CHAT_MODEL_END]: new ModelEndHandler(collectedUsage),
33
29
  [GraphEvents.CHAT_MODEL_STREAM]: new ChatModelStreamHandler(),
34
30
  [GraphEvents.ON_RUN_STEP_COMPLETED]: {
35
- handle: (
36
- event: GraphEvents.ON_RUN_STEP_COMPLETED,
37
- data: t.StreamEventData
38
- ): void => {
31
+ handle: (event: GraphEvents.ON_RUN_STEP_COMPLETED, data: t.StreamEventData): void => {
39
32
  console.log('====== ON_RUN_STEP_COMPLETED ======');
40
- aggregateContent({
41
- event,
42
- data: data as unknown as { result: t.ToolEndEvent },
43
- });
44
- },
33
+ aggregateContent({ event, data: data as unknown as { result: t.ToolEndEvent } });
34
+ }
45
35
  },
46
36
  [GraphEvents.ON_RUN_STEP]: {
47
37
  handle: (event: GraphEvents.ON_RUN_STEP, data: t.RunStep) => {
@@ -49,38 +39,29 @@ async function testThinking(): Promise<void> {
49
39
  },
50
40
  },
51
41
  [GraphEvents.ON_RUN_STEP_DELTA]: {
52
- handle: (
53
- event: GraphEvents.ON_RUN_STEP_DELTA,
54
- data: t.RunStepDeltaEvent
55
- ) => {
42
+ handle: (event: GraphEvents.ON_RUN_STEP_DELTA, data: t.RunStepDeltaEvent) => {
56
43
  aggregateContent({ event, data });
57
44
  },
58
45
  },
59
46
  [GraphEvents.ON_MESSAGE_DELTA]: {
60
- handle: (
61
- event: GraphEvents.ON_MESSAGE_DELTA,
62
- data: t.MessageDeltaEvent
63
- ) => {
47
+ handle: (event: GraphEvents.ON_MESSAGE_DELTA, data: t.MessageDeltaEvent) => {
64
48
  aggregateContent({ event, data });
65
49
  },
66
50
  },
67
51
  [GraphEvents.ON_REASONING_DELTA]: {
68
- handle: (
69
- event: GraphEvents.ON_REASONING_DELTA,
70
- data: t.ReasoningDeltaEvent
71
- ) => {
52
+ handle: (event: GraphEvents.ON_REASONING_DELTA, data: t.ReasoningDeltaEvent) => {
72
53
  aggregateContent({ event, data });
73
54
  },
74
55
  },
75
56
  };
76
57
 
77
58
  const baseLlmConfig: t.LLMConfig = getLLMConfig(Providers.ANTHROPIC);
78
-
59
+
79
60
  // Enable thinking with token budget
80
61
  const llmConfig = {
81
62
  ...baseLlmConfig,
82
63
  model: 'claude-3-7-sonnet-latest',
83
- thinking: { type: 'enabled', budget_tokens: 2000 },
64
+ thinking: { type: "enabled", budget_tokens: 2000 }
84
65
  };
85
66
 
86
67
  const run = await Run.create<t.IState>({
@@ -112,7 +93,7 @@ async function testThinking(): Promise<void> {
112
93
  console.log('Running first query with thinking enabled...');
113
94
  const firstInputs = { messages: [...conversationHistory] };
114
95
  await run.processStream(firstInputs, config);
115
-
96
+
116
97
  // Extract and display thinking blocks
117
98
  const finalMessages = run.getRunMessages();
118
99
 
@@ -120,32 +101,30 @@ async function testThinking(): Promise<void> {
120
101
  console.log('\n\nTest 2: Multi-turn conversation with thinking enabled');
121
102
  const userMessage2 = `Given your previous analysis, what would be the most significant technical challenges in making this transition?`;
122
103
  conversationHistory.push(new HumanMessage(userMessage2));
123
-
104
+
124
105
  console.log('Running second query with thinking enabled...');
125
106
  const secondInputs = { messages: [...conversationHistory] };
126
107
  await run.processStream(secondInputs, config);
127
-
108
+
128
109
  // Display thinking blocks for second response
129
110
  const finalMessages2 = run.getRunMessages();
130
111
 
131
112
  // Test 3: Redacted thinking mode
132
113
  console.log('\n\nTest 3: Redacted thinking mode');
133
- const magicString =
134
- 'ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB';
114
+ const magicString = "ANTHROPIC_MAGIC_STRING_TRIGGER_REDACTED_THINKING_46C9A13E193C177646C7398A98432ECCCE4C1253D5E2D82641AC0E52CC2876CB";
135
115
  const userMessage3 = `${magicString}\n\nExplain how quantum computing works in simple terms.`;
136
-
116
+
137
117
  // Reset conversation for clean test
138
118
  conversationHistory.length = 0;
139
119
  conversationHistory.push(new HumanMessage(userMessage3));
140
-
120
+
141
121
  console.log('Running query with redacted thinking...');
142
122
  const thirdInputs = { messages: [...conversationHistory] };
143
123
  await run.processStream(thirdInputs, config);
144
-
124
+
145
125
  // Display redacted thinking blocks
146
126
  const finalMessages3 = run.getRunMessages();
147
127
  console.log('\n\nThinking feature test completed!');
148
- console.dir(finalMessages3, { depth: null });
149
128
  }
150
129
 
151
130
  process.on('unhandledRejection', (reason, promise) => {
@@ -168,4 +147,4 @@ testThinking().catch((err) => {
168
147
  console.log('Content parts:');
169
148
  console.dir(_contentParts, { depth: null });
170
149
  process.exit(1);
171
- });
150
+ });
@@ -18,13 +18,9 @@ async function testStandardStreaming(): Promise<void> {
18
18
  const { userName, location, provider, currentDate } = await getArgs();
19
19
  const { contentParts, aggregateContent } = createContentAggregator();
20
20
  const customHandlers = {
21
- [GraphEvents.TOOL_END]: new ToolEndHandler(
22
- undefined,
23
- undefined,
24
- (name?: string) => {
25
- return true;
26
- }
27
- ),
21
+ [GraphEvents.TOOL_END]: new ToolEndHandler(undefined, (name?: string) => {
22
+ return true;
23
+ }),
28
24
  [GraphEvents.CHAT_MODEL_END]: {
29
25
  handle: (
30
26
  _event: string,
package/src/stream.ts CHANGED
@@ -339,8 +339,7 @@ hasToolCallChunks: ${hasToolCallChunks}
339
339
  (c) =>
340
340
  (c.type?.startsWith(ContentTypes.THINKING) ?? false) ||
341
341
  (c.type?.startsWith(ContentTypes.REASONING) ?? false) ||
342
- (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false) ||
343
- c.type === 'redacted_thinking'
342
+ (c.type?.startsWith(ContentTypes.REASONING_CONTENT) ?? false)
344
343
  )
345
344
  ) {
346
345
  await graph.dispatchReasoningDelta(stepId, {
@@ -366,8 +365,7 @@ hasToolCallChunks: ${hasToolCallChunks}
366
365
  Array.isArray(chunk.content) &&
367
366
  (chunk.content[0]?.type === ContentTypes.THINKING ||
368
367
  chunk.content[0]?.type === ContentTypes.REASONING ||
369
- chunk.content[0]?.type === ContentTypes.REASONING_CONTENT ||
370
- chunk.content[0]?.type === 'redacted_thinking')
368
+ chunk.content[0]?.type === ContentTypes.REASONING_CONTENT)
371
369
  ) {
372
370
  reasoning_content = 'valid';
373
371
  } else if (
@@ -145,9 +145,9 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
145
145
 
146
146
  /**
147
147
  * Inject session context for code execution tools when available.
148
- * Each file uses its own session_id (supporting multi-session file tracking).
149
148
  * Both session_id and _injected_files are injected directly to invokeParams
150
149
  * (not inside args) so they bypass Zod schema validation and reach config.toolCall.
150
+ * This avoids /files endpoint race conditions.
151
151
  */
152
152
  if (
153
153
  call.name === Constants.EXECUTE_CODE ||
@@ -156,18 +156,14 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
156
156
  const codeSession = this.sessions?.get(Constants.EXECUTE_CODE) as
157
157
  | t.CodeSessionContext
158
158
  | undefined;
159
- if (codeSession?.files != null && codeSession.files.length > 0) {
160
- /**
161
- * Convert tracked files to CodeEnvFile format for the API.
162
- * Each file uses its own session_id (set when file was created).
163
- * This supports files from multiple parallel/sequential executions.
164
- */
159
+ if (codeSession?.session_id != null && codeSession.files.length > 0) {
160
+ /** Convert tracked files to CodeEnvFile format for the API */
165
161
  const fileRefs: t.CodeEnvFile[] = codeSession.files.map((file) => ({
166
- session_id: file.session_id ?? codeSession.session_id,
162
+ session_id: codeSession.session_id,
167
163
  id: file.id,
168
164
  name: file.name,
169
165
  }));
170
- /** Inject latest session_id and files - bypasses Zod, reaches config.toolCall */
166
+ /** Inject session_id and files directly - bypasses Zod, reaches config.toolCall */
171
167
  invokeParams = {
172
168
  ...invokeParams,
173
169
  session_id: codeSession.session_id,
@@ -74,8 +74,6 @@ export type FileRef = {
74
74
  id: string;
75
75
  name: string;
76
76
  path?: string;
77
- /** Session ID this file belongs to (for multi-session file tracking) */
78
- session_id?: string;
79
77
  };
80
78
 
81
79
  export type FileRefs = FileRef[];
@@ -1,27 +0,0 @@
1
- /**
2
- * Type definitions for Bedrock Converse utilities.
3
- */
4
- import type { Message as BedrockMessage, SystemContentBlock as BedrockSystemContentBlock, ContentBlock as BedrockContentBlock, ConverseResponse, ContentBlockDeltaEvent, ConverseStreamMetadataEvent, ContentBlockStartEvent, ReasoningContentBlock, ReasoningContentBlockDelta } from '@aws-sdk/client-bedrock-runtime';
5
- /**
6
- * Reasoning content block type for LangChain messages.
7
- */
8
- export interface MessageContentReasoningBlock {
9
- type: 'reasoning_content';
10
- reasoningText?: {
11
- text?: string;
12
- signature?: string;
13
- };
14
- redactedContent?: string;
15
- }
16
- export interface MessageContentReasoningBlockReasoningTextPartial {
17
- type: 'reasoning_content';
18
- reasoningText: {
19
- text?: string;
20
- signature?: string;
21
- };
22
- }
23
- export interface MessageContentReasoningBlockRedacted {
24
- type: 'reasoning_content';
25
- redactedContent: string;
26
- }
27
- export type { BedrockMessage, BedrockSystemContentBlock, BedrockContentBlock, ConverseResponse, ContentBlockDeltaEvent, ConverseStreamMetadataEvent, ContentBlockStartEvent, ReasoningContentBlock, ReasoningContentBlockDelta, };
@@ -1,5 +0,0 @@
1
- /**
2
- * Bedrock Converse utility exports.
3
- */
4
- export { convertToConverseMessages, extractImageInfo, langchainReasoningBlockToBedrockReasoningBlock, concatenateLangchainReasoningBlocks, } from './message_inputs';
5
- export { convertConverseMessageToLangChainMessage, handleConverseStreamContentBlockStart, handleConverseStreamContentBlockDelta, handleConverseStreamMetadata, bedrockReasoningBlockToLangchainReasoningBlock, bedrockReasoningDeltaToLangchainPartialReasoningBlock, } from './message_outputs';
@@ -1,31 +0,0 @@
1
- /**
2
- * Utility functions for converting LangChain messages to Bedrock Converse messages.
3
- * Ported from @langchain/aws common.js
4
- */
5
- import { type BaseMessage, MessageContentComplex } from '@langchain/core/messages';
6
- import type { BedrockMessage, BedrockSystemContentBlock, BedrockContentBlock, MessageContentReasoningBlock } from '../types';
7
- /**
8
- * Convert a LangChain reasoning block to a Bedrock reasoning block.
9
- */
10
- export declare function langchainReasoningBlockToBedrockReasoningBlock(content: MessageContentReasoningBlock): {
11
- reasoningText?: {
12
- text?: string;
13
- signature?: string;
14
- };
15
- redactedContent?: Uint8Array;
16
- };
17
- /**
18
- * Concatenate consecutive reasoning blocks in content array.
19
- */
20
- export declare function concatenateLangchainReasoningBlocks(content: Array<MessageContentComplex | MessageContentReasoningBlock>): Array<MessageContentComplex | MessageContentReasoningBlock>;
21
- /**
22
- * Extract image info from a base64 string or URL.
23
- */
24
- export declare function extractImageInfo(base64: string): BedrockContentBlock;
25
- /**
26
- * Convert LangChain messages to Bedrock Converse messages.
27
- */
28
- export declare function convertToConverseMessages(messages: BaseMessage[]): {
29
- converseMessages: BedrockMessage[];
30
- converseSystem: BedrockSystemContentBlock[];
31
- };
@@ -1,33 +0,0 @@
1
- /**
2
- * Utility functions for converting Bedrock Converse responses to LangChain messages.
3
- * Ported from @langchain/aws common.js
4
- */
5
- import { AIMessage } from '@langchain/core/messages';
6
- import { ChatGenerationChunk } from '@langchain/core/outputs';
7
- import type { BedrockMessage, ConverseResponse, ContentBlockDeltaEvent, ConverseStreamMetadataEvent, ContentBlockStartEvent, ReasoningContentBlock, ReasoningContentBlockDelta, MessageContentReasoningBlock, MessageContentReasoningBlockReasoningTextPartial, MessageContentReasoningBlockRedacted } from '../types';
8
- /**
9
- * Convert a Bedrock reasoning block delta to a LangChain partial reasoning block.
10
- */
11
- export declare function bedrockReasoningDeltaToLangchainPartialReasoningBlock(reasoningContent: ReasoningContentBlockDelta): MessageContentReasoningBlockReasoningTextPartial | MessageContentReasoningBlockRedacted;
12
- /**
13
- * Convert a Bedrock reasoning block to a LangChain reasoning block.
14
- */
15
- export declare function bedrockReasoningBlockToLangchainReasoningBlock(reasoningContent: ReasoningContentBlock): MessageContentReasoningBlock;
16
- /**
17
- * Convert a Bedrock Converse message to a LangChain message.
18
- */
19
- export declare function convertConverseMessageToLangChainMessage(message: BedrockMessage, responseMetadata: Omit<ConverseResponse, 'output'>): AIMessage;
20
- /**
21
- * Handle a content block delta event from Bedrock Converse stream.
22
- */
23
- export declare function handleConverseStreamContentBlockDelta(contentBlockDelta: ContentBlockDeltaEvent): ChatGenerationChunk;
24
- /**
25
- * Handle a content block start event from Bedrock Converse stream.
26
- */
27
- export declare function handleConverseStreamContentBlockStart(contentBlockStart: ContentBlockStartEvent): ChatGenerationChunk | null;
28
- /**
29
- * Handle a metadata event from Bedrock Converse stream.
30
- */
31
- export declare function handleConverseStreamMetadata(metadata: ConverseStreamMetadataEvent, extra: {
32
- streamUsage: boolean;
33
- }): ChatGenerationChunk;