@librechat/agents 3.3.4 → 3.3.6

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.
Files changed (263) hide show
  1. package/dist/cjs/common/constants.cjs +21 -0
  2. package/dist/cjs/common/constants.cjs.map +1 -1
  3. package/dist/cjs/events.cjs +10 -1
  4. package/dist/cjs/events.cjs.map +1 -1
  5. package/dist/cjs/graphs/Graph.cjs +456 -7
  6. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  7. package/dist/cjs/hooks/HookRegistry.cjs +25 -0
  8. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  9. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +1 -1
  10. package/dist/cjs/hooks/index.cjs +12 -0
  11. package/dist/cjs/hooks/index.cjs.map +1 -1
  12. package/dist/cjs/hooks/types.cjs +1 -0
  13. package/dist/cjs/hooks/types.cjs.map +1 -1
  14. package/dist/cjs/langfuse.cjs +8 -0
  15. package/dist/cjs/langfuse.cjs.map +1 -1
  16. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +1 -3
  17. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  18. package/dist/cjs/llm/invoke.cjs +268 -3
  19. package/dist/cjs/llm/invoke.cjs.map +1 -1
  20. package/dist/cjs/llm/openai/index.cjs +51 -6
  21. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  22. package/dist/cjs/llm/preempt.cjs +132 -0
  23. package/dist/cjs/llm/preempt.cjs.map +1 -0
  24. package/dist/cjs/main.cjs +31 -3
  25. package/dist/cjs/messages/alternation.cjs +92 -0
  26. package/dist/cjs/messages/alternation.cjs.map +1 -0
  27. package/dist/cjs/messages/format.cjs +72 -0
  28. package/dist/cjs/messages/format.cjs.map +1 -1
  29. package/dist/cjs/messages/handoffCue.cjs +63 -0
  30. package/dist/cjs/messages/handoffCue.cjs.map +1 -0
  31. package/dist/cjs/messages/index.cjs +3 -0
  32. package/dist/cjs/messages/injected.cjs +60 -0
  33. package/dist/cjs/messages/injected.cjs.map +1 -0
  34. package/dist/cjs/run.cjs +80 -7
  35. package/dist/cjs/run.cjs.map +1 -1
  36. package/dist/cjs/session/JsonlSessionStore.cjs +1 -1
  37. package/dist/cjs/session/handlers.cjs +18 -9
  38. package/dist/cjs/session/handlers.cjs.map +1 -1
  39. package/dist/cjs/stream.cjs +34 -8
  40. package/dist/cjs/stream.cjs.map +1 -1
  41. package/dist/cjs/tools/BashExecutor.cjs +3 -1
  42. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  43. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +2 -0
  44. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  45. package/dist/cjs/tools/CodeExecutor.cjs +19 -16
  46. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  47. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +2 -0
  48. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  49. package/dist/cjs/tools/ReadFile.cjs +8 -4
  50. package/dist/cjs/tools/ReadFile.cjs.map +1 -1
  51. package/dist/cjs/tools/SkillTool.cjs +2 -0
  52. package/dist/cjs/tools/SkillTool.cjs.map +1 -1
  53. package/dist/cjs/tools/SubagentTool.cjs +3 -0
  54. package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
  55. package/dist/cjs/tools/ToolNode.cjs +91 -50
  56. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  57. package/dist/cjs/tools/ToolSearch.cjs +5 -1
  58. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  59. package/dist/cjs/tools/intentArg.cjs +230 -0
  60. package/dist/cjs/tools/intentArg.cjs.map +1 -0
  61. package/dist/cjs/tools/local/CompileCheckTool.cjs +3 -2
  62. package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
  63. package/dist/cjs/tools/local/LocalCodingTools.cjs +13 -12
  64. package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
  65. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +2 -2
  66. package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
  67. package/dist/cjs/tools/search/keenable-scraper.cjs +90 -0
  68. package/dist/cjs/tools/search/keenable-scraper.cjs.map +1 -0
  69. package/dist/cjs/tools/search/schema.cjs +2 -0
  70. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  71. package/dist/cjs/tools/search/tool.cjs +40 -2
  72. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  73. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -0
  74. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  75. package/dist/cjs/tools/toolOutputReferences.cjs +41 -7
  76. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  77. package/dist/esm/common/constants.mjs +19 -1
  78. package/dist/esm/common/constants.mjs.map +1 -1
  79. package/dist/esm/events.mjs +10 -1
  80. package/dist/esm/events.mjs.map +1 -1
  81. package/dist/esm/graphs/Graph.mjs +455 -6
  82. package/dist/esm/graphs/Graph.mjs.map +1 -1
  83. package/dist/esm/hooks/HookRegistry.mjs +25 -0
  84. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  85. package/dist/esm/hooks/createWorkspacePolicyHook.mjs +1 -1
  86. package/dist/esm/hooks/index.mjs +12 -1
  87. package/dist/esm/hooks/index.mjs.map +1 -1
  88. package/dist/esm/hooks/types.mjs +1 -0
  89. package/dist/esm/hooks/types.mjs.map +1 -1
  90. package/dist/esm/langfuse.mjs +9 -1
  91. package/dist/esm/langfuse.mjs.map +1 -1
  92. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +1 -3
  93. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  94. package/dist/esm/llm/invoke.mjs +270 -6
  95. package/dist/esm/llm/invoke.mjs.map +1 -1
  96. package/dist/esm/llm/openai/index.mjs +51 -6
  97. package/dist/esm/llm/openai/index.mjs.map +1 -1
  98. package/dist/esm/llm/preempt.mjs +131 -0
  99. package/dist/esm/llm/preempt.mjs.map +1 -0
  100. package/dist/esm/main.mjs +11 -7
  101. package/dist/esm/messages/alternation.mjs +91 -0
  102. package/dist/esm/messages/alternation.mjs.map +1 -0
  103. package/dist/esm/messages/format.mjs +72 -0
  104. package/dist/esm/messages/format.mjs.map +1 -1
  105. package/dist/esm/messages/handoffCue.mjs +61 -0
  106. package/dist/esm/messages/handoffCue.mjs.map +1 -0
  107. package/dist/esm/messages/index.mjs +3 -0
  108. package/dist/esm/messages/injected.mjs +60 -0
  109. package/dist/esm/messages/injected.mjs.map +1 -0
  110. package/dist/esm/run.mjs +80 -7
  111. package/dist/esm/run.mjs.map +1 -1
  112. package/dist/esm/session/JsonlSessionStore.mjs +1 -1
  113. package/dist/esm/session/handlers.mjs +19 -10
  114. package/dist/esm/session/handlers.mjs.map +1 -1
  115. package/dist/esm/stream.mjs +33 -9
  116. package/dist/esm/stream.mjs.map +1 -1
  117. package/dist/esm/tools/BashExecutor.mjs +3 -1
  118. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  119. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +2 -0
  120. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  121. package/dist/esm/tools/CodeExecutor.mjs +19 -16
  122. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  123. package/dist/esm/tools/ProgrammaticToolCalling.mjs +2 -0
  124. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  125. package/dist/esm/tools/ReadFile.mjs +8 -4
  126. package/dist/esm/tools/ReadFile.mjs.map +1 -1
  127. package/dist/esm/tools/SkillTool.mjs +2 -0
  128. package/dist/esm/tools/SkillTool.mjs.map +1 -1
  129. package/dist/esm/tools/SubagentTool.mjs +3 -0
  130. package/dist/esm/tools/SubagentTool.mjs.map +1 -1
  131. package/dist/esm/tools/ToolNode.mjs +91 -51
  132. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  133. package/dist/esm/tools/ToolSearch.mjs +5 -1
  134. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  135. package/dist/esm/tools/intentArg.mjs +220 -0
  136. package/dist/esm/tools/intentArg.mjs.map +1 -0
  137. package/dist/esm/tools/local/CompileCheckTool.mjs +3 -2
  138. package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
  139. package/dist/esm/tools/local/LocalCodingTools.mjs +13 -12
  140. package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
  141. package/dist/esm/tools/local/LocalExecutionEngine.mjs +2 -2
  142. package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
  143. package/dist/esm/tools/search/keenable-scraper.mjs +88 -0
  144. package/dist/esm/tools/search/keenable-scraper.mjs.map +1 -0
  145. package/dist/esm/tools/search/schema.mjs +2 -0
  146. package/dist/esm/tools/search/schema.mjs.map +1 -1
  147. package/dist/esm/tools/search/tool.mjs +40 -3
  148. package/dist/esm/tools/search/tool.mjs.map +1 -1
  149. package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -0
  150. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  151. package/dist/esm/tools/toolOutputReferences.mjs +41 -7
  152. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  153. package/dist/types/common/constants.d.ts +18 -0
  154. package/dist/types/graphs/Graph.d.ts +138 -1
  155. package/dist/types/hooks/HookRegistry.d.ts +15 -0
  156. package/dist/types/hooks/index.d.ts +12 -1
  157. package/dist/types/hooks/types.d.ts +45 -6
  158. package/dist/types/index.d.ts +2 -1
  159. package/dist/types/llm/invoke.d.ts +7 -0
  160. package/dist/types/llm/openai/index.d.ts +0 -11
  161. package/dist/types/llm/preempt.d.ts +40 -0
  162. package/dist/types/messages/alternation.d.ts +23 -0
  163. package/dist/types/messages/handoffCue.d.ts +40 -0
  164. package/dist/types/messages/index.d.ts +3 -0
  165. package/dist/types/messages/injected.d.ts +3 -0
  166. package/dist/types/run.d.ts +7 -0
  167. package/dist/types/stream.d.ts +14 -0
  168. package/dist/types/tools/BashExecutor.d.ts +18 -0
  169. package/dist/types/tools/CodeExecutor.d.ts +18 -0
  170. package/dist/types/tools/ReadFile.d.ts +18 -0
  171. package/dist/types/tools/SkillTool.d.ts +18 -0
  172. package/dist/types/tools/SubagentTool.d.ts +9 -0
  173. package/dist/types/tools/ToolNode.d.ts +37 -12
  174. package/dist/types/tools/ToolSearch.d.ts +18 -0
  175. package/dist/types/tools/intentArg.d.ts +119 -0
  176. package/dist/types/tools/ptcTimeout.d.ts +2 -0
  177. package/dist/types/tools/search/keenable-scraper.d.ts +15 -0
  178. package/dist/types/tools/search/schema.d.ts +18 -0
  179. package/dist/types/tools/search/tool.d.ts +18 -0
  180. package/dist/types/tools/search/types.d.ts +31 -2
  181. package/dist/types/tools/toolOutputReferences.d.ts +12 -2
  182. package/dist/types/types/graph.d.ts +8 -1
  183. package/dist/types/types/run.d.ts +65 -0
  184. package/dist/types/types/stream.d.ts +12 -25
  185. package/dist/types/types/tools.d.ts +27 -2
  186. package/package.json +1 -1
  187. package/src/{splitStream.test.ts → aggregator.test.ts} +59 -666
  188. package/src/common/constants.ts +21 -0
  189. package/src/events.ts +15 -1
  190. package/src/graphs/Graph.ts +568 -3
  191. package/src/graphs/__tests__/Graph.contextOverflow.test.ts +18 -7
  192. package/src/graphs/__tests__/Graph.preemptSignal.test.ts +126 -0
  193. package/src/hooks/HookRegistry.ts +40 -0
  194. package/src/hooks/__tests__/preemptBoundary.test.ts +152 -0
  195. package/src/hooks/index.ts +16 -2
  196. package/src/hooks/types.ts +47 -3
  197. package/src/index.ts +2 -1
  198. package/src/langfuse.ts +26 -1
  199. package/src/llm/bedrock/utils/message_inputs.test.ts +82 -0
  200. package/src/llm/bedrock/utils/message_inputs.ts +14 -11
  201. package/src/llm/bedrock/utils/toolResultCachePoint.test.ts +15 -0
  202. package/src/llm/invoke.alternation.test.ts +87 -0
  203. package/src/llm/invoke.handoffCue.test.ts +112 -0
  204. package/src/llm/invoke.ts +417 -8
  205. package/src/llm/openai/index.ts +74 -10
  206. package/src/llm/openai/llm.spec.ts +105 -0
  207. package/src/llm/preempt.test.ts +323 -0
  208. package/src/llm/preempt.ts +178 -0
  209. package/src/messages/alternation.test.ts +212 -0
  210. package/src/messages/alternation.ts +112 -0
  211. package/src/messages/format.ts +91 -0
  212. package/src/messages/formatAgentMessages.steer.test.ts +267 -0
  213. package/src/messages/handoffCue.test.ts +96 -0
  214. package/src/messages/handoffCue.ts +78 -0
  215. package/src/messages/index.ts +3 -0
  216. package/src/messages/injected.test.ts +90 -0
  217. package/src/messages/injected.ts +74 -0
  218. package/src/run.ts +91 -6
  219. package/src/scripts/preempt-probe.ts +330 -0
  220. package/src/scripts/preempt-scenarios.ts +388 -0
  221. package/src/session/handlers.ts +32 -12
  222. package/src/specs/handoffCue.test.ts +165 -0
  223. package/src/specs/langfuse-callbacks.test.ts +352 -2
  224. package/src/specs/preemptSeal.test.ts +309 -0
  225. package/src/stream.dispatch.test.ts +63 -0
  226. package/src/stream.ts +48 -9
  227. package/src/tools/BashExecutor.ts +6 -0
  228. package/src/tools/BashProgrammaticToolCalling.ts +2 -0
  229. package/src/tools/CodeExecutor.ts +6 -0
  230. package/src/tools/ProgrammaticToolCalling.ts +2 -0
  231. package/src/tools/ReadFile.ts +2 -0
  232. package/src/tools/SkillTool.ts +2 -0
  233. package/src/tools/SubagentTool.ts +3 -0
  234. package/src/tools/ToolNode.ts +193 -74
  235. package/src/tools/ToolSearch.ts +3 -0
  236. package/src/tools/__tests__/ToolNode.onResultCompletion.test.ts +174 -0
  237. package/src/tools/__tests__/intentArg.test.ts +281 -0
  238. package/src/tools/__tests__/intentCoverage.test.ts +139 -0
  239. package/src/tools/__tests__/toolOutputReferences.test.ts +83 -0
  240. package/src/tools/intentArg.ts +323 -0
  241. package/src/tools/local/CompileCheckTool.ts +4 -3
  242. package/src/tools/local/LocalCodingTools.ts +14 -13
  243. package/src/tools/ptcTimeout.ts +2 -0
  244. package/src/tools/search/keenable-scraper.test.ts +153 -0
  245. package/src/tools/search/keenable-scraper.ts +137 -0
  246. package/src/tools/search/outcome.test.ts +90 -0
  247. package/src/tools/search/schema.ts +3 -0
  248. package/src/tools/search/tool.ts +60 -3
  249. package/src/tools/search/types.ts +50 -3
  250. package/src/tools/subagent/SubagentExecutor.ts +2 -1
  251. package/src/tools/toolOutputReferences.ts +77 -9
  252. package/src/types/graph.ts +12 -1
  253. package/src/types/run.ts +67 -0
  254. package/src/types/stream.ts +12 -41
  255. package/src/types/tools.ts +24 -2
  256. package/dist/cjs/splitStream.cjs +0 -151
  257. package/dist/cjs/splitStream.cjs.map +0 -1
  258. package/dist/esm/splitStream.mjs +0 -150
  259. package/dist/esm/splitStream.mjs.map +0 -1
  260. package/dist/types/mockStream.d.ts +0 -32
  261. package/dist/types/splitStream.d.ts +0 -37
  262. package/src/mockStream.ts +0 -99
  263. package/src/splitStream.ts +0 -234
