@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,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits `messages` into a head (older, to summarize) and a tail (recent,
|
|
3
|
+
* to preserve verbatim) at user-message boundaries. The most recent
|
|
4
|
+
* user-led turn is always included in the tail; additional older turns
|
|
5
|
+
* are added subject to `turns` and `tokens` caps.
|
|
6
|
+
*
|
|
7
|
+
* Cutting strictly at HumanMessage boundaries ensures that:
|
|
8
|
+
* - tool_use ↔ tool_result pairs are never split (they always live within
|
|
9
|
+
* the same turn);
|
|
10
|
+
* - the first user message is never replaced by a summary, addressing
|
|
11
|
+
* the "first turn destruction" failure mode where a single large
|
|
12
|
+
* user-pasted payload would otherwise be replaced by a generic summary.
|
|
13
|
+
*
|
|
14
|
+
* When `messages` contains no HumanMessage (degenerate state — e.g. system
|
|
15
|
+
* + assistant messages from a programmatic preamble), everything is
|
|
16
|
+
* placed in the head and the tail is empty. The summarize node treats
|
|
17
|
+
* an empty tail as "nothing recent to preserve" and falls through to its
|
|
18
|
+
* existing logic.
|
|
19
|
+
*/
|
|
20
|
+
function splitAtRecencyBoundary(messages, options = {}) {
|
|
21
|
+
const turnsCap = options.turns ?? 2;
|
|
22
|
+
if (messages.length === 0 || turnsCap <= 0) {
|
|
23
|
+
return {
|
|
24
|
+
head: messages,
|
|
25
|
+
tail: [],
|
|
26
|
+
tailTurnCount: 0,
|
|
27
|
+
tailStartIndex: messages.length,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const turnStarts = [];
|
|
31
|
+
for (let i = 0; i < messages.length; i++) {
|
|
32
|
+
if (messages[i].getType() === 'human') {
|
|
33
|
+
turnStarts.push(i);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (turnStarts.length === 0) {
|
|
37
|
+
return {
|
|
38
|
+
head: messages,
|
|
39
|
+
tail: [],
|
|
40
|
+
tailTurnCount: 0,
|
|
41
|
+
tailStartIndex: messages.length,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const lastTurnStart = turnStarts[turnStarts.length - 1];
|
|
45
|
+
let tailStartIndex = lastTurnStart;
|
|
46
|
+
let tailTurnCount = 1;
|
|
47
|
+
const tokensCap = options.tokens;
|
|
48
|
+
const tokenCounter = options.tokenCounter;
|
|
49
|
+
const trackTokens = tokensCap != null && Number.isFinite(tokensCap) && tokenCounter != null;
|
|
50
|
+
/**
|
|
51
|
+
* Token-counting strategy: each candidate turn `t` spans the half-open
|
|
52
|
+
* range `[turnStarts[t], turnStarts[t + 1])` (or `[turnStarts[t], messages.length)`
|
|
53
|
+
* for the most recent turn). Successive iterations of the outer loop
|
|
54
|
+
* walk older turns one at a time and never revisit messages from a
|
|
55
|
+
* later turn — so each message contributes to `tokenCounter` at most
|
|
56
|
+
* once across the entire selection, making the boundary search
|
|
57
|
+
* `O(messages_in_visited_turns)` and bounded by `O(messages.length)`
|
|
58
|
+
* even before the `turnsCap` short-circuit applies. The inner upper
|
|
59
|
+
* bound uses `turnStarts[t + 1]` (a value derived from immutable
|
|
60
|
+
* `turnStarts`) rather than the mutated `tailStartIndex` to make the
|
|
61
|
+
* disjoint-range invariant self-evident.
|
|
62
|
+
*/
|
|
63
|
+
let tailTokens = 0;
|
|
64
|
+
if (trackTokens) {
|
|
65
|
+
for (let i = lastTurnStart; i < messages.length; i++) {
|
|
66
|
+
tailTokens += tokenCounter(messages[i]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (let t = turnStarts.length - 2; t >= 0; t--) {
|
|
70
|
+
if (tailTurnCount >= turnsCap) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
const turnStart = turnStarts[t];
|
|
74
|
+
const turnEnd = turnStarts[t + 1];
|
|
75
|
+
if (trackTokens) {
|
|
76
|
+
let turnTokens = 0;
|
|
77
|
+
for (let i = turnStart; i < turnEnd; i++) {
|
|
78
|
+
turnTokens += tokenCounter(messages[i]);
|
|
79
|
+
}
|
|
80
|
+
if (tailTokens + turnTokens > tokensCap) {
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
tailTokens += turnTokens;
|
|
84
|
+
}
|
|
85
|
+
tailStartIndex = turnStart;
|
|
86
|
+
tailTurnCount += 1;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
head: messages.slice(0, tailStartIndex),
|
|
90
|
+
tail: messages.slice(tailStartIndex),
|
|
91
|
+
tailTurnCount,
|
|
92
|
+
tailStartIndex,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { splitAtRecencyBoundary };
|
|
97
|
+
//# sourceMappingURL=recency.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recency.mjs","sources":["../../../src/messages/recency.ts"],"sourcesContent":["import type { BaseMessage } from '@langchain/core/messages';\n\n/**\n * Configuration for splitting a message list into a head (to be summarized)\n * and a tail (to be preserved verbatim).\n */\nexport interface RecencyWindowOptions {\n /**\n * Maximum number of recent user-led turns to keep in the tail. A \"turn\"\n * begins at a HumanMessage and includes every following AIMessage and\n * ToolMessage up to (but not including) the next HumanMessage. Cutting\n * at turn boundaries guarantees that tool_use / tool_result pairs are\n * never split across the head/tail divide.\n *\n * The most recent turn is always preserved regardless of this value or\n * the token cap, so that a single oversized first message is never\n * destroyed by summarization.\n *\n * Defaults to `2`. A value of `0` disables the recency window (head =\n * everything, tail = empty), restoring the pre-recency-window behavior.\n */\n turns?: number;\n /**\n * Optional cap on tail size in tokens. When set, additional turns\n * beyond the most recent one are added to the tail only while the\n * cumulative token count stays at or below this cap. Turns are added\n * whole — never partially — so a turn that would exceed the cap is\n * left in the head.\n *\n * The most recent turn is always preserved even if it exceeds the cap.\n */\n tokens?: number;\n /** Token-counter used to evaluate the optional `tokens` cap. */\n tokenCounter?: (m: BaseMessage) => number;\n}\n\nexport interface RecencySplit {\n /** Older messages eligible for summarization. Empty when nothing to summarize. */\n head: BaseMessage[];\n /** Recent messages preserved verbatim. Always contains the most recent turn when any HumanMessage exists. */\n tail: BaseMessage[];\n /** Number of user-led turns retained in the tail (0 if no HumanMessage exists). */\n tailTurnCount: number;\n /** Index in the original `messages` array where the tail begins. */\n tailStartIndex: number;\n}\n\n/**\n * Splits `messages` into a head (older, to summarize) and a tail (recent,\n * to preserve verbatim) at user-message boundaries. The most recent\n * user-led turn is always included in the tail; additional older turns\n * are added subject to `turns` and `tokens` caps.\n *\n * Cutting strictly at HumanMessage boundaries ensures that:\n * - tool_use ↔ tool_result pairs are never split (they always live within\n * the same turn);\n * - the first user message is never replaced by a summary, addressing\n * the \"first turn destruction\" failure mode where a single large\n * user-pasted payload would otherwise be replaced by a generic summary.\n *\n * When `messages` contains no HumanMessage (degenerate state — e.g. system\n * + assistant messages from a programmatic preamble), everything is\n * placed in the head and the tail is empty. The summarize node treats\n * an empty tail as \"nothing recent to preserve\" and falls through to its\n * existing logic.\n */\nexport function splitAtRecencyBoundary(\n messages: BaseMessage[],\n options: RecencyWindowOptions = {}\n): RecencySplit {\n const turnsCap = options.turns ?? 2;\n\n if (messages.length === 0 || turnsCap <= 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const turnStarts: number[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].getType() === 'human') {\n turnStarts.push(i);\n }\n }\n\n if (turnStarts.length === 0) {\n return {\n head: messages,\n tail: [],\n tailTurnCount: 0,\n tailStartIndex: messages.length,\n };\n }\n\n const lastTurnStart = turnStarts[turnStarts.length - 1] as number;\n let tailStartIndex = lastTurnStart;\n let tailTurnCount = 1;\n\n const tokensCap = options.tokens;\n const tokenCounter = options.tokenCounter;\n const trackTokens =\n tokensCap != null && Number.isFinite(tokensCap) && tokenCounter != null;\n\n /**\n * Token-counting strategy: each candidate turn `t` spans the half-open\n * range `[turnStarts[t], turnStarts[t + 1])` (or `[turnStarts[t], messages.length)`\n * for the most recent turn). Successive iterations of the outer loop\n * walk older turns one at a time and never revisit messages from a\n * later turn — so each message contributes to `tokenCounter` at most\n * once across the entire selection, making the boundary search\n * `O(messages_in_visited_turns)` and bounded by `O(messages.length)`\n * even before the `turnsCap` short-circuit applies. The inner upper\n * bound uses `turnStarts[t + 1]` (a value derived from immutable\n * `turnStarts`) rather than the mutated `tailStartIndex` to make the\n * disjoint-range invariant self-evident.\n */\n let tailTokens = 0;\n if (trackTokens) {\n for (let i = lastTurnStart; i < messages.length; i++) {\n tailTokens += tokenCounter(messages[i] as BaseMessage);\n }\n }\n\n for (let t = turnStarts.length - 2; t >= 0; t--) {\n if (tailTurnCount >= turnsCap) {\n break;\n }\n const turnStart = turnStarts[t] as number;\n const turnEnd = turnStarts[t + 1] as number;\n\n if (trackTokens) {\n let turnTokens = 0;\n for (let i = turnStart; i < turnEnd; i++) {\n turnTokens += tokenCounter(messages[i] as BaseMessage);\n }\n if (tailTokens + turnTokens > (tokensCap as number)) {\n break;\n }\n tailTokens += turnTokens;\n }\n\n tailStartIndex = turnStart;\n tailTurnCount += 1;\n }\n\n return {\n head: messages.slice(0, tailStartIndex),\n tail: messages.slice(tailStartIndex),\n tailTurnCount,\n tailStartIndex,\n };\n}\n"],"names":[],"mappings":"AA+CA;;;;;;;;;;;;;;;;;;AAkBG;SACa,sBAAsB,CACpC,QAAuB,EACvB,UAAgC,EAAE,EAAA;AAElC,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC;IAEnC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAI,CAAC,EAAE;QAC1C,OAAO;AACL,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,IAAI,EAAE,EAAE;AACR,YAAA,aAAa,EAAE,CAAC;YAChB,cAAc,EAAE,QAAQ,CAAC,MAAM;SAChC;IACH;IAEA,MAAM,UAAU,GAAa,EAAE;AAC/B,IAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACxC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,OAAO,EAAE;AACrC,YAAA,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACpB;IACF;AAEA,IAAA,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3B,OAAO;AACL,YAAA,IAAI,EAAE,QAAQ;AACd,YAAA,IAAI,EAAE,EAAE;AACR,YAAA,aAAa,EAAE,CAAC;YAChB,cAAc,EAAE,QAAQ,CAAC,MAAM;SAChC;IACH;IAEA,MAAM,aAAa,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAW;IACjE,IAAI,cAAc,GAAG,aAAa;IAClC,IAAI,aAAa,GAAG,CAAC;AAErB,IAAA,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM;AAChC,IAAA,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY;AACzC,IAAA,MAAM,WAAW,GACf,SAAS,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,YAAY,IAAI,IAAI;AAEzE;;;;;;;;;;;;AAYG;IACH,IAAI,UAAU,GAAG,CAAC;IAClB,IAAI,WAAW,EAAE;AACf,QAAA,KAAK,IAAI,CAAC,GAAG,aAAa,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpD,UAAU,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAgB,CAAC;QACxD;IACF;AAEA,IAAA,KAAK,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;AAC/C,QAAA,IAAI,aAAa,IAAI,QAAQ,EAAE;YAC7B;QACF;AACA,QAAA,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAW;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,CAAW;QAE3C,IAAI,WAAW,EAAE;YACf,IAAI,UAAU,GAAG,CAAC;AAClB,YAAA,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE;gBACxC,UAAU,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAgB,CAAC;YACxD;AACA,YAAA,IAAI,UAAU,GAAG,UAAU,GAAI,SAAoB,EAAE;gBACnD;YACF;YACA,UAAU,IAAI,UAAU;QAC1B;QAEA,cAAc,GAAG,SAAS;QAC1B,aAAa,IAAI,CAAC;IACpB;IAEA,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC;AACvC,QAAA,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;QACpC,aAAa;QACb,cAAc;KACf;AACH;;;;"}
|
package/dist/esm/run.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { StandardGraph } from './graphs/Graph.mjs';
|
|
|
14
14
|
import { initializeModel } from './llm/init.mjs';
|
|
15
15
|
import { HandlerRegistry } from './events.mjs';
|
|
16
16
|
import { executeHooks } from './hooks/executeHooks.mjs';
|
|
17
|
+
import './hooks/createWorkspacePolicyHook.mjs';
|
|
17
18
|
import { isOpenAILike } from './utils/llm.mjs';
|
|
18
19
|
import { isPresent } from './utils/misc.mjs';
|
|
19
20
|
|
|
@@ -37,6 +38,7 @@ class Run {
|
|
|
37
38
|
hookRegistry;
|
|
38
39
|
humanInTheLoop;
|
|
39
40
|
toolOutputReferences;
|
|
41
|
+
toolExecution;
|
|
40
42
|
indexTokenCountMap;
|
|
41
43
|
calibrationRatio = 1;
|
|
42
44
|
graphRunnable;
|
|
@@ -74,6 +76,7 @@ class Run {
|
|
|
74
76
|
this.hookRegistry = config.hooks;
|
|
75
77
|
this.humanInTheLoop = config.humanInTheLoop;
|
|
76
78
|
this.toolOutputReferences = config.toolOutputReferences;
|
|
79
|
+
this.toolExecution = config.toolExecution;
|
|
77
80
|
if (!config.graphConfig) {
|
|
78
81
|
throw new Error('Graph config not provided');
|
|
79
82
|
}
|
|
@@ -138,6 +141,7 @@ class Run {
|
|
|
138
141
|
standardGraph.hookRegistry = this.hookRegistry;
|
|
139
142
|
standardGraph.humanInTheLoop = this.humanInTheLoop;
|
|
140
143
|
standardGraph.toolOutputReferences = this.toolOutputReferences;
|
|
144
|
+
standardGraph.toolExecution = this.toolExecution;
|
|
141
145
|
this.Graph = standardGraph;
|
|
142
146
|
return standardGraph.createWorkflow();
|
|
143
147
|
}
|
|
@@ -156,6 +160,7 @@ class Run {
|
|
|
156
160
|
multiAgentGraph.hookRegistry = this.hookRegistry;
|
|
157
161
|
multiAgentGraph.humanInTheLoop = this.humanInTheLoop;
|
|
158
162
|
multiAgentGraph.toolOutputReferences = this.toolOutputReferences;
|
|
163
|
+
multiAgentGraph.toolExecution = this.toolExecution;
|
|
159
164
|
this.Graph = multiAgentGraph;
|
|
160
165
|
return multiAgentGraph.createWorkflow();
|
|
161
166
|
}
|
|
@@ -737,6 +742,31 @@ class Run {
|
|
|
737
742
|
* graph state from the checkpoint and re-enters the interrupted node
|
|
738
743
|
* from the start.
|
|
739
744
|
*/
|
|
745
|
+
/**
|
|
746
|
+
* Returns the per-Run file checkpointer when
|
|
747
|
+
* `toolExecution.local.fileCheckpointing === true` was set on the
|
|
748
|
+
* RunConfig. Hosts can capture extra paths or call `rewind()`
|
|
749
|
+
* directly. Returns undefined when checkpointing is disabled.
|
|
750
|
+
*
|
|
751
|
+
* Construction-time invariant: the checkpointer is shared across
|
|
752
|
+
* every ToolNode the graph compiles (single-agent and multi-agent),
|
|
753
|
+
* so a `rewind()` call here unwinds writes made by ANY agent in the
|
|
754
|
+
* run.
|
|
755
|
+
*/
|
|
756
|
+
getFileCheckpointer() {
|
|
757
|
+
return this.Graph?.getOrCreateFileCheckpointer();
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Convenience wrapper that calls `rewind()` on the per-Run file
|
|
761
|
+
* checkpointer. Restores every file the local engine snapshotted
|
|
762
|
+
* during this Run to its pre-write content (and deletes any path
|
|
763
|
+
* that didn't exist before being created). Returns the count of
|
|
764
|
+
* paths processed; returns 0 when checkpointing is disabled.
|
|
765
|
+
*/
|
|
766
|
+
async rewindFiles() {
|
|
767
|
+
const cp = this.getFileCheckpointer();
|
|
768
|
+
return cp == null ? 0 : cp.rewind();
|
|
769
|
+
}
|
|
740
770
|
async resume(resumeValue, callerConfig, streamOptions) {
|
|
741
771
|
return this.processStream(new Command({ resume: resumeValue }), callerConfig, streamOptions);
|
|
742
772
|
}
|
package/dist/esm/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","sources":["../../src/run.ts"],"sourcesContent":["// src/run.ts\nimport './instrumentation';\nimport { CallbackHandler } from '@langfuse/langchain';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { RunnableLambda } from '@langchain/core/runnables';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport {\n Command,\n INTERRUPT,\n MemorySaver,\n isInterrupted,\n} from '@langchain/langgraph';\nimport { HumanMessage } from '@langchain/core/messages';\nimport { BaseCallbackHandler } from '@langchain/core/callbacks/base';\nimport type {\n MessageContentComplex,\n BaseMessage,\n} from '@langchain/core/messages';\nimport type { StringPromptValue } from '@langchain/core/prompt_values';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from '@/types';\nimport {\n createCompletionTitleRunnable,\n createTitleRunnable,\n} from '@/utils/title';\nimport { createTokenCounter, encodingForModel } from '@/utils/tokens';\nimport { GraphEvents, Callback, TitleMethod } from '@/common';\nimport { MultiAgentGraph } from '@/graphs/MultiAgentGraph';\nimport { StandardGraph } from '@/graphs/Graph';\nimport { initializeModel } from '@/llm/init';\nimport { HandlerRegistry } from '@/events';\nimport { executeHooks } from '@/hooks';\nimport { isOpenAILike } from '@/utils/llm';\nimport { isPresent } from '@/utils/misc';\nimport type { HookRegistry } from '@/hooks';\n\nexport const defaultOmitOptions = new Set([\n 'stream',\n 'thinking',\n 'streaming',\n 'maxTokens',\n 'clientOptions',\n 'thinkingConfig',\n 'thinkingBudget',\n 'includeThoughts',\n 'maxOutputTokens',\n 'additionalModelRequestFields',\n]);\n\nexport class Run<_T extends t.BaseGraphState> {\n id: string;\n private tokenCounter?: t.TokenCounter;\n private handlerRegistry?: HandlerRegistry;\n private hookRegistry?: HookRegistry;\n private humanInTheLoop?: t.HumanInTheLoopConfig;\n private toolOutputReferences?: t.ToolOutputReferencesConfig;\n private indexTokenCountMap?: Record<string, number>;\n calibrationRatio: number = 1;\n graphRunnable?: t.CompiledStateWorkflow;\n Graph: StandardGraph | MultiAgentGraph | undefined;\n returnContent: boolean = false;\n private skipCleanup: boolean = false;\n private _streamResult: t.MessageContentComplex[] | undefined;\n /**\n * Captured interrupt payload typed as `unknown` because the SDK\n * does not validate the runtime shape — custom graph nodes can\n * raise interrupts with arbitrary payloads (not just the SDK's\n * `HumanInterruptPayload` union). The public `getInterrupt<T>()`\n * lets callers assert the type they expect.\n */\n private _interrupt: t.RunInterruptResult<unknown> | undefined;\n private _haltedReason: string | undefined;\n\n private constructor(config: Partial<t.RunConfig>) {\n const runId = config.runId ?? '';\n if (!runId) {\n throw new Error('Run ID not provided');\n }\n\n this.id = runId;\n this.tokenCounter = config.tokenCounter;\n this.indexTokenCountMap = config.indexTokenCountMap;\n if (config.calibrationRatio != null && config.calibrationRatio > 0) {\n this.calibrationRatio = config.calibrationRatio;\n }\n\n const handlerRegistry = new HandlerRegistry();\n\n if (config.customHandlers) {\n for (const [eventType, handler] of Object.entries(\n config.customHandlers\n )) {\n handlerRegistry.register(eventType, handler);\n }\n }\n\n this.handlerRegistry = handlerRegistry;\n this.hookRegistry = config.hooks;\n this.humanInTheLoop = config.humanInTheLoop;\n this.toolOutputReferences = config.toolOutputReferences;\n\n if (!config.graphConfig) {\n throw new Error('Graph config not provided');\n }\n\n /** Handle different graph types */\n if (config.graphConfig.type === 'multi-agent') {\n this.graphRunnable = this.createMultiAgentGraph(config.graphConfig);\n if (this.Graph) {\n this.Graph.handlerRegistry = handlerRegistry;\n }\n } else {\n /** Default to legacy graph for 'standard' or undefined type */\n this.graphRunnable = this.createLegacyGraph(config.graphConfig);\n if (this.Graph) {\n this.Graph.compileOptions =\n config.graphConfig.compileOptions ?? this.Graph.compileOptions;\n this.Graph.handlerRegistry = handlerRegistry;\n }\n }\n\n if (config.initialSessions && this.Graph) {\n for (const [key, value] of config.initialSessions) {\n this.Graph.sessions.set(key, value);\n }\n }\n\n this.returnContent = config.returnContent ?? false;\n this.skipCleanup = config.skipCleanup ?? false;\n }\n\n private createLegacyGraph(\n config: t.LegacyGraphConfig | t.StandardGraphConfig\n ): t.CompiledStateWorkflow {\n let agentConfig: t.AgentInputs;\n let signal: AbortSignal | undefined;\n\n /** Check if this is a multi-agent style config (has agents array) */\n if ('agents' in config && Array.isArray(config.agents)) {\n if (config.agents.length === 0) {\n throw new Error('At least one agent must be provided');\n }\n agentConfig = config.agents[0];\n signal = config.signal;\n } else {\n /** Legacy path: build agent config from llmConfig */\n const {\n type: _type,\n llmConfig,\n signal: legacySignal,\n tools = [],\n ...agentInputs\n } = config as t.LegacyGraphConfig;\n const { provider, ...clientOptions } = llmConfig;\n\n agentConfig = {\n ...agentInputs,\n tools,\n provider,\n clientOptions,\n agentId: 'default',\n };\n signal = legacySignal;\n }\n\n const standardGraph = new StandardGraph({\n signal,\n runId: this.id,\n agents: [agentConfig],\n tokenCounter: this.tokenCounter,\n indexTokenCountMap: this.indexTokenCountMap,\n calibrationRatio: this.calibrationRatio,\n });\n /** Propagate compile options from graph config */\n standardGraph.compileOptions = this.applyHITLCheckpointerFallback(\n config.compileOptions\n );\n standardGraph.hookRegistry = this.hookRegistry;\n standardGraph.humanInTheLoop = this.humanInTheLoop;\n standardGraph.toolOutputReferences = this.toolOutputReferences;\n this.Graph = standardGraph;\n return standardGraph.createWorkflow();\n }\n\n private createMultiAgentGraph(\n config: t.MultiAgentGraphConfig\n ): t.CompiledStateWorkflow {\n const { agents, edges, compileOptions } = config;\n\n const multiAgentGraph = new MultiAgentGraph({\n runId: this.id,\n agents,\n edges,\n tokenCounter: this.tokenCounter,\n indexTokenCountMap: this.indexTokenCountMap,\n calibrationRatio: this.calibrationRatio,\n });\n\n multiAgentGraph.compileOptions =\n this.applyHITLCheckpointerFallback(compileOptions);\n\n multiAgentGraph.hookRegistry = this.hookRegistry;\n multiAgentGraph.humanInTheLoop = this.humanInTheLoop;\n multiAgentGraph.toolOutputReferences = this.toolOutputReferences;\n this.Graph = multiAgentGraph;\n return multiAgentGraph.createWorkflow();\n }\n\n /**\n * When the host opted into HITL via `humanInTheLoop: { enabled: true }`\n * and did not supply a checkpointer, install an in-memory `MemorySaver`\n * so `interrupt()` can persist checkpoints and `Command({ resume })`\n * can rebuild state. The fallback is intentionally process-local:\n * production hosts that need durable resumption across processes /\n * restarts must provide their own checkpointer (Redis, Postgres, etc.)\n * on `compileOptions.checkpointer`.\n *\n * No-op when HITL is off (the default — omitted, or\n * `{ enabled: false }`) or the host already supplied a checkpointer\n * of their own. See `HumanInTheLoopConfig` JSDoc for the rationale\n * behind the default-off stance.\n */\n private applyHITLCheckpointerFallback(\n compileOptions: t.CompileOptions | undefined\n ): t.CompileOptions | undefined {\n if (this.humanInTheLoop?.enabled !== true) {\n return compileOptions;\n }\n if (compileOptions?.checkpointer != null) {\n return compileOptions;\n }\n return {\n ...(compileOptions ?? {}),\n checkpointer: new MemorySaver(),\n };\n }\n\n /**\n * Run RunStart + UserPromptSubmit hooks before the graph stream\n * begins, accumulate any `additionalContext` strings into the input\n * messages, and short-circuit when a hook signals the run should not\n * proceed (deny / ask decision on the prompt, or `preventContinuation`\n * on either hook).\n *\n * Returns `true` when the caller should bail with `undefined` (run\n * was halted before any model call); returns `false` to proceed\n * into the stream loop.\n *\n * ## Side effects\n *\n * On the success path:\n * - Mutates `stateInputs.messages` in place to append a\n * consolidated `HumanMessage` carrying any hook\n * `additionalContext` strings. Safe because the host owns the\n * array and `processStream` is the only consumer until LangGraph\n * reads it.\n *\n * On the halt path (returning `true`):\n * - Sets `this._haltedReason` so callers (and the eventual host)\n * can distinguish a hook-driven halt from a natural completion.\n * - Calls `registry.clearSession(this.id)` and\n * `registry.clearHaltSignal(this.id)` because no resume is\n * expected from a pre-stream halt — the run never entered the\n * graph, so the session/halt state for this run would otherwise\n * leak to the next `processStream` invocation on the same\n * registry. Other concurrent runs on the same registry are\n * untouched (halt signals are scoped per session id).\n * - Sets `config.callbacks = undefined` to drop the callback\n * references the caller built (langfuse handler, custom event\n * handler, etc.) since they won't be exercised. Mirrors the\n * equivalent cleanup the `processStream` `finally` block does\n * on the natural-completion path.\n */\n private async runPreStreamHooks(\n stateInputs: t.IState,\n threadId: string | undefined,\n config: Partial<RunnableConfig>\n ): Promise<boolean> {\n const registry = this.hookRegistry;\n /**\n * Defensive guard: `processStream` already validated `this.Graph`\n * before calling this helper, but TypeScript can't propagate that\n * narrowing across method boundaries. The check keeps the body\n * free of `this.Graph!` non-null assertions.\n */\n if (registry == null || this.Graph == null) {\n return false;\n }\n\n const preStreamContexts: string[] = [];\n\n const runStartResult = await executeHooks({\n registry,\n input: {\n hook_event_name: 'RunStart',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n messages: stateInputs.messages,\n },\n sessionId: this.id,\n });\n for (const ctx of runStartResult.additionalContexts) {\n preStreamContexts.push(ctx);\n }\n /**\n * Honor `preventContinuation` from RunStart before the stream\n * starts. Mid-flight halts (from tool/compact/subagent hooks)\n * route through `HookRegistry.haltRun` and are polled by the\n * stream loop in `processStream` — different mechanism, same\n * intent.\n */\n if (runStartResult.preventContinuation === true) {\n this._haltedReason = runStartResult.stopReason ?? 'preventContinuation';\n registry.clearSession(this.id);\n registry.clearHaltSignal(this.id);\n config.callbacks = undefined;\n return true;\n }\n\n const lastHuman = findLastMessageOfType(stateInputs.messages, 'human');\n if (lastHuman != null) {\n const promptResult = await executeHooks({\n registry,\n input: {\n hook_event_name: 'UserPromptSubmit',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n prompt: extractPromptText(lastHuman),\n // attachments: not yet wired — Phase 2 will extract\n // non-text content blocks (images, files) from messages\n },\n sessionId: this.id,\n });\n if (\n promptResult.decision === 'deny' ||\n promptResult.decision === 'ask' ||\n promptResult.preventContinuation === true\n ) {\n /**\n * Always set `_haltedReason` so the host can call\n * `getHaltReason()` and distinguish a hook-blocked prompt\n * from a natural empty-output completion. Three signals can\n * land here, each with its own canonical reason string when\n * the hook didn't supply one.\n */\n if (promptResult.preventContinuation === true) {\n this._haltedReason = promptResult.stopReason ?? 'preventContinuation';\n } else if (promptResult.decision === 'deny') {\n this._haltedReason = promptResult.reason ?? 'prompt_denied';\n } else {\n this._haltedReason =\n promptResult.reason ?? 'prompt_requires_approval';\n }\n registry.clearSession(this.id);\n registry.clearHaltSignal(this.id);\n config.callbacks = undefined;\n return true;\n }\n for (const ctx of promptResult.additionalContexts) {\n preStreamContexts.push(ctx);\n }\n }\n\n if (preStreamContexts.length > 0) {\n /**\n * Wraps the joined hook contexts as a `HumanMessage` even though\n * the intent is system-level guidance. Using a `SystemMessage`\n * mid-conversation is rejected by Anthropic and Google providers\n * (system messages must be the leading entry), so the LangChain\n * convention — also used by `ToolNode.convertInjectedMessages`\n * — is `HumanMessage` carrying `additional_kwargs.role` as a\n * marker for hosts inspecting state. The model still sees a\n * user-role message; the `role: 'system'` field is metadata\n * only. Hosts that want a true system message should compose\n * it into the agent's `instructions` config instead.\n */\n stateInputs.messages.push(\n new HumanMessage({\n content: preStreamContexts.join('\\n\\n'),\n additional_kwargs: { role: 'system', source: 'hook' },\n })\n );\n }\n\n return false;\n }\n\n static async create<T extends t.BaseGraphState>(\n config: t.RunConfig\n ): Promise<Run<T>> {\n /** Create tokenCounter if indexTokenCountMap is provided but tokenCounter is not */\n if (config.indexTokenCountMap && !config.tokenCounter) {\n const gc = config.graphConfig;\n const clientOpts =\n 'agents' in gc ? gc.agents[0]?.clientOptions : gc.clientOptions;\n const model = (clientOpts as { model?: string } | undefined)?.model ?? '';\n config.tokenCounter = await createTokenCounter(encodingForModel(model));\n }\n return new Run<T>(config);\n }\n\n getRunMessages(): BaseMessage[] | undefined {\n if (!this.Graph) {\n throw new Error(\n 'Graph not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n return this.Graph.getRunMessages();\n }\n\n /**\n * Returns the current calibration ratio (EMA of provider-vs-estimate token ratios).\n * Hosts should persist this value and pass it back as `RunConfig.calibrationRatio`\n * on the next run for the same conversation so the pruner starts with an accurate\n * scaling factor instead of the default (1).\n */\n getCalibrationRatio(): number {\n return this.calibrationRatio;\n }\n\n getResolvedInstructionOverhead(): number | undefined {\n return this.Graph?.getResolvedInstructionOverhead();\n }\n\n getToolCount(): number {\n return this.Graph?.getToolCount() ?? 0;\n }\n\n /**\n * Creates a custom event callback handler that intercepts custom events\n * and processes them through our handler registry instead of EventStreamCallbackHandler\n */\n private createCustomEventCallback() {\n return async (\n eventName: string,\n data: unknown,\n runId: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): Promise<void> => {\n // ON_RUN_STEP is dispatched directly via handler registry in\n // Graph.dispatchRunStep (primary, reliable path). Skip the\n // callback-based dispatch to prevent double handling.\n if (\n eventName === GraphEvents.ON_RUN_STEP &&\n this.Graph != null &&\n this.Graph.handlerDispatchedStepIds.has((data as t.RunStep).id)\n ) {\n return;\n }\n const handler = this.handlerRegistry?.getHandler(eventName);\n if (handler && this.Graph) {\n return await handler.handle(\n eventName,\n data as\n | t.StreamEventData\n | t.ModelEndData\n | t.RunStep\n | t.RunStepDeltaEvent\n | t.MessageDeltaEvent\n | t.ReasoningDeltaEvent\n | { result: t.ToolEndEvent },\n metadata,\n this.Graph\n );\n }\n };\n }\n\n async processStream(\n inputs: t.IState | Command,\n callerConfig: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n },\n streamOptions?: t.EventStreamOptions\n ): Promise<MessageContentComplex[] | undefined> {\n if (this.graphRunnable == null) {\n throw new Error(\n 'Run not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n if (!this.Graph) {\n throw new Error(\n 'Graph not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n\n /**\n * `Command` inputs (currently only `Command({ resume })`) are\n * resume-mode invocations: LangGraph rebuilds graph state from the\n * checkpointer, so we skip RunStart / UserPromptSubmit hooks (no\n * new prompt to evaluate) and read run-state from the Graph wrapper\n * instead of `inputs.messages`.\n */\n const isResume = inputs instanceof Command;\n const stateInputs = isResume ? undefined : (inputs as t.IState);\n\n const config: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n } = {\n recursionLimit: 50,\n ...callerConfig,\n configurable: { ...callerConfig.configurable },\n };\n\n /**\n * Skip `resetValues` on resume — we're continuing an in-flight\n * run, not starting a fresh one. Resetting would wipe the\n * sidecars (`toolCallStepIds`, `stepKeyIds`, accumulated\n * `messages`, etc.) the resumed `ToolNode` needs to dispatch\n * tool completions with the correct step ids and re-resolve\n * `{{tool<i>turn<n>}}` references. Pairs with the\n * `awaitingResume` gate on `clearHeavyState` in the `finally`\n * block so the sidecars survive both ends of the interrupt\n * boundary.\n */\n if (!isResume) {\n this.Graph.resetValues(streamOptions?.keepContent);\n }\n this._interrupt = undefined;\n this._haltedReason = undefined;\n this.hookRegistry?.clearHaltSignal(this.id);\n\n /** Custom event callback to intercept and handle custom events */\n const customEventCallback = this.createCustomEventCallback();\n\n const baseCallbacks = (config.callbacks as t.ProvidedCallbacks) ?? [];\n const streamCallbacks = streamOptions?.callbacks\n ? this.getCallbacks(streamOptions.callbacks)\n : [];\n\n const customHandler = BaseCallbackHandler.fromMethods({\n [Callback.CUSTOM_EVENT]: customEventCallback,\n });\n customHandler.awaitHandlers = true;\n\n config.callbacks = baseCallbacks\n .concat(streamCallbacks)\n .concat(customHandler);\n\n if (\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&\n isPresent(process.env.LANGFUSE_BASE_URL)\n ) {\n const userId = config.configurable?.user_id;\n const sessionId = config.configurable?.thread_id;\n const primaryContext = this.Graph.agentContexts.get(\n this.Graph.defaultAgentId\n );\n const traceMetadata = {\n messageId: this.id,\n parentMessageId: config.configurable?.requestBody?.parentMessageId,\n agentName: primaryContext?.name,\n };\n const handler = new CallbackHandler({\n userId,\n sessionId,\n traceMetadata,\n });\n config.callbacks = (\n (config.callbacks as t.ProvidedCallbacks) ?? []\n ).concat([handler]);\n }\n\n if (!this.id) {\n throw new Error('Run ID not provided');\n }\n\n config.run_id = this.id;\n config.configurable = Object.assign(config.configurable ?? {}, {\n run_id: this.id,\n });\n\n const threadId = config.configurable.thread_id as string | undefined;\n\n if (this.hookRegistry != null && stateInputs != null) {\n const shouldHalt = await this.runPreStreamHooks(\n stateInputs,\n threadId,\n config\n );\n if (shouldHalt) {\n return undefined;\n }\n }\n\n /**\n * `streamEvents` accepts both state inputs and `Command` (resume) at\n * runtime, but our `CompiledStateWorkflow` type narrows the first\n * arg to `BaseGraphState`. Cast on the call so the resume path\n * type-checks without widening the wrapper for every caller.\n */\n const stream = this.graphRunnable.streamEvents(inputs as t.IState, config, {\n raiseError: true,\n /**\n * Prevent EventStreamCallbackHandler from processing custom events.\n * Custom events are already handled via our createCustomEventCallback()\n * which routes them through the handlerRegistry.\n * Without this flag, EventStreamCallbackHandler throws errors when\n * custom events are dispatched for run IDs not in its internal map\n * (due to timing issues in parallel execution or after run cleanup).\n */\n ignoreCustomEvent: true,\n });\n\n /**\n * Tracks whether the stream loop threw. Used by the `finally`\n * block to decide whether to honor the interrupt-preservation\n * guard for session hooks: a captured `_interrupt` is only\n * meaningful if the stream completed cleanly. If the loop errored\n * after stashing an interrupt (e.g. a downstream handler throws\n * after the interrupt event landed), the interrupt is stale —\n * preserving session hooks would leak them into the next run.\n */\n let streamThrew = false;\n\n try {\n for await (const event of stream) {\n const { data, metadata, ...info } = event;\n\n const eventName: t.EventName = info.event;\n\n /** Skip custom events as they're handled by our callback */\n if (eventName === GraphEvents.ON_CUSTOM_EVENT) {\n continue;\n }\n\n /**\n * Detect interrupts surfaced by LangGraph as a synthetic\n * `__interrupt__` field on the streamed chunk and stash the\n * first one for the host to read via `run.getInterrupt()`\n * once the stream drains. Captured as `unknown` because the\n * SDK does not validate the runtime payload shape — the\n * built-in ToolNode raises a `HumanInterruptPayload`\n * (`tool_approval` / `ask_user_question`), but custom nodes\n * can pass any payload to `interrupt()`. Callers narrow with\n * the `isToolApprovalInterrupt` / `isAskUserQuestionInterrupt`\n * guards or assert via `getInterrupt<T>()`.\n */\n if (\n this._interrupt == null &&\n data.chunk != null &&\n isInterrupted<unknown>(data.chunk)\n ) {\n const interrupts = data.chunk[INTERRUPT];\n if (interrupts.length > 0) {\n const first = interrupts[0];\n /**\n * Capture the interrupt unconditionally — `interrupt(null)`\n * and `interrupt(undefined)` are valid pauses (a custom\n * node may want to pause without metadata) and the host\n * still needs to know the run is awaiting resume. Gating\n * on `payload != null` would silently downgrade a paused\n * run to \"completed\" and let the `Stop` hook fire,\n * breaking host resume handling.\n */\n this._interrupt = {\n interruptId: first.id ?? '',\n threadId,\n payload: first.value,\n };\n }\n }\n\n const handler = this.handlerRegistry?.getHandler(eventName);\n if (handler) {\n await handler.handle(eventName, data, metadata, this.Graph);\n }\n\n /**\n * Mid-flight halt: any hook (PreToolUse, PostToolUse,\n * PostToolBatch, SubagentStart/Stop, PreCompact, PostCompact)\n * that returned `preventContinuation: true` raises a halt\n * signal on the registry via `executeHooks`. We poll between\n * stream events and break out as soon as one is set so the\n * graph doesn't take another model turn after the halting\n * operation completes.\n *\n * Limitation: the current step (in-flight model call, ongoing\n * tool batch) is not aborted — only the next step is skipped.\n * This matches Claude Code's `continue: false` semantic where\n * the active operation finishes before halting takes effect.\n */\n const haltSignal = this.hookRegistry?.getHaltSignal(this.id);\n if (haltSignal != null) {\n this._haltedReason = haltSignal.reason;\n break;\n }\n }\n\n /**\n * Skip the Stop hook when the run paused on a HITL interrupt\n * (still pending human input) or was halted by a hook (the host\n * already chose to stop, so a Stop hook firing now would be\n * misleading). The host fires Stop on the resumed-and-completed\n * run instead.\n */\n if (\n this._interrupt == null &&\n this._haltedReason == null &&\n this.hookRegistry?.hasHookFor('Stop', this.id) === true\n ) {\n await executeHooks({\n registry: this.hookRegistry,\n input: {\n hook_event_name: 'Stop',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n messages:\n this.Graph.getRunMessages() ?? stateInputs?.messages ?? [],\n stopHookActive: false, // will be true when stop is triggered by a hook (Phase 2)\n },\n sessionId: this.id,\n }).catch(() => {\n /* Stop hook errors must not masquerade as stream failures */\n });\n }\n } catch (err) {\n streamThrew = true;\n if (this.hookRegistry?.hasHookFor('StopFailure', this.id) === true) {\n const runMessages = this.Graph.getRunMessages() ?? [];\n await executeHooks({\n registry: this.hookRegistry,\n input: {\n hook_event_name: 'StopFailure',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n error: err instanceof Error ? err.message : String(err),\n lastAssistantMessage: findLastMessageOfType(runMessages, 'ai'),\n },\n sessionId: this.id,\n }).catch(() => {\n /* swallow hook errors — the original error must propagate */\n });\n }\n throw err;\n } finally {\n /**\n * Preserve session-scoped hooks when the run paused on a HITL\n * interrupt — the very next call will be `Run.resume()`, which\n * needs the same policy hooks (e.g., the `PreToolUse` matcher\n * that triggered the interrupt) to fire on the re-executed node\n * and uphold the approval flow. Clearing here would leak the\n * approval gate on resume. The session is cleared instead at\n * natural completion, error (including errors that happen AFTER\n * an interrupt was captured — those interrupts are stale), or\n * hook-driven halt (including hooks that returned BOTH `ask`\n * and `preventContinuation` — the halt wins, no resume is\n * expected, sessions must drop). Every state where no resume\n * is expected clears.\n */\n if (\n this._interrupt == null ||\n this._haltedReason != null ||\n streamThrew\n ) {\n this.hookRegistry?.clearSession(this.id);\n }\n /**\n * Drop any halt signal raised mid-stream for this run so a\n * subsequent `processStream` / `resume` starts with clean state.\n * The Run captured `_haltedReason` already; the registry entry\n * for this `sessionId` would otherwise spuriously trip the next\n * loop. Other concurrent runs sharing this registry are\n * unaffected — their entries live under their own session ids.\n */\n this.hookRegistry?.clearHaltSignal(this.id);\n\n /**\n * Break the reference chain that keeps heavy data alive via\n * LangGraph's internal `__pregel_scratchpad.currentTaskInput` →\n * `@langchain/core` `RunTree.extra[lc:child_config]` →\n * Node.js `AsyncLocalStorage` context captured by timers/promises.\n *\n * Without this, base64-encoded images/PDFs in message content remain\n * reachable from lingering `Timeout` handles until GC runs.\n */\n if (!this.skipCleanup) {\n if (\n (config.configurable as Record<string, unknown> | undefined) != null\n ) {\n for (const key of Object.getOwnPropertySymbols(config.configurable)) {\n const val = config.configurable[key as unknown as string] as\n | Record<string, unknown>\n | undefined;\n if (\n val != null &&\n typeof val === 'object' &&\n 'currentTaskInput' in val\n ) {\n (val as Record<string, unknown>).currentTaskInput = undefined;\n }\n delete config.configurable[key as unknown as string];\n }\n config.configurable = undefined;\n }\n config.callbacks = undefined;\n }\n\n const result = this.returnContent\n ? this.Graph.getContentParts()\n : undefined;\n\n this.calibrationRatio = this.Graph.getCalibrationRatio();\n\n /**\n * Skip `clearHeavyState()` when the run paused on a clean HITL\n * interrupt awaiting resume — `Run.resume()` re-enters the same\n * `ToolNode` instance and needs the sidecars `clearHeavyState`\n * would wipe (`toolCallStepIds` for completion-event step ids,\n * the `_toolOutputRegistry` for `{{tool<i>turn<n>}}`\n * substitutions, `sessions` for code-env continuity, plus the\n * `hookRegistry` and `humanInTheLoop` config the interrupt\n * branch itself relies on). Without preservation, the resumed\n * tool completion would dispatch `ON_RUN_STEP_COMPLETED` with\n * an empty step id and downstream stream consumers would drop\n * the result.\n *\n * The natural-completion / error / hook-driven-halt paths still\n * clean up — `_haltedReason != null` or `streamThrew` mean no\n * resume is expected. Cross-process resume (host rebuilds the\n * Run from scratch) is a separate concern; see\n * `HumanInTheLoopConfig` JSDoc.\n */\n const awaitingResume =\n this._interrupt != null && this._haltedReason == null && !streamThrew;\n if (!this.skipCleanup && !awaitingResume) {\n this.Graph.clearHeavyState();\n }\n\n this._streamResult = result;\n }\n\n return this._streamResult;\n }\n\n /**\n * Returns the pending interrupt captured during the most recent\n * `processStream` (or `resume`) invocation. `undefined` when the run\n * either has not been streamed yet or completed without pausing.\n *\n * Hosts call this immediately after `processStream` returns to decide\n * whether the run is awaiting human input. Persist the returned\n * descriptor (alongside `thread_id` and the agent run config) so a\n * later `resume(decisions)` can rebuild the run.\n *\n * The default `TPayload` is the SDK's `HumanInterruptPayload` union\n * (`tool_approval` / `ask_user_question`), suitable for the common\n * case where interrupts come from the built-in ToolNode or\n * `askUserQuestion()` helper. Hosts that raise custom interrupts\n * from custom graph nodes pass their own type — the SDK does not\n * validate the runtime shape, it just transports whatever the\n * `interrupt()` call carried. When in doubt, narrow with the\n * `isToolApprovalInterrupt` / `isAskUserQuestionInterrupt` type\n * guards (which accept `unknown`) before reading variant-specific\n * fields.\n */\n getInterrupt<TPayload = t.HumanInterruptPayload>():\n | t.RunInterruptResult<TPayload>\n | undefined {\n return this._interrupt as t.RunInterruptResult<TPayload> | undefined;\n }\n\n /**\n * Returns the reason a hook halted the run via\n * `preventContinuation: true`, or `undefined` if no hook halted.\n *\n * Hosts inspect this after `processStream` returns to distinguish a\n * natural completion (`undefined`) from a hook-driven halt (a\n * truthy string). Independent from `getInterrupt()` — a halted run\n * has no interrupt; an interrupted run has no halt reason.\n */\n getHaltReason(): string | undefined {\n return this._haltedReason;\n }\n\n /**\n * Resume a paused HITL run with the value the user (or whatever\n * decided the interrupt) supplied. The default `TResume` covers the\n * `tool_approval` interrupt (the common case): an array of decisions\n * in `action_requests` order, or a record keyed by `tool_call_id`.\n *\n * For other interrupt types (e.g., `ask_user_question` →\n * `AskUserQuestionResolution`, or any custom interrupt a host raises\n * from a custom node), pass the type parameter and the SDK forwards\n * the value through unchanged. LangGraph delivers it as the return\n * value of the original `interrupt()` call inside the paused node.\n *\n * The host MUST construct this Run with the same `thread_id` and the\n * same checkpointer as the original paused run; LangGraph rebuilds\n * graph state from the checkpoint and re-enters the interrupted node\n * from the start.\n */\n async resume<TResume = t.ToolApprovalDecision[] | t.ToolApprovalDecisionMap>(\n resumeValue: TResume,\n callerConfig: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n },\n streamOptions?: t.EventStreamOptions\n ): Promise<MessageContentComplex[] | undefined> {\n return this.processStream(\n new Command({ resume: resumeValue }),\n callerConfig,\n streamOptions\n );\n }\n\n private createSystemCallback<K extends keyof t.ClientCallbacks>(\n clientCallbacks: t.ClientCallbacks,\n key: K\n ): t.SystemCallbacks[K] {\n return ((...args: unknown[]) => {\n const clientCallback = clientCallbacks[key];\n if (clientCallback && this.Graph) {\n (clientCallback as (...args: unknown[]) => void)(this.Graph, ...args);\n }\n }) as t.SystemCallbacks[K];\n }\n\n getCallbacks(clientCallbacks: t.ClientCallbacks): t.SystemCallbacks {\n return {\n [Callback.TOOL_ERROR]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_ERROR\n ),\n [Callback.TOOL_START]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_START\n ),\n [Callback.TOOL_END]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_END\n ),\n };\n }\n\n async generateTitle({\n provider,\n inputText,\n contentParts,\n titlePrompt,\n clientOptions,\n chainOptions,\n skipLanguage,\n titleMethod = TitleMethod.COMPLETION,\n titlePromptTemplate,\n }: t.RunTitleOptions): Promise<{ language?: string; title?: string }> {\n if (\n chainOptions != null &&\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&\n isPresent(process.env.LANGFUSE_BASE_URL)\n ) {\n const userId = chainOptions.configurable?.user_id;\n const sessionId = chainOptions.configurable?.thread_id;\n const titleContext = this.Graph?.agentContexts.get(\n this.Graph.defaultAgentId\n );\n const traceMetadata = {\n messageId: 'title-' + this.id,\n agentName: titleContext?.name,\n };\n const handler = new CallbackHandler({\n userId,\n sessionId,\n traceMetadata,\n });\n chainOptions.callbacks = (\n (chainOptions.callbacks as t.ProvidedCallbacks) ?? []\n ).concat([handler]);\n }\n\n const convoTemplate = PromptTemplate.fromTemplate(\n titlePromptTemplate ?? 'User: {input}\\nAI: {output}'\n );\n\n const response = contentParts\n .map((part) => {\n if (part?.type === 'text') return part.text;\n return '';\n })\n .join('\\n');\n\n const model = initializeModel({\n provider,\n clientOptions,\n }) as t.ChatModelInstance;\n\n if (\n isOpenAILike(provider) &&\n (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)\n ) {\n model.temperature = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.temperature as number;\n model.topP = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.topP as number;\n model.frequencyPenalty = (\n clientOptions as t.OpenAIClientOptions | undefined\n )?.frequencyPenalty as number;\n model.presencePenalty = (\n clientOptions as t.OpenAIClientOptions | undefined\n )?.presencePenalty as number;\n model.n = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.n as number;\n }\n\n const convoToTitleInput = new RunnableLambda({\n func: (\n promptValue: StringPromptValue\n ): { convo: string; inputText: string; skipLanguage?: boolean } => ({\n convo: promptValue.value,\n inputText,\n skipLanguage,\n }),\n }).withConfig({ runName: 'ConvoTransform' });\n\n const titleChain =\n titleMethod === TitleMethod.COMPLETION\n ? await createCompletionTitleRunnable(model, titlePrompt)\n : await createTitleRunnable(model, titlePrompt);\n\n /** Pipes `convoTemplate` -> `transformer` -> `titleChain` */\n const fullChain = convoTemplate\n .withConfig({ runName: 'ConvoTemplate' })\n .pipe(convoToTitleInput)\n .pipe(titleChain)\n .withConfig({ runName: 'TitleChain' });\n\n const invokeConfig = Object.assign({}, chainOptions, {\n run_id: this.id,\n runId: this.id,\n });\n\n try {\n return await fullChain.invoke(\n { input: inputText, output: response },\n invokeConfig\n );\n } catch (_e) {\n // Fallback: strip callbacks to avoid EventStream tracer errors in certain environments\n // But preserve langfuse handler if it exists\n const langfuseHandler = (\n invokeConfig.callbacks as t.ProvidedCallbacks\n )?.find((cb) => cb instanceof CallbackHandler);\n const { callbacks: _cb, ...rest } = invokeConfig;\n const safeConfig = Object.assign({}, rest, {\n callbacks: langfuseHandler ? [langfuseHandler] : [],\n });\n return await fullChain.invoke(\n { input: inputText, output: response },\n safeConfig as Partial<RunnableConfig>\n );\n }\n }\n}\n\nfunction findLastMessageOfType(\n messages: BaseMessage[],\n type: string\n): BaseMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].getType() === type) {\n return messages[i];\n }\n }\n return undefined;\n}\n\nfunction extractPromptText(message: BaseMessage): string {\n const content = message.content;\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return String(content);\n }\n const parts: string[] = [];\n for (const block of content) {\n if (\n typeof block === 'object' &&\n 'type' in block &&\n block.type === 'text' &&\n 'text' in block &&\n typeof block.text === 'string'\n ) {\n parts.push(block.text);\n }\n }\n return parts.join('\\n');\n}\n"],"names":["ChatOpenAI","AzureChatOpenAI"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run.mjs","sources":["../../src/run.ts"],"sourcesContent":["// src/run.ts\nimport './instrumentation';\nimport { CallbackHandler } from '@langfuse/langchain';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { RunnableLambda } from '@langchain/core/runnables';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport {\n Command,\n INTERRUPT,\n MemorySaver,\n isInterrupted,\n} from '@langchain/langgraph';\nimport { HumanMessage } from '@langchain/core/messages';\nimport { BaseCallbackHandler } from '@langchain/core/callbacks/base';\nimport type {\n MessageContentComplex,\n BaseMessage,\n} from '@langchain/core/messages';\nimport type { StringPromptValue } from '@langchain/core/prompt_values';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from '@/types';\nimport {\n createCompletionTitleRunnable,\n createTitleRunnable,\n} from '@/utils/title';\nimport { createTokenCounter, encodingForModel } from '@/utils/tokens';\nimport { GraphEvents, Callback, TitleMethod } from '@/common';\nimport { MultiAgentGraph } from '@/graphs/MultiAgentGraph';\nimport { StandardGraph } from '@/graphs/Graph';\nimport { initializeModel } from '@/llm/init';\nimport { HandlerRegistry } from '@/events';\nimport { executeHooks } from '@/hooks';\nimport { isOpenAILike } from '@/utils/llm';\nimport { isPresent } from '@/utils/misc';\nimport type { HookRegistry } from '@/hooks';\n\nexport const defaultOmitOptions = new Set([\n 'stream',\n 'thinking',\n 'streaming',\n 'maxTokens',\n 'clientOptions',\n 'thinkingConfig',\n 'thinkingBudget',\n 'includeThoughts',\n 'maxOutputTokens',\n 'additionalModelRequestFields',\n]);\n\nexport class Run<_T extends t.BaseGraphState> {\n id: string;\n private tokenCounter?: t.TokenCounter;\n private handlerRegistry?: HandlerRegistry;\n private hookRegistry?: HookRegistry;\n private humanInTheLoop?: t.HumanInTheLoopConfig;\n private toolOutputReferences?: t.ToolOutputReferencesConfig;\n private toolExecution?: t.ToolExecutionConfig;\n private indexTokenCountMap?: Record<string, number>;\n calibrationRatio: number = 1;\n graphRunnable?: t.CompiledStateWorkflow;\n Graph: StandardGraph | MultiAgentGraph | undefined;\n returnContent: boolean = false;\n private skipCleanup: boolean = false;\n private _streamResult: t.MessageContentComplex[] | undefined;\n /**\n * Captured interrupt payload typed as `unknown` because the SDK\n * does not validate the runtime shape — custom graph nodes can\n * raise interrupts with arbitrary payloads (not just the SDK's\n * `HumanInterruptPayload` union). The public `getInterrupt<T>()`\n * lets callers assert the type they expect.\n */\n private _interrupt: t.RunInterruptResult<unknown> | undefined;\n private _haltedReason: string | undefined;\n\n private constructor(config: Partial<t.RunConfig>) {\n const runId = config.runId ?? '';\n if (!runId) {\n throw new Error('Run ID not provided');\n }\n\n this.id = runId;\n this.tokenCounter = config.tokenCounter;\n this.indexTokenCountMap = config.indexTokenCountMap;\n if (config.calibrationRatio != null && config.calibrationRatio > 0) {\n this.calibrationRatio = config.calibrationRatio;\n }\n\n const handlerRegistry = new HandlerRegistry();\n\n if (config.customHandlers) {\n for (const [eventType, handler] of Object.entries(\n config.customHandlers\n )) {\n handlerRegistry.register(eventType, handler);\n }\n }\n\n this.handlerRegistry = handlerRegistry;\n this.hookRegistry = config.hooks;\n this.humanInTheLoop = config.humanInTheLoop;\n this.toolOutputReferences = config.toolOutputReferences;\n this.toolExecution = config.toolExecution;\n\n if (!config.graphConfig) {\n throw new Error('Graph config not provided');\n }\n\n /** Handle different graph types */\n if (config.graphConfig.type === 'multi-agent') {\n this.graphRunnable = this.createMultiAgentGraph(config.graphConfig);\n if (this.Graph) {\n this.Graph.handlerRegistry = handlerRegistry;\n }\n } else {\n /** Default to legacy graph for 'standard' or undefined type */\n this.graphRunnable = this.createLegacyGraph(config.graphConfig);\n if (this.Graph) {\n this.Graph.compileOptions =\n config.graphConfig.compileOptions ?? this.Graph.compileOptions;\n this.Graph.handlerRegistry = handlerRegistry;\n }\n }\n\n if (config.initialSessions && this.Graph) {\n for (const [key, value] of config.initialSessions) {\n this.Graph.sessions.set(key, value);\n }\n }\n\n this.returnContent = config.returnContent ?? false;\n this.skipCleanup = config.skipCleanup ?? false;\n }\n\n private createLegacyGraph(\n config: t.LegacyGraphConfig | t.StandardGraphConfig\n ): t.CompiledStateWorkflow {\n let agentConfig: t.AgentInputs;\n let signal: AbortSignal | undefined;\n\n /** Check if this is a multi-agent style config (has agents array) */\n if ('agents' in config && Array.isArray(config.agents)) {\n if (config.agents.length === 0) {\n throw new Error('At least one agent must be provided');\n }\n agentConfig = config.agents[0];\n signal = config.signal;\n } else {\n /** Legacy path: build agent config from llmConfig */\n const {\n type: _type,\n llmConfig,\n signal: legacySignal,\n tools = [],\n ...agentInputs\n } = config as t.LegacyGraphConfig;\n const { provider, ...clientOptions } = llmConfig;\n\n agentConfig = {\n ...agentInputs,\n tools,\n provider,\n clientOptions,\n agentId: 'default',\n };\n signal = legacySignal;\n }\n\n const standardGraph = new StandardGraph({\n signal,\n runId: this.id,\n agents: [agentConfig],\n tokenCounter: this.tokenCounter,\n indexTokenCountMap: this.indexTokenCountMap,\n calibrationRatio: this.calibrationRatio,\n });\n /** Propagate compile options from graph config */\n standardGraph.compileOptions = this.applyHITLCheckpointerFallback(\n config.compileOptions\n );\n standardGraph.hookRegistry = this.hookRegistry;\n standardGraph.humanInTheLoop = this.humanInTheLoop;\n standardGraph.toolOutputReferences = this.toolOutputReferences;\n standardGraph.toolExecution = this.toolExecution;\n this.Graph = standardGraph;\n return standardGraph.createWorkflow();\n }\n\n private createMultiAgentGraph(\n config: t.MultiAgentGraphConfig\n ): t.CompiledStateWorkflow {\n const { agents, edges, compileOptions } = config;\n\n const multiAgentGraph = new MultiAgentGraph({\n runId: this.id,\n agents,\n edges,\n tokenCounter: this.tokenCounter,\n indexTokenCountMap: this.indexTokenCountMap,\n calibrationRatio: this.calibrationRatio,\n });\n\n multiAgentGraph.compileOptions =\n this.applyHITLCheckpointerFallback(compileOptions);\n\n multiAgentGraph.hookRegistry = this.hookRegistry;\n multiAgentGraph.humanInTheLoop = this.humanInTheLoop;\n multiAgentGraph.toolOutputReferences = this.toolOutputReferences;\n multiAgentGraph.toolExecution = this.toolExecution;\n this.Graph = multiAgentGraph;\n return multiAgentGraph.createWorkflow();\n }\n\n /**\n * When the host opted into HITL via `humanInTheLoop: { enabled: true }`\n * and did not supply a checkpointer, install an in-memory `MemorySaver`\n * so `interrupt()` can persist checkpoints and `Command({ resume })`\n * can rebuild state. The fallback is intentionally process-local:\n * production hosts that need durable resumption across processes /\n * restarts must provide their own checkpointer (Redis, Postgres, etc.)\n * on `compileOptions.checkpointer`.\n *\n * No-op when HITL is off (the default — omitted, or\n * `{ enabled: false }`) or the host already supplied a checkpointer\n * of their own. See `HumanInTheLoopConfig` JSDoc for the rationale\n * behind the default-off stance.\n */\n private applyHITLCheckpointerFallback(\n compileOptions: t.CompileOptions | undefined\n ): t.CompileOptions | undefined {\n if (this.humanInTheLoop?.enabled !== true) {\n return compileOptions;\n }\n if (compileOptions?.checkpointer != null) {\n return compileOptions;\n }\n return {\n ...(compileOptions ?? {}),\n checkpointer: new MemorySaver(),\n };\n }\n\n /**\n * Run RunStart + UserPromptSubmit hooks before the graph stream\n * begins, accumulate any `additionalContext` strings into the input\n * messages, and short-circuit when a hook signals the run should not\n * proceed (deny / ask decision on the prompt, or `preventContinuation`\n * on either hook).\n *\n * Returns `true` when the caller should bail with `undefined` (run\n * was halted before any model call); returns `false` to proceed\n * into the stream loop.\n *\n * ## Side effects\n *\n * On the success path:\n * - Mutates `stateInputs.messages` in place to append a\n * consolidated `HumanMessage` carrying any hook\n * `additionalContext` strings. Safe because the host owns the\n * array and `processStream` is the only consumer until LangGraph\n * reads it.\n *\n * On the halt path (returning `true`):\n * - Sets `this._haltedReason` so callers (and the eventual host)\n * can distinguish a hook-driven halt from a natural completion.\n * - Calls `registry.clearSession(this.id)` and\n * `registry.clearHaltSignal(this.id)` because no resume is\n * expected from a pre-stream halt — the run never entered the\n * graph, so the session/halt state for this run would otherwise\n * leak to the next `processStream` invocation on the same\n * registry. Other concurrent runs on the same registry are\n * untouched (halt signals are scoped per session id).\n * - Sets `config.callbacks = undefined` to drop the callback\n * references the caller built (langfuse handler, custom event\n * handler, etc.) since they won't be exercised. Mirrors the\n * equivalent cleanup the `processStream` `finally` block does\n * on the natural-completion path.\n */\n private async runPreStreamHooks(\n stateInputs: t.IState,\n threadId: string | undefined,\n config: Partial<RunnableConfig>\n ): Promise<boolean> {\n const registry = this.hookRegistry;\n /**\n * Defensive guard: `processStream` already validated `this.Graph`\n * before calling this helper, but TypeScript can't propagate that\n * narrowing across method boundaries. The check keeps the body\n * free of `this.Graph!` non-null assertions.\n */\n if (registry == null || this.Graph == null) {\n return false;\n }\n\n const preStreamContexts: string[] = [];\n\n const runStartResult = await executeHooks({\n registry,\n input: {\n hook_event_name: 'RunStart',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n messages: stateInputs.messages,\n },\n sessionId: this.id,\n });\n for (const ctx of runStartResult.additionalContexts) {\n preStreamContexts.push(ctx);\n }\n /**\n * Honor `preventContinuation` from RunStart before the stream\n * starts. Mid-flight halts (from tool/compact/subagent hooks)\n * route through `HookRegistry.haltRun` and are polled by the\n * stream loop in `processStream` — different mechanism, same\n * intent.\n */\n if (runStartResult.preventContinuation === true) {\n this._haltedReason = runStartResult.stopReason ?? 'preventContinuation';\n registry.clearSession(this.id);\n registry.clearHaltSignal(this.id);\n config.callbacks = undefined;\n return true;\n }\n\n const lastHuman = findLastMessageOfType(stateInputs.messages, 'human');\n if (lastHuman != null) {\n const promptResult = await executeHooks({\n registry,\n input: {\n hook_event_name: 'UserPromptSubmit',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n prompt: extractPromptText(lastHuman),\n // attachments: not yet wired — Phase 2 will extract\n // non-text content blocks (images, files) from messages\n },\n sessionId: this.id,\n });\n if (\n promptResult.decision === 'deny' ||\n promptResult.decision === 'ask' ||\n promptResult.preventContinuation === true\n ) {\n /**\n * Always set `_haltedReason` so the host can call\n * `getHaltReason()` and distinguish a hook-blocked prompt\n * from a natural empty-output completion. Three signals can\n * land here, each with its own canonical reason string when\n * the hook didn't supply one.\n */\n if (promptResult.preventContinuation === true) {\n this._haltedReason = promptResult.stopReason ?? 'preventContinuation';\n } else if (promptResult.decision === 'deny') {\n this._haltedReason = promptResult.reason ?? 'prompt_denied';\n } else {\n this._haltedReason =\n promptResult.reason ?? 'prompt_requires_approval';\n }\n registry.clearSession(this.id);\n registry.clearHaltSignal(this.id);\n config.callbacks = undefined;\n return true;\n }\n for (const ctx of promptResult.additionalContexts) {\n preStreamContexts.push(ctx);\n }\n }\n\n if (preStreamContexts.length > 0) {\n /**\n * Wraps the joined hook contexts as a `HumanMessage` even though\n * the intent is system-level guidance. Using a `SystemMessage`\n * mid-conversation is rejected by Anthropic and Google providers\n * (system messages must be the leading entry), so the LangChain\n * convention — also used by `ToolNode.convertInjectedMessages`\n * — is `HumanMessage` carrying `additional_kwargs.role` as a\n * marker for hosts inspecting state. The model still sees a\n * user-role message; the `role: 'system'` field is metadata\n * only. Hosts that want a true system message should compose\n * it into the agent's `instructions` config instead.\n */\n stateInputs.messages.push(\n new HumanMessage({\n content: preStreamContexts.join('\\n\\n'),\n additional_kwargs: { role: 'system', source: 'hook' },\n })\n );\n }\n\n return false;\n }\n\n static async create<T extends t.BaseGraphState>(\n config: t.RunConfig\n ): Promise<Run<T>> {\n /** Create tokenCounter if indexTokenCountMap is provided but tokenCounter is not */\n if (config.indexTokenCountMap && !config.tokenCounter) {\n const gc = config.graphConfig;\n const clientOpts =\n 'agents' in gc ? gc.agents[0]?.clientOptions : gc.clientOptions;\n const model = (clientOpts as { model?: string } | undefined)?.model ?? '';\n config.tokenCounter = await createTokenCounter(encodingForModel(model));\n }\n return new Run<T>(config);\n }\n\n getRunMessages(): BaseMessage[] | undefined {\n if (!this.Graph) {\n throw new Error(\n 'Graph not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n return this.Graph.getRunMessages();\n }\n\n /**\n * Returns the current calibration ratio (EMA of provider-vs-estimate token ratios).\n * Hosts should persist this value and pass it back as `RunConfig.calibrationRatio`\n * on the next run for the same conversation so the pruner starts with an accurate\n * scaling factor instead of the default (1).\n */\n getCalibrationRatio(): number {\n return this.calibrationRatio;\n }\n\n getResolvedInstructionOverhead(): number | undefined {\n return this.Graph?.getResolvedInstructionOverhead();\n }\n\n getToolCount(): number {\n return this.Graph?.getToolCount() ?? 0;\n }\n\n /**\n * Creates a custom event callback handler that intercepts custom events\n * and processes them through our handler registry instead of EventStreamCallbackHandler\n */\n private createCustomEventCallback() {\n return async (\n eventName: string,\n data: unknown,\n runId: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): Promise<void> => {\n // ON_RUN_STEP is dispatched directly via handler registry in\n // Graph.dispatchRunStep (primary, reliable path). Skip the\n // callback-based dispatch to prevent double handling.\n if (\n eventName === GraphEvents.ON_RUN_STEP &&\n this.Graph != null &&\n this.Graph.handlerDispatchedStepIds.has((data as t.RunStep).id)\n ) {\n return;\n }\n const handler = this.handlerRegistry?.getHandler(eventName);\n if (handler && this.Graph) {\n return await handler.handle(\n eventName,\n data as\n | t.StreamEventData\n | t.ModelEndData\n | t.RunStep\n | t.RunStepDeltaEvent\n | t.MessageDeltaEvent\n | t.ReasoningDeltaEvent\n | { result: t.ToolEndEvent },\n metadata,\n this.Graph\n );\n }\n };\n }\n\n async processStream(\n inputs: t.IState | Command,\n callerConfig: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n },\n streamOptions?: t.EventStreamOptions\n ): Promise<MessageContentComplex[] | undefined> {\n if (this.graphRunnable == null) {\n throw new Error(\n 'Run not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n if (!this.Graph) {\n throw new Error(\n 'Graph not initialized. Make sure to use Run.create() to instantiate the Run.'\n );\n }\n\n /**\n * `Command` inputs (currently only `Command({ resume })`) are\n * resume-mode invocations: LangGraph rebuilds graph state from the\n * checkpointer, so we skip RunStart / UserPromptSubmit hooks (no\n * new prompt to evaluate) and read run-state from the Graph wrapper\n * instead of `inputs.messages`.\n */\n const isResume = inputs instanceof Command;\n const stateInputs = isResume ? undefined : (inputs as t.IState);\n\n const config: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n } = {\n recursionLimit: 50,\n ...callerConfig,\n configurable: { ...callerConfig.configurable },\n };\n\n /**\n * Skip `resetValues` on resume — we're continuing an in-flight\n * run, not starting a fresh one. Resetting would wipe the\n * sidecars (`toolCallStepIds`, `stepKeyIds`, accumulated\n * `messages`, etc.) the resumed `ToolNode` needs to dispatch\n * tool completions with the correct step ids and re-resolve\n * `{{tool<i>turn<n>}}` references. Pairs with the\n * `awaitingResume` gate on `clearHeavyState` in the `finally`\n * block so the sidecars survive both ends of the interrupt\n * boundary.\n */\n if (!isResume) {\n this.Graph.resetValues(streamOptions?.keepContent);\n }\n this._interrupt = undefined;\n this._haltedReason = undefined;\n this.hookRegistry?.clearHaltSignal(this.id);\n\n /** Custom event callback to intercept and handle custom events */\n const customEventCallback = this.createCustomEventCallback();\n\n const baseCallbacks = (config.callbacks as t.ProvidedCallbacks) ?? [];\n const streamCallbacks = streamOptions?.callbacks\n ? this.getCallbacks(streamOptions.callbacks)\n : [];\n\n const customHandler = BaseCallbackHandler.fromMethods({\n [Callback.CUSTOM_EVENT]: customEventCallback,\n });\n customHandler.awaitHandlers = true;\n\n config.callbacks = baseCallbacks\n .concat(streamCallbacks)\n .concat(customHandler);\n\n if (\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&\n isPresent(process.env.LANGFUSE_BASE_URL)\n ) {\n const userId = config.configurable?.user_id;\n const sessionId = config.configurable?.thread_id;\n const primaryContext = this.Graph.agentContexts.get(\n this.Graph.defaultAgentId\n );\n const traceMetadata = {\n messageId: this.id,\n parentMessageId: config.configurable?.requestBody?.parentMessageId,\n agentName: primaryContext?.name,\n };\n const handler = new CallbackHandler({\n userId,\n sessionId,\n traceMetadata,\n });\n config.callbacks = (\n (config.callbacks as t.ProvidedCallbacks) ?? []\n ).concat([handler]);\n }\n\n if (!this.id) {\n throw new Error('Run ID not provided');\n }\n\n config.run_id = this.id;\n config.configurable = Object.assign(config.configurable ?? {}, {\n run_id: this.id,\n });\n\n const threadId = config.configurable.thread_id as string | undefined;\n\n if (this.hookRegistry != null && stateInputs != null) {\n const shouldHalt = await this.runPreStreamHooks(\n stateInputs,\n threadId,\n config\n );\n if (shouldHalt) {\n return undefined;\n }\n }\n\n /**\n * `streamEvents` accepts both state inputs and `Command` (resume) at\n * runtime, but our `CompiledStateWorkflow` type narrows the first\n * arg to `BaseGraphState`. Cast on the call so the resume path\n * type-checks without widening the wrapper for every caller.\n */\n const stream = this.graphRunnable.streamEvents(inputs as t.IState, config, {\n raiseError: true,\n /**\n * Prevent EventStreamCallbackHandler from processing custom events.\n * Custom events are already handled via our createCustomEventCallback()\n * which routes them through the handlerRegistry.\n * Without this flag, EventStreamCallbackHandler throws errors when\n * custom events are dispatched for run IDs not in its internal map\n * (due to timing issues in parallel execution or after run cleanup).\n */\n ignoreCustomEvent: true,\n });\n\n /**\n * Tracks whether the stream loop threw. Used by the `finally`\n * block to decide whether to honor the interrupt-preservation\n * guard for session hooks: a captured `_interrupt` is only\n * meaningful if the stream completed cleanly. If the loop errored\n * after stashing an interrupt (e.g. a downstream handler throws\n * after the interrupt event landed), the interrupt is stale —\n * preserving session hooks would leak them into the next run.\n */\n let streamThrew = false;\n\n try {\n for await (const event of stream) {\n const { data, metadata, ...info } = event;\n\n const eventName: t.EventName = info.event;\n\n /** Skip custom events as they're handled by our callback */\n if (eventName === GraphEvents.ON_CUSTOM_EVENT) {\n continue;\n }\n\n /**\n * Detect interrupts surfaced by LangGraph as a synthetic\n * `__interrupt__` field on the streamed chunk and stash the\n * first one for the host to read via `run.getInterrupt()`\n * once the stream drains. Captured as `unknown` because the\n * SDK does not validate the runtime payload shape — the\n * built-in ToolNode raises a `HumanInterruptPayload`\n * (`tool_approval` / `ask_user_question`), but custom nodes\n * can pass any payload to `interrupt()`. Callers narrow with\n * the `isToolApprovalInterrupt` / `isAskUserQuestionInterrupt`\n * guards or assert via `getInterrupt<T>()`.\n */\n if (\n this._interrupt == null &&\n data.chunk != null &&\n isInterrupted<unknown>(data.chunk)\n ) {\n const interrupts = data.chunk[INTERRUPT];\n if (interrupts.length > 0) {\n const first = interrupts[0];\n /**\n * Capture the interrupt unconditionally — `interrupt(null)`\n * and `interrupt(undefined)` are valid pauses (a custom\n * node may want to pause without metadata) and the host\n * still needs to know the run is awaiting resume. Gating\n * on `payload != null` would silently downgrade a paused\n * run to \"completed\" and let the `Stop` hook fire,\n * breaking host resume handling.\n */\n this._interrupt = {\n interruptId: first.id ?? '',\n threadId,\n payload: first.value,\n };\n }\n }\n\n const handler = this.handlerRegistry?.getHandler(eventName);\n if (handler) {\n await handler.handle(eventName, data, metadata, this.Graph);\n }\n\n /**\n * Mid-flight halt: any hook (PreToolUse, PostToolUse,\n * PostToolBatch, SubagentStart/Stop, PreCompact, PostCompact)\n * that returned `preventContinuation: true` raises a halt\n * signal on the registry via `executeHooks`. We poll between\n * stream events and break out as soon as one is set so the\n * graph doesn't take another model turn after the halting\n * operation completes.\n *\n * Limitation: the current step (in-flight model call, ongoing\n * tool batch) is not aborted — only the next step is skipped.\n * This matches Claude Code's `continue: false` semantic where\n * the active operation finishes before halting takes effect.\n */\n const haltSignal = this.hookRegistry?.getHaltSignal(this.id);\n if (haltSignal != null) {\n this._haltedReason = haltSignal.reason;\n break;\n }\n }\n\n /**\n * Skip the Stop hook when the run paused on a HITL interrupt\n * (still pending human input) or was halted by a hook (the host\n * already chose to stop, so a Stop hook firing now would be\n * misleading). The host fires Stop on the resumed-and-completed\n * run instead.\n */\n if (\n this._interrupt == null &&\n this._haltedReason == null &&\n this.hookRegistry?.hasHookFor('Stop', this.id) === true\n ) {\n await executeHooks({\n registry: this.hookRegistry,\n input: {\n hook_event_name: 'Stop',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n messages:\n this.Graph.getRunMessages() ?? stateInputs?.messages ?? [],\n stopHookActive: false, // will be true when stop is triggered by a hook (Phase 2)\n },\n sessionId: this.id,\n }).catch(() => {\n /* Stop hook errors must not masquerade as stream failures */\n });\n }\n } catch (err) {\n streamThrew = true;\n if (this.hookRegistry?.hasHookFor('StopFailure', this.id) === true) {\n const runMessages = this.Graph.getRunMessages() ?? [];\n await executeHooks({\n registry: this.hookRegistry,\n input: {\n hook_event_name: 'StopFailure',\n runId: this.id,\n threadId,\n agentId: this.Graph.defaultAgentId,\n error: err instanceof Error ? err.message : String(err),\n lastAssistantMessage: findLastMessageOfType(runMessages, 'ai'),\n },\n sessionId: this.id,\n }).catch(() => {\n /* swallow hook errors — the original error must propagate */\n });\n }\n throw err;\n } finally {\n /**\n * Preserve session-scoped hooks when the run paused on a HITL\n * interrupt — the very next call will be `Run.resume()`, which\n * needs the same policy hooks (e.g., the `PreToolUse` matcher\n * that triggered the interrupt) to fire on the re-executed node\n * and uphold the approval flow. Clearing here would leak the\n * approval gate on resume. The session is cleared instead at\n * natural completion, error (including errors that happen AFTER\n * an interrupt was captured — those interrupts are stale), or\n * hook-driven halt (including hooks that returned BOTH `ask`\n * and `preventContinuation` — the halt wins, no resume is\n * expected, sessions must drop). Every state where no resume\n * is expected clears.\n */\n if (\n this._interrupt == null ||\n this._haltedReason != null ||\n streamThrew\n ) {\n this.hookRegistry?.clearSession(this.id);\n }\n /**\n * Drop any halt signal raised mid-stream for this run so a\n * subsequent `processStream` / `resume` starts with clean state.\n * The Run captured `_haltedReason` already; the registry entry\n * for this `sessionId` would otherwise spuriously trip the next\n * loop. Other concurrent runs sharing this registry are\n * unaffected — their entries live under their own session ids.\n */\n this.hookRegistry?.clearHaltSignal(this.id);\n\n /**\n * Break the reference chain that keeps heavy data alive via\n * LangGraph's internal `__pregel_scratchpad.currentTaskInput` →\n * `@langchain/core` `RunTree.extra[lc:child_config]` →\n * Node.js `AsyncLocalStorage` context captured by timers/promises.\n *\n * Without this, base64-encoded images/PDFs in message content remain\n * reachable from lingering `Timeout` handles until GC runs.\n */\n if (!this.skipCleanup) {\n if (\n (config.configurable as Record<string, unknown> | undefined) != null\n ) {\n for (const key of Object.getOwnPropertySymbols(config.configurable)) {\n const val = config.configurable[key as unknown as string] as\n | Record<string, unknown>\n | undefined;\n if (\n val != null &&\n typeof val === 'object' &&\n 'currentTaskInput' in val\n ) {\n (val as Record<string, unknown>).currentTaskInput = undefined;\n }\n delete config.configurable[key as unknown as string];\n }\n config.configurable = undefined;\n }\n config.callbacks = undefined;\n }\n\n const result = this.returnContent\n ? this.Graph.getContentParts()\n : undefined;\n\n this.calibrationRatio = this.Graph.getCalibrationRatio();\n\n /**\n * Skip `clearHeavyState()` when the run paused on a clean HITL\n * interrupt awaiting resume — `Run.resume()` re-enters the same\n * `ToolNode` instance and needs the sidecars `clearHeavyState`\n * would wipe (`toolCallStepIds` for completion-event step ids,\n * the `_toolOutputRegistry` for `{{tool<i>turn<n>}}`\n * substitutions, `sessions` for code-env continuity, plus the\n * `hookRegistry` and `humanInTheLoop` config the interrupt\n * branch itself relies on). Without preservation, the resumed\n * tool completion would dispatch `ON_RUN_STEP_COMPLETED` with\n * an empty step id and downstream stream consumers would drop\n * the result.\n *\n * The natural-completion / error / hook-driven-halt paths still\n * clean up — `_haltedReason != null` or `streamThrew` mean no\n * resume is expected. Cross-process resume (host rebuilds the\n * Run from scratch) is a separate concern; see\n * `HumanInTheLoopConfig` JSDoc.\n */\n const awaitingResume =\n this._interrupt != null && this._haltedReason == null && !streamThrew;\n if (!this.skipCleanup && !awaitingResume) {\n this.Graph.clearHeavyState();\n }\n\n this._streamResult = result;\n }\n\n return this._streamResult;\n }\n\n /**\n * Returns the pending interrupt captured during the most recent\n * `processStream` (or `resume`) invocation. `undefined` when the run\n * either has not been streamed yet or completed without pausing.\n *\n * Hosts call this immediately after `processStream` returns to decide\n * whether the run is awaiting human input. Persist the returned\n * descriptor (alongside `thread_id` and the agent run config) so a\n * later `resume(decisions)` can rebuild the run.\n *\n * The default `TPayload` is the SDK's `HumanInterruptPayload` union\n * (`tool_approval` / `ask_user_question`), suitable for the common\n * case where interrupts come from the built-in ToolNode or\n * `askUserQuestion()` helper. Hosts that raise custom interrupts\n * from custom graph nodes pass their own type — the SDK does not\n * validate the runtime shape, it just transports whatever the\n * `interrupt()` call carried. When in doubt, narrow with the\n * `isToolApprovalInterrupt` / `isAskUserQuestionInterrupt` type\n * guards (which accept `unknown`) before reading variant-specific\n * fields.\n */\n getInterrupt<TPayload = t.HumanInterruptPayload>():\n | t.RunInterruptResult<TPayload>\n | undefined {\n return this._interrupt as t.RunInterruptResult<TPayload> | undefined;\n }\n\n /**\n * Returns the reason a hook halted the run via\n * `preventContinuation: true`, or `undefined` if no hook halted.\n *\n * Hosts inspect this after `processStream` returns to distinguish a\n * natural completion (`undefined`) from a hook-driven halt (a\n * truthy string). Independent from `getInterrupt()` — a halted run\n * has no interrupt; an interrupted run has no halt reason.\n */\n getHaltReason(): string | undefined {\n return this._haltedReason;\n }\n\n /**\n * Resume a paused HITL run with the value the user (or whatever\n * decided the interrupt) supplied. The default `TResume` covers the\n * `tool_approval` interrupt (the common case): an array of decisions\n * in `action_requests` order, or a record keyed by `tool_call_id`.\n *\n * For other interrupt types (e.g., `ask_user_question` →\n * `AskUserQuestionResolution`, or any custom interrupt a host raises\n * from a custom node), pass the type parameter and the SDK forwards\n * the value through unchanged. LangGraph delivers it as the return\n * value of the original `interrupt()` call inside the paused node.\n *\n * The host MUST construct this Run with the same `thread_id` and the\n * same checkpointer as the original paused run; LangGraph rebuilds\n * graph state from the checkpoint and re-enters the interrupted node\n * from the start.\n */\n /**\n * Returns the per-Run file checkpointer when\n * `toolExecution.local.fileCheckpointing === true` was set on the\n * RunConfig. Hosts can capture extra paths or call `rewind()`\n * directly. Returns undefined when checkpointing is disabled.\n *\n * Construction-time invariant: the checkpointer is shared across\n * every ToolNode the graph compiles (single-agent and multi-agent),\n * so a `rewind()` call here unwinds writes made by ANY agent in the\n * run.\n */\n getFileCheckpointer(): t.LocalFileCheckpointer | undefined {\n return this.Graph?.getOrCreateFileCheckpointer();\n }\n\n /**\n * Convenience wrapper that calls `rewind()` on the per-Run file\n * checkpointer. Restores every file the local engine snapshotted\n * during this Run to its pre-write content (and deletes any path\n * that didn't exist before being created). Returns the count of\n * paths processed; returns 0 when checkpointing is disabled.\n */\n async rewindFiles(): Promise<number> {\n const cp = this.getFileCheckpointer();\n return cp == null ? 0 : cp.rewind();\n }\n\n async resume<TResume = t.ToolApprovalDecision[] | t.ToolApprovalDecisionMap>(\n resumeValue: TResume,\n callerConfig: Partial<RunnableConfig> & {\n version: 'v1' | 'v2';\n run_id?: string;\n },\n streamOptions?: t.EventStreamOptions\n ): Promise<MessageContentComplex[] | undefined> {\n return this.processStream(\n new Command({ resume: resumeValue }),\n callerConfig,\n streamOptions\n );\n }\n\n private createSystemCallback<K extends keyof t.ClientCallbacks>(\n clientCallbacks: t.ClientCallbacks,\n key: K\n ): t.SystemCallbacks[K] {\n return ((...args: unknown[]) => {\n const clientCallback = clientCallbacks[key];\n if (clientCallback && this.Graph) {\n (clientCallback as (...args: unknown[]) => void)(this.Graph, ...args);\n }\n }) as t.SystemCallbacks[K];\n }\n\n getCallbacks(clientCallbacks: t.ClientCallbacks): t.SystemCallbacks {\n return {\n [Callback.TOOL_ERROR]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_ERROR\n ),\n [Callback.TOOL_START]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_START\n ),\n [Callback.TOOL_END]: this.createSystemCallback(\n clientCallbacks,\n Callback.TOOL_END\n ),\n };\n }\n\n async generateTitle({\n provider,\n inputText,\n contentParts,\n titlePrompt,\n clientOptions,\n chainOptions,\n skipLanguage,\n titleMethod = TitleMethod.COMPLETION,\n titlePromptTemplate,\n }: t.RunTitleOptions): Promise<{ language?: string; title?: string }> {\n if (\n chainOptions != null &&\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&\n isPresent(process.env.LANGFUSE_BASE_URL)\n ) {\n const userId = chainOptions.configurable?.user_id;\n const sessionId = chainOptions.configurable?.thread_id;\n const titleContext = this.Graph?.agentContexts.get(\n this.Graph.defaultAgentId\n );\n const traceMetadata = {\n messageId: 'title-' + this.id,\n agentName: titleContext?.name,\n };\n const handler = new CallbackHandler({\n userId,\n sessionId,\n traceMetadata,\n });\n chainOptions.callbacks = (\n (chainOptions.callbacks as t.ProvidedCallbacks) ?? []\n ).concat([handler]);\n }\n\n const convoTemplate = PromptTemplate.fromTemplate(\n titlePromptTemplate ?? 'User: {input}\\nAI: {output}'\n );\n\n const response = contentParts\n .map((part) => {\n if (part?.type === 'text') return part.text;\n return '';\n })\n .join('\\n');\n\n const model = initializeModel({\n provider,\n clientOptions,\n }) as t.ChatModelInstance;\n\n if (\n isOpenAILike(provider) &&\n (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)\n ) {\n model.temperature = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.temperature as number;\n model.topP = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.topP as number;\n model.frequencyPenalty = (\n clientOptions as t.OpenAIClientOptions | undefined\n )?.frequencyPenalty as number;\n model.presencePenalty = (\n clientOptions as t.OpenAIClientOptions | undefined\n )?.presencePenalty as number;\n model.n = (clientOptions as t.OpenAIClientOptions | undefined)\n ?.n as number;\n }\n\n const convoToTitleInput = new RunnableLambda({\n func: (\n promptValue: StringPromptValue\n ): { convo: string; inputText: string; skipLanguage?: boolean } => ({\n convo: promptValue.value,\n inputText,\n skipLanguage,\n }),\n }).withConfig({ runName: 'ConvoTransform' });\n\n const titleChain =\n titleMethod === TitleMethod.COMPLETION\n ? await createCompletionTitleRunnable(model, titlePrompt)\n : await createTitleRunnable(model, titlePrompt);\n\n /** Pipes `convoTemplate` -> `transformer` -> `titleChain` */\n const fullChain = convoTemplate\n .withConfig({ runName: 'ConvoTemplate' })\n .pipe(convoToTitleInput)\n .pipe(titleChain)\n .withConfig({ runName: 'TitleChain' });\n\n const invokeConfig = Object.assign({}, chainOptions, {\n run_id: this.id,\n runId: this.id,\n });\n\n try {\n return await fullChain.invoke(\n { input: inputText, output: response },\n invokeConfig\n );\n } catch (_e) {\n // Fallback: strip callbacks to avoid EventStream tracer errors in certain environments\n // But preserve langfuse handler if it exists\n const langfuseHandler = (\n invokeConfig.callbacks as t.ProvidedCallbacks\n )?.find((cb) => cb instanceof CallbackHandler);\n const { callbacks: _cb, ...rest } = invokeConfig;\n const safeConfig = Object.assign({}, rest, {\n callbacks: langfuseHandler ? [langfuseHandler] : [],\n });\n return await fullChain.invoke(\n { input: inputText, output: response },\n safeConfig as Partial<RunnableConfig>\n );\n }\n }\n}\n\nfunction findLastMessageOfType(\n messages: BaseMessage[],\n type: string\n): BaseMessage | undefined {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].getType() === type) {\n return messages[i];\n }\n }\n return undefined;\n}\n\nfunction extractPromptText(message: BaseMessage): string {\n const content = message.content;\n if (typeof content === 'string') {\n return content;\n }\n if (!Array.isArray(content)) {\n return String(content);\n }\n const parts: string[] = [];\n for (const block of content) {\n if (\n typeof block === 'object' &&\n 'type' in block &&\n block.type === 'text' &&\n 'text' in block &&\n typeof block.text === 'string'\n ) {\n parts.push(block.text);\n }\n }\n return parts.join('\\n');\n}\n"],"names":["ChatOpenAI","AzureChatOpenAI"],"mappings":"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"}
|
|
@@ -3,13 +3,26 @@ import { ContentTypes, StepTypes, GraphEvents } from '../common/enum.mjs';
|
|
|
3
3
|
import { emitAgentLog, safeDispatchCustomEvent } from '../utils/events.mjs';
|
|
4
4
|
import { tryFallbackProviders, attemptInvoke } from '../llm/invoke.mjs';
|
|
5
5
|
import { createRemoveAllMessage } from '../messages/reducer.mjs';
|
|
6
|
+
import { splitAtRecencyBoundary } from '../messages/recency.mjs';
|
|
6
7
|
import { getMaxOutputTokensKey } from '../llm/request.mjs';
|
|
7
8
|
import { addCacheControl } from '../messages/cache.mjs';
|
|
8
9
|
import { initializeModel } from '../llm/init.mjs';
|
|
9
10
|
import { getChunkContent } from '../stream.mjs';
|
|
10
11
|
import { executeHooks } from '../hooks/executeHooks.mjs';
|
|
12
|
+
import '../hooks/createWorkspacePolicyHook.mjs';
|
|
11
13
|
|
|
12
14
|
const SUMMARIZATION_PARAM_KEYS = new Set(['maxSummaryTokens']);
|
|
15
|
+
/**
|
|
16
|
+
* Default number of recent user-led turns preserved verbatim during
|
|
17
|
+
* compaction. A turn begins at a HumanMessage and includes every
|
|
18
|
+
* following AIMessage and ToolMessage up to the next HumanMessage.
|
|
19
|
+
* The most recent turn is always retained regardless of this value;
|
|
20
|
+
* the default of `2` additionally keeps the prior exchange so the
|
|
21
|
+
* model has fresh context on what just happened. Setting
|
|
22
|
+
* `retainRecent.turns` to `0` reverts to the legacy "summarize every
|
|
23
|
+
* message" behavior.
|
|
24
|
+
*/
|
|
25
|
+
const DEFAULT_RETAIN_RECENT_TURNS = 2;
|
|
13
26
|
/**
|
|
14
27
|
* Token overhead of the XML wrapper + instruction text added around the
|
|
15
28
|
* summary at injection time in AgentContext.buildSystemRunnable:
|
|
@@ -455,7 +468,7 @@ async function executeSummarizationWithFallback(params) {
|
|
|
455
468
|
}
|
|
456
469
|
/** Dispatches run step completion, ON_SUMMARIZE_COMPLETE, and rebuilds token map. */
|
|
457
470
|
async function dispatchCompletionEvents(params) {
|
|
458
|
-
const { graph, runnableConfig, stepId, summaryBlock, agentContext, runStep, summaryUsage, agentId, } = params;
|
|
471
|
+
const { graph, runnableConfig, stepId, summaryBlock, agentContext, runStep, summaryUsage, agentId, messagesAfterCount, } = params;
|
|
459
472
|
runStep.summary = summaryBlock;
|
|
460
473
|
if (summaryUsage) {
|
|
461
474
|
runStep.usage = {
|
|
@@ -491,7 +504,7 @@ async function dispatchCompletionEvents(params) {
|
|
|
491
504
|
threadId,
|
|
492
505
|
agentId,
|
|
493
506
|
summary: summaryText,
|
|
494
|
-
messagesAfterCount
|
|
507
|
+
messagesAfterCount,
|
|
495
508
|
},
|
|
496
509
|
sessionId,
|
|
497
510
|
}).catch(() => {
|
|
@@ -515,10 +528,55 @@ function createSummarizeNode({ agentContext, graph, generateStepId, }) {
|
|
|
515
528
|
}, { runId: graph.runId, agentId: request.agentId });
|
|
516
529
|
return { summarizationRequest: undefined };
|
|
517
530
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
531
|
+
/**
|
|
532
|
+
* Capture the original-tool-content map locally before doing the
|
|
533
|
+
* split. We need it in three places: to restore the head for
|
|
534
|
+
* summarizer quality, to leave intact on the skip path (state is
|
|
535
|
+
* unchanged), and — critically — to carry forward the tail-relevant
|
|
536
|
+
* entries on the summarize-fired path. Clearing it eagerly here
|
|
537
|
+
* would lose the originals for masked tool messages that the
|
|
538
|
+
* recency window keeps in the tail; a future summarization could
|
|
539
|
+
* then only summarize the masked stub instead of the full payload.
|
|
540
|
+
*/
|
|
541
|
+
const originalPending = agentContext.pendingOriginalToolContent;
|
|
542
|
+
const restoredMessages = restoreOriginalToolContent(state.messages, originalPending);
|
|
521
543
|
const runnableConfig = config ?? graph.config;
|
|
544
|
+
const retainRecent = agentContext.summarizationConfig?.retainRecent;
|
|
545
|
+
const { head: messagesToRefine, tailStartIndex } = splitAtRecencyBoundary(restoredMessages, {
|
|
546
|
+
turns: retainRecent?.turns ?? DEFAULT_RETAIN_RECENT_TURNS,
|
|
547
|
+
tokens: retainRecent?.tokens,
|
|
548
|
+
tokenCounter: agentContext.tokenCounter,
|
|
549
|
+
});
|
|
550
|
+
/**
|
|
551
|
+
* Use the *masked* messages for the retained tail so that any
|
|
552
|
+
* truncation prune applied to oversized ToolMessage content stays
|
|
553
|
+
* truncated in live state. The summarizer above reads the restored
|
|
554
|
+
* (full-content) head for summary quality, but reinjecting restored
|
|
555
|
+
* tool payloads into state would defeat masking and bloat the
|
|
556
|
+
* checkpoint, forcing more expensive re-pruning on later turns.
|
|
557
|
+
* `restoreOriginalToolContent` returns an array with identical
|
|
558
|
+
* length and structure to `state.messages` (replacements only at
|
|
559
|
+
* specific indices), so the same tailStartIndex slices both arrays
|
|
560
|
+
* at the same turn boundary.
|
|
561
|
+
*/
|
|
562
|
+
const messagesToRetain = state.messages.slice(tailStartIndex);
|
|
563
|
+
if (messagesToRefine.length === 0) {
|
|
564
|
+
/**
|
|
565
|
+
* Recency window covers the entire conversation — there is no
|
|
566
|
+
* older content to summarize. Skipping prevents the model from
|
|
567
|
+
* destroying the user's most recent message (e.g. a large pasted
|
|
568
|
+
* payload on the first turn) by replacing it with a generic
|
|
569
|
+
* checkpoint summary. Mark the trigger so the same unchanged
|
|
570
|
+
* state is not re-evaluated on the next prune cycle.
|
|
571
|
+
*/
|
|
572
|
+
emitAgentLog(config, 'debug', 'summarize', 'Summarization skipped — recency window retains all messages', {
|
|
573
|
+
messagesRetained: messagesToRetain.length,
|
|
574
|
+
retainTurns: retainRecent?.turns ?? DEFAULT_RETAIN_RECENT_TURNS,
|
|
575
|
+
}, { runId: graph.runId, agentId: request.agentId });
|
|
576
|
+
agentContext.markSummarizationTriggered(state.messages.length);
|
|
577
|
+
return { summarizationRequest: undefined };
|
|
578
|
+
}
|
|
579
|
+
const clientConfig = buildSummarizationClientConfig(agentContext, agentContext.summarizationConfig);
|
|
522
580
|
const stepKey = `summarize-${request.agentId}`;
|
|
523
581
|
const [stepId, stepIndex] = generateStepId(stepKey);
|
|
524
582
|
const placeholderSummary = {
|
|
@@ -657,10 +715,46 @@ function createSummarizeNode({ agentContext, graph, generateStepId, }) {
|
|
|
657
715
|
runStep,
|
|
658
716
|
summaryUsage,
|
|
659
717
|
agentId: request.agentId,
|
|
718
|
+
messagesAfterCount: messagesToRetain.length,
|
|
660
719
|
});
|
|
720
|
+
/**
|
|
721
|
+
* `dispatchCompletionEvents` calls `rebuildTokenMapAfterSummarization({})`
|
|
722
|
+
* which resets the dedupe baseline to 0 — correct under the legacy
|
|
723
|
+
* "remove-all only" shape where no messages survived, but stale once
|
|
724
|
+
* the recency window keeps a tail. Realign the baseline to the
|
|
725
|
+
* surviving tail length so a subsequent prune cycle on the unchanged
|
|
726
|
+
* tail short-circuits via `shouldSkipSummarization` instead of
|
|
727
|
+
* looping back into another summarize call.
|
|
728
|
+
*/
|
|
729
|
+
agentContext.markSummarizationTriggered(messagesToRetain.length);
|
|
730
|
+
/**
|
|
731
|
+
* Carry forward the original-content entries that correspond to the
|
|
732
|
+
* retained tail, reindexed for the post-removeAll state where tail
|
|
733
|
+
* messages start at index 0. Without this, a future summarization
|
|
734
|
+
* that pulls these tail messages into its head would only see the
|
|
735
|
+
* masked stubs (since `setSummary` clears `pruneMessages`, and the
|
|
736
|
+
* fresh pruner at the next turn has no record of prior masks).
|
|
737
|
+
* Entries for indices < `tailStartIndex` belong to messages we just
|
|
738
|
+
* summarized — they are no longer reachable so they are dropped.
|
|
739
|
+
*/
|
|
740
|
+
if (originalPending != null && originalPending.size > 0) {
|
|
741
|
+
const tailPending = new Map();
|
|
742
|
+
for (const [idx, content] of originalPending) {
|
|
743
|
+
if (idx >= tailStartIndex) {
|
|
744
|
+
tailPending.set(idx - tailStartIndex, content);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
agentContext.pendingOriginalToolContent =
|
|
748
|
+
tailPending.size > 0 ? tailPending : undefined;
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
agentContext.pendingOriginalToolContent = undefined;
|
|
752
|
+
}
|
|
661
753
|
return {
|
|
662
754
|
summarizationRequest: undefined,
|
|
663
|
-
messages:
|
|
755
|
+
messages: messagesToRetain.length > 0
|
|
756
|
+
? [createRemoveAllMessage(), ...messagesToRetain]
|
|
757
|
+
: [createRemoveAllMessage()],
|
|
664
758
|
};
|
|
665
759
|
};
|
|
666
760
|
}
|