@librechat/agents 3.1.77-dev.1 → 3.1.78-dev.0
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/common/enum.cjs +54 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +148 -4
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +291 -0
- package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -0
- package/dist/cjs/llm/openai/index.cjs +317 -1
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +90 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/anthropicToolCache.cjs +102 -0
- package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -0
- package/dist/cjs/messages/prune.cjs +27 -0
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/recency.cjs +99 -0
- package/dist/cjs/messages/recency.cjs.map +1 -0
- package/dist/cjs/run.cjs +30 -0
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +100 -6
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +635 -23
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/local/CompileCheckTool.cjs +227 -0
- package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -0
- package/dist/cjs/tools/local/FileCheckpointer.cjs +90 -0
- package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalCodingTools.cjs +1098 -0
- package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +1042 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalExecutionTools.cjs +122 -0
- package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +453 -0
- package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -0
- package/dist/cjs/tools/local/attachments.cjs +183 -0
- package/dist/cjs/tools/local/attachments.cjs.map +1 -0
- package/dist/cjs/tools/local/bashAst.cjs +129 -0
- package/dist/cjs/tools/local/bashAst.cjs.map +1 -0
- package/dist/cjs/tools/local/editStrategies.cjs +188 -0
- package/dist/cjs/tools/local/editStrategies.cjs.map +1 -0
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +141 -0
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -0
- package/dist/cjs/tools/local/syntaxCheck.cjs +182 -0
- package/dist/cjs/tools/local/syntaxCheck.cjs.map +1 -0
- package/dist/cjs/tools/local/textEncoding.cjs +30 -0
- package/dist/cjs/tools/local/textEncoding.cjs.map +1 -0
- package/dist/cjs/tools/local/workspaceFS.cjs +51 -0
- package/dist/cjs/tools/local/workspaceFS.cjs.map +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/esm/common/enum.mjs +53 -1
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +149 -5
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs +289 -0
- package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -0
- package/dist/esm/llm/openai/index.mjs +318 -2
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +17 -2
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/anthropicToolCache.mjs +99 -0
- package/dist/esm/messages/anthropicToolCache.mjs.map +1 -0
- package/dist/esm/messages/prune.mjs +26 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/recency.mjs +97 -0
- package/dist/esm/messages/recency.mjs.map +1 -0
- package/dist/esm/run.mjs +30 -0
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +100 -6
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +635 -23
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/local/CompileCheckTool.mjs +223 -0
- package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -0
- package/dist/esm/tools/local/FileCheckpointer.mjs +87 -0
- package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -0
- package/dist/esm/tools/local/LocalCodingTools.mjs +1075 -0
- package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -0
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +1022 -0
- package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -0
- package/dist/esm/tools/local/LocalExecutionTools.mjs +117 -0
- package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -0
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +448 -0
- package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -0
- package/dist/esm/tools/local/attachments.mjs +180 -0
- package/dist/esm/tools/local/attachments.mjs.map +1 -0
- package/dist/esm/tools/local/bashAst.mjs +126 -0
- package/dist/esm/tools/local/bashAst.mjs.map +1 -0
- package/dist/esm/tools/local/editStrategies.mjs +185 -0
- package/dist/esm/tools/local/editStrategies.mjs.map +1 -0
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +137 -0
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -0
- package/dist/esm/tools/local/syntaxCheck.mjs +179 -0
- package/dist/esm/tools/local/syntaxCheck.mjs.map +1 -0
- package/dist/esm/tools/local/textEncoding.mjs +27 -0
- package/dist/esm/tools/local/textEncoding.mjs.map +1 -0
- package/dist/esm/tools/local/workspaceFS.mjs +49 -0
- package/dist/esm/tools/local/workspaceFS.mjs.map +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/types/common/enum.d.ts +39 -1
- package/dist/types/graphs/Graph.d.ts +34 -0
- package/dist/types/hooks/createWorkspacePolicyHook.d.ts +95 -0
- package/dist/types/hooks/index.d.ts +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/llm/openai/index.d.ts +17 -0
- package/dist/types/messages/anthropicToolCache.d.ts +51 -0
- package/dist/types/messages/index.d.ts +2 -0
- package/dist/types/messages/prune.d.ts +11 -0
- package/dist/types/messages/recency.d.ts +64 -0
- package/dist/types/run.d.ts +21 -0
- package/dist/types/tools/ToolNode.d.ts +145 -2
- package/dist/types/tools/local/CompileCheckTool.d.ts +31 -0
- package/dist/types/tools/local/FileCheckpointer.d.ts +39 -0
- package/dist/types/tools/local/LocalCodingTools.d.ts +57 -0
- package/dist/types/tools/local/LocalExecutionEngine.d.ts +149 -0
- package/dist/types/tools/local/LocalExecutionTools.d.ts +9 -0
- package/dist/types/tools/local/LocalProgrammaticToolCalling.d.ts +21 -0
- package/dist/types/tools/local/attachments.d.ts +84 -0
- package/dist/types/tools/local/bashAst.d.ts +11 -0
- package/dist/types/tools/local/editStrategies.d.ts +28 -0
- package/dist/types/tools/local/index.d.ts +12 -0
- package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +38 -0
- package/dist/types/tools/local/syntaxCheck.d.ts +42 -0
- package/dist/types/tools/local/textEncoding.d.ts +21 -0
- package/dist/types/tools/local/workspaceFS.d.ts +49 -0
- package/dist/types/types/hitl.d.ts +56 -27
- package/dist/types/types/run.d.ts +8 -1
- package/dist/types/types/summarize.d.ts +30 -0
- package/dist/types/types/tools.d.ts +341 -6
- package/package.json +21 -2
- package/src/common/enum.ts +54 -0
- package/src/graphs/Graph.ts +164 -6
- package/src/hooks/__tests__/compactHooks.test.ts +38 -2
- package/src/hooks/__tests__/createWorkspacePolicyHook.test.ts +393 -0
- package/src/hooks/createWorkspacePolicyHook.ts +355 -0
- package/src/hooks/index.ts +6 -0
- package/src/index.ts +1 -0
- package/src/llm/openai/deepseek.test.ts +479 -0
- package/src/llm/openai/index.ts +484 -1
- package/src/messages/__tests__/anthropicToolCache.test.ts +125 -0
- package/src/messages/__tests__/recency.test.ts +267 -0
- package/src/messages/anthropicToolCache.ts +116 -0
- package/src/messages/index.ts +2 -0
- package/src/messages/prune.ts +27 -1
- package/src/messages/recency.ts +155 -0
- package/src/run.ts +31 -0
- package/src/scripts/compare_pi_vs_ours.ts +840 -0
- package/src/scripts/local_engine.ts +166 -0
- package/src/scripts/local_engine_checkpointer.ts +205 -0
- package/src/scripts/local_engine_compile.ts +263 -0
- package/src/scripts/local_engine_hooks.ts +226 -0
- package/src/scripts/local_engine_image.ts +201 -0
- package/src/scripts/local_engine_ptc.ts +151 -0
- package/src/scripts/local_engine_workspace.ts +258 -0
- package/src/scripts/summarization-recency.ts +462 -0
- package/src/specs/prune.test.ts +39 -0
- package/src/summarization/__tests__/node.test.ts +499 -3
- package/src/summarization/node.ts +124 -7
- package/src/tools/ToolNode.ts +769 -20
- package/src/tools/__tests__/LocalExecutionTools.test.ts +2647 -0
- package/src/tools/__tests__/ProgrammaticToolCalling.test.ts +175 -0
- package/src/tools/__tests__/ToolNode.outputReferences.test.ts +114 -0
- package/src/tools/__tests__/ToolNode.session.test.ts +84 -0
- package/src/tools/__tests__/directToolHITLResumeScope.test.ts +467 -0
- package/src/tools/__tests__/directToolHooks.test.ts +411 -0
- package/src/tools/__tests__/localToolNames.test.ts +73 -0
- package/src/tools/__tests__/workspaceSeam.test.ts +134 -0
- package/src/tools/local/CompileCheckTool.ts +278 -0
- package/src/tools/local/FileCheckpointer.ts +93 -0
- package/src/tools/local/LocalCodingTools.ts +1342 -0
- package/src/tools/local/LocalExecutionEngine.ts +1329 -0
- package/src/tools/local/LocalExecutionTools.ts +167 -0
- package/src/tools/local/LocalProgrammaticToolCalling.ts +594 -0
- package/src/tools/local/__tests__/FileCheckpointer.test.ts +120 -0
- package/src/tools/local/__tests__/editStrategies.test.ts +134 -0
- package/src/tools/local/attachments.ts +251 -0
- package/src/tools/local/bashAst.ts +151 -0
- package/src/tools/local/editStrategies.ts +188 -0
- package/src/tools/local/index.ts +12 -0
- package/src/tools/local/resolveLocalExecutionTools.ts +208 -0
- package/src/tools/local/syntaxCheck.ts +243 -0
- package/src/tools/local/textEncoding.ts +37 -0
- package/src/tools/local/workspaceFS.ts +89 -0
- package/src/types/hitl.ts +56 -27
- package/src/types/run.ts +12 -1
- package/src/types/summarize.ts +31 -0
- package/src/types/tools.ts +359 -7
package/src/graphs/Graph.ts
CHANGED
|
@@ -20,10 +20,13 @@ import {
|
|
|
20
20
|
extractToolDiscoveries,
|
|
21
21
|
addBedrockCacheControl,
|
|
22
22
|
formatArtifactPayload,
|
|
23
|
+
enforceOriginalContentCap,
|
|
23
24
|
formatContentStrings,
|
|
24
25
|
createPruneMessages,
|
|
25
26
|
addCacheControl,
|
|
26
27
|
getMessageId,
|
|
28
|
+
makeIsDeferred,
|
|
29
|
+
partitionAndMarkAnthropicToolCache,
|
|
27
30
|
} from '@/messages';
|
|
28
31
|
import {
|
|
29
32
|
GraphNodeKeys,
|
|
@@ -53,6 +56,8 @@ import { createSchemaOnlyTools } from '@/tools/schema';
|
|
|
53
56
|
import { AgentContext } from '@/agents/AgentContext';
|
|
54
57
|
import { createFakeStreamingLLM } from '@/llm/fake';
|
|
55
58
|
import { handleToolCalls } from '@/tools/handlers';
|
|
59
|
+
import { resolveLocalToolsForBinding } from '@/tools/local';
|
|
60
|
+
import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
|
|
56
61
|
import { isThinkingEnabled } from '@/llm/request';
|
|
57
62
|
import { initializeModel } from '@/llm/init';
|
|
58
63
|
import { HandlerRegistry } from '@/events';
|
|
@@ -142,6 +147,11 @@ export abstract class Graph<
|
|
|
142
147
|
* graph compiles.
|
|
143
148
|
*/
|
|
144
149
|
toolOutputReferences: t.ToolOutputReferencesConfig | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* Run-scoped execution backend for built-in code tools. Defaults to the
|
|
152
|
+
* remote Code API sandbox when unset.
|
|
153
|
+
*/
|
|
154
|
+
toolExecution: t.ToolExecutionConfig | undefined;
|
|
145
155
|
/**
|
|
146
156
|
* Shared registry instance used by every ToolNode compiled from this
|
|
147
157
|
* graph. Lazily constructed on first access so multi-agent graphs
|
|
@@ -176,6 +186,7 @@ export abstract class Graph<
|
|
|
176
186
|
this.hookRegistry = undefined;
|
|
177
187
|
this.humanInTheLoop = undefined;
|
|
178
188
|
this.toolOutputReferences = undefined;
|
|
189
|
+
this.toolExecution = undefined;
|
|
179
190
|
/**
|
|
180
191
|
* ToolNodes compiled from this graph captured the registry
|
|
181
192
|
* instance at construction time, so simply dropping the Graph's
|
|
@@ -186,9 +197,38 @@ export abstract class Graph<
|
|
|
186
197
|
*/
|
|
187
198
|
this._toolOutputRegistry?.clear();
|
|
188
199
|
this._toolOutputRegistry = undefined;
|
|
200
|
+
// NB: `_fileCheckpointer` is intentionally NOT cleared here.
|
|
201
|
+
// `Run.processStream()` calls `clearHeavyState()` in its
|
|
202
|
+
// finally block on natural-completion / error paths — exactly
|
|
203
|
+
// when the host is most likely to want `Run.rewindFiles()` (for
|
|
204
|
+
// rollback after a failed batch). Per-Run isolation is already
|
|
205
|
+
// automatic because each `Run.create()` constructs a brand-new
|
|
206
|
+
// Graph instance, so the next Run gets its own checkpointer
|
|
207
|
+
// without us needing to reset this field. Codex P1 #32: pre-fix
|
|
208
|
+
// the checkpointer was nulled before the caller could reach it.
|
|
209
|
+
// Flush each compiled ToolNode's direct-path turn cache so it
|
|
210
|
+
// doesn't leak across Runs (Codex P2 #33). The cache survives
|
|
211
|
+
// `run()` re-entry by design (resume-stable), but end-of-Run
|
|
212
|
+
// is the right point to reset it.
|
|
213
|
+
for (const node of this._compiledToolNodes) {
|
|
214
|
+
node.clearDirectPathTurns();
|
|
215
|
+
}
|
|
216
|
+
this._compiledToolNodes.clear();
|
|
189
217
|
this.sessions.clear();
|
|
190
218
|
}
|
|
191
219
|
|
|
220
|
+
/**
|
|
221
|
+
* Subclass hook to register a freshly compiled ToolNode so
|
|
222
|
+
* `clearHeavyState` can flush its per-Run direct-path turn cache
|
|
223
|
+
* at end-of-Run. Internal — called from `initializeTools` in the
|
|
224
|
+
* concrete graph subclasses.
|
|
225
|
+
*/
|
|
226
|
+
protected registerCompiledToolNode(node: {
|
|
227
|
+
clearDirectPathTurns(): void;
|
|
228
|
+
}): void {
|
|
229
|
+
this._compiledToolNodes.add(node);
|
|
230
|
+
}
|
|
231
|
+
|
|
192
232
|
/**
|
|
193
233
|
* Returns the shared `ToolOutputReferenceRegistry` for this run,
|
|
194
234
|
* constructing it on first access. Returns `undefined` when the
|
|
@@ -216,6 +256,56 @@ export abstract class Graph<
|
|
|
216
256
|
}
|
|
217
257
|
return this._toolOutputRegistry;
|
|
218
258
|
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Single per-Run file checkpointer shared across every ToolNode the
|
|
262
|
+
* graph compiles. Lazily constructed when
|
|
263
|
+
* `toolExecution.local.fileCheckpointing === true` so multi-agent
|
|
264
|
+
* graphs see ONE snapshot store, not one-per-agent. Returns
|
|
265
|
+
* undefined when checkpointing is disabled or the local engine
|
|
266
|
+
* isn't selected. Exposed via `Run.getFileCheckpointer()` /
|
|
267
|
+
* `Run.rewindFiles()`.
|
|
268
|
+
*/
|
|
269
|
+
private _fileCheckpointer?: t.LocalFileCheckpointer;
|
|
270
|
+
/**
|
|
271
|
+
* ToolNodes compiled into this Graph's workflow. Tracked so
|
|
272
|
+
* `clearHeavyState()` can flush their per-Run direct-path turn
|
|
273
|
+
* cache (`directPathTurns`) at end-of-Run — that map intentionally
|
|
274
|
+
* survives `run()` re-entry (resume-stable per Codex P2 #30) but
|
|
275
|
+
* would otherwise grow linearly with tool calls and could collide
|
|
276
|
+
* across Runs if a provider reuses call ids (Codex P2 #33).
|
|
277
|
+
*/
|
|
278
|
+
private _compiledToolNodes: Set<{
|
|
279
|
+
clearDirectPathTurns(): void;
|
|
280
|
+
}> = new Set();
|
|
281
|
+
public getOrCreateFileCheckpointer():
|
|
282
|
+
| t.LocalFileCheckpointer
|
|
283
|
+
| undefined {
|
|
284
|
+
// Return the cached instance unconditionally if one exists. The
|
|
285
|
+
// toolExecution check below decides whether to *create* a new
|
|
286
|
+
// one — `clearHeavyState` nulls `this.toolExecution` at end-of-
|
|
287
|
+
// Run, but we want post-Run `Run.rewindFiles()` to still resolve
|
|
288
|
+
// to the checkpointer that captured the writes. Codex P1 #32.
|
|
289
|
+
if (this._fileCheckpointer != null) {
|
|
290
|
+
return this._fileCheckpointer;
|
|
291
|
+
}
|
|
292
|
+
if (
|
|
293
|
+
this.toolExecution?.engine !== 'local' ||
|
|
294
|
+
this.toolExecution.local?.fileCheckpointing !== true
|
|
295
|
+
) {
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
// Eagerly create via the bundle factory so the construction path
|
|
299
|
+
// matches the bundle-only callers (and future bundle-internal
|
|
300
|
+
// cleanup hooks fire). The bundle factory itself accepts a pre-
|
|
301
|
+
// supplied checkpointer when present, so re-injecting this one
|
|
302
|
+
// into every ToolNode is idempotent.
|
|
303
|
+
const bundle = createLocalCodingToolBundle(
|
|
304
|
+
this.toolExecution.local ?? {}
|
|
305
|
+
);
|
|
306
|
+
this._fileCheckpointer = bundle.checkpointer;
|
|
307
|
+
return this._fileCheckpointer;
|
|
308
|
+
}
|
|
219
309
|
}
|
|
220
310
|
|
|
221
311
|
export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
@@ -577,7 +667,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
577
667
|
}
|
|
578
668
|
}
|
|
579
669
|
|
|
580
|
-
|
|
670
|
+
const node = new CustomToolNode<t.BaseGraphState>({
|
|
581
671
|
tools: allTools,
|
|
582
672
|
toolMap: allToolMap,
|
|
583
673
|
eventDrivenMode: true,
|
|
@@ -588,13 +678,17 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
588
678
|
toolRegistry: agentContext?.toolRegistry,
|
|
589
679
|
hookRegistry: this.hookRegistry,
|
|
590
680
|
humanInTheLoop: this.humanInTheLoop,
|
|
681
|
+
toolExecution: this.toolExecution,
|
|
591
682
|
directToolNames: directToolNames.size > 0 ? directToolNames : undefined,
|
|
592
683
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
593
684
|
maxToolResultChars: agentContext?.maxToolResultChars,
|
|
594
685
|
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
|
|
595
|
-
|
|
686
|
+
fileCheckpointer: this.getOrCreateFileCheckpointer(),
|
|
687
|
+
errorHandler: (data, metadata): Promise<void> =>
|
|
596
688
|
StandardGraph.handleToolCallErrorStatic(this, data, metadata),
|
|
597
689
|
});
|
|
690
|
+
this.registerCompiledToolNode(node);
|
|
691
|
+
return node;
|
|
598
692
|
}
|
|
599
693
|
|
|
600
694
|
const graphTools = agentContext?.graphTools as t.GenericTool[] | undefined;
|
|
@@ -613,18 +707,24 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
613
707
|
])
|
|
614
708
|
: currentToolMap;
|
|
615
709
|
|
|
616
|
-
|
|
710
|
+
const node = new CustomToolNode<t.BaseGraphState>({
|
|
617
711
|
tools: allTraditionalTools,
|
|
618
712
|
toolMap: traditionalToolMap,
|
|
619
713
|
toolCallStepIds: this.toolCallStepIds,
|
|
620
|
-
errorHandler: (data, metadata) =>
|
|
714
|
+
errorHandler: (data, metadata): Promise<void> =>
|
|
621
715
|
StandardGraph.handleToolCallErrorStatic(this, data, metadata),
|
|
622
716
|
toolRegistry: agentContext?.toolRegistry,
|
|
623
717
|
sessions: this.sessions,
|
|
718
|
+
toolExecution: this.toolExecution,
|
|
719
|
+
hookRegistry: this.hookRegistry,
|
|
720
|
+
humanInTheLoop: this.humanInTheLoop,
|
|
624
721
|
maxContextTokens: agentContext?.maxContextTokens,
|
|
625
722
|
maxToolResultChars: agentContext?.maxToolResultChars,
|
|
626
723
|
toolOutputRegistry: this.getOrCreateToolOutputRegistry(),
|
|
724
|
+
fileCheckpointer: this.getOrCreateFileCheckpointer(),
|
|
627
725
|
});
|
|
726
|
+
this.registerCompiledToolNode(node);
|
|
727
|
+
return node;
|
|
628
728
|
}
|
|
629
729
|
|
|
630
730
|
overrideTestModel(
|
|
@@ -688,7 +788,37 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
688
788
|
agentContext.markToolsAsDiscovered(discoveredNames);
|
|
689
789
|
}
|
|
690
790
|
|
|
691
|
-
const
|
|
791
|
+
const rawToolsForBinding = resolveLocalToolsForBinding({
|
|
792
|
+
tools: agentContext.getToolsForBinding(),
|
|
793
|
+
toolExecution: this.toolExecution,
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Anthropic prompt-cache breakpoint on the tool definitions.
|
|
798
|
+
*
|
|
799
|
+
* Without this, the (often static) tool inventory shows up as
|
|
800
|
+
* fresh input on every turn — measured at ~28k tokens/turn for
|
|
801
|
+
* the local engine's coding-tool bundle, dominating per-turn
|
|
802
|
+
* cost even when message-level caching is on.
|
|
803
|
+
*
|
|
804
|
+
* Strategy: partition tools into [static, deferred] and stamp
|
|
805
|
+
* `cache_control: ephemeral` on the last static tool.
|
|
806
|
+
* Discovered deferred tools that arrive across turns sit *after*
|
|
807
|
+
* the breakpoint and don't invalidate the prefix.
|
|
808
|
+
*/
|
|
809
|
+
let toolsForBinding = rawToolsForBinding;
|
|
810
|
+
if (
|
|
811
|
+
agentContext.provider === Providers.ANTHROPIC &&
|
|
812
|
+
(agentContext.clientOptions as t.AnthropicClientOptions | undefined)
|
|
813
|
+
?.promptCache === true
|
|
814
|
+
) {
|
|
815
|
+
toolsForBinding =
|
|
816
|
+
partitionAndMarkAnthropicToolCache(
|
|
817
|
+
rawToolsForBinding,
|
|
818
|
+
makeIsDeferred(agentContext.toolDefinitions)
|
|
819
|
+
) ?? rawToolsForBinding;
|
|
820
|
+
}
|
|
821
|
+
|
|
692
822
|
let model =
|
|
693
823
|
this.overrideModel ??
|
|
694
824
|
initializeModel({
|
|
@@ -804,7 +934,35 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
804
934
|
|
|
805
935
|
if (triggerResult) {
|
|
806
936
|
if (originalToolContent != null && originalToolContent.size > 0) {
|
|
807
|
-
|
|
937
|
+
/**
|
|
938
|
+
* Merge — never overwrite — the pruner's masking record
|
|
939
|
+
* into pendingOriginalToolContent. Carry-over entries
|
|
940
|
+
* from a prior summarize (preserved by the recency
|
|
941
|
+
* window for masked tool messages still in the tail) and
|
|
942
|
+
* the current pruner's new entries are both keyed by
|
|
943
|
+
* indices in the current `state.messages`, so a key-wise
|
|
944
|
+
* union is correct. Overwriting would discard the
|
|
945
|
+
* carry-over and reduce summary fidelity when those
|
|
946
|
+
* masked tail messages eventually move into the head.
|
|
947
|
+
*/
|
|
948
|
+
if (agentContext.pendingOriginalToolContent == null) {
|
|
949
|
+
agentContext.pendingOriginalToolContent = originalToolContent;
|
|
950
|
+
} else {
|
|
951
|
+
for (const [idx, content] of originalToolContent) {
|
|
952
|
+
agentContext.pendingOriginalToolContent.set(idx, content);
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Re-apply the per-store char cap after the union. The
|
|
956
|
+
* pruner enforces ORIGINAL_CONTENT_MAX_CHARS inside its
|
|
957
|
+
* own map via the onContentStored callback, but a
|
|
958
|
+
* key-wise merge with recency carry-over bypasses that
|
|
959
|
+
* accounting and could let the merged map grow without
|
|
960
|
+
* bound across long sessions.
|
|
961
|
+
*/
|
|
962
|
+
enforceOriginalContentCap(
|
|
963
|
+
agentContext.pendingOriginalToolContent
|
|
964
|
+
);
|
|
965
|
+
}
|
|
808
966
|
}
|
|
809
967
|
|
|
810
968
|
emitAgentLog(
|
|
@@ -58,7 +58,14 @@ function buildConversation(): t.IState {
|
|
|
58
58
|
async function createCompactingRun(
|
|
59
59
|
tokenCounter: t.TokenCounter,
|
|
60
60
|
hooks?: HookRegistry,
|
|
61
|
-
runId = 'compact-run'
|
|
61
|
+
runId = 'compact-run',
|
|
62
|
+
/**
|
|
63
|
+
* Recency-window setting. Defaults to `{ turns: 0 }` for these tests so
|
|
64
|
+
* the post-compaction state is the legacy "remove-all only" shape, which
|
|
65
|
+
* the original assertions were written against. Tests that want to
|
|
66
|
+
* exercise the recency-window path should pass an explicit value.
|
|
67
|
+
*/
|
|
68
|
+
retainRecent: { turns: number } = { turns: 0 }
|
|
62
69
|
): Promise<Run<t.IState>> {
|
|
63
70
|
const conversation = buildConversation();
|
|
64
71
|
const indexTokenCountMap: Record<string, number> = {};
|
|
@@ -79,6 +86,7 @@ async function createCompactingRun(
|
|
|
79
86
|
summarizationEnabled: true,
|
|
80
87
|
summarizationConfig: {
|
|
81
88
|
provider: Providers.OPENAI,
|
|
89
|
+
retainRecent,
|
|
82
90
|
},
|
|
83
91
|
},
|
|
84
92
|
returnContent: true,
|
|
@@ -138,7 +146,7 @@ describe('Compaction hook integration', () => {
|
|
|
138
146
|
});
|
|
139
147
|
|
|
140
148
|
describe('PostCompact', () => {
|
|
141
|
-
it('fires with summary text after compaction', async () => {
|
|
149
|
+
it('fires with summary text after compaction (legacy retainRecent.turns=0 shape)', async () => {
|
|
142
150
|
const registry = new HookRegistry();
|
|
143
151
|
let captured: PostCompactHookInput | undefined;
|
|
144
152
|
const hook: HookCallback<'PostCompact'> = async (
|
|
@@ -161,6 +169,34 @@ describe('Compaction hook integration', () => {
|
|
|
161
169
|
expect(captured!.messagesAfterCount).toBe(0);
|
|
162
170
|
expect(captured!.agentId).toBeDefined();
|
|
163
171
|
});
|
|
172
|
+
|
|
173
|
+
it('reports the recency-tail length in messagesAfterCount when retainRecent.turns > 0', async () => {
|
|
174
|
+
const registry = new HookRegistry();
|
|
175
|
+
let captured: PostCompactHookInput | undefined;
|
|
176
|
+
const hook: HookCallback<'PostCompact'> = async (
|
|
177
|
+
input
|
|
178
|
+
): Promise<PostCompactHookOutput> => {
|
|
179
|
+
captured = input;
|
|
180
|
+
return {};
|
|
181
|
+
};
|
|
182
|
+
registry.register('PostCompact', { hooks: [hook] });
|
|
183
|
+
|
|
184
|
+
const run = await createCompactingRun(
|
|
185
|
+
tokenCounter,
|
|
186
|
+
registry,
|
|
187
|
+
'compact-recency-run',
|
|
188
|
+
{ turns: 2 }
|
|
189
|
+
);
|
|
190
|
+
run.Graph!.overrideTestModel(['Final answer after compaction.']);
|
|
191
|
+
const inputs = buildConversation();
|
|
192
|
+
await run.processStream(inputs, callerConfig);
|
|
193
|
+
|
|
194
|
+
expect(captured).toBeDefined();
|
|
195
|
+
expect(captured!.hook_event_name).toBe('PostCompact');
|
|
196
|
+
// buildConversation produces 20 user-led turns of [user, ai]. With
|
|
197
|
+
// retainRecent.turns=2, the tail is the last 2 turns = 4 messages.
|
|
198
|
+
expect(captured!.messagesAfterCount).toBe(4);
|
|
199
|
+
});
|
|
164
200
|
});
|
|
165
201
|
|
|
166
202
|
describe('error resilience', () => {
|