@@ -1,5 +1,6 @@
1
1
  require("../common/enum.cjs");
2
2
  require("../common/index.cjs");
3
+ const require_intentArg = require("./intentArg.cjs");
3
4
  //#region src/tools/ReadFile.ts
4
5
  const ReadFileToolName = "read_file";
5
6
  const ReadFileToolDescription = `Read the contents of a file. Returns text content with line numbers for easy reference.
@@ -19,10 +20,13 @@ CONSTRAINTS:
19
20
  - Do not guess file paths. Use paths from the skill documentation or tool output.`;
20
21
  const ReadFileToolSchema = {
21
22
  type: "object",
22
- properties: { path: {
23
- type: "string",
24
- description: "Path to the file. For skill files: \"{skillName}/{path}\" (e.g. \"pdf-analyzer/src/utils.py\"). For code execution output: the path as returned by the execution tool."
25
- } },
23
+ properties: {
24
+ intent: { ...require_intentArg.INTENT_PROPERTY },
25
+ path: {
26
+ type: "string",
27
+ description: "Path to the file. For skill files: \"{skillName}/{path}\" (e.g. \"pdf-analyzer/src/utils.py\"). For code execution output: the path as returned by the execution tool."
28
+ }
29
+ },
26
30
  required: ["path"]
27
31
  };
