@librechat/agents 3.2.33 → 3.2.34
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/cjs/llm/bedrock/index.cjs +21 -2
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +38 -2
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +6 -0
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +48 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +19 -0
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/stream.cjs +20 -2
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +41 -4
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/streamedToolCallSeals.cjs +30 -1
- package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +22 -3
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs +38 -3
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +6 -0
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +48 -1
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +19 -0
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/stream.mjs +21 -3
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +41 -4
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/streamedToolCallSeals.mjs +25 -2
- package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -1
- package/dist/types/llm/bedrock/utils/index.d.ts +1 -1
- package/dist/types/llm/bedrock/utils/message_outputs.d.ts +9 -0
- package/dist/types/llm/vertexai/index.d.ts +10 -0
- package/dist/types/tools/ToolNode.d.ts +8 -0
- package/dist/types/tools/streamedToolCallSeals.d.ts +5 -1
- package/dist/types/types/tools.d.ts +10 -0
- package/package.json +1 -1
- package/src/__tests__/stream.eagerEventExecution.test.ts +703 -0
- package/src/llm/bedrock/index.ts +40 -0
- package/src/llm/bedrock/streamSealDispatch.test.ts +158 -0
- package/src/llm/bedrock/utils/index.ts +1 -0
- package/src/llm/bedrock/utils/message_outputs.test.ts +85 -0
- package/src/llm/bedrock/utils/message_outputs.ts +43 -0
- package/src/llm/google/utils/common.test.ts +64 -0
- package/src/llm/google/utils/common.ts +18 -0
- package/src/llm/openai/index.ts +95 -1
- package/src/llm/openai/sequentialToolCallSeals.test.ts +199 -0
- package/src/llm/vertexai/index.ts +31 -0
- package/src/llm/vertexai/sealStreamedToolCalls.test.ts +88 -0
- package/src/llm/vertexai/streamSealDispatch.test.ts +148 -0
- package/src/stream.ts +40 -6
- package/src/tools/ToolNode.ts +85 -3
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +368 -0
- package/src/tools/streamedToolCallSeals.ts +37 -9
- package/src/types/tools.ts +10 -0
|
@@ -1,7 +1,30 @@
|
|
|
1
|
+
//#region src/tools/streamedToolCallSeals.ts
|
|
2
|
+
const STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY = "lc_streamed_tool_call_adapter";
|
|
1
3
|
const STREAMED_TOOL_CALL_SEAL_METADATA_KEY = "lc_streamed_tool_call_seal";
|
|
2
4
|
const OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER = "openai_responses";
|
|
5
|
+
const BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER = "bedrock_converse";
|
|
6
|
+
const GOOGLE_STREAMED_TOOL_CALL_ADAPTER = "google_genai";
|
|
7
|
+
const OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER = "openai_chat_sequential";
|
|
8
|
+
const STREAMED_TOOL_CALL_ADAPTERS = new Set([
|
|
9
|
+
OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER,
|
|
10
|
+
BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER,
|
|
11
|
+
GOOGLE_STREAMED_TOOL_CALL_ADAPTER,
|
|
12
|
+
OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER
|
|
13
|
+
]);
|
|
14
|
+
/**
|
|
15
|
+
* Adapters whose wire protocol streams tool calls strictly sequentially by
|
|
16
|
+
* index, so a prior call is sealed the moment a later index begins. Used by
|
|
17
|
+
* the stream handler to extend next-index sealing beyond the provider-keyed
|
|
18
|
+
* Anthropic allowlist.
|
|
19
|
+
*/
|
|
20
|
+
const SEQUENTIAL_SEAL_STREAMED_TOOL_CALL_ADAPTERS = new Set([OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER]);
|
|
21
|
+
function streamedToolCallAdapterAllowsSequentialSeal(metadata) {
|
|
22
|
+
const adapter = getStreamedToolCallAdapter(metadata);
|
|
23
|
+
return adapter != null && SEQUENTIAL_SEAL_STREAMED_TOOL_CALL_ADAPTERS.has(adapter);
|
|
24
|
+
}
|
|
3
25
|
function getStreamedToolCallAdapter(metadata) {
|
|
4
|
-
|
|
26
|
+
const adapter = metadata?.[STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY];
|
|
27
|
+
if (typeof adapter === "string" && STREAMED_TOOL_CALL_ADAPTERS.has(adapter)) return adapter;
|
|
5
28
|
}
|
|
6
29
|
function getStreamedToolCallSeal(metadata) {
|
|
7
30
|
const seal = metadata?.[STREAMED_TOOL_CALL_SEAL_METADATA_KEY];
|
|
@@ -19,6 +42,6 @@ function getStreamedToolCallSeal(metadata) {
|
|
|
19
42
|
};
|
|
20
43
|
}
|
|
21
44
|
//#endregion
|
|
22
|
-
export { getStreamedToolCallAdapter, getStreamedToolCallSeal };
|
|
45
|
+
export { BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER, GOOGLE_STREAMED_TOOL_CALL_ADAPTER, OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER, STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY, STREAMED_TOOL_CALL_SEAL_METADATA_KEY, getStreamedToolCallAdapter, getStreamedToolCallSeal, streamedToolCallAdapterAllowsSequentialSeal };
|
|
23
46
|
|
|
24
47
|
//# sourceMappingURL=streamedToolCallSeals.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamedToolCallSeals.mjs","names":[],"sources":["../../../src/tools/streamedToolCallSeals.ts"],"sourcesContent":["export const STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY =\n 'lc_streamed_tool_call_adapter';\nexport const STREAMED_TOOL_CALL_SEAL_METADATA_KEY =\n 'lc_streamed_tool_call_seal';\nexport const OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER = 'openai_responses';\n\nexport type StreamedToolCallAdapter =\n typeof OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER;\n\nexport type StreamedToolCallSeal =\n | {\n kind: 'single';\n id?: string;\n index?: number;\n }\n | {\n kind: 'all';\n };\n\nexport function getStreamedToolCallAdapter(\n metadata: Record<string, unknown> | undefined\n): StreamedToolCallAdapter | undefined {\n
|
|
1
|
+
{"version":3,"file":"streamedToolCallSeals.mjs","names":[],"sources":["../../../src/tools/streamedToolCallSeals.ts"],"sourcesContent":["export const STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY =\n 'lc_streamed_tool_call_adapter';\nexport const STREAMED_TOOL_CALL_SEAL_METADATA_KEY =\n 'lc_streamed_tool_call_seal';\nexport const OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER = 'openai_responses';\nexport const BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER = 'bedrock_converse';\nexport const GOOGLE_STREAMED_TOOL_CALL_ADAPTER = 'google_genai';\nexport const OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER =\n 'openai_chat_sequential';\n\nexport type StreamedToolCallAdapter =\n | typeof OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER\n | typeof BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER\n | typeof GOOGLE_STREAMED_TOOL_CALL_ADAPTER\n | typeof OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER;\n\nconst STREAMED_TOOL_CALL_ADAPTERS: ReadonlySet<string> = new Set([\n OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER,\n BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER,\n GOOGLE_STREAMED_TOOL_CALL_ADAPTER,\n OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER,\n]);\n\n/**\n * Adapters whose wire protocol streams tool calls strictly sequentially by\n * index, so a prior call is sealed the moment a later index begins. Used by\n * the stream handler to extend next-index sealing beyond the provider-keyed\n * Anthropic allowlist.\n */\nconst SEQUENTIAL_SEAL_STREAMED_TOOL_CALL_ADAPTERS: ReadonlySet<string> =\n new Set([OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER]);\n\nexport function streamedToolCallAdapterAllowsSequentialSeal(\n metadata: Record<string, unknown> | undefined\n): boolean {\n const adapter = getStreamedToolCallAdapter(metadata);\n return (\n adapter != null && SEQUENTIAL_SEAL_STREAMED_TOOL_CALL_ADAPTERS.has(adapter)\n );\n}\n\nexport type StreamedToolCallSeal =\n | {\n kind: 'single';\n id?: string;\n index?: number;\n }\n | {\n kind: 'all';\n };\n\nexport function getStreamedToolCallAdapter(\n metadata: Record<string, unknown> | undefined\n): StreamedToolCallAdapter | undefined {\n const adapter = metadata?.[STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY];\n if (typeof adapter === 'string' && STREAMED_TOOL_CALL_ADAPTERS.has(adapter)) {\n return adapter as StreamedToolCallAdapter;\n }\n return undefined;\n}\n\nexport function getStreamedToolCallSeal(\n metadata: Record<string, unknown> | undefined\n): StreamedToolCallSeal | undefined {\n const seal = metadata?.[STREAMED_TOOL_CALL_SEAL_METADATA_KEY];\n if (seal == null || typeof seal !== 'object') {\n return undefined;\n }\n if (!('kind' in seal)) {\n return undefined;\n }\n if (seal.kind === 'all') {\n return { kind: 'all' };\n }\n if (seal.kind !== 'single') {\n return undefined;\n }\n const id = 'id' in seal && typeof seal.id === 'string' ? seal.id : undefined;\n const index =\n 'index' in seal && typeof seal.index === 'number' ? seal.index : undefined;\n if (id == null && index == null) {\n return undefined;\n }\n return { kind: 'single', id, index };\n}\n"],"mappings":";AAAA,MAAa,0CACX;AACF,MAAa,uCACX;AACF,MAAa,8CAA8C;AAC3D,MAAa,8CAA8C;AAC3D,MAAa,oCAAoC;AACjD,MAAa,oDACX;AAQF,MAAM,8BAAmD,IAAI,IAAI;CAC/D;CACA;CACA;CACA;AACF,CAAC;;;;;;;AAQD,MAAM,8CACJ,IAAI,IAAI,CAAC,iDAAiD,CAAC;AAE7D,SAAgB,4CACd,UACS;CACT,MAAM,UAAU,2BAA2B,QAAQ;CACnD,OACE,WAAW,QAAQ,4CAA4C,IAAI,OAAO;AAE9E;AAYA,SAAgB,2BACd,UACqC;CACrC,MAAM,UAAU,WAAW;CAC3B,IAAI,OAAO,YAAY,YAAY,4BAA4B,IAAI,OAAO,GACxE,OAAO;AAGX;AAEA,SAAgB,wBACd,UACkC;CAClC,MAAM,OAAO,WAAW;CACxB,IAAI,QAAQ,QAAQ,OAAO,SAAS,UAClC;CAEF,IAAI,EAAE,UAAU,OACd;CAEF,IAAI,KAAK,SAAS,OAChB,OAAO,EAAE,MAAM,MAAM;CAEvB,IAAI,KAAK,SAAS,UAChB;CAEF,MAAM,KAAK,QAAQ,QAAQ,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK,KAAA;CACnE,MAAM,QACJ,WAAW,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAA;CACnE,IAAI,MAAM,QAAQ,SAAS,MACzB;CAEF,OAAO;EAAE,MAAM;EAAU;EAAI;CAAM;AACrC"}
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Bedrock Converse utility exports.
|
|
3
3
|
*/
|
|
4
4
|
export { convertToConverseMessages, extractImageInfo, langchainReasoningBlockToBedrockReasoningBlock, concatenateLangchainReasoningBlocks, } from './message_inputs';
|
|
5
|
-
export { convertConverseMessageToLangChainMessage, handleConverseStreamContentBlockStart, handleConverseStreamContentBlockDelta, handleConverseStreamMetadata, bedrockReasoningBlockToLangchainReasoningBlock, bedrockReasoningDeltaToLangchainPartialReasoningBlock, } from './message_outputs';
|
|
5
|
+
export { convertConverseMessageToLangChainMessage, createConverseToolUseStopChunk, handleConverseStreamContentBlockStart, handleConverseStreamContentBlockDelta, handleConverseStreamMetadata, bedrockReasoningBlockToLangchainReasoningBlock, bedrockReasoningDeltaToLangchainPartialReasoningBlock, } from './message_outputs';
|
|
@@ -25,6 +25,15 @@ export declare function handleConverseStreamContentBlockDelta(contentBlockDelta:
|
|
|
25
25
|
* Handle a content block start event from Bedrock Converse stream.
|
|
26
26
|
*/
|
|
27
27
|
export declare function handleConverseStreamContentBlockStart(contentBlockStart: ContentBlockStartEvent): ChatGenerationChunk | null;
|
|
28
|
+
/**
|
|
29
|
+
* Build the chunk emitted when a Converse `contentBlockStop` event closes a
|
|
30
|
+
* toolUse block. The Converse protocol guarantees a block's input is complete
|
|
31
|
+
* at `contentBlockStop`, so this chunk carries an explicit streamed tool-call
|
|
32
|
+
* seal for that block index. The empty `args` delta merges as a no-op into the
|
|
33
|
+
* accumulated tool call; id/name are omitted so the chunk matches the existing
|
|
34
|
+
* entry purely by index.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createConverseToolUseStopChunk(contentBlockIndex: number): ChatGenerationChunk;
|
|
28
37
|
/**
|
|
29
38
|
* Handle a metadata event from Bedrock Converse stream.
|
|
30
39
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChatGoogle } from '@langchain/google-gauth';
|
|
2
|
+
import { AIMessageChunk } from '@langchain/core/messages';
|
|
2
3
|
import type { GeminiContent, GoogleAIModelRequestParams, GoogleAbstractedClient } from '@langchain/google-common';
|
|
3
4
|
import type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
|
|
4
5
|
import type { BaseMessage, UsageMetadata } from '@langchain/core/messages';
|
|
@@ -29,6 +30,15 @@ import type { GoogleThinkingConfig, VertexAIClientOptions } from '@/types';
|
|
|
29
30
|
* overriding `_convertToUsageMetadata`.
|
|
30
31
|
*/
|
|
31
32
|
export declare function repairStreamUsageMetadata(current: UsageMetadata | undefined, generationInfoUsage: UsageMetadata | undefined): UsageMetadata | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* The Gemini API delivers function calls as complete objects — never as
|
|
35
|
+
* partial arg deltas. `@langchain/google-common` pre-parses each streamed
|
|
36
|
+
* functionCall part into `tool_calls` (invalid args land in
|
|
37
|
+
* `invalid_tool_calls` instead), so a chunk whose tool-call chunks all parsed
|
|
38
|
+
* cleanly is sealed on arrival for eager tool execution. Anything that fails
|
|
39
|
+
* the parse check is left unstamped and falls back to the lazy path.
|
|
40
|
+
*/
|
|
41
|
+
export declare function sealCompleteStreamedToolCalls(message: AIMessageChunk): void;
|
|
32
42
|
/**
|
|
33
43
|
* Fixes thought signatures on functionCall parts in the formatted Gemini request.
|
|
34
44
|
*
|
|
@@ -350,6 +350,14 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
350
350
|
*/
|
|
351
351
|
private dispatchPostToolBatchAndInjectContext;
|
|
352
352
|
private dispatchStepCompleted;
|
|
353
|
+
/**
|
|
354
|
+
* Emits the completed run step for a single host-reported result before
|
|
355
|
+
* the batch resolves. Mirrors the batch loop's output formatting exactly;
|
|
356
|
+
* callers gate on the no-hooks/no-HITL configuration, so the raw result
|
|
357
|
+
* content here is also the final content. Returns whether the event was
|
|
358
|
+
* actually dispatched so the caller can fall back to batch-time emission.
|
|
359
|
+
*/
|
|
360
|
+
private dispatchEarlyToolCompletion;
|
|
353
361
|
/**
|
|
354
362
|
* Converts InjectedMessage instances to LangChain HumanMessage objects.
|
|
355
363
|
* Both 'user' and 'system' roles become HumanMessage to avoid provider
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export declare const STREAMED_TOOL_CALL_ADAPTER_METADATA_KEY = "lc_streamed_tool_call_adapter";
|
|
2
2
|
export declare const STREAMED_TOOL_CALL_SEAL_METADATA_KEY = "lc_streamed_tool_call_seal";
|
|
3
3
|
export declare const OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER = "openai_responses";
|
|
4
|
-
export
|
|
4
|
+
export declare const BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER = "bedrock_converse";
|
|
5
|
+
export declare const GOOGLE_STREAMED_TOOL_CALL_ADAPTER = "google_genai";
|
|
6
|
+
export declare const OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER = "openai_chat_sequential";
|
|
7
|
+
export type StreamedToolCallAdapter = typeof OPENAI_RESPONSES_STREAMED_TOOL_CALL_ADAPTER | typeof BEDROCK_CONVERSE_STREAMED_TOOL_CALL_ADAPTER | typeof GOOGLE_STREAMED_TOOL_CALL_ADAPTER | typeof OPENAI_CHAT_SEQUENTIAL_STREAMED_TOOL_CALL_ADAPTER;
|
|
8
|
+
export declare function streamedToolCallAdapterAllowsSequentialSeal(metadata: Record<string, unknown> | undefined): boolean;
|
|
5
9
|
export type StreamedToolCallSeal = {
|
|
6
10
|
kind: 'single';
|
|
7
11
|
id?: string;
|
|
@@ -382,6 +382,16 @@ export type ToolExecuteBatchRequest = {
|
|
|
382
382
|
resolve: (results: ToolExecuteResult[]) => void;
|
|
383
383
|
/** Promise rejector - handler calls this on fatal error */
|
|
384
384
|
reject: (error: Error) => void;
|
|
385
|
+
/**
|
|
386
|
+
* Optional per-call result channel. When present, the handler MAY invoke
|
|
387
|
+
* this as each tool call settles (before the final `resolve`) so the
|
|
388
|
+
* graph can emit that call's completion event without waiting for the
|
|
389
|
+
* slowest call in the batch. Purely an emission fast-path: the handler
|
|
390
|
+
* must still pass every result to `resolve`, which remains the
|
|
391
|
+
* authoritative batch outcome. Only provided when no post-tool hooks or
|
|
392
|
+
* human-in-the-loop flows could change a result after execution.
|
|
393
|
+
*/
|
|
394
|
+
onResult?: (result: ToolExecuteResult) => void;
|
|
385
395
|
};
|
|
386
396
|
/**
|
|
387
397
|
* A message injected into graph state by any tool execution handler.
|