@librechat/agents 3.3.3 → 3.3.4
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/agents/AgentContext.cjs +2 -1
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +342 -109
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +3 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +79 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +37 -10
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +19 -7
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/invoke.cjs +64 -3
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +41 -5
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +25 -4
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +4 -1
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +19 -2
- package/dist/cjs/messages/cache.cjs +54 -33
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/contextPruning.cjs +17 -43
- package/dist/cjs/messages/contextPruning.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +315 -23
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +218 -60
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/index.cjs +1 -1
- package/dist/cjs/messages/prune.cjs +503 -127
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/stream.cjs +7 -3
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +28 -14
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +54 -41
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/toolOutputReferences.cjs +6 -0
- package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
- package/dist/cjs/utils/index.cjs +1 -1
- package/dist/cjs/utils/llm.cjs +1 -1
- package/dist/cjs/utils/llm.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +307 -20
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/cjs/utils/toolContent.cjs +1514 -0
- package/dist/cjs/utils/toolContent.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +2 -1
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +349 -116
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +3 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +79 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +37 -10
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +19 -7
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/invoke.mjs +65 -5
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +41 -5
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +25 -4
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +4 -1
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/main.mjs +7 -7
- package/dist/esm/messages/cache.mjs +55 -34
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/contextPruning.mjs +17 -43
- package/dist/esm/messages/contextPruning.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +305 -24
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +218 -61
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/index.mjs +1 -1
- package/dist/esm/messages/prune.mjs +500 -128
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/stream.mjs +7 -3
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +28 -14
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +54 -41
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/toolOutputReferences.mjs +6 -0
- package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
- package/dist/esm/utils/index.mjs +1 -1
- package/dist/esm/utils/llm.mjs +1 -1
- package/dist/esm/utils/llm.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +307 -21
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/esm/utils/toolContent.mjs +1503 -0
- package/dist/esm/utils/toolContent.mjs.map +1 -0
- package/dist/types/graphs/Graph.d.ts +1 -1
- package/dist/types/llm/invoke.d.ts +27 -1
- package/dist/types/llm/openai/index.d.ts +4 -0
- package/dist/types/llm/openai/utils/index.d.ts +2 -0
- package/dist/types/llm/openrouter/index.d.ts +5 -0
- package/dist/types/messages/contextPruning.d.ts +2 -1
- package/dist/types/messages/core.d.ts +36 -0
- package/dist/types/messages/format.d.ts +6 -0
- package/dist/types/messages/prune.d.ts +16 -12
- package/dist/types/types/stream.d.ts +1 -1
- package/dist/types/utils/tokens.d.ts +7 -0
- package/dist/types/utils/toolContent.d.ts +107 -0
- package/package.json +1 -1
- package/src/__tests__/stream.eagerEventExecution.test.ts +74 -0
- package/src/agents/AgentContext.ts +1 -0
- package/src/graphs/Graph.ts +698 -200
- package/src/graphs/MultiAgentGraph.ts +6 -1
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +1128 -4
- package/src/llm/anthropic/utils/message_inputs.ts +158 -12
- package/src/llm/anthropic/utils/tool-id-normalization.test.ts +109 -0
- package/src/llm/bedrock/utils/message_inputs.test.ts +49 -1
- package/src/llm/bedrock/utils/message_inputs.ts +86 -13
- package/src/llm/google/utils/common.test.ts +75 -9
- package/src/llm/google/utils/common.ts +34 -3
- package/src/llm/invoke.test.ts +488 -0
- package/src/llm/invoke.ts +196 -2
- package/src/llm/openai/index.ts +106 -6
- package/src/llm/openai/utils/index.ts +109 -53
- package/src/llm/openai/utils/messages.test.ts +330 -1
- package/src/llm/openrouter/index.ts +12 -2
- package/src/llm/openrouter/reasoning.test.ts +314 -0
- package/src/messages/__tests__/observationMasking.test.ts +93 -2
- package/src/messages/cache.tail.test.ts +193 -0
- package/src/messages/cache.test.ts +113 -0
- package/src/messages/cache.ts +92 -60
- package/src/messages/contextPruning.test.ts +184 -0
- package/src/messages/contextPruning.ts +49 -42
- package/src/messages/core.ts +653 -40
- package/src/messages/ensureThinkingBlock.test.ts +49 -1
- package/src/messages/foldToollessToolBlocks.test.ts +163 -5
- package/src/messages/format.ts +363 -91
- package/src/messages/formatAgentMessages.test.ts +604 -14
- package/src/messages/formatAgentMessages.tools.test.ts +103 -0
- package/src/messages/prune.ts +996 -183
- package/src/specs/prune.test.ts +1083 -6
- package/src/specs/summarization-unit.test.ts +105 -0
- package/src/specs/tokens.test.ts +609 -32
- package/src/stream.ts +23 -15
- package/src/summarization/__tests__/node.test.ts +77 -0
- package/src/summarization/node.ts +46 -18
- package/src/tools/ToolNode.ts +147 -68
- package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +148 -1
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +112 -3
- package/src/tools/__tests__/annotateMessagesForLLM.test.ts +32 -0
- package/src/tools/__tests__/directToolHooks.test.ts +255 -7
- package/src/tools/toolOutputReferences.ts +6 -0
- package/src/types/stream.ts +1 -1
- package/src/utils/llm.test.ts +18 -0
- package/src/utils/llm.ts +4 -1
- package/src/utils/tokens.ts +586 -31
- package/src/utils/toolContent.test.ts +1432 -0
- package/src/utils/toolContent.ts +2707 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ToolMessage, type BaseMessage } from '@langchain/core/messages';
|
|
2
|
+
type ToolContent = BaseMessage['content'];
|
|
3
|
+
/**
|
|
4
|
+
* Serializes values that providers render as JSON without throwing on values
|
|
5
|
+
* such as bigint or circular diagnostic metadata.
|
|
6
|
+
*/
|
|
7
|
+
export declare function serializeStructuredValue(value: unknown): string;
|
|
8
|
+
type StructuredWorkState = {
|
|
9
|
+
remaining: number;
|
|
10
|
+
characterRemaining: number;
|
|
11
|
+
exceeded: boolean;
|
|
12
|
+
failurePlaceholder?: string;
|
|
13
|
+
propertyCache: WeakMap<object, Map<string, unknown>>;
|
|
14
|
+
propertyCacheEntries: number;
|
|
15
|
+
};
|
|
16
|
+
export type BoundedStructuredSerialization = {
|
|
17
|
+
/** Provider-facing head/tail preview, bounded by `maxChars`. */
|
|
18
|
+
content: string;
|
|
19
|
+
/** Exact serialized prefix up to the defensive traversal-work ceiling. */
|
|
20
|
+
prefix: string;
|
|
21
|
+
/** Exact length, or `Number.MAX_SAFE_INTEGER` when traversal was capped. */
|
|
22
|
+
originalChars: number;
|
|
23
|
+
truncated: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Serializes structured output while retaining at most the requested provider
|
|
27
|
+
* preview and registry prefix. The traversal never calls `toJSON` and never
|
|
28
|
+
* materializes the complete serialized string when it exceeds those limits.
|
|
29
|
+
*
|
|
30
|
+
* `prefixChars` is useful for the tool-output registry: it receives the exact
|
|
31
|
+
* serialized prefix up to `registry.perOutputLimit`, while `content` retains
|
|
32
|
+
* the provider-facing head/tail truncation behavior at `maxChars`. Property
|
|
33
|
+
* accessors are represented by a fixed placeholder instead of being invoked.
|
|
34
|
+
*/
|
|
35
|
+
export declare function serializeStructuredValueBounded(value: unknown, maxChars: number, prefixChars?: number, work?: StructuredWorkState): BoundedStructuredSerialization;
|
|
36
|
+
export declare function isAtomicToolContentBlock(value: unknown): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Produces the text representation providers use for structured tool results.
|
|
39
|
+
* Text-only block arrays stay readable; opaque blocks use canonical JSON.
|
|
40
|
+
*/
|
|
41
|
+
export declare function serializeToolContent(content: unknown): string;
|
|
42
|
+
export declare function getToolContentCharLength(content: unknown): number;
|
|
43
|
+
/**
|
|
44
|
+
* Produces provider-facing tool-result text without ever exceeding `maxChars`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function serializeToolContentBounded(content: unknown, maxChars: number): string;
|
|
47
|
+
export type CompactToolContentResult = {
|
|
48
|
+
content: ToolContent;
|
|
49
|
+
changed: boolean;
|
|
50
|
+
originalChars: number;
|
|
51
|
+
};
|
|
52
|
+
export type CacheControlledTextToolContent = [
|
|
53
|
+
{
|
|
54
|
+
type: 'text';
|
|
55
|
+
text: string;
|
|
56
|
+
cache_control: {
|
|
57
|
+
type: 'ephemeral';
|
|
58
|
+
ttl?: '1h';
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
/** Reads one safe text block and returns its bounded text payload. */
|
|
63
|
+
export declare function getBoundedSingleTextToolContent(content: unknown, maxChars: number): string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Canonicalizes the single cache-decorated text block produced by tail prompt
|
|
66
|
+
* caching without invoking accessors or custom serialization hooks.
|
|
67
|
+
*/
|
|
68
|
+
export declare function getBoundedCacheControlledTextToolContent(content: unknown, maxChars: number): CacheControlledTextToolContent | undefined;
|
|
69
|
+
export type ComputerCallOutputScreenshot = {
|
|
70
|
+
type: 'input_image';
|
|
71
|
+
image_url: string;
|
|
72
|
+
detail?: InputImageDetail;
|
|
73
|
+
} | {
|
|
74
|
+
type: 'input_image';
|
|
75
|
+
file_id: string;
|
|
76
|
+
detail?: InputImageDetail;
|
|
77
|
+
} | {
|
|
78
|
+
type: 'computer_screenshot';
|
|
79
|
+
image_url: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: 'computer_screenshot';
|
|
82
|
+
file_id: string;
|
|
83
|
+
};
|
|
84
|
+
type InputImageDetail = 'low' | 'high' | 'auto' | 'original';
|
|
85
|
+
/**
|
|
86
|
+
* Selects the exact screenshot shape accepted by LangChain's Responses
|
|
87
|
+
* converter without invoking accessors or user-defined serialization hooks.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getComputerCallOutputScreenshot(content: unknown): ComputerCallOutputScreenshot | undefined;
|
|
90
|
+
/** Returns the provider image URL when a screenshot is URL-backed. */
|
|
91
|
+
export declare function getComputerCallOutputImageUrl(content: unknown): string | undefined;
|
|
92
|
+
/** Returns whether content can be sent as a native computer screenshot. */
|
|
93
|
+
export declare function isComputerCallOutputContent(content: unknown): content is ToolContent;
|
|
94
|
+
/** Returns whether a ToolMessage carries the native computer-output marker. */
|
|
95
|
+
export declare function hasComputerCallOutputMarker(message: BaseMessage): boolean;
|
|
96
|
+
/** Native Responses computer screenshots are indivisible provider payloads. */
|
|
97
|
+
export declare function isComputerCallOutputMessage(message: BaseMessage): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Bounds structured tool output without slicing binary/media payloads.
|
|
100
|
+
* Purely textual/structured arrays become a universally valid string tool
|
|
101
|
+
* result. For mixed-media arrays, compactable blocks become one text preview
|
|
102
|
+
* while atomic blocks remain intact.
|
|
103
|
+
*/
|
|
104
|
+
export declare function compactToolContent(content: unknown, maxChars: number): CompactToolContentResult;
|
|
105
|
+
/** Clones a ToolMessage while retaining fields omitted by ad-hoc clones. */
|
|
106
|
+
export declare function cloneToolMessageWithContent(message: ToolMessage, content: ToolContent, artifact?: unknown): ToolMessage;
|
|
107
|
+
export {};
|
package/package.json
CHANGED
|
@@ -2498,6 +2498,80 @@ describe('ChatModelStreamHandler eager event tool execution', () => {
|
|
|
2498
2498
|
).toBe(true);
|
|
2499
2499
|
});
|
|
2500
2500
|
|
|
2501
|
+
it('serializes bigint output before eager completion dispatch', async () => {
|
|
2502
|
+
const graph = createGraph();
|
|
2503
|
+
const completedEvents: Array<{ result: t.ToolEndEvent }> = [];
|
|
2504
|
+
jest
|
|
2505
|
+
.spyOn(events, 'safeDispatchCustomEvent')
|
|
2506
|
+
.mockImplementation(async (event, data): Promise<void> => {
|
|
2507
|
+
if (event === GraphEvents.ON_RUN_STEP_COMPLETED) {
|
|
2508
|
+
completedEvents.push(data as { result: t.ToolEndEvent });
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2511
|
+
if (event !== GraphEvents.ON_TOOL_EXECUTE) {
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
const batch = data as t.ToolExecuteBatchRequest;
|
|
2515
|
+
batch.resolve([
|
|
2516
|
+
{
|
|
2517
|
+
toolCallId: 'call_weather',
|
|
2518
|
+
status: 'success',
|
|
2519
|
+
content: [{ rowsRead: BigInt(42) }],
|
|
2520
|
+
},
|
|
2521
|
+
]);
|
|
2522
|
+
});
|
|
2523
|
+
|
|
2524
|
+
const handler = new ChatModelStreamHandler();
|
|
2525
|
+
const metadata = { langgraph_node: 'agent' };
|
|
2526
|
+
await handler.handle(
|
|
2527
|
+
GraphEvents.CHAT_MODEL_STREAM,
|
|
2528
|
+
{
|
|
2529
|
+
chunk: {
|
|
2530
|
+
content: '',
|
|
2531
|
+
tool_call_chunks: [
|
|
2532
|
+
{
|
|
2533
|
+
id: 'call_weather',
|
|
2534
|
+
name: 'weather',
|
|
2535
|
+
args: '{"city":"NYC"}',
|
|
2536
|
+
index: 0,
|
|
2537
|
+
},
|
|
2538
|
+
],
|
|
2539
|
+
} as unknown as t.StreamChunk,
|
|
2540
|
+
},
|
|
2541
|
+
metadata,
|
|
2542
|
+
graph
|
|
2543
|
+
);
|
|
2544
|
+
await handler.handle(
|
|
2545
|
+
GraphEvents.CHAT_MODEL_STREAM,
|
|
2546
|
+
{
|
|
2547
|
+
chunk: {
|
|
2548
|
+
content: '',
|
|
2549
|
+
tool_call_chunks: [
|
|
2550
|
+
{
|
|
2551
|
+
id: 'call_stock',
|
|
2552
|
+
name: 'stock',
|
|
2553
|
+
args: '{"ticker":"C',
|
|
2554
|
+
index: 1,
|
|
2555
|
+
},
|
|
2556
|
+
],
|
|
2557
|
+
} as unknown as t.StreamChunk,
|
|
2558
|
+
},
|
|
2559
|
+
metadata,
|
|
2560
|
+
graph
|
|
2561
|
+
);
|
|
2562
|
+
|
|
2563
|
+
await graph.eagerEventToolExecutions.get('call_weather')?.promise;
|
|
2564
|
+
|
|
2565
|
+
expect(completedEvents).toHaveLength(1);
|
|
2566
|
+
expect(
|
|
2567
|
+
(
|
|
2568
|
+
completedEvents[0].result as {
|
|
2569
|
+
tool_call?: { output?: string };
|
|
2570
|
+
}
|
|
2571
|
+
).tool_call?.output
|
|
2572
|
+
).toBe('[{"rowsRead":"42"}]');
|
|
2573
|
+
});
|
|
2574
|
+
|
|
2501
2575
|
it('does not emit a stale eager completion after the active execution is invalidated', async () => {
|
|
2502
2576
|
const graph = createGraph({
|
|
2503
2577
|
getAgentContext: jest.fn(
|
|
@@ -1638,6 +1638,7 @@ export class AgentContext {
|
|
|
1638
1638
|
provider: this.provider,
|
|
1639
1639
|
tokenCounter,
|
|
1640
1640
|
maxTokens: this.maxContextTokens,
|
|
1641
|
+
maxToolResultChars: this.maxToolResultChars,
|
|
1641
1642
|
thinkingEnabled: isThinkingEnabled(this.provider, this.clientOptions),
|
|
1642
1643
|
indexTokenCountMap,
|
|
1643
1644
|
contextPruningConfig: this.contextPruningConfig,
|