28
32
  const ReadFileToolDefinition = {
@@ -1 +1 @@
1
- {"version":3,"file":"ReadFile.cjs","names":[],"sources":["../../../src/tools/ReadFile.ts"],"sourcesContent":["// src/tools/ReadFile.ts\nimport { Constants } from '@/common';\n\nexport const ReadFileToolName = Constants.READ_FILE;\n\nexport const ReadFileToolDescription = `Read the contents of a file. Returns text content with line numbers for easy reference.\n\nFor skill files, use the path format: {skillName}/{filePath} (e.g. \"pdf-analyzer/src/utils.py\", \"code-review/SKILL.md\").\n\nBEHAVIOR:\n- Text files: returned with numbered lines.\n- Images (png, jpeg, gif, webp): returned as visual content the model can see.\n- PDFs: returned as document content.\n- Other binary files: metadata returned with a note to use bash for processing.\n- Large files (>256KB text, >10MB binary): metadata only.\n- SKILL.md: returns the skill's instructions directly.\n\nCONSTRAINTS:\n- Only files from invoked skills or code execution output are accessible.\n- Do not guess file paths. Use paths from the skill documentation or tool output.`;\n\nexport const ReadFileToolSchema = {\n type: 'object',\n properties: {\n path: {\n type: 'string',\n description:\n 'Path to the file. For skill files: \"{skillName}/{path}\" (e.g. \"pdf-analyzer/src/utils.py\"). For code execution output: the path as returned by the execution tool.',\n },\n },\n required: ['path'],\n} as const;\n\nexport const ReadFileToolDefinition = {\n name: ReadFileToolName,\n description: ReadFileToolDescription,\n parameters: ReadFileToolSchema,\n responseFormat: 'content_and_artifact' as const,\n} as const;\n"],"mappings":";;;AAGA,MAAa,mBAAA;AAEb,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAa,qBAAqB;CAChC,MAAM;CACN,YAAY,EACV,MAAM;EACJ,MAAM;EACN,aACE;CACJ,EACF;CACA,UAAU,CAAC,MAAM;AACnB;AAEA,MAAa,yBAAyB;CACpC,MAAM;CACN,aAAa;CACb,YAAY;CACZ,gBAAgB;AAClB"}
1
+ {"version":3,"file":"ReadFile.cjs","names":["INTENT_PROPERTY"],"sources":["../../../src/tools/ReadFile.ts"],"sourcesContent":["// src/tools/ReadFile.ts\nimport { INTENT_PROPERTY } from '@/tools/intentArg';\nimport { Constants } from '@/common';\n\nexport const ReadFileToolName = Constants.READ_FILE;\n\nexport const ReadFileToolDescription = `Read the contents of a file. Returns text content with line numbers for easy reference.\n\nFor skill files, use the path format: {skillName}/{filePath} (e.g. \"pdf-analyzer/src/utils.py\", \"code-review/SKILL.md\").\n\nBEHAVIOR:\n- Text files: returned with numbered lines.\n- Images (png, jpeg, gif, webp): returned as visual content the model can see.\n- PDFs: returned as document content.\n- Other binary files: metadata returned with a note to use bash for processing.\n- Large files (>256KB text, >10MB binary): metadata only.\n- SKILL.md: returns the skill's instructions directly.\n\nCONSTRAINTS:\n- Only files from invoked skills or code execution output are accessible.\n- Do not guess file paths. Use paths from the skill documentation or tool output.`;\n\nexport const ReadFileToolSchema = {\n type: 'object',\n properties: {\n intent: { ...INTENT_PROPERTY },\n path: {\n type: 'string',\n description:\n 'Path to the file. For skill files: \"{skillName}/{path}\" (e.g. \"pdf-analyzer/src/utils.py\"). For code execution output: the path as returned by the execution tool.',\n },\n },\n required: ['path'],\n} as const;\n\nexport const ReadFileToolDefinition = {\n name: ReadFileToolName,\n description: ReadFileToolDescription,\n parameters: ReadFileToolSchema,\n responseFormat: 'content_and_artifact' as const,\n} as const;\n"],"mappings":";;;;AAIA,MAAa,mBAAA;AAEb,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAa,qBAAqB;CAChC,MAAM;CACN,YAAY;EACV,QAAQ,EAAE,GAAGA,kBAAAA,gBAAgB;EAC7B,MAAM;GACJ,MAAM;GACN,aACE;EACJ;CACF;CACA,UAAU,CAAC,MAAM;AACnB;AAEA,MAAa,yBAAyB;CACpC,MAAM;CACN,aAAa;CACb,YAAY;CACZ,gBAAgB;AAClB"}
@@ -1,5 +1,6 @@
1
1
  require("../common/enum.cjs");
2
2
  require("../common/index.cjs");
3
+ const require_intentArg = require("./intentArg.cjs");
3
4
  //#region src/tools/SkillTool.ts
4
5
  const SkillToolName = "skill";
5
6
  const SkillToolDescription = `Invoke a skill from the user's library. Skills provide domain-specific instructions loaded into the conversation context, and may also provide files accessible via available tools depending on the runtime environment.
@@ -24,6 +25,7 @@ CONSTRAINTS:
24
25
  const SkillToolSchema = {
25
26
  type: "object",
26
27
  properties: {
28
+ intent: { ...require_intentArg.INTENT_PROPERTY },
27
29
  skillName: {
28
30
  type: "string",
29
31
  description: "The kebab-case identifier of the skill to invoke (e.g. \"financial-analyzer\", \"meeting-notes\"). Must match a name from the \"Available Skills\" section."
@@ -1 +1 @@
1
- {"version":3,"file":"SkillTool.cjs","names":[],"sources":["../../../src/tools/SkillTool.ts"],"sourcesContent":["// src/tools/SkillTool.ts\nimport { Constants } from '@/common';\n\nexport const SkillToolName = Constants.SKILL_TOOL;\n\nexport const SkillToolDescription = `Invoke a skill from the user's library. Skills provide domain-specific instructions loaded into the conversation context, and may also provide files accessible via available tools depending on the runtime environment.\n\nWHEN TO USE:\n- The user's request matches a skill listed in the \"Available Skills\" section of the system prompt.\n- You MUST invoke the matching skill BEFORE attempting the task yourself.\n\nWHAT HAPPENS:\n- The skill's full instructions are loaded into the conversation as context.\n- Files bundled with the skill may become accessible via available tools.\n- Follow the skill's instructions to complete the task.\n\nCONSTRAINTS:\n- Do not invoke a skill that is already active in this conversation.\n- Skill names come from the catalog only. Do not guess names.`;\n\n/**\n * JSON Schema for the SkillTool parameters.\n * Single source of truth used by both SkillToolDefinition (LCTool registry)\n * and createSkillTool() (DynamicStructuredTool instance).\n */\nexport const SkillToolSchema = {\n type: 'object',\n properties: {\n skillName: {\n type: 'string',\n description:\n 'The kebab-case identifier of the skill to invoke (e.g. \"financial-analyzer\", \"meeting-notes\"). Must match a name from the \"Available Skills\" section.',\n },\n args: {\n type: 'string',\n description: 'Optional freeform arguments string passed to the skill.',\n },\n },\n required: ['skillName'],\n} as const;\n\nexport const SkillToolDefinition = {\n name: SkillToolName,\n description: SkillToolDescription,\n parameters: SkillToolSchema,\n} as const;\n"],"mappings":";;;AAGA,MAAa,gBAAA;AAEb,MAAa,uBAAuB;;;;;;;;;;;;;;;;;;;AAoBpC,MAAa,kBAAkB;CAC7B,MAAM;CACN,YAAY;EACV,WAAW;GACT,MAAM;GACN,aACE;EACJ;EACA,MAAM;GACJ,MAAM;GACN,aAAa;EACf;CACF;CACA,UAAU,CAAC,WAAW;AACxB;AAEA,MAAa,sBAAsB;CACjC,MAAM;CACN,aAAa;CACb,YAAY;AACd"}
1
+ {"version":3,"file":"SkillTool.cjs","names":["INTENT_PROPERTY"],"sources":["../../../src/tools/SkillTool.ts"],"sourcesContent":["// src/tools/SkillTool.ts\nimport { INTENT_PROPERTY } from '@/tools/intentArg';\nimport { Constants } from '@/common';\n\nexport const SkillToolName = Constants.SKILL_TOOL;\n\nexport const SkillToolDescription = `Invoke a skill from the user's library. Skills provide domain-specific instructions loaded into the conversation context, and may also provide files accessible via available tools depending on the runtime environment.\n\nWHEN TO USE:\n- The user's request matches a skill listed in the \"Available Skills\" section of the system prompt.\n- You MUST invoke the matching skill BEFORE attempting the task yourself.\n\nWHAT HAPPENS:\n- The skill's full instructions are loaded into the conversation as context.\n- Files bundled with the skill may become accessible via available tools.\n- Follow the skill's instructions to complete the task.\n\nCONSTRAINTS:\n- Do not invoke a skill that is already active in this conversation.\n- Skill names come from the catalog only. Do not guess names.`;\n\n/**\n * JSON Schema for the SkillTool parameters.\n * Single source of truth used by both SkillToolDefinition (LCTool registry)\n * and createSkillTool() (DynamicStructuredTool instance).\n */\nexport const SkillToolSchema = {\n type: 'object',\n properties: {\n intent: { ...INTENT_PROPERTY },\n skillName: {\n type: 'string',\n description:\n 'The kebab-case identifier of the skill to invoke (e.g. \"financial-analyzer\", \"meeting-notes\"). Must match a name from the \"Available Skills\" section.',\n },\n args: {\n type: 'string',\n description: 'Optional freeform arguments string passed to the skill.',\n },\n },\n required: ['skillName'],\n} as const;\n\nexport const SkillToolDefinition = {\n name: SkillToolName,\n description: SkillToolDescription,\n parameters: SkillToolSchema,\n} as const;\n"],"mappings":";;;;AAIA,MAAa,gBAAA;AAEb,MAAa,uBAAuB;;;;;;;;;;;;;;;;;;;AAoBpC,MAAa,kBAAkB;CAC7B,MAAM;CACN,YAAY;EACV,QAAQ,EAAE,GAAGA,kBAAAA,gBAAgB;EAC7B,WAAW;GACT,MAAM;GACN,aACE;EACJ;EACA,MAAM;GACJ,MAAM;GACN,aAAa;EACf;CACF;CACA,UAAU,CAAC,WAAW;AACxB;AAEA,MAAa,sBAAsB;CACjC,MAAM;CACN,aAAa;CACb,YAAY;AACd"}
@@ -1,5 +1,6 @@
1
1
  require("../common/enum.cjs");
