@librechat/agents 3.1.77 → 3.1.78
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 +155 -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/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 +31 -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 +156 -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/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 +31 -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/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/tools/subagent/SubagentExecutor.d.ts +29 -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 +173 -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/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/subagent-configurable-inheritance.ts +252 -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__/SubagentExecutor.test.ts +148 -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/tools/subagent/SubagentExecutor.ts +60 -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
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine-agnostic filesystem seam for the local-coding tool suite.
|
|
3
|
+
*
|
|
4
|
+
* The current "local" engine maps every operation to Node's
|
|
5
|
+
* `fs/promises` against the host machine. A future engine — e.g. a
|
|
6
|
+
* stateful remote sandbox (e2b / Modal / Daytona / ssh-jail) —
|
|
7
|
+
* supplies its own `WorkspaceFS` implementation and reuses every
|
|
8
|
+
* tool factory unchanged. Same fuzzy-match `edit_file`, same
|
|
9
|
+
* checkpointer, same syntax-check, same image attachments — only
|
|
10
|
+
* the underlying I/O changes.
|
|
11
|
+
*
|
|
12
|
+
* Path semantics belong to the implementation. The local engine
|
|
13
|
+
* interprets paths as host filesystem paths; a remote engine would
|
|
14
|
+
* interpret them as remote-namespace paths. Tool factories don't
|
|
15
|
+
* inspect the strings beyond passing them through.
|
|
16
|
+
*
|
|
17
|
+
* Keep this surface minimal. Add a method only when an existing
|
|
18
|
+
* tool genuinely needs it; resist the temptation to mirror all of
|
|
19
|
+
* `fs/promises`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
mkdir as fsMkdir,
|
|
24
|
+
open as fsOpen,
|
|
25
|
+
readdir as fsReaddir,
|
|
26
|
+
readFile as fsReadFile,
|
|
27
|
+
realpath as fsRealpath,
|
|
28
|
+
stat as fsStat,
|
|
29
|
+
unlink as fsUnlink,
|
|
30
|
+
writeFile as fsWriteFile,
|
|
31
|
+
} from 'fs/promises';
|
|
32
|
+
import type { MakeDirectoryOptions, Stats, WriteFileOptions } from 'fs';
|
|
33
|
+
import type { FileHandle } from 'fs/promises';
|
|
34
|
+
|
|
35
|
+
export type ReaddirEntry = {
|
|
36
|
+
name: string;
|
|
37
|
+
isFile(): boolean;
|
|
38
|
+
isDirectory(): boolean;
|
|
39
|
+
isSymbolicLink(): boolean;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export interface WorkspaceFS {
|
|
43
|
+
readFile(path: string, encoding: 'utf8'): Promise<string>;
|
|
44
|
+
readFile(path: string): Promise<Buffer>;
|
|
45
|
+
writeFile(
|
|
46
|
+
path: string,
|
|
47
|
+
content: string | Buffer,
|
|
48
|
+
options?: WriteFileOptions
|
|
49
|
+
): Promise<void>;
|
|
50
|
+
stat(path: string): Promise<Stats>;
|
|
51
|
+
readdir(
|
|
52
|
+
path: string,
|
|
53
|
+
options: { withFileTypes: true }
|
|
54
|
+
): Promise<ReaddirEntry[]>;
|
|
55
|
+
readdir(path: string): Promise<string[]>;
|
|
56
|
+
mkdir(path: string, options?: MakeDirectoryOptions): Promise<void>;
|
|
57
|
+
realpath(path: string): Promise<string>;
|
|
58
|
+
unlink(path: string): Promise<void>;
|
|
59
|
+
/** Open a file for low-level read access (used by binary detection). */
|
|
60
|
+
open(path: string, flags: 'r'): Promise<FileHandle>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Default `WorkspaceFS` backed by Node's `fs/promises` module.
|
|
65
|
+
* Returned by `getWorkspaceFS(config)` when the host hasn't supplied
|
|
66
|
+
* an override on `local.exec.fs`.
|
|
67
|
+
*/
|
|
68
|
+
export const nodeWorkspaceFS: WorkspaceFS = {
|
|
69
|
+
// The runtime impl ignores the encoding-vs-buffer distinction; the
|
|
70
|
+
// overload signatures above are what callers see.
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
readFile: ((path: string, encoding?: 'utf8') =>
|
|
73
|
+
encoding != null
|
|
74
|
+
? fsReadFile(path, encoding)
|
|
75
|
+
: fsReadFile(path)) as WorkspaceFS['readFile'],
|
|
76
|
+
writeFile: (path, content, options) =>
|
|
77
|
+
fsWriteFile(path, content, options ?? 'utf8'),
|
|
78
|
+
stat: (path) => fsStat(path),
|
|
79
|
+
readdir: ((path: string, options?: { withFileTypes: true }) =>
|
|
80
|
+
options?.withFileTypes === true
|
|
81
|
+
? fsReaddir(path, { withFileTypes: true })
|
|
82
|
+
: fsReaddir(path)) as WorkspaceFS['readdir'],
|
|
83
|
+
mkdir: async (path, options) => {
|
|
84
|
+
await fsMkdir(path, options);
|
|
85
|
+
},
|
|
86
|
+
realpath: (path) => fsRealpath(path),
|
|
87
|
+
unlink: (path) => fsUnlink(path),
|
|
88
|
+
open: (path, flags) => fsOpen(path, flags),
|
|
89
|
+
};
|
|
@@ -40,6 +40,35 @@ export type SubagentExecuteParams = {
|
|
|
40
40
|
* without relying on event ordering heuristics.
|
|
41
41
|
*/
|
|
42
42
|
parentToolCallId?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Snapshot of the parent invocation's `config.configurable` at the
|
|
45
|
+
* spawn-tool call site. Inherited verbatim into the child workflow's
|
|
46
|
+
* `configurable` so host-set fields (`requestBody`, `user`,
|
|
47
|
+
* `userMCPAuthMap`, etc.) propagate — fixing MCP body-placeholder
|
|
48
|
+
* substitution and per-user lookups for subagent tool calls.
|
|
49
|
+
*
|
|
50
|
+
* Inheritance details (verified empirically against LangGraph):
|
|
51
|
+
* - host-set keys propagate as-is into the child's tool dispatches;
|
|
52
|
+
* - `thread_id` propagates (with `childRunId` as a fallback when
|
|
53
|
+
* parent did not supply one) — matches the "subagent is part of
|
|
54
|
+
* the same conversation" mental model and aligns with the
|
|
55
|
+
* `sessionId: this.parentRunId` convention this executor already
|
|
56
|
+
* uses for `SubagentStart` / `SubagentStop` hooks;
|
|
57
|
+
* - `parent_run_id` propagates when the host put it on parent's
|
|
58
|
+
* configurable;
|
|
59
|
+
* - `run_id` is *overwritten by the LangGraph runtime* at child
|
|
60
|
+
* invoke time regardless of what we forward — child's tool
|
|
61
|
+
* dispatches see the child graph's runtime runId in
|
|
62
|
+
* `configurable.run_id`, not the parent's. Hosts that need
|
|
63
|
+
* parent-scoped run identity for downstream consumers should
|
|
64
|
+
* plumb it via a host-defined key (e.g. `requestBody.messageId`),
|
|
65
|
+
* not `run_id`.
|
|
66
|
+
*
|
|
67
|
+
* A future revision will likely make this inheritance configurable
|
|
68
|
+
* per spawn type — background / async subagents may want isolation
|
|
69
|
+
* rather than sharing parent's host context.
|
|
70
|
+
*/
|
|
71
|
+
parentConfigurable?: Record<string, unknown>;
|
|
43
72
|
};
|
|
44
73
|
|
|
45
74
|
export type SubagentExecuteResult = {
|
|
@@ -246,6 +275,36 @@ export class SubagentExecutor {
|
|
|
246
275
|
* nested trace pollution).
|
|
247
276
|
*/
|
|
248
277
|
const callbacks: Callbacks = forwarder ? [forwarder] : [];
|
|
278
|
+
/**
|
|
279
|
+
* Inherit the parent's `configurable` verbatim — host-set fields
|
|
280
|
+
* (`requestBody`, `user`, `userMCPAuthMap`, etc.) AND the run-
|
|
281
|
+
* identity fields (`run_id`, `parent_run_id`, `thread_id`) all
|
|
282
|
+
* propagate.
|
|
283
|
+
*
|
|
284
|
+
* Run-identity propagation is intentional and matches the
|
|
285
|
+
* convention this executor itself already uses for `SubagentStart`
|
|
286
|
+
* / `SubagentStop` hooks (`sessionId: this.parentRunId`): the
|
|
287
|
+
* subagent runs under the parent's session scope, not its own.
|
|
288
|
+
* Forwarding `run_id` / `parent_run_id` / `thread_id` makes
|
|
289
|
+
* `ToolNode`'s hook lookups (`hasHookFor(eventName, runId)`),
|
|
290
|
+
* `ToolOutputReferenceRegistry` keying, and trace lineage all
|
|
291
|
+
* resolve to the parent's session for tools dispatched from the
|
|
292
|
+
* subagent — so `PreToolUse` / `PostToolUse` hooks the host
|
|
293
|
+
* registered against the parent's run fire for subagent tool
|
|
294
|
+
* calls too. "Same run" matches the user-perceptual mental model.
|
|
295
|
+
*
|
|
296
|
+
* `thread_id` falls back to `childRunId` only when the parent
|
|
297
|
+
* didn't supply one (legacy behavior preserved for hosts that
|
|
298
|
+
* never set thread_id).
|
|
299
|
+
*
|
|
300
|
+
* NOTE: a future revision will likely make this configurable per
|
|
301
|
+
* spawn type — e.g. a background / async subagent that runs after
|
|
302
|
+
* the parent's run completes wants isolation, not inheritance.
|
|
303
|
+
* For now the inheritance path matches LibreChat's primary use
|
|
304
|
+
* case (synchronous subagents within a single user turn).
|
|
305
|
+
*/
|
|
306
|
+
const inheritedConfigurable: Record<string, unknown> =
|
|
307
|
+
params.parentConfigurable ?? {};
|
|
249
308
|
result = await workflow.invoke(
|
|
250
309
|
{ messages: [new HumanMessage(description)] },
|
|
251
310
|
{
|
|
@@ -255,6 +314,7 @@ export class SubagentExecutor {
|
|
|
255
314
|
runName: `subagent:${subagentType}`,
|
|
256
315
|
configurable: {
|
|
257
316
|
thread_id: childRunId,
|
|
317
|
+
...inheritedConfigurable,
|
|
258
318
|
},
|
|
259
319
|
}
|
|
260
320
|
);
|
package/src/types/hitl.ts
CHANGED
|
@@ -233,39 +233,68 @@ export function isAskUserQuestionInterrupt(
|
|
|
233
233
|
* matches the pre-HITL behavior so existing hosts upgrading the SDK
|
|
234
234
|
* see no change until they're ready to wire the resume UI.
|
|
235
235
|
*
|
|
236
|
-
* ## Scope:
|
|
236
|
+
* ## Scope: every tool the ToolNode runs
|
|
237
237
|
*
|
|
238
|
-
* The interrupt path is wired into `
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
238
|
+
* The interrupt path is wired into both `dispatchToolEvents` (the
|
|
239
|
+
* event-driven path) and `runDirectToolWithLifecycleHooks` (the
|
|
240
|
+
* direct path used by `directToolNames` entries — graph-managed
|
|
241
|
+
* handoff/subagent tools and every in-process `graphTool` instance).
|
|
242
|
+
* `PreToolUse` hooks fire for every tool the ToolNode invokes, and
|
|
243
|
+
* HITL approval gates every tool whose hook returns `'ask'` —
|
|
244
|
+
* regardless of whether the tool is dispatched as an event or
|
|
245
|
+
* invoked in-process. This convergence happened in two follow-up
|
|
246
|
+
* commits to the original HITL surface (see `Graph.ts` —
|
|
247
|
+
* `hookRegistry`/`humanInTheLoop` are passed in both
|
|
248
|
+
* event-driven and legacy branches; and `ToolNode.runDirectToolWithLifecycleHooks`
|
|
249
|
+
* — direct-path tools build their own single-tool `tool_approval`
|
|
250
|
+
* payload and raise `interrupt()` the same way the event path does).
|
|
246
251
|
*
|
|
247
252
|
* Practical implications:
|
|
248
|
-
* -
|
|
249
|
-
*
|
|
250
|
-
* -
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
253
|
+
* - Every host gets the full HITL surface across every tool the
|
|
254
|
+
* model calls — event-dispatched, direct, mixed.
|
|
255
|
+
* - `createToolPolicyHook` and `createWorkspacePolicyHook` apply
|
|
256
|
+
* uniformly. A hook can be registered without knowing or caring
|
|
257
|
+
* which path the tool will take.
|
|
258
|
+
* - Direct tools that the host opted into via `directToolNames` no
|
|
259
|
+
* longer bypass policy. If you need a tool to skip the hook
|
|
260
|
+
* surface entirely, omit it from any registered matcher.
|
|
261
|
+
*
|
|
262
|
+
* ## Resume re-execution: every tool in the interrupted batch
|
|
263
|
+
*
|
|
264
|
+
* LangGraph rolls back to the start of the interrupted node on
|
|
265
|
+
* resume. That means **every tool in the same batch as the one that
|
|
266
|
+
* interrupted re-runs from the top on the resume pass**, not just
|
|
267
|
+
* the interrupting tool, and not just the direct half (this used to
|
|
268
|
+
* be framed as a direct-tool-specific concern; it is not — it
|
|
269
|
+
* applies to event-dispatched siblings too). Practical contract:
|
|
270
|
+
*
|
|
271
|
+
* - The body of the interrupting tool itself runs **once** total
|
|
272
|
+
* (the first pass interrupted *before* the body, the resume pass
|
|
273
|
+
* ran the body after the host's decision was applied).
|
|
274
|
+
* - The body of any sibling tool that already executed in the
|
|
275
|
+
* same batch before the interrupting tool runs **twice** — once
|
|
276
|
+
* on the first pass, once on the resume pass.
|
|
277
|
+
* - `PreToolUse` hooks fire **once per pass per tool**. A hook
|
|
278
|
+
* that always returns `'ask'` will loop forever on resume; real
|
|
279
|
+
* hooks should be deterministic w.r.t. inputs and use the
|
|
280
|
+
* `'ask' → host approves → resume → hook returns 'allow'`
|
|
281
|
+
* pattern, where the second-pass `allow` reflects the host
|
|
282
|
+
* having recorded the approval (e.g., a session-scoped approved-
|
|
283
|
+
* paths set keyed by `runId`).
|
|
284
|
+
*
|
|
285
|
+
* Consequence: any tool with side effects MUST be idempotent if
|
|
286
|
+
* there's any chance another tool in the same batch could trigger
|
|
287
|
+
* an interrupt. This applies equally to direct tools (handoffs,
|
|
288
|
+
* subagents) and to event tools.
|
|
262
289
|
*
|
|
263
290
|
* ## Note on idempotency
|
|
264
291
|
*
|
|
265
|
-
*
|
|
266
|
-
* from the start on resume, which
|
|
267
|
-
* Hooks that produce side effects
|
|
268
|
-
* two invocations per
|
|
292
|
+
* Same root cause as the resume re-execution above: LangGraph
|
|
293
|
+
* re-runs the interrupted node from the start on resume, which
|
|
294
|
+
* fires `PreToolUse` hooks again. Hooks that produce side effects
|
|
295
|
+
* (logging, external calls) will see at least two invocations per
|
|
296
|
+
* paused turn — exactly two for the interrupting tool, possibly
|
|
297
|
+
* more across siblings.
|
|
269
298
|
*/
|
|
270
299
|
export interface HumanInTheLoopConfig {
|
|
271
300
|
/**
|
package/src/types/run.ts
CHANGED
|
@@ -11,7 +11,11 @@ import type * as s from '@/types/stream';
|
|
|
11
11
|
import type * as e from '@/common/enum';
|
|
12
12
|
import type * as g from '@/types/graph';
|
|
13
13
|
import type * as l from '@/types/llm';
|
|
14
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
ToolSessionMap,
|
|
16
|
+
ToolExecutionConfig,
|
|
17
|
+
ToolOutputReferencesConfig,
|
|
18
|
+
} from '@/types/tools';
|
|
15
19
|
import type { HumanInTheLoopConfig } from '@/types/hitl';
|
|
16
20
|
import type { HookRegistry } from '@/hooks';
|
|
17
21
|
|
|
@@ -157,6 +161,13 @@ export type RunConfig = {
|
|
|
157
161
|
* placeholders. Disabled by default so existing runs are unaffected.
|
|
158
162
|
*/
|
|
159
163
|
toolOutputReferences?: ToolOutputReferencesConfig;
|
|
164
|
+
/**
|
|
165
|
+
* Selects the execution backend for built-in code tools. Omit this to keep
|
|
166
|
+
* the remote LibreChat Code API sandbox. Set `{ engine: 'local' }` to run
|
|
167
|
+
* code execution locally and auto-bind the local coding tool suite unless
|
|
168
|
+
* `local.includeCodingTools` is set to `false`.
|
|
169
|
+
*/
|
|
170
|
+
toolExecution?: ToolExecutionConfig;
|
|
160
171
|
/**
|
|
161
172
|
* First-class human-in-the-loop (HITL) flow for this run.
|
|
162
173
|
*
|
package/src/types/summarize.ts
CHANGED
|
@@ -10,6 +10,30 @@ export type SummarizationTrigger = {
|
|
|
10
10
|
value: number;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Controls how many recent messages are preserved verbatim during
|
|
15
|
+
* compaction. The most recent user-led turn is always preserved
|
|
16
|
+
* regardless of these caps, so a single oversized first message is
|
|
17
|
+
* never destroyed by summarization.
|
|
18
|
+
*/
|
|
19
|
+
export type RetainRecentConfig = {
|
|
20
|
+
/**
|
|
21
|
+
* Maximum number of recent user-led turns to keep in the tail. A turn
|
|
22
|
+
* begins at a HumanMessage and includes every following AIMessage and
|
|
23
|
+
* ToolMessage up to (but not including) the next HumanMessage. Cutting
|
|
24
|
+
* at turn boundaries guarantees tool_use / tool_result pairs are never
|
|
25
|
+
* split. Set to `0` to disable the recency window (legacy behavior:
|
|
26
|
+
* summarize everything). Defaults to `2`.
|
|
27
|
+
*/
|
|
28
|
+
turns?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Optional cap on retained-recent tokens beyond the most recent turn.
|
|
31
|
+
* Older turns are added whole only while cumulative tokens stay below
|
|
32
|
+
* the cap. Defaults to undefined (no cap; bounded only by `turns`).
|
|
33
|
+
*/
|
|
34
|
+
tokens?: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
13
37
|
export type SummarizationConfig = {
|
|
14
38
|
provider?: Providers;
|
|
15
39
|
model?: string;
|
|
@@ -20,6 +44,13 @@ export type SummarizationConfig = {
|
|
|
20
44
|
maxSummaryTokens?: number;
|
|
21
45
|
/** Fraction of the token budget reserved as headroom (0–1). Defaults to 0.05. */
|
|
22
46
|
reserveRatio?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Recent-message preservation policy. When unset, defaults to
|
|
49
|
+
* `{ turns: 2 }` so the last two user-led turns are kept verbatim
|
|
50
|
+
* while older content is summarized. Setting `{ turns: 0 }` reverts
|
|
51
|
+
* to the legacy behavior of summarizing every message.
|
|
52
|
+
*/
|
|
53
|
+
retainRecent?: RetainRecentConfig;
|
|
23
54
|
};
|
|
24
55
|
|
|
25
56
|
export interface SummarizeResult {
|