Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@librechat/agents",
"version": "3.1.70",
"version": "3.1.71",
"main": "./dist/cjs/main.cjs",
"module": "./dist/esm/main.mjs",
"types": "./dist/types/index.d.ts",
Expand Down
55 changes: 55 additions & 0 deletions src/graphs/Graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
import { SubagentExecutor, resolveSubagentConfigs } from '@/tools/subagent';
import { buildSubagentToolParams } from '@/tools/SubagentTool';
import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
import { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
import { attemptInvoke, tryFallbackProviders } from '@/llm/invoke';
import { shouldTriggerSummarization } from '@/summarization';
Expand Down Expand Up @@ -128,6 +129,19 @@ export abstract class Graph<
invokedToolIds?: Set<string>;
handlerRegistry: HandlerRegistry | undefined;
hookRegistry: HookRegistry | undefined;
/**
* Run-scoped config for the tool output reference registry. Threaded
* from `RunConfig.toolOutputReferences` down into every ToolNode this
* graph compiles.
*/
toolOutputReferences: t.ToolOutputReferencesConfig | undefined;
/**
* Shared registry instance used by every ToolNode compiled from this
* graph. Lazily constructed on first access so multi-agent graphs
* produce one registry per run (not one per agent), letting cross-
* agent `{{tool<i>turn<n>}}` substitutions resolve.
*/
private _toolOutputRegistry?: ToolOutputReferenceRegistry;
/**
* Tool session contexts for automatic state persistence across tool invocations.
* Keyed by tool name (e.g., Constants.EXECUTE_CODE).
Expand All @@ -153,8 +167,47 @@ export abstract class Graph<
this.invokedToolIds = undefined;
this.handlerRegistry = undefined;
this.hookRegistry = undefined;
this.toolOutputReferences = undefined;
/**
* ToolNodes compiled from this graph captured the registry
* instance at construction time, so simply dropping the Graph's
* own reference would leave their captured reference — and every
* stored `tool<i>turn<n>` entry, plus up to `maxTotalSize` of raw
* output — alive across subsequent `processStream()` calls. Wipe
* the registry's contents first so subsequent runs start fresh.
*/
this._toolOutputRegistry?.clear();
this._toolOutputRegistry = undefined;
this.sessions.clear();
}

/**
* Returns the shared `ToolOutputReferenceRegistry` for this run,
* constructing it on first access. Returns `undefined` when the
* feature is disabled. All ToolNodes compiled from this graph share
* this single instance so cross-agent `{{…}}` references resolve.
*
* @internal Public so `attemptInvoke` can read it through the typed
* `InvokeContext` and project ToolMessages into LLM-facing annotated
* copies right before each provider call (see
* `annotateMessagesForLLM`). Host code should not call this directly
* — registry mutations outside the ToolNode lifecycle break the
* partitioning, eviction, and turn-counter invariants.
*/
public getOrCreateToolOutputRegistry():
| ToolOutputReferenceRegistry
| undefined {
if (this.toolOutputReferences?.enabled !== true) {
return undefined;
}
if (this._toolOutputRegistry == null) {
this._toolOutputRegistry = new ToolOutputReferenceRegistry({
maxOutputSize: this.toolOutputReferences.maxOutputSize,
maxTotalSize: this.toolOutputReferences.maxTotalSize,
});
}
return this._toolOutputRegistry;
}
}

export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
Expand Down Expand Up @@ -516,6 +569,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
maxContextTokens: agentContext?.maxContextTokens,
maxToolResultChars: agentContext?.maxToolResultChars,
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
errorHandler: (data, metadata) =>
StandardGraph.handleToolCallErrorStatic(this, data, metadata),
});
Expand Down Expand Up @@ -547,6 +601,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
sessions: this.sessions,
maxContextTokens: agentContext?.maxContextTokens,
maxToolResultChars: agentContext?.maxToolResultChars,
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
});
}

Expand Down
Loading
Loading