2
2
  require("../common/index.cjs");
3
+ const require_intentArg = require("./intentArg.cjs");
3
4
  //#region src/tools/SubagentTool.ts
4
5
  const SubagentToolName = "subagent";
5
6
  const SubagentToolDescription = `Delegate a task to a specialized subagent that runs in an isolated context window. The subagent executes independently and returns only its final text result — all intermediate tool calls, reasoning, and context stay isolated.
@@ -22,6 +23,7 @@ const SUBAGENT_TYPE_PROP_DESCRIPTION = "Which subagent type to delegate to. Must
22
23
  const SubagentToolSchema = {
23
24
  type: "object",
24
25
  properties: {
26
+ intent: { ...require_intentArg.INTENT_PROPERTY },
25
27
  description: {
26
28
  type: "string",
27
29
  description: DESCRIPTION_PROP_DESCRIPTION
@@ -51,6 +53,7 @@ function buildSubagentToolParams(configs) {
51
53
  schema: {
52
54
  type: "object",
53
55
  properties: {
56
+ intent: { ...require_intentArg.INTENT_PROPERTY },
54
57
  description: {
55
58
  type: "string",
56
59
  description: DESCRIPTION_PROP_DESCRIPTION
@@ -1 +1 @@
1
- {"version":3,"file":"SubagentTool.cjs","names":[],"sources":["../../../src/tools/SubagentTool.ts"],"sourcesContent":["import type { JsonSchemaType, LCTool } from '@/types/tools';\nimport type { SubagentConfig } from '@/types';\nimport { Constants } from '@/common';\n\nexport const SubagentToolName = Constants.SUBAGENT;\n\nexport const SubagentToolDescription = `Delegate a task to a specialized subagent that runs in an isolated context window. The subagent executes independently and returns only its final text result — all intermediate tool calls, reasoning, and context stay isolated.\n\nWHEN TO USE:\n- The task is self-contained and can be described in a single prompt.\n- You want to offload verbose or exploratory work without bloating your own context.\n- A specialized subagent is available for the task domain.\n\nWHAT HAPPENS:\n- A fresh agent is created with the task description as its only input.\n- The subagent runs to completion using its own tools and context.\n- Only the final text response is returned to you.\n\nCONSTRAINTS:\n- subagent_type must match one of the available types listed below.\n- The subagent cannot see your conversation history.`;\n\nconst DESCRIPTION_PROP_DESCRIPTION =\n 'Complete task description for the subagent. This is the ONLY information it receives — include all necessary context, requirements, and constraints.';\n\nconst SUBAGENT_TYPE_PROP_DESCRIPTION =\n 'Which subagent type to delegate to. Must be one of the available types.';\n\nexport const SubagentToolSchema = {\n type: 'object',\n properties: {\n description: {\n type: 'string',\n description: DESCRIPTION_PROP_DESCRIPTION,\n },\n subagent_type: {\n type: 'string',\n description: SUBAGENT_TYPE_PROP_DESCRIPTION,\n },\n },\n required: ['description', 'subagent_type'] as string[],\n} as const;\n\nexport const SubagentToolDefinition: LCTool = {\n name: SubagentToolName,\n description: SubagentToolDescription,\n parameters: SubagentToolSchema,\n};\n\n/**\n * Build the name, schema, and description params for `tool()` from available configs.\n * Used by `Graph.createAgentNode()` when constructing the runtime tool instance.\n * Extends `SubagentToolSchema` by populating `subagent_type.enum` dynamically.\n */\nexport function buildSubagentToolParams(configs: SubagentConfig[]): {\n name: string;\n schema: JsonSchemaType;\n description: string;\n} {\n const types = configs.map((c) => c.type);\n const typeDescriptions = configs\n .map((c) => `- \"${c.type}\" (${c.name}): ${c.description}`)\n .join('\\n');\n\n return {\n name: SubagentToolName,\n schema: {\n type: 'object',\n properties: {\n description: {\n type: 'string',\n description: DESCRIPTION_PROP_DESCRIPTION,\n },\n subagent_type: {\n type: 'string',\n enum: types,\n description: `${SUBAGENT_TYPE_PROP_DESCRIPTION} Available: ${types.join(', ')}.`,\n },\n },\n required: ['description', 'subagent_type'],\n },\n description: `${SubagentToolDescription}\\n\\nAvailable types:\\n${typeDescriptions}`,\n };\n}\n\n/**\n * Create a SubagentTool LCTool definition with dynamic enum and description\n * populated from the available subagent configs.\n * Used for the tool registry in event-driven mode.\n */\nexport function createSubagentToolDefinition(\n configs: SubagentConfig[]\n): LCTool {\n const params = buildSubagentToolParams(configs);\n return {\n name: params.name,\n description: params.description,\n parameters: params.schema,\n };\n}\n"],"mappings":";;;AAIA,MAAa,mBAAA;AAEb,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAM,+BACJ;AAEF,MAAM,iCACJ;AAEF,MAAa,qBAAqB;CAChC,MAAM;CACN,YAAY;EACV,aAAa;GACX,MAAM;GACN,aAAa;EACf;EACA,eAAe;GACb,MAAM;GACN,aAAa;EACf;CACF;CACA,UAAU,CAAC,eAAe,eAAe;AAC3C;AAEA,MAAa,yBAAiC;CAC5C,MAAM;CACN,aAAa;CACb,YAAY;AACd;;;;;;AAOA,SAAgB,wBAAwB,SAItC;CACA,MAAM,QAAQ,QAAQ,KAAK,MAAM,EAAE,IAAI;CACvC,MAAM,mBAAmB,QACtB,KAAK,MAAM,MAAM,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,aAAa,CAAC,CACzD,KAAK,IAAI;CAEZ,OAAO;EACL,MAAM;EACN,QAAQ;GACN,MAAM;GACN,YAAY;IACV,aAAa;KACX,MAAM;KACN,aAAa;IACf;IACA,eAAe;KACb,MAAM;KACN,MAAM;KACN,aAAa,GAAG,+BAA+B,cAAc,MAAM,KAAK,IAAI,EAAE;IAChF;GACF;GACA,UAAU,CAAC,eAAe,eAAe;EAC3C;EACA,aAAa,GAAG,wBAAwB,wBAAwB;CAClE;AACF;;;;;;AAOA,SAAgB,6BACd,SACQ;CACR,MAAM,SAAS,wBAAwB,OAAO;CAC9C,OAAO;EACL,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,YAAY,OAAO;CACrB;AACF"}
1
+ {"version":3,"file":"SubagentTool.cjs","names":["INTENT_PROPERTY"],"sources":["../../../src/tools/SubagentTool.ts"],"sourcesContent":["import type { JsonSchemaType, LCTool } from '@/types/tools';\nimport type { SubagentConfig } from '@/types';\nimport { INTENT_PROPERTY } from '@/tools/intentArg';\nimport { Constants } from '@/common';\n\nexport const SubagentToolName = Constants.SUBAGENT;\n\nexport const SubagentToolDescription = `Delegate a task to a specialized subagent that runs in an isolated context window. The subagent executes independently and returns only its final text result — all intermediate tool calls, reasoning, and context stay isolated.\n\nWHEN TO USE:\n- The task is self-contained and can be described in a single prompt.\n- You want to offload verbose or exploratory work without bloating your own context.\n- A specialized subagent is available for the task domain.\n\nWHAT HAPPENS:\n- A fresh agent is created with the task description as its only input.\n- The subagent runs to completion using its own tools and context.\n- Only the final text response is returned to you.\n\nCONSTRAINTS:\n- subagent_type must match one of the available types listed below.\n- The subagent cannot see your conversation history.`;\n\nconst DESCRIPTION_PROP_DESCRIPTION =\n 'Complete task description for the subagent. This is the ONLY information it receives — include all necessary context, requirements, and constraints.';\n\nconst SUBAGENT_TYPE_PROP_DESCRIPTION =\n 'Which subagent type to delegate to. Must be one of the available types.';\n\nexport const SubagentToolSchema = {\n type: 'object',\n properties: {\n intent: { ...INTENT_PROPERTY },\n description: {\n type: 'string',\n description: DESCRIPTION_PROP_DESCRIPTION,\n },\n subagent_type: {\n type: 'string',\n description: SUBAGENT_TYPE_PROP_DESCRIPTION,\n },\n },\n required: ['description', 'subagent_type'] as string[],\n} as const;\n\nexport const SubagentToolDefinition: LCTool = {\n name: SubagentToolName,\n description: SubagentToolDescription,\n parameters: SubagentToolSchema,\n};\n\n/**\n * Build the name, schema, and description params for `tool()` from available configs.\n * Used by `Graph.createAgentNode()` when constructing the runtime tool instance.\n * Extends `SubagentToolSchema` by populating `subagent_type.enum` dynamically.\n */\nexport function buildSubagentToolParams(configs: SubagentConfig[]): {\n name: string;\n schema: JsonSchemaType;\n description: string;\n} {\n const types = configs.map((c) => c.type);\n const typeDescriptions = configs\n .map((c) => `- \"${c.type}\" (${c.name}): ${c.description}`)\n .join('\\n');\n\n return {\n name: SubagentToolName,\n schema: {\n type: 'object',\n properties: {\n intent: { ...INTENT_PROPERTY },\n description: {\n type: 'string',\n description: DESCRIPTION_PROP_DESCRIPTION,\n },\n subagent_type: {\n type: 'string',\n enum: types,\n description: `${SUBAGENT_TYPE_PROP_DESCRIPTION} Available: ${types.join(', ')}.`,\n },\n },\n required: ['description', 'subagent_type'],\n },\n description: `${SubagentToolDescription}\\n\\nAvailable types:\\n${typeDescriptions}`,\n };\n}\n\n/**\n * Create a SubagentTool LCTool definition with dynamic enum and description\n * populated from the available subagent configs.\n * Used for the tool registry in event-driven mode.\n */\nexport function createSubagentToolDefinition(\n configs: SubagentConfig[]\n): LCTool {\n const params = buildSubagentToolParams(configs);\n return {\n name: params.name,\n description: params.description,\n parameters: params.schema,\n };\n}\n"],"mappings":";;;;AAKA,MAAa,mBAAA;AAEb,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAM,+BACJ;AAEF,MAAM,iCACJ;AAEF,MAAa,qBAAqB;CAChC,MAAM;CACN,YAAY;EACV,QAAQ,EAAE,GAAGA,kBAAAA,gBAAgB;EAC7B,aAAa;GACX,MAAM;GACN,aAAa;EACf;EACA,eAAe;GACb,MAAM;GACN,aAAa;EACf;CACF;CACA,UAAU,CAAC,eAAe,eAAe;AAC3C;AAEA,MAAa,yBAAiC;CAC5C,MAAM;CACN,aAAa;CACb,YAAY;AACd;;;;;;AAOA,SAAgB,wBAAwB,SAItC;CACA,MAAM,QAAQ,QAAQ,KAAK,MAAM,EAAE,IAAI;CACvC,MAAM,mBAAmB,QACtB,KAAK,MAAM,MAAM,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,aAAa,CAAC,CACzD,KAAK,IAAI;CAEZ,OAAO;EACL,MAAM;EACN,QAAQ;GACN,MAAM;GACN,YAAY;IACV,QAAQ,EAAE,GAAGA,kBAAAA,gBAAgB;IAC7B,aAAa;KACX,MAAM;KACN,aAAa;IACf;IACA,eAAe;KACb,MAAM;KACN,MAAM;KACN,aAAa,GAAG,+BAA+B,cAAc,MAAM,KAAK,IAAI,EAAE;IAChF;GACF;GACA,UAAU,CAAC,eAAe,eAAe;EAC3C;EACA,aAAa,GAAG,wBAAwB,wBAAwB;CAClE;AACF;;;;;;AAOA,SAAgB,6BACd,SACQ;CACR,MAAM,SAAS,wBAAwB,OAAO;CAC9C,OAAO;EACL,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,YAAY,OAAO;CACrB;AACF"}
@@ -3,9 +3,10 @@ const require_enum = require("../common/enum.cjs");
3
3
  require("../common/index.cjs");
4
4
  const require_truncation = require("../utils/truncation.cjs");
5
5
  const require_toolContent = require("../utils/toolContent.cjs");
6
- const require_langchain = require("../messages/langchain.cjs");
7
6
  const require_events = require("../utils/events.cjs");
7
+ const require_injected = require("../messages/injected.cjs");
8
8
  const require_eagerEventExecution = require("./eagerEventExecution.cjs");
9
+ const require_intentArg = require("./intentArg.cjs");
9
10
  const require_toolOutputReferences = require("./toolOutputReferences.cjs");
10
11
  const require_run = require("../utils/run.cjs");
11
12
  require("../utils/index.cjs");
@@ -19,6 +20,12 @@ let _langchain_langgraph = require("@langchain/langgraph");
19
20
  let nanoid = require("nanoid");
20
21
  let _langchain_core_singletons = require("@langchain/core/singletons");
21
22
  //#region src/tools/ToolNode.ts
23
+ function createToolErrorOwnership() {
24
+ return {
25
+ handlerOwned: /* @__PURE__ */ new Set(),
26
+ undispatched: /* @__PURE__ */ new Set()
27
+ };
28
+ }
22
29
  /**
23
30
  * Produces the provider preview and, when requested, the exact registry prefix
24
31
  * in one bounded traversal. String outputs already exist in memory when a tool
@@ -251,12 +258,12 @@ var ToolNode = class extends require_run.RunnableCallable {
251
258
  toolCallStepIds;
252
259
  errorHandler;
253
260
  /**
254
- * Tool call ids whose `errorHandler` did NOT dispatch the error completion
255
- * event (it returned `false` or threw). The output loop must dispatch the
256
- * completion for these itself skipping them there would strand the
257
- * client's tool-call part without a terminal event.
261
+ * Fallback error-completion ownership for calls that reach `runTool`
262
+ * outside a batch context (direct `runTool` use in tests / embedders).
263
+ * Batch-scoped ownership is threaded via `RunToolBatchContext` instead
264
+ * see {@link ToolErrorOwnership} for why per-invocation scoping matters.
258
265
  */
259
- undispatchedToolErrors = /* @__PURE__ */ new Set();
266
+ looseErrorOwnership = createToolErrorOwnership();
260
267
  toolUsageCount;
261
268
  /** Maps toolCallId → turn captured in runTool, used by handleRunToolCompletions */
262
269
  toolCallTurns = /* @__PURE__ */ new Map();
@@ -543,8 +550,9 @@ var ToolNode = class extends require_run.RunnableCallable {
543
550
  const tool = this.toolMap.get(call.name);
544
551
  const registry = this.toolOutputRegistry;
545
552
  let resolveFn;
546
- if (preBatchSnapshot != null) resolveFn = (_runId, args) => preBatchSnapshot.resolve(args);
547
- else if (registry != null) resolveFn = (runIdArg, args) => registry.resolve(runIdArg, args);
553
+ const resolveOptions = { substituteIntentKey: this.toolDeclaresBusinessIntent(call.name) };
554
+ if (preBatchSnapshot != null) resolveFn = (_runId, args) => preBatchSnapshot.resolve(args, resolveOptions);
555
+ else if (registry != null) resolveFn = (runIdArg, args) => registry.resolve(runIdArg, args, resolveOptions);
548
556
  /**
549
557
  * Precompute the reference key once per call — captured locally
550
558
  * so concurrent `invoke()` calls on the same ToolNode cannot race
@@ -737,12 +745,14 @@ var ToolNode = class extends require_run.RunnableCallable {
737
745
  if (!this.handleToolErrors) throw e;
738
746
  if ((0, _langchain_langgraph.isGraphInterrupt)(e)) throw e;
739
747
  if (this.errorHandler) try {
740
- if (await this.errorHandler({
748
+ const dispatched = await this.errorHandler({
741
749
  error: e,
742
750
  id: call.id,
743
751
  name: call.name,
744
752
  input: call.args
745
- }, config.metadata) === false && call.id != null && call.id !== "")
753
+ }, config.metadata);
754
+ const ownership = batchContext.errorOwnership ?? this.looseErrorOwnership;
755
+ if (call.id != null && call.id !== "") if (dispatched === false)
746
756
  /**
747
757
  * The handler could not dispatch the error completion (typically
748
758
  * a resume pass, where a fast-failing tool errors before the
@@ -750,8 +760,10 @@ var ToolNode = class extends require_run.RunnableCallable {
750
760
  * output loop dispatches the completion itself instead of
751
761
  * assuming the handler covered it.
752
762
  */
753
- this.undispatchedToolErrors.add(call.id);
763
+ ownership.undispatched.add(call.id);
764
+ else ownership.handlerOwned.add(call.id);
754
765
  } catch (handlerError) {
766
+ if (call.id != null && call.id !== "") (batchContext.errorOwnership ?? this.looseErrorOwnership).handlerOwned.add(call.id);
755
767
  console.error("Error in errorHandler:", {
756
768
  toolName: call.name,
757
769
  toolCallId: call.id,
@@ -852,11 +864,12 @@ var ToolNode = class extends require_run.RunnableCallable {
852
864
  const turn = usageCount;
853
865
  const stepId = this.toolCallStepIds?.get(call.id ?? "") ?? "";
854
866
  let resolvedArgs = call.args;
867
+ const hookResolveOptions = { substituteIntentKey: this.toolDeclaresBusinessIntent(call.name) };
855
868
  if (batchContext.preBatchSnapshot != null) {
856
- const { resolved } = batchContext.preBatchSnapshot.resolve(call.args);
869
+ const { resolved } = batchContext.preBatchSnapshot.resolve(call.args, hookResolveOptions);
857
870
  resolvedArgs = resolved;
858
871
  } else if (this.toolOutputRegistry != null) {
859
- const { resolved } = this.toolOutputRegistry.resolve(registryRunId, call.args);
872
+ const { resolved } = this.toolOutputRegistry.resolve(registryRunId, call.args, hookResolveOptions);
860
873
  resolvedArgs = resolved;
861
874
  }
862
875
  let effectiveCall = call;
@@ -968,6 +981,16 @@ var ToolNode = class extends require_run.RunnableCallable {
968
981
  }
969
982
  }
970
983
  }
984
+ /**
985
+ * A hook (`PreToolUse.updatedInput`) or HITL `edit` decision rewrote the
986
+ * args: expose the EFFECTIVE args to downstream completion handling
987
+ * (`handleRunToolCompletions` reads this sink), so the emitted
988
+ * `tool_call.args` — and any intent/outcome label resolved from them —
989
+ * reflect what the tool actually ran with. `runTool`'s own placeholder
990
+ * substitution may overwrite this entry with the post-substitution args,
991
+ * which is strictly more accurate.
992
+ */
993
+ if (effectiveCall !== call && batchContext.resolvedArgsByCallId != null && call.id != null && call.id !== "") batchContext.resolvedArgsByCallId.set(call.id, effectiveCall.args);
971
994
  const output = await this.runTool(effectiveCall, config, {
972
995
  ...batchContext,
973
996
  usageCount
@@ -1174,7 +1197,8 @@ var ToolNode = class extends require_run.RunnableCallable {
1174
1197
  * by `runTool`. Threaded as a local map (instead of instance state)
1175
1198
  * so concurrent batches cannot read each other's entries.
1176
1199
  */
1177
- async handleRunToolCompletions(calls, outputs, config, resolvedArgsByCallId) {
1200
+ async handleRunToolCompletions(calls, outputs, config, resolvedArgsByCallId, errorOwnership) {
1201
+ const ownership = errorOwnership ?? this.looseErrorOwnership;
1178
1202
  for (let i = 0; i < calls.length; i++) {
1179
1203
  const call = calls[i];
1180
1204
  const output = outputs[i];
@@ -1182,8 +1206,13 @@ var ToolNode = class extends require_run.RunnableCallable {
1182
1206
  if ((0, _langchain_langgraph.isCommand)(output)) continue;
1183
1207
  const toolMessage = output;
1184
1208
  const toolCallId = call.id ?? "";
1185
- if (toolMessage.status === "error" && this.errorHandler != null) if (this.undispatchedToolErrors.has(toolCallId)) this.undispatchedToolErrors.delete(toolCallId);
1186
- else continue;
1209
+ if (toolMessage.status === "error" && this.errorHandler != null) {
1210
+ if (ownership.handlerOwned.has(toolCallId)) {
1211
+ ownership.handlerOwned.delete(toolCallId);
1212
+ continue;
1213
+ }
1214
+ ownership.undispatched.delete(toolCallId);
1215
+ }
1187
1216
  if (this.sessions && this.participatesInCodeSession(call.name)) {
1188
1217
  const artifact = toolMessage.artifact;
1189
1218
  const execSessionId = artifact?.session_id;
@@ -1195,12 +1224,23 @@ var ToolNode = class extends require_run.RunnableCallable {
1195
1224
  if (require_toolContent.isComputerCallOutputMessage(toolMessage)) contentString = require_truncation.truncateToolResultContent("[Computer screenshot omitted from completion event]", this.maxToolResultChars);
1196
1225
  else if (typeof toolMessage.content === "string") contentString = toolMessage.content;
1197
1226
  else contentString = require_toolContent.serializeStructuredValueBounded(toolMessage.content, this.maxToolResultChars).content;
1227
+ /**
1228
+ * Prefer the post-substitution args when a `{{…}}` placeholder
1229
+ * was resolved in `runTool`. This keeps
1230
+ * `ON_RUN_STEP_COMPLETED.tool_call.args` consistent with what
1231
+ * the tool actually received rather than leaking the template.
1232
+ */
1233
+ const effectiveArgs = resolvedArgsByCallId?.get(toolCallId) ?? call.args;
1234
+ /** Authored outcomes apply to failed calls too (“Search failed for…”);
1235
+ * without one, an error call simply stays unlabeled. */
1236
+ const outcome = require_intentArg.resolveToolOutcome(effectiveArgs, require_intentArg.readOutcomeFields(toolMessage.artifact), { isError: toolMessage.status === "error" });
1198
1237
  const tool_call = {
1199
- args: require_toolContent.serializeToolContentBounded(resolvedArgsByCallId?.get(toolCallId) ?? call.args ?? {}, this.maxToolResultChars),
1238
+ args: require_toolContent.serializeToolContentBounded(effectiveArgs ?? {}, this.maxToolResultChars),
1200
1239
  name: call.name,
1201
1240
  id: toolCallId,
1202
1241
  output: contentString,
1203
- progress: 1
1242
+ progress: 1,
1243
+ ...outcome != null && { outcome }
1204
1244
  };
1205
1245
  await require_events.safeDispatchCustomEvent("on_run_step_completed", { result: {
1206
1246
  id: stepId,
@@ -1254,7 +1294,7 @@ var ToolNode = class extends require_run.RunnableCallable {
1254
1294
  resolvedArgs = pre.resolved;
1255
1295
  if (pre.unresolved.length > 0 && call.id != null) unresolvedByCallId.set(call.id, pre.unresolved);
1256
1296
  } else if (registry != null) {
1257
- const { resolved, unresolved } = registry.resolve(registryRunId, originalArgs);
1297
+ const { resolved, unresolved } = registry.resolve(registryRunId, originalArgs, { substituteIntentKey: this.toolDeclaresBusinessIntent(call.name) });
1258
1298
  resolvedArgs = resolved;
1259
1299
  if (unresolved.length > 0 && call.id != null) unresolvedByCallId.set(call.id, unresolved);
1260
1300
  }
@@ -1430,7 +1470,7 @@ var ToolNode = class extends require_run.RunnableCallable {
1430
1470
  */
1431
1471
  const applyInputOverride = (entry, nextArgs) => {
1432
1472
  if (registry != null) {
1433
- const { resolved, unresolved } = (preBatchSnapshot ?? { resolve: (args) => registry.resolve(registryRunId, args) }).resolve(nextArgs);
1473
+ const { resolved, unresolved } = (preBatchSnapshot ?? { resolve: (args, options) => registry.resolve(registryRunId, args, options) }).resolve(nextArgs, { substituteIntentKey: this.toolDeclaresBusinessIntent(entry.call.name) });
1434
1474
  entry.args = resolved;
1435
1475
  if (entry.call.id != null) if (unresolved.length > 0) unresolvedByCallId.set(entry.call.id, unresolved);
1436
1476
  else unresolvedByCallId.delete(entry.call.id);
@@ -1774,7 +1814,7 @@ var ToolNode = class extends require_run.RunnableCallable {
1774
1814
  this.storeCodeSessionFromResults(results, requestMap);
1775
1815
  for (const result of results) {
1776
1816
  if (result.injectedMessages && result.injectedMessages.length > 0) try {
1777
- injected.push(...this.convertInjectedMessages(result.injectedMessages));
1817
+ injected.push(...require_injected.convertInjectedMessages(result.injectedMessages));
1778
1818
  } catch (e) {
1779
1819
  console.warn(`[ToolNode] Failed to convert injectedMessages for toolCallId=${result.toolCallId}:`, e instanceof Error ? e.message : e);
1780
1820
  }
@@ -1892,7 +1932,7 @@ var ToolNode = class extends require_run.RunnableCallable {
1892
1932
  ...successRefMeta != null && { additional_kwargs: successRefMeta }
1893
1933
  });
1894
1934
  }
1895
- if (!eagerCompletionDispatchedIds.has(result.toolCallId) && !earlyCompletionDispatchedIds.has(result.toolCallId)) await this.dispatchStepCompleted(result.toolCallId, toolName, request?.args ?? {}, contentString, config, request?.turn);
1935
+ if (!eagerCompletionDispatchedIds.has(result.toolCallId) && !earlyCompletionDispatchedIds.has(result.toolCallId)) await this.dispatchStepCompleted(result.toolCallId, toolName, request?.args ?? {}, contentString, config, request?.turn, require_intentArg.resolveToolOutcome(request?.args, require_intentArg.outcomeFieldsFromResult(result), { isError: result.status === "error" }));
1896
1936
  postToolBatchEntryByCallId.set(result.toolCallId, {
1897
1937
  toolName,
1898
1938
  toolInput: request?.args ?? {},
@@ -2023,12 +2063,26 @@ var ToolNode = class extends require_run.RunnableCallable {
2023
2063
  * user speech (e.g. steering) sits closest to the next model call.
2024
2064
  */
2025
2065
  if (hookInjectedMessages.length > 0) try {
2026
- injected.push(...this.convertInjectedMessages(hookInjectedMessages));
2066
+ injected.push(...require_injected.convertInjectedMessages(hookInjectedMessages));
2027
2067
  } catch (e) {
2028
2068
  console.warn("[ToolNode] Failed to convert PostToolBatch injectedMessages:", e instanceof Error ? e.message : e);
2029
2069
  }
2030
2070
  }
2031
- async dispatchStepCompleted(toolCallId, toolName, args, output, config, turn) {
2071
+ /**
2072
+ * Whether `name`'s own schema declares a BUSINESS parameter called
2073
+ * `intent` (declared, and not the injected label contract — see
2074
+ * `isIntentLabelProperty`). Such a parameter must keep participating in
2075
+ * `{{tool…}}` placeholder substitution; only the display label is exempt.
2076
+ */
2077
+ toolDeclaresBusinessIntent(name) {
2078
+ const instance = this.toolMap.get(name);
2079
+ const instanceProp = instance?.schema?.properties?.["intent"] ?? instance?.schema?.shape?.["intent"];
2080
+ if (instanceProp != null) return !require_intentArg.isIntentLabelProperty(instanceProp);
2081
+ const defProp = this.toolRegistry?.get(name)?.parameters?.properties?.[require_intentArg.INTENT_ARG];
2082
+ if (defProp != null) return !require_intentArg.isIntentLabelProperty(defProp);
2083
+ return false;
2084
+ }
2085
+ async dispatchStepCompleted(toolCallId, toolName, args, output, config, turn, outcome) {
2032
2086
  const stepId = this.toolCallStepIds?.get(toolCallId) ?? "";
2033
2087
  if (!stepId) console.warn(`[ToolNode] toolCallStepIds missing entry for toolCallId=${toolCallId} (tool=${toolName}). This indicates a race between the stream consumer and graph execution. Map size: ${this.toolCallStepIds?.size ?? 0}`);
2034
2088
  return await require_events.safeDispatchCustomEvent("on_run_step_completed", { result: {
@@ -2040,7 +2094,8 @@ var ToolNode = class extends require_run.RunnableCallable {
2040
2094
  name: toolName,
2041
2095
  id: toolCallId,
2042
2096
  output,
2043
- progress: 1
2097
+ progress: 1,
2098
+ ...outcome != null && { outcome }
2044
2099
  }
2045
2100
  } }, config) !== false;
2046
2101
  }
@@ -2053,27 +2108,7 @@ var ToolNode = class extends require_run.RunnableCallable {
2053
2108
  */
2054
2109
  async dispatchEarlyToolCompletion(result, request, config) {
2055
2110
  const output = result.status === "error" ? require_truncation.truncateToolResultContent(`Error: ${result.errorMessage ?? "Unknown error"}\n Please fix your mistakes.`, this.maxToolResultChars) : serializeToolOutputWithinLimits(result.content, this.maxToolResultChars).content;
2056
- return this.dispatchStepCompleted(result.toolCallId, request.name, request.args, output, config, request.turn);
2057
- }
2058
- /**
2059
- * Converts InjectedMessage instances to LangChain HumanMessage objects.
2060
- * Both 'user' and 'system' roles become HumanMessage to avoid provider
2061
- * rejections (Anthropic/Google reject non-leading SystemMessages).
2062
- * The original role is preserved in additional_kwargs for downstream consumers.
2063
- */
2064
- convertInjectedMessages(messages) {
2065
- const converted = [];
2066
- for (const msg of messages) {
2067
- const additional_kwargs = { role: msg.role };
2068
- if (msg.isMeta != null) additional_kwargs.isMeta = msg.isMeta;
2069
- if (msg.source != null) additional_kwargs.source = msg.source;
2070
- if (msg.skillName != null) additional_kwargs.skillName = msg.skillName;
2071
- converted.push(new _langchain_core_messages.HumanMessage({
2072
- content: require_langchain.toLangChainContent(msg.content),
2073
- additional_kwargs
2074
- }));
2075
- }
2076
- return converted;
2111
+ return this.dispatchStepCompleted(result.toolCallId, request.name, request.args, output, config, request.turn, require_intentArg.resolveToolOutcome(request.args, require_intentArg.outcomeFieldsFromResult(result), { isError: result.status === "error" }));
2077
2112
  }
2078
2113
  /**
2079
2114
  * Execute a group of direct (in-process) tool calls with interrupt-safe
@@ -2154,6 +2189,8 @@ var ToolNode = class extends require_run.RunnableCallable {
2154
2189
  * ToolNode cannot read or wipe each other's entries.
2155
2190
  */
2156
2191
  const resolvedArgsByCallId = /* @__PURE__ */ new Map();
2192
+ /** Per-invocation error-completion ownership — see `ToolErrorOwnership`. */
2193
+ const errorOwnership = createToolErrorOwnership();
2157
2194
  const batchScopeId = config.configurable?.run_id ?? `\0anon-${this.anonBatchCounter++}`;
2158
2195
  const turn = this.toolOutputRegistry?.nextTurn(batchScopeId) ?? 0;
2159
2196
  let outputs;
@@ -2171,6 +2208,7 @@ var ToolNode = class extends require_run.RunnableCallable {
2171
2208
  turn,
2172
2209
  batchScopeId,
2173
2210
  resolvedArgsByCallId,
2211
+ errorOwnership,
2174
2212
  additionalContextsSink: directAdditionalContexts,
2175
2213
  runInput: sendState
2176
2214
  });
@@ -2181,7 +2219,7 @@ var ToolNode = class extends require_run.RunnableCallable {
2181
2219
  source: "hook"
2182
2220
  }
2183
2221
  })] : [sendOutput];
2184
- await this.handleRunToolCompletions([input.lg_tool_call], [sendOutput], config, resolvedArgsByCallId);
2222
+ await this.handleRunToolCompletions([input.lg_tool_call], [sendOutput], config, resolvedArgsByCallId, errorOwnership);
2185
2223
  } else {
2186
2224
  let messages;
2187
2225
  if (Array.isArray(input)) messages = input;
@@ -2259,7 +2297,7 @@ var ToolNode = class extends require_run.RunnableCallable {
2259
2297
  const preBatchSnapshot = this.toolOutputRegistry?.snapshot(batchScopeId);
2260
2298
  if (preBatchSnapshot != null) {
2261
2299
  for (const entry of eventEntries) if (entry.call.id != null) {
2262
- const { resolved, unresolved } = preBatchSnapshot.resolve(entry.call.args);
2300
+ const { resolved, unresolved } = preBatchSnapshot.resolve(entry.call.args, { substituteIntentKey: this.toolDeclaresBusinessIntent(entry.call.name) });
2263
2301
  preResolvedEventArgs.set(entry.call.id, {
2264
2302
  resolved,
2265
2303
  unresolved
@@ -2271,11 +2309,12 @@ var ToolNode = class extends require_run.RunnableCallable {
2271
2309
  turn,
2272
2310
  batchScopeId,
2273
2311
  resolvedArgsByCallId,
2312
+ errorOwnership,
2274
2313
  preBatchSnapshot,
2275
2314
  additionalContextsSink: directAdditionalContexts,
2276
2315
  runInput: input
2277
2316
  }) : [];
2278
- if (directCalls.length > 0 && directOutputs.length > 0) await this.handleRunToolCompletions(directCalls, directOutputs, config, resolvedArgsByCallId);
2317
+ if (directCalls.length > 0 && directOutputs.length > 0) await this.handleRunToolCompletions(directCalls, directOutputs, config, resolvedArgsByCallId, errorOwnership);
2279
2318
  const eventResult = eventCalls.length > 0 ? await this.dispatchToolEvents(eventCalls, config, {
2280
2319
  batchIndices: eventIndices,
2281
2320
  turn,
@@ -2306,11 +2345,12 @@ var ToolNode = class extends require_run.RunnableCallable {
2306
2345
  turn,
2307
2346
  batchScopeId,
2308
2347
  resolvedArgsByCallId,
2348
+ errorOwnership,
2309
2349
  preBatchSnapshot,
2310
2350
  additionalContextsSink: directAdditionalContexts,
2311
2351
  runInput: input
2312
2352
  });
2313
- await this.handleRunToolCompletions(filteredCalls, toolOutputs, config, resolvedArgsByCallId);
2353
+ await this.handleRunToolCompletions(filteredCalls, toolOutputs, config, resolvedArgsByCallId, errorOwnership);
2314
2354
  outputs = directAdditionalContexts.length > 0 ? [...toolOutputs, new _langchain_core_messages.HumanMessage({
2315
2355
  content: directAdditionalContexts.join("\n\n"),
2316
2356
  additional_kwargs: {
@@ -2417,6 +2457,7 @@ function toolsCondition(state, toolNode, invokedToolIds) {
2417
2457
  }
2418
2458
  //#endregion
2419
2459
  exports.ToolNode = ToolNode;
2460
+ exports.createToolErrorOwnership = createToolErrorOwnership;
2420
2461
  exports.toolsCondition = toolsCondition;
2421
2462
 
2422
2463
  //# sourceMappingURL=ToolNode.cjs.map