@librechat/agents 3.2.32 → 3.2.33

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 (573) hide show
  1. package/dist/cjs/_virtual/_rolldown/runtime.cjs +23 -0
  2. package/dist/cjs/agents/AgentContext.cjs +844 -1046
  3. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  4. package/dist/cjs/common/constants.cjs +13 -13
  5. package/dist/cjs/common/constants.cjs.map +1 -1
  6. package/dist/cjs/common/enum.cjs +233 -240
  7. package/dist/cjs/common/enum.cjs.map +1 -1
  8. package/dist/cjs/common/index.cjs +2 -0
  9. package/dist/cjs/events.cjs +121 -169
  10. package/dist/cjs/events.cjs.map +1 -1
  11. package/dist/cjs/graphs/Graph.cjs +1389 -1807
  12. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  13. package/dist/cjs/graphs/MultiAgentGraph.cjs +713 -945
  14. package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
  15. package/dist/cjs/graphs/index.cjs +2 -0
  16. package/dist/cjs/hitl/askUserQuestion.cjs +60 -62
  17. package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -1
  18. package/dist/cjs/hitl/index.cjs +1 -0
  19. package/dist/cjs/hooks/HookRegistry.cjs +176 -202
  20. package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
  21. package/dist/cjs/hooks/createToolPolicyHook.cjs +71 -101
  22. package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -1
  23. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs +170 -273
  24. package/dist/cjs/hooks/createWorkspacePolicyHook.cjs.map +1 -1
  25. package/dist/cjs/hooks/executeHooks.cjs +227 -282
  26. package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
  27. package/dist/cjs/hooks/index.cjs +6 -0
  28. package/dist/cjs/hooks/matchers.cjs +196 -230
  29. package/dist/cjs/hooks/matchers.cjs.map +1 -1
  30. package/dist/cjs/hooks/types.cjs +24 -24
  31. package/dist/cjs/hooks/types.cjs.map +1 -1
  32. package/dist/cjs/instrumentation.cjs +110 -137
  33. package/dist/cjs/instrumentation.cjs.map +1 -1
  34. package/dist/cjs/langchain/google-common.cjs +0 -3
  35. package/dist/cjs/langchain/index.cjs +80 -43
  36. package/dist/cjs/langchain/language_models/chat_models.cjs +0 -3
  37. package/dist/cjs/langchain/messages/tool.cjs +0 -3
  38. package/dist/cjs/langchain/messages.cjs +35 -18
  39. package/dist/cjs/langchain/openai.cjs +0 -3
  40. package/dist/cjs/langchain/prompts.cjs +5 -8
  41. package/dist/cjs/langchain/runnables.cjs +11 -10
  42. package/dist/cjs/langchain/tools.cjs +14 -11
  43. package/dist/cjs/langchain/utils/env.cjs +5 -8
  44. package/dist/cjs/langfuse.cjs +60 -79
  45. package/dist/cjs/langfuse.cjs.map +1 -1
  46. package/dist/cjs/langfuseToolOutputTracing.cjs +267 -399
  47. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
  48. package/dist/cjs/llm/anthropic/index.cjs +432 -562
  49. package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
  50. package/dist/cjs/llm/anthropic/types.cjs +23 -47
  51. package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
  52. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +441 -731
  53. package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
  54. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +171 -256
  55. package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
  56. package/dist/cjs/llm/anthropic/utils/output_parsers.cjs +2 -0
  57. package/dist/cjs/llm/anthropic/utils/tools.cjs +12 -26
  58. package/dist/cjs/llm/anthropic/utils/tools.cjs.map +1 -1
  59. package/dist/cjs/llm/bedrock/index.cjs +195 -240
  60. package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
  61. package/dist/cjs/llm/bedrock/toolCache.cjs +84 -106
  62. package/dist/cjs/llm/bedrock/toolCache.cjs.map +1 -1
  63. package/dist/cjs/llm/bedrock/utils/index.cjs +2 -0
  64. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +357 -620
  65. package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
  66. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +105 -149
  67. package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
  68. package/dist/cjs/llm/fake.cjs +86 -96
  69. package/dist/cjs/llm/fake.cjs.map +1 -1
  70. package/dist/cjs/llm/google/index.cjs +183 -237
  71. package/dist/cjs/llm/google/index.cjs.map +1 -1
  72. package/dist/cjs/llm/google/utils/common.cjs +398 -674
  73. package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
  74. package/dist/cjs/llm/google/utils/zod_to_genai_parameters.cjs +2 -0
  75. package/dist/cjs/llm/init.cjs +44 -53
  76. package/dist/cjs/llm/init.cjs.map +1 -1
  77. package/dist/cjs/llm/invoke.cjs +142 -182
  78. package/dist/cjs/llm/invoke.cjs.map +1 -1
  79. package/dist/cjs/llm/openai/index.cjs +991 -1276
  80. package/dist/cjs/llm/openai/index.cjs.map +1 -1
  81. package/dist/cjs/llm/openai/utils/index.cjs +189 -316
  82. package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
  83. package/dist/cjs/llm/openrouter/index.cjs +102 -153
  84. package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
  85. package/dist/cjs/llm/openrouter/toolCache.cjs +35 -44
  86. package/dist/cjs/llm/openrouter/toolCache.cjs.map +1 -1
  87. package/dist/cjs/llm/providers.cjs +29 -37
  88. package/dist/cjs/llm/providers.cjs.map +1 -1
  89. package/dist/cjs/llm/request.cjs +20 -33
  90. package/dist/cjs/llm/request.cjs.map +1 -1
  91. package/dist/cjs/llm/vertexai/index.cjs +427 -453
  92. package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
  93. package/dist/cjs/main.cjs +547 -528
  94. package/dist/cjs/messages/anthropicToolCache.cjs +68 -119
  95. package/dist/cjs/messages/anthropicToolCache.cjs.map +1 -1
  96. package/dist/cjs/messages/cache.cjs +305 -418
  97. package/dist/cjs/messages/cache.cjs.map +1 -1
  98. package/dist/cjs/messages/content.cjs +36 -49
  99. package/dist/cjs/messages/content.cjs.map +1 -1
  100. package/dist/cjs/messages/contextPruning.cjs +112 -145
  101. package/dist/cjs/messages/contextPruning.cjs.map +1 -1
  102. package/dist/cjs/messages/contextPruningSettings.cjs +36 -46
  103. package/dist/cjs/messages/contextPruningSettings.cjs.map +1 -1
  104. package/dist/cjs/messages/core.cjs +256 -397
  105. package/dist/cjs/messages/core.cjs.map +1 -1
  106. package/dist/cjs/messages/format.cjs +904 -1387
  107. package/dist/cjs/messages/format.cjs.map +1 -1
  108. package/dist/cjs/messages/ids.cjs +16 -20
  109. package/dist/cjs/messages/ids.cjs.map +1 -1
  110. package/dist/cjs/messages/index.cjs +12 -0
  111. package/dist/cjs/messages/langchain.cjs +18 -18
  112. package/dist/cjs/messages/langchain.cjs.map +1 -1
  113. package/dist/cjs/messages/prune.cjs +1054 -1517
  114. package/dist/cjs/messages/prune.cjs.map +1 -1
  115. package/dist/cjs/messages/recency.cjs +77 -95
  116. package/dist/cjs/messages/recency.cjs.map +1 -1
  117. package/dist/cjs/messages/reducer.cjs +63 -78
  118. package/dist/cjs/messages/reducer.cjs.map +1 -1
  119. package/dist/cjs/messages/tools.cjs +51 -79
  120. package/dist/cjs/messages/tools.cjs.map +1 -1
  121. package/dist/cjs/openai/index.cjs +171 -217
  122. package/dist/cjs/openai/index.cjs.map +1 -1
  123. package/dist/cjs/responses/index.cjs +302 -391
  124. package/dist/cjs/responses/index.cjs.map +1 -1
  125. package/dist/cjs/run.cjs +903 -1113
  126. package/dist/cjs/run.cjs.map +1 -1
  127. package/dist/cjs/session/AgentSession.cjs +805 -986
  128. package/dist/cjs/session/AgentSession.cjs.map +1 -1
  129. package/dist/cjs/session/JsonlSessionStore.cjs +327 -410
  130. package/dist/cjs/session/JsonlSessionStore.cjs.map +1 -1
  131. package/dist/cjs/session/handlers.cjs +192 -208
  132. package/dist/cjs/session/handlers.cjs.map +1 -1
  133. package/dist/cjs/session/ids.cjs +9 -10
  134. package/dist/cjs/session/ids.cjs.map +1 -1
  135. package/dist/cjs/session/index.cjs +4 -0
  136. package/dist/cjs/session/messageSerialization.cjs +94 -156
  137. package/dist/cjs/session/messageSerialization.cjs.map +1 -1
  138. package/dist/cjs/splitStream.cjs +147 -206
  139. package/dist/cjs/splitStream.cjs.map +1 -1
  140. package/dist/cjs/stream.cjs +856 -1344
  141. package/dist/cjs/stream.cjs.map +1 -1
  142. package/dist/cjs/summarization/index.cjs +57 -101
  143. package/dist/cjs/summarization/index.cjs.map +1 -1
  144. package/dist/cjs/summarization/node.cjs +643 -796
  145. package/dist/cjs/summarization/node.cjs.map +1 -1
  146. package/dist/cjs/tools/BashExecutor.cjs +110 -136
  147. package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
  148. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +165 -245
  149. package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
  150. package/dist/cjs/tools/Calculator.cjs +36 -57
  151. package/dist/cjs/tools/Calculator.cjs.map +1 -1
  152. package/dist/cjs/tools/CodeExecutor.cjs +126 -168
  153. package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
  154. package/dist/cjs/tools/CodeSessionFileSummary.cjs +36 -46
  155. package/dist/cjs/tools/CodeSessionFileSummary.cjs.map +1 -1
  156. package/dist/cjs/tools/ProgrammaticToolCalling.cjs +459 -649
  157. package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
  158. package/dist/cjs/tools/ReadFile.cjs +17 -20
  159. package/dist/cjs/tools/ReadFile.cjs.map +1 -1
  160. package/dist/cjs/tools/SkillTool.cjs +26 -27
  161. package/dist/cjs/tools/SkillTool.cjs.map +1 -1
  162. package/dist/cjs/tools/SubagentTool.cjs +59 -61
  163. package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
  164. package/dist/cjs/tools/ToolNode.cjs +2109 -2686
  165. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  166. package/dist/cjs/tools/ToolSearch.cjs +663 -825
  167. package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
  168. package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs +248 -340
  169. package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs.map +1 -1
  170. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +170 -197
  171. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -1
  172. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +425 -520
  173. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -1
  174. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +91 -124
  175. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -1
  176. package/dist/cjs/tools/cloudflare/index.cjs +4 -0
  177. package/dist/cjs/tools/eagerEventExecution.cjs +75 -99
  178. package/dist/cjs/tools/eagerEventExecution.cjs.map +1 -1
  179. package/dist/cjs/tools/handlers.cjs +200 -262
  180. package/dist/cjs/tools/handlers.cjs.map +1 -1
  181. package/dist/cjs/tools/local/CompileCheckTool.cjs +150 -212
  182. package/dist/cjs/tools/local/CompileCheckTool.cjs.map +1 -1
  183. package/dist/cjs/tools/local/FileCheckpointer.cjs +77 -85
  184. package/dist/cjs/tools/local/FileCheckpointer.cjs.map +1 -1
  185. package/dist/cjs/tools/local/LocalCodingTools.cjs +763 -1022
  186. package/dist/cjs/tools/local/LocalCodingTools.cjs.map +1 -1
  187. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +666 -941
  188. package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
  189. package/dist/cjs/tools/local/LocalExecutionTools.cjs +49 -92
  190. package/dist/cjs/tools/local/LocalExecutionTools.cjs.map +1 -1
  191. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +286 -354
  192. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  193. package/dist/cjs/tools/local/attachments.cjs +108 -165
  194. package/dist/cjs/tools/local/attachments.cjs.map +1 -1
  195. package/dist/cjs/tools/local/bashAst.cjs +99 -113
  196. package/dist/cjs/tools/local/bashAst.cjs.map +1 -1
  197. package/dist/cjs/tools/local/editStrategies.cjs +126 -169
  198. package/dist/cjs/tools/local/editStrategies.cjs.map +1 -1
  199. package/dist/cjs/tools/local/index.cjs +12 -0
  200. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +136 -218
  201. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  202. package/dist/cjs/tools/local/syntaxCheck.cjs +142 -161
  203. package/dist/cjs/tools/local/syntaxCheck.cjs.map +1 -1
  204. package/dist/cjs/tools/local/textEncoding.cjs +25 -23
  205. package/dist/cjs/tools/local/textEncoding.cjs.map +1 -1
  206. package/dist/cjs/tools/local/workspaceFS.cjs +38 -46
  207. package/dist/cjs/tools/local/workspaceFS.cjs.map +1 -1
  208. package/dist/cjs/tools/ptcTimeout.cjs +27 -47
  209. package/dist/cjs/tools/ptcTimeout.cjs.map +1 -1
  210. package/dist/cjs/tools/schema.cjs +24 -23
  211. package/dist/cjs/tools/schema.cjs.map +1 -1
  212. package/dist/cjs/tools/search/anthropic.cjs +24 -33
  213. package/dist/cjs/tools/search/anthropic.cjs.map +1 -1
  214. package/dist/cjs/tools/search/content.cjs +95 -137
  215. package/dist/cjs/tools/search/content.cjs.map +1 -1
  216. package/dist/cjs/tools/search/firecrawl.cjs +141 -172
  217. package/dist/cjs/tools/search/firecrawl.cjs.map +1 -1
  218. package/dist/cjs/tools/search/format.cjs +128 -196
  219. package/dist/cjs/tools/search/format.cjs.map +1 -1
  220. package/dist/cjs/tools/search/highlights.cjs +165 -232
  221. package/dist/cjs/tools/search/highlights.cjs.map +1 -1
  222. package/dist/cjs/tools/search/index.cjs +2 -0
  223. package/dist/cjs/tools/search/rerankers.cjs +151 -174
  224. package/dist/cjs/tools/search/rerankers.cjs.map +1 -1
  225. package/dist/cjs/tools/search/schema.cjs +40 -39
  226. package/dist/cjs/tools/search/schema.cjs.map +1 -1
  227. package/dist/cjs/tools/search/search.cjs +428 -530
  228. package/dist/cjs/tools/search/search.cjs.map +1 -1
  229. package/dist/cjs/tools/search/serper-scraper.cjs +106 -127
  230. package/dist/cjs/tools/search/serper-scraper.cjs.map +1 -1
  231. package/dist/cjs/tools/search/tavily-scraper.cjs +129 -181
  232. package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -1
  233. package/dist/cjs/tools/search/tavily-search.cjs +295 -359
  234. package/dist/cjs/tools/search/tavily-search.cjs.map +1 -1
  235. package/dist/cjs/tools/search/tool.cjs +260 -299
  236. package/dist/cjs/tools/search/tool.cjs.map +1 -1
  237. package/dist/cjs/tools/search/utils.cjs +74 -117
  238. package/dist/cjs/tools/search/utils.cjs.map +1 -1
  239. package/dist/cjs/tools/skillCatalog.cjs +54 -72
  240. package/dist/cjs/tools/skillCatalog.cjs.map +1 -1
  241. package/dist/cjs/tools/streamedToolCallSeals.cjs +19 -36
  242. package/dist/cjs/tools/streamedToolCallSeals.cjs.map +1 -1
  243. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +612 -771
  244. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  245. package/dist/cjs/tools/subagent/index.cjs +1 -0
  246. package/dist/cjs/tools/toolOutputReferences.cjs +523 -630
  247. package/dist/cjs/tools/toolOutputReferences.cjs.map +1 -1
  248. package/dist/cjs/utils/callbacks.cjs +11 -21
  249. package/dist/cjs/utils/callbacks.cjs.map +1 -1
  250. package/dist/cjs/utils/errors.cjs +70 -95
  251. package/dist/cjs/utils/errors.cjs.map +1 -1
  252. package/dist/cjs/utils/events.cjs +32 -42
  253. package/dist/cjs/utils/events.cjs.map +1 -1
  254. package/dist/cjs/utils/graph.cjs +8 -12
  255. package/dist/cjs/utils/graph.cjs.map +1 -1
  256. package/dist/cjs/utils/handlers.cjs +60 -82
  257. package/dist/cjs/utils/handlers.cjs.map +1 -1
  258. package/dist/cjs/utils/index.cjs +9 -0
  259. package/dist/cjs/utils/llm.cjs +19 -27
  260. package/dist/cjs/utils/llm.cjs.map +1 -1
  261. package/dist/cjs/utils/misc.cjs +30 -46
  262. package/dist/cjs/utils/misc.cjs.map +1 -1
  263. package/dist/cjs/utils/run.cjs +50 -66
  264. package/dist/cjs/utils/run.cjs.map +1 -1
  265. package/dist/cjs/utils/schema.cjs +11 -19
  266. package/dist/cjs/utils/schema.cjs.map +1 -1
  267. package/dist/cjs/utils/title.cjs +71 -106
  268. package/dist/cjs/utils/title.cjs.map +1 -1
  269. package/dist/cjs/utils/tokens.cjs +186 -283
  270. package/dist/cjs/utils/tokens.cjs.map +1 -1
  271. package/dist/cjs/utils/truncation.cjs +95 -114
  272. package/dist/cjs/utils/truncation.cjs.map +1 -1
  273. package/dist/esm/agents/AgentContext.mjs +844 -1044
  274. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  275. package/dist/esm/common/constants.mjs +13 -11
  276. package/dist/esm/common/constants.mjs.map +1 -1
  277. package/dist/esm/common/enum.mjs +221 -238
  278. package/dist/esm/common/enum.mjs.map +1 -1
  279. package/dist/esm/common/index.mjs +3 -0
  280. package/dist/esm/events.mjs +121 -167
  281. package/dist/esm/events.mjs.map +1 -1
  282. package/dist/esm/graphs/Graph.mjs +1388 -1804
  283. package/dist/esm/graphs/Graph.mjs.map +1 -1
  284. package/dist/esm/graphs/MultiAgentGraph.mjs +713 -943
  285. package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
  286. package/dist/esm/graphs/index.mjs +3 -0
  287. package/dist/esm/hitl/askUserQuestion.mjs +60 -60
  288. package/dist/esm/hitl/askUserQuestion.mjs.map +1 -1
  289. package/dist/esm/hitl/index.mjs +2 -0
  290. package/dist/esm/hooks/HookRegistry.mjs +176 -200
  291. package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
  292. package/dist/esm/hooks/createToolPolicyHook.mjs +71 -99
  293. package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -1
  294. package/dist/esm/hooks/createWorkspacePolicyHook.mjs +170 -271
  295. package/dist/esm/hooks/createWorkspacePolicyHook.mjs.map +1 -1
  296. package/dist/esm/hooks/executeHooks.mjs +227 -280
  297. package/dist/esm/hooks/executeHooks.mjs.map +1 -1
  298. package/dist/esm/hooks/index.mjs +7 -0
  299. package/dist/esm/hooks/matchers.mjs +196 -228
  300. package/dist/esm/hooks/matchers.mjs.map +1 -1
  301. package/dist/esm/hooks/types.mjs +24 -22
  302. package/dist/esm/hooks/types.mjs.map +1 -1
  303. package/dist/esm/instrumentation.mjs +109 -132
  304. package/dist/esm/instrumentation.mjs.map +1 -1
  305. package/dist/esm/langchain/google-common.mjs +1 -2
  306. package/dist/esm/langchain/index.mjs +5 -5
  307. package/dist/esm/langchain/language_models/chat_models.mjs +1 -2
  308. package/dist/esm/langchain/messages/tool.mjs +1 -2
  309. package/dist/esm/langchain/messages.mjs +2 -2
  310. package/dist/esm/langchain/openai.mjs +1 -2
  311. package/dist/esm/langchain/prompts.mjs +2 -2
  312. package/dist/esm/langchain/runnables.mjs +2 -2
  313. package/dist/esm/langchain/tools.mjs +2 -2
  314. package/dist/esm/langchain/utils/env.mjs +2 -2
  315. package/dist/esm/langfuse.mjs +60 -76
  316. package/dist/esm/langfuse.mjs.map +1 -1
  317. package/dist/esm/langfuseToolOutputTracing.mjs +267 -395
  318. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
  319. package/dist/esm/llm/anthropic/index.mjs +432 -559
  320. package/dist/esm/llm/anthropic/index.mjs.map +1 -1
  321. package/dist/esm/llm/anthropic/types.mjs +23 -45
  322. package/dist/esm/llm/anthropic/types.mjs.map +1 -1
  323. package/dist/esm/llm/anthropic/utils/message_inputs.mjs +439 -725
  324. package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
  325. package/dist/esm/llm/anthropic/utils/message_outputs.mjs +171 -253
  326. package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
  327. package/dist/esm/llm/anthropic/utils/output_parsers.mjs +3 -0
  328. package/dist/esm/llm/anthropic/utils/tools.mjs +12 -24
  329. package/dist/esm/llm/anthropic/utils/tools.mjs.map +1 -1
  330. package/dist/esm/llm/bedrock/index.mjs +195 -238
  331. package/dist/esm/llm/bedrock/index.mjs.map +1 -1
  332. package/dist/esm/llm/bedrock/toolCache.mjs +84 -104
  333. package/dist/esm/llm/bedrock/toolCache.mjs.map +1 -1
  334. package/dist/esm/llm/bedrock/utils/index.mjs +3 -0
  335. package/dist/esm/llm/bedrock/utils/message_inputs.mjs +357 -618
  336. package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
  337. package/dist/esm/llm/bedrock/utils/message_outputs.mjs +105 -147
  338. package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
  339. package/dist/esm/llm/fake.mjs +86 -94
  340. package/dist/esm/llm/fake.mjs.map +1 -1
  341. package/dist/esm/llm/google/index.mjs +183 -235
  342. package/dist/esm/llm/google/index.mjs.map +1 -1
  343. package/dist/esm/llm/google/utils/common.mjs +397 -666
  344. package/dist/esm/llm/google/utils/common.mjs.map +1 -1
  345. package/dist/esm/llm/google/utils/zod_to_genai_parameters.mjs +3 -0
  346. package/dist/esm/llm/init.mjs +44 -51
  347. package/dist/esm/llm/init.mjs.map +1 -1
  348. package/dist/esm/llm/invoke.mjs +142 -180
  349. package/dist/esm/llm/invoke.mjs.map +1 -1
  350. package/dist/esm/llm/openai/index.mjs +991 -1271
  351. package/dist/esm/llm/openai/index.mjs.map +1 -1
  352. package/dist/esm/llm/openai/utils/index.mjs +188 -312
  353. package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
  354. package/dist/esm/llm/openrouter/index.mjs +102 -151
  355. package/dist/esm/llm/openrouter/index.mjs.map +1 -1
  356. package/dist/esm/llm/openrouter/toolCache.mjs +35 -42
  357. package/dist/esm/llm/openrouter/toolCache.mjs.map +1 -1
  358. package/dist/esm/llm/providers.mjs +29 -34
  359. package/dist/esm/llm/providers.mjs.map +1 -1
  360. package/dist/esm/llm/request.mjs +20 -31
  361. package/dist/esm/llm/request.mjs.map +1 -1
  362. package/dist/esm/llm/vertexai/index.mjs +427 -449
  363. package/dist/esm/llm/vertexai/index.mjs.map +1 -1
  364. package/dist/esm/main.mjs +99 -87
  365. package/dist/esm/messages/anthropicToolCache.mjs +68 -117
  366. package/dist/esm/messages/anthropicToolCache.mjs.map +1 -1
  367. package/dist/esm/messages/cache.mjs +305 -416
  368. package/dist/esm/messages/cache.mjs.map +1 -1
  369. package/dist/esm/messages/content.mjs +36 -47
  370. package/dist/esm/messages/content.mjs.map +1 -1
  371. package/dist/esm/messages/contextPruning.mjs +112 -143
  372. package/dist/esm/messages/contextPruning.mjs.map +1 -1
  373. package/dist/esm/messages/contextPruningSettings.mjs +36 -44
  374. package/dist/esm/messages/contextPruningSettings.mjs.map +1 -1
  375. package/dist/esm/messages/core.mjs +254 -393
  376. package/dist/esm/messages/core.mjs.map +1 -1
  377. package/dist/esm/messages/format.mjs +902 -1383
  378. package/dist/esm/messages/format.mjs.map +1 -1
  379. package/dist/esm/messages/ids.mjs +16 -18
  380. package/dist/esm/messages/ids.mjs.map +1 -1
  381. package/dist/esm/messages/index.mjs +13 -0
  382. package/dist/esm/messages/langchain.mjs +18 -16
  383. package/dist/esm/messages/langchain.mjs.map +1 -1
  384. package/dist/esm/messages/prune.mjs +1053 -1514
  385. package/dist/esm/messages/prune.mjs.map +1 -1
  386. package/dist/esm/messages/recency.mjs +77 -93
  387. package/dist/esm/messages/recency.mjs.map +1 -1
  388. package/dist/esm/messages/reducer.mjs +63 -76
  389. package/dist/esm/messages/reducer.mjs.map +1 -1
  390. package/dist/esm/messages/tools.mjs +49 -75
  391. package/dist/esm/messages/tools.mjs.map +1 -1
  392. package/dist/esm/openai/index.mjs +170 -215
  393. package/dist/esm/openai/index.mjs.map +1 -1
  394. package/dist/esm/responses/index.mjs +301 -389
  395. package/dist/esm/responses/index.mjs.map +1 -1
  396. package/dist/esm/run.mjs +903 -1111
  397. package/dist/esm/run.mjs.map +1 -1
  398. package/dist/esm/session/AgentSession.mjs +806 -985
  399. package/dist/esm/session/AgentSession.mjs.map +1 -1
  400. package/dist/esm/session/JsonlSessionStore.mjs +326 -407
  401. package/dist/esm/session/JsonlSessionStore.mjs.map +1 -1
  402. package/dist/esm/session/handlers.mjs +192 -206
  403. package/dist/esm/session/handlers.mjs.map +1 -1
  404. package/dist/esm/session/ids.mjs +9 -8
  405. package/dist/esm/session/ids.mjs.map +1 -1
  406. package/dist/esm/session/index.mjs +5 -0
  407. package/dist/esm/session/messageSerialization.mjs +94 -154
  408. package/dist/esm/session/messageSerialization.mjs.map +1 -1
  409. package/dist/esm/splitStream.mjs +147 -204
  410. package/dist/esm/splitStream.mjs.map +1 -1
  411. package/dist/esm/stream.mjs +854 -1341
  412. package/dist/esm/stream.mjs.map +1 -1
  413. package/dist/esm/summarization/index.mjs +57 -99
  414. package/dist/esm/summarization/index.mjs.map +1 -1
  415. package/dist/esm/summarization/node.mjs +640 -790
  416. package/dist/esm/summarization/node.mjs.map +1 -1
  417. package/dist/esm/tools/BashExecutor.mjs +103 -129
  418. package/dist/esm/tools/BashExecutor.mjs.map +1 -1
  419. package/dist/esm/tools/BashProgrammaticToolCalling.mjs +162 -239
  420. package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
  421. package/dist/esm/tools/Calculator.mjs +34 -36
  422. package/dist/esm/tools/Calculator.mjs.map +1 -1
  423. package/dist/esm/tools/CodeExecutor.mjs +123 -164
  424. package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
  425. package/dist/esm/tools/CodeSessionFileSummary.mjs +36 -44
  426. package/dist/esm/tools/CodeSessionFileSummary.mjs.map +1 -1
  427. package/dist/esm/tools/ProgrammaticToolCalling.mjs +454 -644
  428. package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
  429. package/dist/esm/tools/ReadFile.mjs +17 -18
  430. package/dist/esm/tools/ReadFile.mjs.map +1 -1
  431. package/dist/esm/tools/SkillTool.mjs +26 -25
  432. package/dist/esm/tools/SkillTool.mjs.map +1 -1
  433. package/dist/esm/tools/SubagentTool.mjs +59 -59
  434. package/dist/esm/tools/SubagentTool.mjs.map +1 -1
  435. package/dist/esm/tools/ToolNode.mjs +2107 -2684
  436. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  437. package/dist/esm/tools/ToolSearch.mjs +659 -804
  438. package/dist/esm/tools/ToolSearch.mjs.map +1 -1
  439. package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs +248 -338
  440. package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs.map +1 -1
  441. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +170 -195
  442. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -1
  443. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +424 -517
  444. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -1
  445. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +91 -122
  446. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -1
  447. package/dist/esm/tools/cloudflare/index.mjs +5 -0
  448. package/dist/esm/tools/eagerEventExecution.mjs +75 -96
  449. package/dist/esm/tools/eagerEventExecution.mjs.map +1 -1
  450. package/dist/esm/tools/handlers.mjs +200 -260
  451. package/dist/esm/tools/handlers.mjs.map +1 -1
  452. package/dist/esm/tools/local/CompileCheckTool.mjs +150 -210
  453. package/dist/esm/tools/local/CompileCheckTool.mjs.map +1 -1
  454. package/dist/esm/tools/local/FileCheckpointer.mjs +77 -83
  455. package/dist/esm/tools/local/FileCheckpointer.mjs.map +1 -1
  456. package/dist/esm/tools/local/LocalCodingTools.mjs +760 -1017
  457. package/dist/esm/tools/local/LocalCodingTools.mjs.map +1 -1
  458. package/dist/esm/tools/local/LocalExecutionEngine.mjs +663 -936
  459. package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
  460. package/dist/esm/tools/local/LocalExecutionTools.mjs +49 -90
  461. package/dist/esm/tools/local/LocalExecutionTools.mjs.map +1 -1
  462. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +283 -349
  463. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  464. package/dist/esm/tools/local/attachments.mjs +108 -163
  465. package/dist/esm/tools/local/attachments.mjs.map +1 -1
  466. package/dist/esm/tools/local/bashAst.mjs +99 -111
  467. package/dist/esm/tools/local/bashAst.mjs.map +1 -1
  468. package/dist/esm/tools/local/editStrategies.mjs +126 -167
  469. package/dist/esm/tools/local/editStrategies.mjs.map +1 -1
  470. package/dist/esm/tools/local/index.mjs +13 -0
  471. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +136 -216
  472. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  473. package/dist/esm/tools/local/syntaxCheck.mjs +138 -155
  474. package/dist/esm/tools/local/syntaxCheck.mjs.map +1 -1
  475. package/dist/esm/tools/local/textEncoding.mjs +25 -21
  476. package/dist/esm/tools/local/textEncoding.mjs.map +1 -1
  477. package/dist/esm/tools/local/workspaceFS.mjs +38 -44
  478. package/dist/esm/tools/local/workspaceFS.mjs.map +1 -1
  479. package/dist/esm/tools/ptcTimeout.mjs +27 -42
  480. package/dist/esm/tools/ptcTimeout.mjs.map +1 -1
  481. package/dist/esm/tools/schema.mjs +24 -21
  482. package/dist/esm/tools/schema.mjs.map +1 -1
  483. package/dist/esm/tools/search/anthropic.mjs +24 -31
  484. package/dist/esm/tools/search/anthropic.mjs.map +1 -1
  485. package/dist/esm/tools/search/content.mjs +93 -116
  486. package/dist/esm/tools/search/content.mjs.map +1 -1
  487. package/dist/esm/tools/search/firecrawl.mjs +139 -169
  488. package/dist/esm/tools/search/firecrawl.mjs.map +1 -1
  489. package/dist/esm/tools/search/format.mjs +128 -194
  490. package/dist/esm/tools/search/format.mjs.map +1 -1
  491. package/dist/esm/tools/search/highlights.mjs +165 -230
  492. package/dist/esm/tools/search/highlights.mjs.map +1 -1
  493. package/dist/esm/tools/search/index.mjs +3 -0
  494. package/dist/esm/tools/search/rerankers.mjs +149 -168
  495. package/dist/esm/tools/search/rerankers.mjs.map +1 -1
  496. package/dist/esm/tools/search/schema.mjs +39 -37
  497. package/dist/esm/tools/search/schema.mjs.map +1 -1
  498. package/dist/esm/tools/search/search.mjs +426 -528
  499. package/dist/esm/tools/search/search.mjs.map +1 -1
  500. package/dist/esm/tools/search/serper-scraper.mjs +104 -124
  501. package/dist/esm/tools/search/serper-scraper.mjs.map +1 -1
  502. package/dist/esm/tools/search/tavily-scraper.mjs +127 -178
  503. package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -1
  504. package/dist/esm/tools/search/tavily-search.mjs +293 -357
  505. package/dist/esm/tools/search/tavily-search.mjs.map +1 -1
  506. package/dist/esm/tools/search/tool.mjs +259 -297
  507. package/dist/esm/tools/search/tool.mjs.map +1 -1
  508. package/dist/esm/tools/search/utils.mjs +74 -115
  509. package/dist/esm/tools/search/utils.mjs.map +1 -1
  510. package/dist/esm/tools/skillCatalog.mjs +54 -70
  511. package/dist/esm/tools/skillCatalog.mjs.map +1 -1
  512. package/dist/esm/tools/streamedToolCallSeals.mjs +19 -31
  513. package/dist/esm/tools/streamedToolCallSeals.mjs.map +1 -1
  514. package/dist/esm/tools/subagent/SubagentExecutor.mjs +612 -768
  515. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  516. package/dist/esm/tools/subagent/index.mjs +2 -0
  517. package/dist/esm/tools/toolOutputReferences.mjs +523 -624
  518. package/dist/esm/tools/toolOutputReferences.mjs.map +1 -1
  519. package/dist/esm/utils/callbacks.mjs +11 -19
  520. package/dist/esm/utils/callbacks.mjs.map +1 -1
  521. package/dist/esm/utils/errors.mjs +70 -93
  522. package/dist/esm/utils/errors.mjs.map +1 -1
  523. package/dist/esm/utils/events.mjs +32 -40
  524. package/dist/esm/utils/events.mjs.map +1 -1
  525. package/dist/esm/utils/graph.mjs +8 -10
  526. package/dist/esm/utils/graph.mjs.map +1 -1
  527. package/dist/esm/utils/handlers.mjs +60 -80
  528. package/dist/esm/utils/handlers.mjs.map +1 -1
  529. package/dist/esm/utils/index.mjs +10 -0
  530. package/dist/esm/utils/llm.mjs +19 -25
  531. package/dist/esm/utils/llm.mjs.map +1 -1
  532. package/dist/esm/utils/misc.mjs +30 -44
  533. package/dist/esm/utils/misc.mjs.map +1 -1
  534. package/dist/esm/utils/run.mjs +50 -64
  535. package/dist/esm/utils/run.mjs.map +1 -1
  536. package/dist/esm/utils/schema.mjs +11 -17
  537. package/dist/esm/utils/schema.mjs.map +1 -1
  538. package/dist/esm/utils/title.mjs +71 -104
  539. package/dist/esm/utils/title.mjs.map +1 -1
  540. package/dist/esm/utils/tokens.mjs +186 -281
  541. package/dist/esm/utils/tokens.mjs.map +1 -1
  542. package/dist/esm/utils/truncation.mjs +95 -112
  543. package/dist/esm/utils/truncation.mjs.map +1 -1
  544. package/dist/types/tools/search/tool.d.ts +17 -0
  545. package/dist/types/tools/search/types.d.ts +4 -0
  546. package/package.json +4 -10
  547. package/src/tools/search/highlights.ts +9 -1
  548. package/src/tools/search/search.ts +41 -3
  549. package/src/tools/search/source-processing.test.ts +373 -0
  550. package/src/tools/search/tool.ts +22 -2
  551. package/src/tools/search/types.ts +4 -0
  552. package/dist/cjs/langchain/google-common.cjs.map +0 -1
  553. package/dist/cjs/langchain/index.cjs.map +0 -1
  554. package/dist/cjs/langchain/language_models/chat_models.cjs.map +0 -1
  555. package/dist/cjs/langchain/messages/tool.cjs.map +0 -1
  556. package/dist/cjs/langchain/messages.cjs.map +0 -1
  557. package/dist/cjs/langchain/openai.cjs.map +0 -1
  558. package/dist/cjs/langchain/prompts.cjs.map +0 -1
  559. package/dist/cjs/langchain/runnables.cjs.map +0 -1
  560. package/dist/cjs/langchain/tools.cjs.map +0 -1
  561. package/dist/cjs/langchain/utils/env.cjs.map +0 -1
  562. package/dist/cjs/main.cjs.map +0 -1
  563. package/dist/esm/langchain/google-common.mjs.map +0 -1
  564. package/dist/esm/langchain/index.mjs.map +0 -1
  565. package/dist/esm/langchain/language_models/chat_models.mjs.map +0 -1
  566. package/dist/esm/langchain/messages/tool.mjs.map +0 -1
  567. package/dist/esm/langchain/messages.mjs.map +0 -1
  568. package/dist/esm/langchain/openai.mjs.map +0 -1
  569. package/dist/esm/langchain/prompts.mjs.map +0 -1
  570. package/dist/esm/langchain/runnables.mjs.map +0 -1
  571. package/dist/esm/langchain/tools.mjs.map +0 -1
  572. package/dist/esm/langchain/utils/env.mjs.map +0 -1
  573. package/dist/esm/main.mjs.map +0 -1
@@ -1,1104 +1,844 @@
1
- 'use strict';
2
-
3
- var path = require('path');
4
- var diff = require('diff');
5
- var tools = require('@langchain/core/tools');
6
- var LocalProgrammaticToolCalling = require('./LocalProgrammaticToolCalling.cjs');
7
- var LocalExecutionEngine = require('./LocalExecutionEngine.cjs');
8
- var LocalExecutionTools = require('./LocalExecutionTools.cjs');
9
- var CompileCheckTool = require('./CompileCheckTool.cjs');
10
- var attachments = require('./attachments.cjs');
11
- var FileCheckpointer = require('./FileCheckpointer.cjs');
12
- var editStrategies = require('./editStrategies.cjs');
13
- var textEncoding = require('./textEncoding.cjs');
14
- var syntaxCheck = require('./syntaxCheck.cjs');
15
- var _enum = require('../../common/enum.cjs');
16
-
17
- const MAX_READ_CHARS = 256000;
1
+ require("../../common/enum.cjs");
2
+ require("../../common/index.cjs");
3
+ const require_LocalExecutionEngine = require("./LocalExecutionEngine.cjs");
4
+ const require_CompileCheckTool = require("./CompileCheckTool.cjs");
5
+ const require_FileCheckpointer = require("./FileCheckpointer.cjs");
6
+ const require_LocalProgrammaticToolCalling = require("./LocalProgrammaticToolCalling.cjs");
7
+ const require_LocalExecutionTools = require("./LocalExecutionTools.cjs");
8
+ const require_attachments = require("./attachments.cjs");
9
+ const require_editStrategies = require("./editStrategies.cjs");
10
+ const require_textEncoding = require("./textEncoding.cjs");
11
+ const require_syntaxCheck = require("./syntaxCheck.cjs");
12
+ let _langchain_core_tools = require("@langchain/core/tools");
13
+ let path = require("path");
14
+ let diff = require("diff");
15
+ //#region src/tools/local/LocalCodingTools.ts
16
+ const MAX_READ_CHARS = 256e3;
18
17
  const DEFAULT_MAX_RESULTS = 200;
19
18
  const DEFAULT_MAX_READ_BYTES = 10 * 1024 * 1024;
20
- const BINARY_DETECTION_BYTES = 8000;
19
+ const BINARY_DETECTION_BYTES = 8e3;
21
20
  /**
22
- * Tool name aliases retained for back-compat with consumers that imported
23
- * the per-file `Local*ToolName` constants. The canonical names live on
24
- * `Constants.*` (see `src/common/enum.ts`); these aliases just point at
25
- * them so a typo upstream gets caught at the type level.
26
- */
27
- const LocalWriteFileToolName = _enum.Constants.WRITE_FILE;
28
- const LocalEditFileToolName = _enum.Constants.EDIT_FILE;
29
- const LocalGrepSearchToolName = _enum.Constants.GREP_SEARCH;
30
- const LocalGlobSearchToolName = _enum.Constants.GLOB_SEARCH;
31
- const LocalListDirectoryToolName = _enum.Constants.LIST_DIRECTORY;
21
+ * Tool name aliases retained for back-compat with consumers that imported
22
+ * the per-file `Local*ToolName` constants. The canonical names live on
23
+ * `Constants.*` (see `src/common/enum.ts`); these aliases just point at
24
+ * them so a typo upstream gets caught at the type level.
25
+ */
26
+ const LocalWriteFileToolName = "write_file";
27
+ const LocalEditFileToolName = "edit_file";
28
+ const LocalGrepSearchToolName = "grep_search";
29
+ const LocalGlobSearchToolName = "glob_search";
30
+ const LocalListDirectoryToolName = "list_directory";
32
31
  const LocalReadFileToolSchema = {
33
- type: 'object',
34
- properties: {
35
- file_path: {
36
- type: 'string',
37
- description: 'Path to a local file, relative to the configured cwd unless absolute paths are allowed.',
38
- },
39
- offset: {
40
- type: 'integer',
41
- description: 'Optional 1-indexed line offset for large files.',
42
- },
43
- limit: {
44
- type: 'integer',
45
- description: 'Optional maximum number of lines to return.',
46
- },
47
- },
48
- required: ['file_path'],
32
+ type: "object",
33
+ properties: {
34
+ file_path: {
35
+ type: "string",
36
+ description: "Path to a local file, relative to the configured cwd unless absolute paths are allowed."
37
+ },
38
+ offset: {
39
+ type: "integer",
40
+ description: "Optional 1-indexed line offset for large files."
41
+ },
42
+ limit: {
43
+ type: "integer",
44
+ description: "Optional maximum number of lines to return."
45
+ }
46
+ },
47
+ required: ["file_path"]
49
48
  };
50
49
  const LocalWriteFileToolSchema = {
51
- type: 'object',
52
- properties: {
53
- file_path: {
54
- type: 'string',
55
- description: 'Path to write, relative to the configured cwd unless absolute paths are allowed.',
56
- },
57
- content: {
58
- type: 'string',
59
- description: 'Complete file contents to write.',
60
- },
61
- },
62
- required: ['file_path', 'content'],
50
+ type: "object",
51
+ properties: {
52
+ file_path: {
53
+ type: "string",
54
+ description: "Path to write, relative to the configured cwd unless absolute paths are allowed."
55
+ },
56
+ content: {
57
+ type: "string",
58
+ description: "Complete file contents to write."
59
+ }
60
+ },
61
+ required: ["file_path", "content"]
63
62
  };
64
63
  const LocalEditFileToolSchema = {
65
- type: 'object',
66
- properties: {
67
- file_path: {
68
- type: 'string',
69
- description: 'Path to edit, relative to the configured cwd unless absolute paths are allowed.',
70
- },
71
- old_text: {
72
- type: 'string',
73
- description: 'Exact text to replace. Must appear exactly once.',
74
- },
75
- new_text: {
76
- type: 'string',
77
- description: 'Replacement text.',
78
- },
79
- edits: {
80
- type: 'array',
81
- description: 'Optional batch of exact replacements. Each old_text must appear exactly once in the original file.',
82
- items: {
83
- type: 'object',
84
- properties: {
85
- old_text: { type: 'string' },
86
- new_text: { type: 'string' },
87
- },
88
- required: ['old_text', 'new_text'],
89
- },
90
- },
91
- },
92
- required: ['file_path'],
64
+ type: "object",
65
+ properties: {
66
+ file_path: {
67
+ type: "string",
68
+ description: "Path to edit, relative to the configured cwd unless absolute paths are allowed."
69
+ },
70
+ old_text: {
71
+ type: "string",
72
+ description: "Exact text to replace. Must appear exactly once."
73
+ },
74
+ new_text: {
75
+ type: "string",
76
+ description: "Replacement text."
77
+ },
78
+ edits: {
79
+ type: "array",
80
+ description: "Optional batch of exact replacements. Each old_text must appear exactly once in the original file.",
81
+ items: {
82
+ type: "object",
83
+ properties: {
84
+ old_text: { type: "string" },
85
+ new_text: { type: "string" }
86
+ },
87
+ required: ["old_text", "new_text"]
88
+ }
89
+ }
90
+ },
91
+ required: ["file_path"]
93
92
  };
94
93
  const LocalGrepSearchToolSchema = {
95
- type: 'object',
96
- properties: {
97
- pattern: {
98
- type: 'string',
99
- description: 'Regex pattern to search for.',
100
- },
101
- path: {
102
- type: 'string',
103
- description: 'Directory or file to search. Defaults to cwd.',
104
- },
105
- glob: {
106
- type: 'string',
107
- description: 'Optional file glob passed to rg -g.',
108
- },
109
- max_results: {
110
- type: 'integer',
111
- description: 'Maximum matching lines to return.',
112
- },
113
- },
114
- required: ['pattern'],
94
+ type: "object",
95
+ properties: {
96
+ pattern: {
97
+ type: "string",
98
+ description: "Regex pattern to search for."
99
+ },
100
+ path: {
101
+ type: "string",
102
+ description: "Directory or file to search. Defaults to cwd."
103
+ },
104
+ glob: {
105
+ type: "string",
106
+ description: "Optional file glob passed to rg -g."
107
+ },
108
+ max_results: {
109
+ type: "integer",
110
+ description: "Maximum matching lines to return."
111
+ }
112
+ },
113
+ required: ["pattern"]
115
114
  };
116
115
  const LocalGlobSearchToolSchema = {
117
- type: 'object',
118
- properties: {
119
- pattern: {
120
- type: 'string',
121
- description: 'File glob pattern, for example "src/**/*.ts".',
122
- },
123
- path: {
124
- type: 'string',
125
- description: 'Directory to search. Defaults to cwd.',
126
- },
127
- max_results: {
128
- type: 'integer',
129
- description: 'Maximum file paths to return.',
130
- },
131
- },
132
- required: ['pattern'],
116
+ type: "object",
117
+ properties: {
118
+ pattern: {
119
+ type: "string",
120
+ description: "File glob pattern, for example \"src/**/*.ts\"."
121
+ },
122
+ path: {
123
+ type: "string",
124
+ description: "Directory to search. Defaults to cwd."
125
+ },
126
+ max_results: {
127
+ type: "integer",
128
+ description: "Maximum file paths to return."
129
+ }
130
+ },
131
+ required: ["pattern"]
133
132
  };
134
133
  const LocalListDirectoryToolSchema = {
135
- type: 'object',
136
- properties: {
137
- path: {
138
- type: 'string',
139
- description: 'Directory to list. Defaults to cwd.',
140
- },
141
- },
134
+ type: "object",
135
+ properties: { path: {
136
+ type: "string",
137
+ description: "Directory to list. Defaults to cwd."
138
+ } }
142
139
  };
143
140
  function lineWindow(content, offset, limit) {
144
- const start = Math.max((offset ?? 1) - 1, 0);
145
- // Avoid splitting the whole file when the caller asked for a small
146
- // window. For a 10 MB file with `offset: 1, limit: 10`, the prior
147
- // `content.split('\n')` allocated millions of strings to throw all
148
- // but 10 away. We walk newline indices directly: O(start + limit)
149
- // instead of O(file). When `limit` is omitted, fall back to the
150
- // simple split — it's the same amount of work either way.
151
- if (limit == null || limit <= 0) {
152
- const lines = content.split('\n');
153
- const selected = lines.slice(start);
154
- const numbered = selected
155
- .map((line, index) => `${String(start + index + 1).padStart(6, ' ')}\t${line}`)
156
- .join('\n');
157
- return {
158
- text: LocalExecutionEngine.truncateLocalOutput(numbered, MAX_READ_CHARS),
159
- truncated: numbered.length > MAX_READ_CHARS,
160
- };
161
- }
162
- // Walk to the start line by counting newlines.
163
- let cursor = 0;
164
- for (let i = 0; i < start; i++) {
165
- const next = content.indexOf('\n', cursor);
166
- if (next === -1) {
167
- // File has fewer lines than `offset` — return empty window.
168
- return { text: '', truncated: false };
169
- }
170
- cursor = next + 1;
171
- }
172
- // Collect up to `limit` lines from `cursor`.
173
- const out = [];
174
- let pos = cursor;
175
- let exhausted = true;
176
- for (let k = 0; k < limit; k++) {
177
- const next = content.indexOf('\n', pos);
178
- if (next === -1) {
179
- out.push(content.slice(pos));
180
- break;
181
- }
182
- out.push(content.slice(pos, next));
183
- pos = next + 1;
184
- if (k === limit - 1 && pos < content.length) {
185
- exhausted = false;
186
- }
187
- }
188
- const numbered = out
189
- .map((text, index) => `${String(start + index + 1).padStart(6, ' ')}\t${text}`)
190
- .join('\n');
191
- return {
192
- text: LocalExecutionEngine.truncateLocalOutput(numbered, MAX_READ_CHARS),
193
- truncated: !exhausted || numbered.length > MAX_READ_CHARS,
194
- };
141
+ const start = Math.max((offset ?? 1) - 1, 0);
142
+ if (limit == null || limit <= 0) {
143
+ const numbered = content.split("\n").slice(start).map((line, index) => `${String(start + index + 1).padStart(6, " ")}\t${line}`).join("\n");
144
+ return {
145
+ text: require_LocalExecutionEngine.truncateLocalOutput(numbered, MAX_READ_CHARS),
146
+ truncated: numbered.length > MAX_READ_CHARS
147
+ };
148
+ }
149
+ let cursor = 0;
150
+ for (let i = 0; i < start; i++) {
151
+ const next = content.indexOf("\n", cursor);
152
+ if (next === -1) return {
153
+ text: "",
154
+ truncated: false
155
+ };
156
+ cursor = next + 1;
157
+ }
158
+ const out = [];
159
+ let pos = cursor;
160
+ let exhausted = true;
161
+ for (let k = 0; k < limit; k++) {
162
+ const next = content.indexOf("\n", pos);
163
+ if (next === -1) {
164
+ out.push(content.slice(pos));
165
+ break;
166
+ }
167
+ out.push(content.slice(pos, next));
168
+ pos = next + 1;
169
+ if (k === limit - 1 && pos < content.length) exhausted = false;
170
+ }
171
+ const numbered = out.map((text, index) => `${String(start + index + 1).padStart(6, " ")}\t${text}`).join("\n");
172
+ return {
173
+ text: require_LocalExecutionEngine.truncateLocalOutput(numbered, MAX_READ_CHARS),
174
+ truncated: !exhausted || numbered.length > MAX_READ_CHARS
175
+ };
195
176
  }
196
- const MAX_DIFF_CHARS = 4000;
197
- async function maybeRunSyntaxCheck(path, config) {
198
- const mode = config.postEditSyntaxCheck ?? 'off';
199
- if (mode === 'off')
200
- return undefined;
201
- const outcome = await syntaxCheck.runPostEditSyntaxCheck(path, config);
202
- if (outcome == null)
203
- return undefined;
204
- return { mode, outcome };
177
+ const MAX_DIFF_CHARS = 4e3;
178
+ async function maybeRunSyntaxCheck(path$1, config) {
179
+ const mode = config.postEditSyntaxCheck ?? "off";
180
+ if (mode === "off") return void 0;
181
+ const outcome = await require_syntaxCheck.runPostEditSyntaxCheck(path$1, config);
182
+ if (outcome == null) return void 0;
183
+ return {
184
+ mode,
185
+ outcome
186
+ };
205
187
  }
206
188
  function appendSyntaxCheckSummary(base, run) {
207
- if (run == null)
208
- return base;
209
- if (run.outcome.ok)
210
- return base;
211
- const banner = run.mode === 'strict'
212
- ? `\n\n[syntax-check FAILED via ${run.outcome.checker}]\n`
213
- : `\n\n[syntax-check warning via ${run.outcome.checker}]\n`;
214
- return `${base}${banner}${run.outcome.output}`;
189
+ if (run == null) return base;
190
+ if (run.outcome.ok) return base;
191
+ return `${base}${run.mode === "strict" ? `\n\n[syntax-check FAILED via ${run.outcome.checker}]\n` : `\n\n[syntax-check warning via ${run.outcome.checker}]\n`}${run.outcome.output}`;
215
192
  }
216
193
  /**
217
- * Revert a write_file/edit_file mutation in `postEditSyntaxCheck:
218
- * 'strict'` mode after the post-write syntax check failed. Strict
219
- * mode advertises a safety gate, so leaving the corrupted file on
220
- * disk + throwing is a half-broken contract — the model "reacts" to
221
- * the error but the next call sees broken on-disk state. Codex P2
222
- * [49]. Best-effort: a swallowed error here means the workspace is
223
- * still in the bad post-write state, but we still throw the
224
- * original syntax-check error so the caller knows.
225
- *
226
- * - If the file existed pre-write: restore the previous bytes with
227
- * the original encoding.
228
- * - If the file is brand-new: unlink it.
229
- */
230
- async function revertStrictWrite(fs, path, existed, before, encoding) {
231
- try {
232
- if (existed) {
233
- // encodeFile uses encoding.{hasBom,newline} to restore the
234
- // on-disk shape; the `text` field is overridden by the
235
- // explicit `before` arg we pass in.
236
- await fs.writeFile(path, textEncoding.encodeFile(before, { ...encoding, text: before }), 'utf8');
237
- }
238
- else {
239
- await fs.unlink(path);
240
- }
241
- }
242
- catch {
243
- /* best-effort: caller still sees the original syntax error */
244
- }
194
+ * Revert a write_file/edit_file mutation in `postEditSyntaxCheck:
195
+ * 'strict'` mode after the post-write syntax check failed. Strict
196
+ * mode advertises a safety gate, so leaving the corrupted file on
197
+ * disk + throwing is a half-broken contract — the model "reacts" to
198
+ * the error but the next call sees broken on-disk state. Codex P2
199
+ * [49]. Best-effort: a swallowed error here means the workspace is
200
+ * still in the bad post-write state, but we still throw the
201
+ * original syntax-check error so the caller knows.
202
+ *
203
+ * - If the file existed pre-write: restore the previous bytes with
204
+ * the original encoding.
205
+ * - If the file is brand-new: unlink it.
206
+ */
207
+ async function revertStrictWrite(fs, path$2, existed, before, encoding) {
208
+ try {
209
+ if (existed) await fs.writeFile(path$2, require_textEncoding.encodeFile(before, {
210
+ ...encoding,
211
+ text: before
212
+ }), "utf8");
213
+ else await fs.unlink(path$2);
214
+ } catch {}
245
215
  }
246
216
  function summariseDiff(filePath, before, after) {
247
- if (before === after) {
248
- return '(no textual changes)';
249
- }
250
- const name = path.basename(filePath);
251
- const patch = diff.createTwoFilesPatch(name, name, before, after, '', '', {
252
- context: 3,
253
- });
254
- if (patch.length <= MAX_DIFF_CHARS) {
255
- return patch;
256
- }
257
- return (patch.slice(0, MAX_DIFF_CHARS) +
258
- `\n[... diff truncated, ${patch.length - MAX_DIFF_CHARS} more chars ...]`);
217
+ if (before === after) return "(no textual changes)";
218
+ const name = (0, path.basename)(filePath);
219
+ const patch = (0, diff.createTwoFilesPatch)(name, name, before, after, "", "", { context: 3 });
220
+ if (patch.length <= MAX_DIFF_CHARS) return patch;
221
+ return patch.slice(0, MAX_DIFF_CHARS) + `\n[... diff truncated, ${patch.length - MAX_DIFF_CHARS} more chars ...]`;
259
222
  }
260
223
  function normalizeEdits(input) {
261
- const edits = Array.isArray(input.edits)
262
- ? input.edits.map((edit) => ({
263
- oldText: edit.old_text ?? '',
264
- newText: edit.new_text ?? '',
265
- }))
266
- : [];
267
- if (input.old_text != null || input.new_text != null) {
268
- edits.push({
269
- oldText: input.old_text ?? '',
270
- newText: input.new_text ?? '',
271
- });
272
- }
273
- return edits;
224
+ const edits = Array.isArray(input.edits) ? input.edits.map((edit) => ({
225
+ oldText: edit.old_text ?? "",
226
+ newText: edit.new_text ?? ""
227
+ })) : [];
228
+ if (input.old_text != null || input.new_text != null) edits.push({
229
+ oldText: input.old_text ?? "",
230
+ newText: input.new_text ?? ""
231
+ });
232
+ return edits;
274
233
  }
275
234
  function toolDefinition(name, description, parameters) {
276
- return {
277
- name,
278
- description,
279
- parameters,
280
- allowed_callers: ['direct', 'code_execution'],
281
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
282
- toolType: 'builtin',
283
- };
235
+ return {
236
+ name,
237
+ description,
238
+ parameters,
239
+ allowed_callers: ["direct", "code_execution"],
240
+ responseFormat: "content_and_artifact",
241
+ toolType: "builtin"
242
+ };
284
243
  }
285
- async function looksBinary(path, fs) {
286
- let handle;
287
- try {
288
- handle = await fs.open(path, 'r');
289
- const sample = Buffer.alloc(BINARY_DETECTION_BYTES);
290
- const { bytesRead } = await handle.read(sample, 0, BINARY_DETECTION_BYTES, 0);
291
- for (let i = 0; i < bytesRead; i++) {
292
- if (sample[i] === 0) {
293
- return true;
294
- }
295
- }
296
- return false;
297
- }
298
- finally {
299
- await handle?.close();
300
- }
244
+ async function looksBinary(path$3, fs) {
245
+ let handle;
246
+ try {
247
+ handle = await fs.open(path$3, "r");
248
+ const sample = Buffer.alloc(BINARY_DETECTION_BYTES);
249
+ const { bytesRead } = await handle.read(sample, 0, BINARY_DETECTION_BYTES, 0);
250
+ for (let i = 0; i < bytesRead; i++) if (sample[i] === 0) return true;
251
+ return false;
252
+ } finally {
253
+ await handle?.close();
254
+ }
301
255
  }
302
256
  const DEFAULT_MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
303
257
  function createLocalReadFileTool(config = {}) {
304
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
305
- return tools.tool(async (rawInput) => {
306
- const input = rawInput;
307
- const path = await LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, 'read');
308
- const fileStat = await fs.stat(path);
309
- if (!fileStat.isFile()) {
310
- throw new Error(`Path is not a file: ${input.file_path}`);
311
- }
312
- const maxBytes = Math.max(config.maxReadBytes ?? DEFAULT_MAX_READ_BYTES, 1);
313
- if (fileStat.size > maxBytes) {
314
- const stub = `File is ${fileStat.size} bytes, exceeds the ${maxBytes}-byte read cap. Read a slice via bash (e.g. head/sed) or raise local.maxReadBytes.`;
315
- return [stub, { path, bytes: fileStat.size, truncated: true }];
316
- }
317
- if (await looksBinary(path, fs)) {
318
- const attachmentMode = config.attachReadAttachments ?? 'off';
319
- if (attachmentMode !== 'off') {
320
- const attachment = await attachments.classifyAttachment({
321
- path,
322
- bytes: fileStat.size,
323
- mode: attachmentMode,
324
- maxBytes: config.maxAttachmentBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES,
325
- // Route through the configured WorkspaceFS so a custom
326
- // engine sees the same path semantics as `read_file`
327
- // itself (manual review finding F).
328
- fs,
329
- });
330
- if (attachment.kind === 'image') {
331
- return [
332
- attachments.imageAttachmentContent(path, attachment),
333
- {
334
- path,
335
- bytes: fileStat.size,
336
- mime: attachment.mime,
337
- attachment: 'image',
338
- },
339
- ];
340
- }
341
- if (attachment.kind === 'pdf') {
342
- return [
343
- [
344
- {
345
- type: 'text',
346
- text: `Read ${path} (application/pdf, ${fileStat.size} bytes). PDF attached as base64 data URL; vision-capable models that accept PDF will render it.`,
347
- },
348
- {
349
- type: 'image_url',
350
- image_url: { url: attachment.dataUrl },
351
- },
352
- ],
353
- {
354
- path,
355
- bytes: fileStat.size,
356
- mime: attachment.mime,
357
- attachment: 'pdf',
358
- },
359
- ];
360
- }
361
- if (attachment.kind === 'oversize') {
362
- return [
363
- `Refusing to embed ${attachment.mime} attachment (${attachment.bytes} bytes exceeds ${attachment.maxBytes}-byte cap).`,
364
- {
365
- path,
366
- bytes: fileStat.size,
367
- mime: attachment.mime,
368
- attachment: 'oversize',
369
- },
370
- ];
371
- }
372
- if (attachment.kind === 'binary') {
373
- return [
374
- `Refusing to read binary file (${fileStat.size} bytes, ${attachment.mime}): ${path}`,
375
- {
376
- path,
377
- bytes: fileStat.size,
378
- mime: attachment.mime,
379
- binary: true,
380
- },
381
- ];
382
- }
383
- // text-or-unknown falls through to the text-read path below.
384
- }
385
- else {
386
- return [
387
- `Refusing to read binary file (${fileStat.size} bytes): ${path}`,
388
- { path, bytes: fileStat.size, binary: true },
389
- ];
390
- }
391
- }
392
- const content = await fs.readFile(path, 'utf8');
393
- const result = lineWindow(content, input.offset, input.limit);
394
- return [
395
- result.truncated ? `${result.text}\n[truncated]` : result.text,
396
- { path, bytes: fileStat.size },
397
- ];
398
- }, {
399
- name: _enum.Constants.READ_FILE,
400
- description: 'Read a local text file from the configured working directory with line numbers. ' +
401
- 'When `attachReadAttachments` is enabled (e.g. images-only), reading an image returns an ' +
402
- '`image_url` content block so vision-capable models can see the file directly.',
403
- schema: LocalReadFileToolSchema,
404
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
405
- });
258
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
259
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
260
+ const input = rawInput;
261
+ const path$4 = await require_LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, "read");
262
+ const fileStat = await fs.stat(path$4);
263
+ if (!fileStat.isFile()) throw new Error(`Path is not a file: ${input.file_path}`);
264
+ const maxBytes = Math.max(config.maxReadBytes ?? DEFAULT_MAX_READ_BYTES, 1);
265
+ if (fileStat.size > maxBytes) return [`File is ${fileStat.size} bytes, exceeds the ${maxBytes}-byte read cap. Read a slice via bash (e.g. head/sed) or raise local.maxReadBytes.`, {
266
+ path: path$4,
267
+ bytes: fileStat.size,
268
+ truncated: true
269
+ }];
270
+ if (await looksBinary(path$4, fs)) {
271
+ const attachmentMode = config.attachReadAttachments ?? "off";
272
+ if (attachmentMode !== "off") {
273
+ const attachment = await require_attachments.classifyAttachment({
274
+ path: path$4,
275
+ bytes: fileStat.size,
276
+ mode: attachmentMode,
277
+ maxBytes: config.maxAttachmentBytes ?? DEFAULT_MAX_ATTACHMENT_BYTES,
278
+ fs
279
+ });
280
+ if (attachment.kind === "image") return [require_attachments.imageAttachmentContent(path$4, attachment), {
281
+ path: path$4,
282
+ bytes: fileStat.size,
283
+ mime: attachment.mime,
284
+ attachment: "image"
285
+ }];
286
+ if (attachment.kind === "pdf") return [[{
287
+ type: "text",
288
+ text: `Read ${path$4} (application/pdf, ${fileStat.size} bytes). PDF attached as base64 data URL; vision-capable models that accept PDF will render it.`
289
+ }, {
290
+ type: "image_url",
291
+ image_url: { url: attachment.dataUrl }
292
+ }], {
293
+ path: path$4,
294
+ bytes: fileStat.size,
295
+ mime: attachment.mime,
296
+ attachment: "pdf"
297
+ }];
298
+ if (attachment.kind === "oversize") return [`Refusing to embed ${attachment.mime} attachment (${attachment.bytes} bytes exceeds ${attachment.maxBytes}-byte cap).`, {
299
+ path: path$4,
300
+ bytes: fileStat.size,
301
+ mime: attachment.mime,
302
+ attachment: "oversize"
303
+ }];
304
+ if (attachment.kind === "binary") return [`Refusing to read binary file (${fileStat.size} bytes, ${attachment.mime}): ${path$4}`, {
305
+ path: path$4,
306
+ bytes: fileStat.size,
307
+ mime: attachment.mime,
308
+ binary: true
309
+ }];
310
+ } else return [`Refusing to read binary file (${fileStat.size} bytes): ${path$4}`, {
311
+ path: path$4,
312
+ bytes: fileStat.size,
313
+ binary: true
314
+ }];
315
+ }
316
+ const result = lineWindow(await fs.readFile(path$4, "utf8"), input.offset, input.limit);
317
+ return [result.truncated ? `${result.text}\n[truncated]` : result.text, {
318
+ path: path$4,
319
+ bytes: fileStat.size
320
+ }];
321
+ }, {
322
+ name: "read_file",
323
+ description: "Read a local text file from the configured working directory with line numbers. When `attachReadAttachments` is enabled (e.g. images-only), reading an image returns an `image_url` content block so vision-capable models can see the file directly.",
324
+ schema: LocalReadFileToolSchema,
325
+ responseFormat: "content_and_artifact"
326
+ });
406
327
  }
407
328
  function createLocalWriteFileTool(config = {}, checkpointer) {
408
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
409
- return tools.tool(async (rawInput) => {
410
- const input = rawInput;
411
- if (config.readOnly === true) {
412
- throw new Error('write_file is blocked in read-only local mode.');
413
- }
414
- const path$1 = await LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, 'write');
415
- if (checkpointer != null) {
416
- await checkpointer.captureBeforeWrite(path$1);
417
- }
418
- let before = '';
419
- let encoding = { text: '', hasBom: false, newline: '\n' };
420
- let existed = false;
421
- try {
422
- const raw = await fs.readFile(path$1, 'utf8');
423
- const decoded = textEncoding.decodeFile(raw);
424
- before = decoded.text;
425
- encoding = decoded;
426
- existed = true;
427
- }
428
- catch {
429
- existed = false;
430
- }
431
- await fs.mkdir(path.dirname(path$1), { recursive: true });
432
- const finalText = textEncoding.encodeFile(input.content, encoding);
433
- await fs.writeFile(path$1, finalText, 'utf8');
434
- const syntax = await maybeRunSyntaxCheck(path$1, config);
435
- const diff = existed
436
- ? summariseDiff(path$1, before, input.content)
437
- : `(new file, ${input.content.length} chars)`;
438
- const baseSummary = existed
439
- ? `Overwrote ${path$1} (${input.content.length} chars). Diff:\n${diff}`
440
- : `Created ${path$1} (${input.content.length} chars).`;
441
- const summary = appendSyntaxCheckSummary(baseSummary, syntax);
442
- if (syntax?.outcome.ok === false && syntax.mode === 'strict') {
443
- // Roll back the write so strict mode is an actual gate, not
444
- // "fail the call AND leave the corrupted file on disk".
445
- // Codex P2 [49].
446
- await revertStrictWrite(fs, path$1, existed, before, encoding);
447
- throw new Error(`write_file syntax check failed (${syntax.outcome.checker}); reverted to pre-write state.\n${syntax.outcome.output}`);
448
- }
449
- return [
450
- summary,
451
- {
452
- path: path$1,
453
- bytes: finalText.length,
454
- new_file: !existed,
455
- newline: encoding.newline === '\r\n' ? 'CRLF' : 'LF',
456
- had_bom: encoding.hasBom,
457
- ...(syntax != null && syntax.outcome.ok === false
458
- ? { syntax_error: syntax.outcome.checker }
459
- : {}),
460
- },
461
- ];
462
- }, {
463
- name: LocalWriteFileToolName,
464
- description: 'Create or overwrite a local text file in the configured working directory. ' +
465
- 'Preserves the existing BOM and line endings when overwriting; defaults to LF without BOM for new files. ' +
466
- 'Returns a unified diff of the changes when overwriting.',
467
- schema: LocalWriteFileToolSchema,
468
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
469
- });
329
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
330
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
331
+ const input = rawInput;
332
+ if (config.readOnly === true) throw new Error("write_file is blocked in read-only local mode.");
333
+ const path$5 = await require_LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, "write");
334
+ if (checkpointer != null) await checkpointer.captureBeforeWrite(path$5);
335
+ let before = "";
336
+ let encoding = {
337
+ text: "",
338
+ hasBom: false,
339
+ newline: "\n"
340
+ };
341
+ let existed = false;
342
+ try {
343
+ const decoded = require_textEncoding.decodeFile(await fs.readFile(path$5, "utf8"));
344
+ before = decoded.text;
345
+ encoding = decoded;
346
+ existed = true;
347
+ } catch {
348
+ existed = false;
349
+ }
350
+ await fs.mkdir((0, path.dirname)(path$5), { recursive: true });
351
+ const finalText = require_textEncoding.encodeFile(input.content, encoding);
352
+ await fs.writeFile(path$5, finalText, "utf8");
353
+ const syntax = await maybeRunSyntaxCheck(path$5, config);
354
+ const diff$1 = existed ? summariseDiff(path$5, before, input.content) : `(new file, ${input.content.length} chars)`;
355
+ const summary = appendSyntaxCheckSummary(existed ? `Overwrote ${path$5} (${input.content.length} chars). Diff:\n${diff$1}` : `Created ${path$5} (${input.content.length} chars).`, syntax);
356
+ if (syntax?.outcome.ok === false && syntax.mode === "strict") {
357
+ await revertStrictWrite(fs, path$5, existed, before, encoding);
358
+ throw new Error(`write_file syntax check failed (${syntax.outcome.checker}); reverted to pre-write state.\n${syntax.outcome.output}`);
359
+ }
360
+ return [summary, {
361
+ path: path$5,
362
+ bytes: finalText.length,
363
+ new_file: !existed,
364
+ newline: encoding.newline === "\r\n" ? "CRLF" : "LF",
365
+ had_bom: encoding.hasBom,
366
+ ...syntax != null && syntax.outcome.ok === false ? { syntax_error: syntax.outcome.checker } : {}
367
+ }];
368
+ }, {
369
+ name: LocalWriteFileToolName,
370
+ description: "Create or overwrite a local text file in the configured working directory. Preserves the existing BOM and line endings when overwriting; defaults to LF without BOM for new files. Returns a unified diff of the changes when overwriting.",
371
+ schema: LocalWriteFileToolSchema,
372
+ responseFormat: "content_and_artifact"
373
+ });
470
374
  }
471
375
  function createLocalEditFileTool(config = {}, checkpointer) {
472
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
473
- return tools.tool(async (rawInput) => {
474
- const input = rawInput;
475
- if (config.readOnly === true) {
476
- throw new Error('edit_file is blocked in read-only local mode.');
477
- }
478
- const edits = normalizeEdits(input);
479
- if (edits.length === 0) {
480
- throw new Error('edit_file requires old_text/new_text or edits[].');
481
- }
482
- const path = await LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, 'write');
483
- const raw = await fs.readFile(path, 'utf8');
484
- const encoding = textEncoding.decodeFile(raw);
485
- const original = encoding.text;
486
- let next = original;
487
- const strategiesUsed = [];
488
- for (let i = 0; i < edits.length; i++) {
489
- const edit = edits[i];
490
- const match = editStrategies.locateEdit(next, edit.oldText);
491
- if (match == null) {
492
- throw new Error(`Edit ${i + 1}/${edits.length}: could not locate old_text in ${input.file_path}. ` +
493
- 'Tried exact, line-trimmed, whitespace-normalized, and indentation-flexible matching. ' +
494
- 'Re-read the file and copy the literal lines.');
495
- }
496
- strategiesUsed.push(match.strategy);
497
- next = editStrategies.applyEdit(next, match, edit.newText);
498
- }
499
- if (checkpointer != null) {
500
- await checkpointer.captureBeforeWrite(path);
501
- }
502
- const finalText = textEncoding.encodeFile(next, encoding);
503
- await fs.writeFile(path, finalText, 'utf8');
504
- const syntax = await maybeRunSyntaxCheck(path, config);
505
- const diff = summariseDiff(path, original, next);
506
- const fuzzy = strategiesUsed.some((s) => s !== 'exact');
507
- const baseSummary = `Applied ${edits.length} edit(s) to ${path}` +
508
- (fuzzy ? ` (strategies: ${strategiesUsed.join(', ')})` : '') +
509
- `. Diff:\n${diff}`;
510
- const summary = appendSyntaxCheckSummary(baseSummary, syntax);
511
- if (syntax?.outcome.ok === false && syntax.mode === 'strict') {
512
- // Restore the pre-edit bytes so strict mode is an actual
513
- // gate (Codex P2 [49]). edit_file always operates on an
514
- // existing file, so `existed = true` here.
515
- await revertStrictWrite(fs, path, true, original, encoding);
516
- throw new Error(`edit_file syntax check failed (${syntax.outcome.checker}); reverted to pre-edit state.\n${syntax.outcome.output}`);
517
- }
518
- return [
519
- summary,
520
- {
521
- path,
522
- edits: edits.length,
523
- strategies: strategiesUsed,
524
- newline: encoding.newline === '\r\n' ? 'CRLF' : 'LF',
525
- had_bom: encoding.hasBom,
526
- ...(syntax != null && syntax.outcome.ok === false
527
- ? { syntax_error: syntax.outcome.checker }
528
- : {}),
529
- },
530
- ];
531
- }, {
532
- name: LocalEditFileToolName,
533
- description: 'Apply exact text replacements to a local file. The matcher tries exact, line-trimmed, whitespace-normalized, and indentation-flexible strategies in order so common LLM whitespace mistakes are recoverable. Each old_text must still match exactly one location. Returns a unified diff of the changes.',
534
- schema: LocalEditFileToolSchema,
535
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
536
- });
376
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
377
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
378
+ const input = rawInput;
379
+ if (config.readOnly === true) throw new Error("edit_file is blocked in read-only local mode.");
380
+ const edits = normalizeEdits(input);
381
+ if (edits.length === 0) throw new Error("edit_file requires old_text/new_text or edits[].");
382
+ const path$6 = await require_LocalExecutionEngine.resolveWorkspacePathSafe(input.file_path, config, "write");
383
+ const encoding = require_textEncoding.decodeFile(await fs.readFile(path$6, "utf8"));
384
+ const original = encoding.text;
385
+ let next = original;
386
+ const strategiesUsed = [];
387
+ for (let i = 0; i < edits.length; i++) {
388
+ const edit = edits[i];
389
+ const match = require_editStrategies.locateEdit(next, edit.oldText);
390
+ if (match == null) throw new Error(`Edit ${i + 1}/${edits.length}: could not locate old_text in ${input.file_path}. Tried exact, line-trimmed, whitespace-normalized, and indentation-flexible matching. Re-read the file and copy the literal lines.`);
391
+ strategiesUsed.push(match.strategy);
392
+ next = require_editStrategies.applyEdit(next, match, edit.newText);
393
+ }
394
+ if (checkpointer != null) await checkpointer.captureBeforeWrite(path$6);
395
+ const finalText = require_textEncoding.encodeFile(next, encoding);
396
+ await fs.writeFile(path$6, finalText, "utf8");
397
+ const syntax = await maybeRunSyntaxCheck(path$6, config);
398
+ const diff$2 = summariseDiff(path$6, original, next);
399
+ const fuzzy = strategiesUsed.some((s) => s !== "exact");
400
+ const summary = appendSyntaxCheckSummary(`Applied ${edits.length} edit(s) to ${path$6}` + (fuzzy ? ` (strategies: ${strategiesUsed.join(", ")})` : "") + `. Diff:\n${diff$2}`, syntax);
401
+ if (syntax?.outcome.ok === false && syntax.mode === "strict") {
402
+ await revertStrictWrite(fs, path$6, true, original, encoding);
403
+ throw new Error(`edit_file syntax check failed (${syntax.outcome.checker}); reverted to pre-edit state.\n${syntax.outcome.output}`);
404
+ }
405
+ return [summary, {
406
+ path: path$6,
407
+ edits: edits.length,
408
+ strategies: strategiesUsed,
409
+ newline: encoding.newline === "\r\n" ? "CRLF" : "LF",
410
+ had_bom: encoding.hasBom,
411
+ ...syntax != null && syntax.outcome.ok === false ? { syntax_error: syntax.outcome.checker } : {}
412
+ }];
413
+ }, {
414
+ name: LocalEditFileToolName,
415
+ description: "Apply exact text replacements to a local file. The matcher tries exact, line-trimmed, whitespace-normalized, and indentation-flexible strategies in order so common LLM whitespace mistakes are recoverable. Each old_text must still match exactly one location. Returns a unified diff of the changes.",
416
+ schema: LocalEditFileToolSchema,
417
+ responseFormat: "content_and_artifact"
418
+ });
537
419
  }
538
420
  /**
539
- * Ripgrep availability cache, keyed on the *effective execution
540
- * backend* — whatever function `getSpawn(config)` returns. Without
541
- * the backend key, a Run that probes `rg` over Node's
542
- * `child_process.spawn` would poison subsequent Runs whose
543
- * `local.exec.spawn` routes to a remote sandbox or container that
544
- * doesn't have rg installed: the cached `true` would skip the probe,
545
- * the rg invocation would throw, and the Node fallback wouldn't be
546
- * reached. Per-backend caching avoids that without paying for a
547
- * spawn-per-search.
548
- */
549
- // Per-backend × per-env cache. Codex P1 #34 — keying by spawn
550
- // backend alone misses the case where two Runs share a backend but
551
- // vary `local.env` (especially PATH). Stale cache then claims `rg`
552
- // is available, the rg path runs, and the spawn fails with ENOENT
553
- // instead of falling back to the Node walker. The inner Map is
554
- // keyed by a stable JSON hash of the effective env so each unique
555
- // env gets its own probe.
556
- let ripgrepAvailabilityByBackend = new WeakMap();
421
+ * Ripgrep availability cache, keyed on the *effective execution
422
+ * backend* — whatever function `getSpawn(config)` returns. Without
423
+ * the backend key, a Run that probes `rg` over Node's
424
+ * `child_process.spawn` would poison subsequent Runs whose
425
+ * `local.exec.spawn` routes to a remote sandbox or container that
426
+ * doesn't have rg installed: the cached `true` would skip the probe,
427
+ * the rg invocation would throw, and the Node fallback wouldn't be
428
+ * reached. Per-backend caching avoids that without paying for a
429
+ * spawn-per-search.
430
+ */
431
+ let ripgrepAvailabilityByBackend = /* @__PURE__ */ new WeakMap();
557
432
  function envCacheKey(env) {
558
- // PATH is the only env entry that affects command lookup, but
559
- // hashing the whole env keeps the key correct for hosts that
560
- // vary anything else relevant. Stable JSON via sorted keys so
561
- // {A:1,B:2} and {B:2,A:1} produce the same hash.
562
- if (env == null)
563
- return '';
564
- const sorted = {};
565
- for (const k of Object.keys(env).sort()) {
566
- sorted[k] = env[k];
567
- }
568
- return JSON.stringify(sorted);
433
+ if (env == null) return "";
434
+ const sorted = {};
435
+ for (const k of Object.keys(env).sort()) sorted[k] = env[k];
436
+ return JSON.stringify(sorted);
569
437
  }
570
438
  async function isRipgrepAvailable(config) {
571
- const backend = LocalExecutionEngine.getSpawn(config);
572
- let envMap = ripgrepAvailabilityByBackend.get(backend);
573
- if (envMap == null) {
574
- envMap = new Map();
575
- ripgrepAvailabilityByBackend.set(backend, envMap);
576
- }
577
- const envKey = envCacheKey(config.env);
578
- let probePromise = envMap.get(envKey);
579
- if (probePromise == null) {
580
- probePromise = LocalExecutionEngine.spawnLocalProcess('rg', ['--version'], { ...config, timeoutMs: 5000, sandbox: { enabled: false } }, { internal: true })
581
- .then((probe) => probe.exitCode === 0)
582
- .catch(() => false);
583
- envMap.set(envKey, probePromise);
584
- }
585
- return probePromise;
439
+ const backend = require_LocalExecutionEngine.getSpawn(config);
440
+ let envMap = ripgrepAvailabilityByBackend.get(backend);
441
+ if (envMap == null) {
442
+ envMap = /* @__PURE__ */ new Map();
443
+ ripgrepAvailabilityByBackend.set(backend, envMap);
444
+ }
445
+ const envKey = envCacheKey(config.env);
446
+ let probePromise = envMap.get(envKey);
447
+ if (probePromise == null) {
448
+ probePromise = require_LocalExecutionEngine.spawnLocalProcess("rg", ["--version"], {
449
+ ...config,
450
+ timeoutMs: 5e3,
451
+ sandbox: { enabled: false }
452
+ }, { internal: true }).then((probe) => probe.exitCode === 0).catch(() => false);
453
+ envMap.set(envKey, probePromise);
454
+ }
455
+ return probePromise;
586
456
  }
587
457
  /**
588
- * Test-only reset hook. Clears the ripgrep-availability cache so
589
- * tests can swap in mocked spawn backends and reprobe deterministically.
590
- *
591
- * @internal Not part of the public SDK surface; the leading underscore
592
- * and `@internal` tag together signal that consumers should not call
593
- * this. Tests import it via the module path directly.
594
- */
458
+ * Test-only reset hook. Clears the ripgrep-availability cache so
459
+ * tests can swap in mocked spawn backends and reprobe deterministically.
460
+ *
461
+ * @internal Not part of the public SDK surface; the leading underscore
462
+ * and `@internal` tag together signal that consumers should not call
463
+ * this. Tests import it via the module path directly.
464
+ */
595
465
  function _resetRipgrepCacheForTests() {
596
- ripgrepAvailabilityByBackend = new WeakMap();
466
+ ripgrepAvailabilityByBackend = /* @__PURE__ */ new WeakMap();
597
467
  }
598
- // Skipped by the Node-fallback walker (used when ripgrep is
599
- // unavailable). Covers common build outputs, virtualenvs, and
600
- // caches so a `grep_search`/`glob_search` on a large monorepo or a
601
- // Python project with `.venv/` doesn't read every file under those
602
- // trees. ripgrep itself respects .gitignore so it doesn't need this
603
- // list. Audit follow-up from the comprehensive review (finding #3).
604
468
  const SKIP_DIRS = new Set([
605
- '.git',
606
- '.svn',
607
- '.hg',
608
- 'node_modules',
609
- '.next',
610
- '.nuxt',
611
- '.cache',
612
- '.parcel-cache',
613
- '.turbo',
614
- 'dist',
615
- 'build',
616
- 'out',
617
- 'target',
618
- 'vendor',
619
- 'coverage',
620
- '.nyc_output',
621
- '__pycache__',
622
- '.venv',
623
- 'venv',
624
- 'env',
625
- '.tox',
626
- '.mypy_cache',
627
- '.pytest_cache',
628
- '.ruff_cache',
469
+ ".git",
470
+ ".svn",
471
+ ".hg",
472
+ "node_modules",
473
+ ".next",
474
+ ".nuxt",
475
+ ".cache",
476
+ ".parcel-cache",
477
+ ".turbo",
478
+ "dist",
479
+ "build",
480
+ "out",
481
+ "target",
482
+ "vendor",
483
+ "coverage",
484
+ ".nyc_output",
485
+ "__pycache__",
486
+ ".venv",
487
+ "venv",
488
+ "env",
489
+ ".tox",
490
+ ".mypy_cache",
491
+ ".pytest_cache",
492
+ ".ruff_cache"
629
493
  ]);
630
494
  function globToRegExp(pattern) {
631
- let result = '^';
632
- for (let i = 0; i < pattern.length; i++) {
633
- const c = pattern[i];
634
- if (c === '*') {
635
- if (pattern[i + 1] === '*') {
636
- result += '.*';
637
- i += 1;
638
- if (pattern[i + 1] === '/') {
639
- i += 1;
640
- }
641
- }
642
- else {
643
- result += '[^/]*';
644
- }
645
- }
646
- else if (c === '?') {
647
- result += '[^/]';
648
- }
649
- else if ('.+^$|(){}[]\\'.includes(c)) {
650
- result += '\\' + c;
651
- }
652
- else {
653
- result += c;
654
- }
655
- }
656
- result += '$';
657
- return new RegExp(result);
495
+ let result = "^";
496
+ for (let i = 0; i < pattern.length; i++) {
497
+ const c = pattern[i];
498
+ if (c === "*") if (pattern[i + 1] === "*") {
499
+ result += ".*";
500
+ i += 1;
501
+ if (pattern[i + 1] === "/") i += 1;
502
+ } else result += "[^/]*";
503
+ else if (c === "?") result += "[^/]";
504
+ else if (".+^$|(){}[]\\".includes(c)) result += "\\" + c;
505
+ else result += c;
506
+ }
507
+ result += "$";
508
+ return new RegExp(result);
658
509
  }
659
510
  async function* walkFiles(root, fs) {
660
- const stack = [root];
661
- while (stack.length > 0) {
662
- const dir = stack.pop();
663
- let entries;
664
- try {
665
- entries = await fs.readdir(dir, { withFileTypes: true });
666
- }
667
- catch {
668
- continue;
669
- }
670
- for (const entry of entries) {
671
- if (entry.name.startsWith('.git') || SKIP_DIRS.has(entry.name)) {
672
- continue;
673
- }
674
- const full = `${dir}/${entry.name}`;
675
- if (entry.isDirectory()) {
676
- stack.push(full);
677
- }
678
- else if (entry.isFile()) {
679
- yield full;
680
- }
681
- }
682
- }
511
+ const stack = [root];
512
+ while (stack.length > 0) {
513
+ const dir = stack.pop();
514
+ let entries;
515
+ try {
516
+ entries = await fs.readdir(dir, { withFileTypes: true });
517
+ } catch {
518
+ continue;
519
+ }
520
+ for (const entry of entries) {
521
+ if (entry.name.startsWith(".git") || SKIP_DIRS.has(entry.name)) continue;
522
+ const full = `${dir}/${entry.name}`;
523
+ if (entry.isDirectory()) stack.push(full);
524
+ else if (entry.isFile()) yield full;
525
+ }
526
+ }
683
527
  }
684
528
  /**
685
- * Catastrophic-backtracking guardrails for the fallback grep path.
686
- *
687
- * Without ripgrep we run the model-supplied pattern through Node's
688
- * `RegExp` engine, which uses a backtracking implementation. Patterns
689
- * with nested unbounded quantifiers (`(a+)+`, `(.*)*`, etc.) can
690
- * monopolise the event loop for arbitrary wall-clock time on
691
- * pathological input, and `setTimeout` cannot interrupt a synchronous
692
- * `RegExp.exec`. Manual review (finding D) flagged this as a real DoS.
693
- *
694
- * Mitigations applied here, in order of severity:
695
- * 1. Cap pattern length so an obviously oversize regex is rejected
696
- * before compile.
697
- * 2. Reject patterns that contain a nested unbounded quantifier of
698
- * the form `(...+|*)([+*]|{n,})` — the standard pathological
699
- * shape. Still a heuristic (not a full safety proof), but blocks
700
- * every common DoS construction we've seen in coding-agent logs.
701
- * 3. Wall-clock budget for the overall search: each file's regex
702
- * pass is checked against a deadline; once exceeded the search
703
- * bails with a partial result. Doesn't interrupt a stuck
704
- * `exec()` call, but stops a slow pattern from making the whole
705
- * Run hang once the first hung file finishes.
706
- *
707
- * Hosts that need bulletproof regex safety should install `rg` —
708
- * ripgrep uses RE2 internally and has no backtracking.
709
- */
529
+ * Catastrophic-backtracking guardrails for the fallback grep path.
530
+ *
531
+ * Without ripgrep we run the model-supplied pattern through Node's
532
+ * `RegExp` engine, which uses a backtracking implementation. Patterns
533
+ * with nested unbounded quantifiers (`(a+)+`, `(.*)*`, etc.) can
534
+ * monopolise the event loop for arbitrary wall-clock time on
535
+ * pathological input, and `setTimeout` cannot interrupt a synchronous
536
+ * `RegExp.exec`. Manual review (finding D) flagged this as a real DoS.
537
+ *
538
+ * Mitigations applied here, in order of severity:
539
+ * 1. Cap pattern length so an obviously oversize regex is rejected
540
+ * before compile.
541
+ * 2. Reject patterns that contain a nested unbounded quantifier of
542
+ * the form `(...+|*)([+*]|{n,})` — the standard pathological
543
+ * shape. Still a heuristic (not a full safety proof), but blocks
544
+ * every common DoS construction we've seen in coding-agent logs.
545
+ * 3. Wall-clock budget for the overall search: each file's regex
546
+ * pass is checked against a deadline; once exceeded the search
547
+ * bails with a partial result. Doesn't interrupt a stuck
548
+ * `exec()` call, but stops a slow pattern from making the whole
549
+ * Run hang once the first hung file finishes.
550
+ *
551
+ * Hosts that need bulletproof regex safety should install `rg` —
552
+ * ripgrep uses RE2 internally and has no backtracking.
553
+ */
710
554
  const MAX_FALLBACK_PATTERN_LENGTH = 1024;
711
- const FALLBACK_GREP_BUDGET_MS = 5000;
712
- // Per-file byte cap. Codex P2 #41 — without it, the whole-file
713
- // `readFile` + `split('\n')` for a multi-GB log is an unbounded
714
- // allocation that the wall-clock budget (checked between files)
715
- // can't interrupt. Hosts that need to grep large files should
716
- // install ripgrep.
555
+ const FALLBACK_GREP_BUDGET_MS = 5e3;
717
556
  const FALLBACK_GREP_MAX_FILE_BYTES = 5 * 1024 * 1024;
718
557
  /**
719
- * Heuristic: walks `pattern` to find any `(<contents>)<quant>` where
720
- * `<contents>` itself has an unbounded quantifier. Catches the
721
- * classic `(a+)+` form AND the double-nested `((a+)+)` form (which a
722
- * single-pass regex misses because `[^)]*` stops at the first inner
723
- * close-paren). Misses sufficiently obfuscated cases — bulletproof
724
- * ReDoS detection requires a real parser. The 5 s wall-clock budget
725
- * is the hard backstop for anything this slip past.
726
- */
558
+ * Heuristic: walks `pattern` to find any `(<contents>)<quant>` where
559
+ * `<contents>` itself has an unbounded quantifier. Catches the
560
+ * classic `(a+)+` form AND the double-nested `((a+)+)` form (which a
561
+ * single-pass regex misses because `[^)]*` stops at the first inner
562
+ * close-paren). Misses sufficiently obfuscated cases — bulletproof
563
+ * ReDoS detection requires a real parser. The 5 s wall-clock budget
564
+ * is the hard backstop for anything this slip past.
565
+ */
727
566
  function hasNestedUnboundedQuantifier(pattern) {
728
- for (let i = 1; i < pattern.length - 1; i++) {
729
- if (pattern[i] !== ')')
730
- continue;
731
- if (pattern[i - 1] === '\\')
732
- continue;
733
- const next = pattern[i + 1];
734
- if (next !== '+' && next !== '*' && next !== '{')
735
- continue;
736
- // Walk back to find the matching opening paren (respecting depth
737
- // and `\(` escapes).
738
- let depth = 1;
739
- let j = i - 1;
740
- while (j >= 0) {
741
- const c = pattern[j];
742
- const escaped = j > 0 && pattern[j - 1] === '\\';
743
- if (!escaped) {
744
- if (c === ')')
745
- depth++;
746
- else if (c === '(') {
747
- depth--;
748
- if (depth === 0)
749
- break;
750
- }
751
- }
752
- j--;
753
- }
754
- if (j < 0)
755
- continue;
756
- const inner = pattern.slice(j + 1, i);
757
- if (/(?<!\\)[+*]/.test(inner))
758
- return true;
759
- }
760
- return false;
761
- }
762
- class FallbackGrepError extends Error {
763
- kind;
764
- constructor(kind, message) {
765
- super(message);
766
- this.kind = kind;
767
- }
567
+ for (let i = 1; i < pattern.length - 1; i++) {
568
+ if (pattern[i] !== ")") continue;
569
+ if (pattern[i - 1] === "\\") continue;
570
+ const next = pattern[i + 1];
571
+ if (next !== "+" && next !== "*" && next !== "{") continue;
572
+ let depth = 1;
573
+ let j = i - 1;
574
+ while (j >= 0) {
575
+ const c = pattern[j];
576
+ if (!(j > 0 && pattern[j - 1] === "\\")) {
577
+ if (c === ")") depth++;
578
+ else if (c === "(") {
579
+ depth--;
580
+ if (depth === 0) break;
581
+ }
582
+ }
583
+ j--;
584
+ }
585
+ if (j < 0) continue;
586
+ const inner = pattern.slice(j + 1, i);
587
+ if (/(?<!\\)[+*]/.test(inner)) return true;
588
+ }
589
+ return false;
768
590
  }
591
+ var FallbackGrepError = class extends Error {
592
+ kind;
593
+ constructor(kind, message) {
594
+ super(message);
595
+ this.kind = kind;
596
+ }
597
+ };
769
598
  function compileFallbackRegex(pattern) {
770
- if (pattern.length > MAX_FALLBACK_PATTERN_LENGTH) {
771
- throw new FallbackGrepError('pattern-too-long', `Pattern exceeds ${MAX_FALLBACK_PATTERN_LENGTH}-char fallback cap (install ripgrep for unbounded patterns).`);
772
- }
773
- if (hasNestedUnboundedQuantifier(pattern)) {
774
- throw new FallbackGrepError('unsafe-pattern', 'Pattern contains a nested unbounded quantifier (e.g. `(a+)+` or `((a+)+)`) which can cause catastrophic backtracking in the Node fallback. Install ripgrep for RE2-safe matching.');
775
- }
776
- try {
777
- return new RegExp(pattern);
778
- }
779
- catch (e) {
780
- throw new FallbackGrepError('invalid-pattern', `Invalid regex: ${e.message}`);
781
- }
599
+ if (pattern.length > MAX_FALLBACK_PATTERN_LENGTH) throw new FallbackGrepError("pattern-too-long", `Pattern exceeds ${MAX_FALLBACK_PATTERN_LENGTH}-char fallback cap (install ripgrep for unbounded patterns).`);
600
+ if (hasNestedUnboundedQuantifier(pattern)) throw new FallbackGrepError("unsafe-pattern", "Pattern contains a nested unbounded quantifier (e.g. `(a+)+` or `((a+)+)`) which can cause catastrophic backtracking in the Node fallback. Install ripgrep for RE2-safe matching.");
601
+ try {
602
+ return new RegExp(pattern);
603
+ } catch (e) {
604
+ throw new FallbackGrepError("invalid-pattern", `Invalid regex: ${e.message}`);
605
+ }
782
606
  }
783
607
  /** Renders fallback-grep output: real matches first, skip diagnostics appended. */
784
608
  function formatFallbackGrepDisplay(result) {
785
- if (result.matches.length > 0) {
786
- return [...result.matches, ...result.skipped].join('\n');
787
- }
788
- if (result.skipped.length > 0) {
789
- return result.skipped.join('\n');
790
- }
791
- return 'No matches found.';
609
+ if (result.matches.length > 0) return [...result.matches, ...result.skipped].join("\n");
610
+ if (result.skipped.length > 0) return result.skipped.join("\n");
611
+ return "No matches found.";
792
612
  }
793
613
  async function fallbackGrep(root, pattern, globFilter, maxResults, fs) {
794
- const rx = compileFallbackRegex(pattern);
795
- const deadline = Date.now() + FALLBACK_GREP_BUDGET_MS;
796
- const globRx = globFilter != null && globFilter !== ''
797
- ? globToRegExp(globFilter)
798
- : undefined;
799
- const matches = [];
800
- // Track skipped (oversize) files separately so they don't consume
801
- // the maxResults budget. Codex P2 [43]: round 14's fix pushed skip
802
- // sentinels into `matches`, so a directory of one oversize non-
803
- // matching file falsely reported `matches: 1`, and enough
804
- // oversize files could fill the budget before any real match was
805
- // scanned. Now diagnostics are appended after real matches and
806
- // independent of the budget.
807
- const skippedDiagnostics = [];
808
- for await (const file of walkFiles(root, fs)) {
809
- if (Date.now() > deadline) {
810
- // Wall-clock budget exceeded — return partial results rather
811
- // than letting a slow pattern hang the Run.
812
- return { matches, skipped: skippedDiagnostics };
813
- }
814
- if (globRx != null) {
815
- const rel = file.startsWith(root + '/')
816
- ? file.slice(root.length + 1)
817
- : file;
818
- if (!globRx.test(rel)) {
819
- continue;
820
- }
821
- }
822
- // Skip files larger than the per-file cap and remember them as
823
- // diagnostics (NOT as matches). Codex P2 [41]: pre-fix
824
- // `fs.readFile` then `.split('\n')` allocated the whole file +
825
- // an array of every line, which a single multi-GB log could
826
- // turn into an OOM even after the regex DoS guards.
827
- let stat;
828
- try {
829
- stat = await fs.stat(file);
830
- }
831
- catch {
832
- continue;
833
- }
834
- if (stat.size > FALLBACK_GREP_MAX_FILE_BYTES) {
835
- skippedDiagnostics.push(`${file}:0:[skipped: file > ${FALLBACK_GREP_MAX_FILE_BYTES} bytes; install ripgrep for unbounded grep]`);
836
- continue;
837
- }
838
- let content;
839
- try {
840
- content = await fs.readFile(file, 'utf8');
841
- }
842
- catch {
843
- continue;
844
- }
845
- if (content.includes('\0')) {
846
- continue;
847
- }
848
- // Re-check the deadline AFTER the read — a slow disk on one
849
- // file can blow the budget without us noticing.
850
- if (Date.now() > deadline) {
851
- return { matches, skipped: skippedDiagnostics };
852
- }
853
- const lines = content.split('\n');
854
- for (let i = 0; i < lines.length; i++) {
855
- if (rx.test(lines[i])) {
856
- matches.push(`${file}:${i + 1}:${lines[i]}`);
857
- if (matches.length >= maxResults) {
858
- return { matches, skipped: skippedDiagnostics };
859
- }
860
- }
861
- }
862
- }
863
- return { matches, skipped: skippedDiagnostics };
614
+ const rx = compileFallbackRegex(pattern);
615
+ const deadline = Date.now() + FALLBACK_GREP_BUDGET_MS;
616
+ const globRx = globFilter != null && globFilter !== "" ? globToRegExp(globFilter) : void 0;
617
+ const matches = [];
618
+ const skippedDiagnostics = [];
619
+ for await (const file of walkFiles(root, fs)) {
620
+ if (Date.now() > deadline) return {
621
+ matches,
622
+ skipped: skippedDiagnostics
623
+ };
624
+ if (globRx != null) {
625
+ const rel = file.startsWith(root + "/") ? file.slice(root.length + 1) : file;
626
+ if (!globRx.test(rel)) continue;
627
+ }
628
+ let stat;
629
+ try {
630
+ stat = await fs.stat(file);
631
+ } catch {
632
+ continue;
633
+ }
634
+ if (stat.size > FALLBACK_GREP_MAX_FILE_BYTES) {
635
+ skippedDiagnostics.push(`${file}:0:[skipped: file > ${FALLBACK_GREP_MAX_FILE_BYTES} bytes; install ripgrep for unbounded grep]`);
636
+ continue;
637
+ }
638
+ let content;
639
+ try {
640
+ content = await fs.readFile(file, "utf8");
641
+ } catch {
642
+ continue;
643
+ }
644
+ if (content.includes("\0")) continue;
645
+ if (Date.now() > deadline) return {
646
+ matches,
647
+ skipped: skippedDiagnostics
648
+ };
649
+ const lines = content.split("\n");
650
+ for (let i = 0; i < lines.length; i++) if (rx.test(lines[i])) {
651
+ matches.push(`${file}:${i + 1}:${lines[i]}`);
652
+ if (matches.length >= maxResults) return {
653
+ matches,
654
+ skipped: skippedDiagnostics
655
+ };
656
+ }
657
+ }
658
+ return {
659
+ matches,
660
+ skipped: skippedDiagnostics
661
+ };
864
662
  }
865
663
  async function fallbackGlob(root, pattern, maxResults, fs) {
866
- const rx = globToRegExp(pattern);
867
- const out = [];
868
- for await (const file of walkFiles(root, fs)) {
869
- const rel = file.startsWith(root + '/')
870
- ? file.slice(root.length + 1)
871
- : file;
872
- if (rx.test(rel)) {
873
- out.push(file);
874
- if (out.length >= maxResults) {
875
- break;
876
- }
877
- }
878
- }
879
- return out;
664
+ const rx = globToRegExp(pattern);
665
+ const out = [];
666
+ for await (const file of walkFiles(root, fs)) {
667
+ const rel = file.startsWith(root + "/") ? file.slice(root.length + 1) : file;
668
+ if (rx.test(rel)) {
669
+ out.push(file);
670
+ if (out.length >= maxResults) break;
671
+ }
672
+ }
673
+ return out;
880
674
  }
881
675
  function createLocalGrepSearchTool(config = {}) {
882
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
883
- return tools.tool(async (rawInput) => {
884
- const input = rawInput;
885
- const target = await LocalExecutionEngine.resolveWorkspacePathSafe(input.path ?? '.', config, 'read');
886
- const maxResults = Math.max(input.max_results ?? DEFAULT_MAX_RESULTS, 1);
887
- if (await isRipgrepAvailable(config)) {
888
- // Pass the pattern through `-e` so dash-prefixed patterns
889
- // like `-foo` are treated as the search regex, not as a
890
- // (probably-unknown) flag. `rg --help` explicitly requires
891
- // `-e/--regexp` (or `--`) for that case. Same trick avoids
892
- // any future flag-conflict if a user query happens to look
893
- // like an rg long option.
894
- const args = [
895
- '--line-number',
896
- '--column',
897
- '--hidden',
898
- '--glob',
899
- '!.git/**',
900
- ...(input.glob != null && input.glob !== ''
901
- ? ['--glob', input.glob]
902
- : []),
903
- '-e',
904
- input.pattern,
905
- target,
906
- ];
907
- const result = await LocalExecutionEngine.spawnLocalProcess('rg', args, {
908
- ...config,
909
- timeoutMs: config.timeoutMs ?? 30000,
910
- });
911
- // ripgrep exit codes:
912
- // 0 at least one match
913
- // 1 → no matches (clean — "No matches found.")
914
- // 2 → real error (bad regex, unreadable target, etc.)
915
- // Without this branch (Codex P2 #23 — same fix shape glob_search
916
- // got from P2 #13), exit-2 errors silently mapped to
917
- // `matches: 0`, so the agent treated tooling failures as a
918
- // genuine absence of matches.
919
- if (result.timedOut ||
920
- (result.exitCode != null && result.exitCode > 1)) {
921
- const detail = result.stderr.trim() || `rg exited ${result.exitCode}`;
922
- return [
923
- `grep_search failed: ${detail}`,
924
- {
925
- matches: 0,
926
- engine: 'ripgrep',
927
- error: detail,
928
- exitCode: result.exitCode,
929
- },
930
- ];
931
- }
932
- const lines = result.stdout
933
- .split('\n')
934
- .filter(Boolean)
935
- .slice(0, maxResults);
936
- const output = lines.length > 0
937
- ? lines.join('\n')
938
- : result.stderr.trim() || 'No matches found.';
939
- return [output, { matches: lines.length, engine: 'ripgrep' }];
940
- }
941
- try {
942
- const { matches, skipped } = await fallbackGrep(target, input.pattern, input.glob, maxResults, fs);
943
- // Artifact count: ONLY real matches (Codex P2 [43] —
944
- // skip sentinels used to inflate the count and the budget).
945
- const display = formatFallbackGrepDisplay({ matches, skipped });
946
- return [
947
- display,
948
- {
949
- matches: matches.length,
950
- skipped: skipped.length,
951
- engine: 'node-fallback',
952
- },
953
- ];
954
- }
955
- catch (e) {
956
- if (e instanceof FallbackGrepError) {
957
- return [
958
- `grep_search refused the pattern: ${e.message}`,
959
- {
960
- matches: 0,
961
- engine: 'node-fallback',
962
- error: e.message,
963
- kind: e.kind,
964
- },
965
- ];
966
- }
967
- throw e;
968
- }
969
- }, {
970
- name: LocalGrepSearchToolName,
971
- description: 'Search local files for a regex pattern (ripgrep when available, Node fallback otherwise).',
972
- schema: LocalGrepSearchToolSchema,
973
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
974
- });
676
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
677
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
678
+ const input = rawInput;
679
+ const target = await require_LocalExecutionEngine.resolveWorkspacePathSafe(input.path ?? ".", config, "read");
680
+ const maxResults = Math.max(input.max_results ?? DEFAULT_MAX_RESULTS, 1);
681
+ if (await isRipgrepAvailable(config)) {
682
+ const result = await require_LocalExecutionEngine.spawnLocalProcess("rg", [
683
+ "--line-number",
684
+ "--column",
685
+ "--hidden",
686
+ "--glob",
687
+ "!.git/**",
688
+ ...input.glob != null && input.glob !== "" ? ["--glob", input.glob] : [],
689
+ "-e",
690
+ input.pattern,
691
+ target
692
+ ], {
693
+ ...config,
694
+ timeoutMs: config.timeoutMs ?? 3e4
695
+ });
696
+ if (result.timedOut || result.exitCode != null && result.exitCode > 1) {
697
+ const detail = result.stderr.trim() || `rg exited ${result.exitCode}`;
698
+ return [`grep_search failed: ${detail}`, {
699
+ matches: 0,
700
+ engine: "ripgrep",
701
+ error: detail,
702
+ exitCode: result.exitCode
703
+ }];
704
+ }
705
+ const lines = result.stdout.split("\n").filter(Boolean).slice(0, maxResults);
706
+ return [lines.length > 0 ? lines.join("\n") : result.stderr.trim() || "No matches found.", {
707
+ matches: lines.length,
708
+ engine: "ripgrep"
709
+ }];
710
+ }
711
+ try {
712
+ const { matches, skipped } = await fallbackGrep(target, input.pattern, input.glob, maxResults, fs);
713
+ return [formatFallbackGrepDisplay({
714
+ matches,
715
+ skipped
716
+ }), {
717
+ matches: matches.length,
718
+ skipped: skipped.length,
719
+ engine: "node-fallback"
720
+ }];
721
+ } catch (e) {
722
+ if (e instanceof FallbackGrepError) return [`grep_search refused the pattern: ${e.message}`, {
723
+ matches: 0,
724
+ engine: "node-fallback",
725
+ error: e.message,
726
+ kind: e.kind
727
+ }];
728
+ throw e;
729
+ }
730
+ }, {
731
+ name: LocalGrepSearchToolName,
732
+ description: "Search local files for a regex pattern (ripgrep when available, Node fallback otherwise).",
733
+ schema: LocalGrepSearchToolSchema,
734
+ responseFormat: "content_and_artifact"
735
+ });
975
736
  }
976
737
  function createLocalGlobSearchTool(config = {}) {
977
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
978
- return tools.tool(async (rawInput) => {
979
- const input = rawInput;
980
- const target = await LocalExecutionEngine.resolveWorkspacePathSafe(input.path ?? '.', config, 'read');
981
- const maxResults = Math.max(input.max_results ?? DEFAULT_MAX_RESULTS, 1);
982
- if (await isRipgrepAvailable(config)) {
983
- const result = await LocalExecutionEngine.spawnLocalProcess('rg', [
984
- '--files',
985
- '--hidden',
986
- '--glob',
987
- '!.git/**',
988
- '--glob',
989
- input.pattern,
990
- target,
991
- ], { ...config, timeoutMs: config.timeoutMs ?? 30000 });
992
- // rg --files exit codes:
993
- // 0 → at least one file matched
994
- // 1 → no files matched (clean — "No files found.")
995
- // 2 → real error (bad glob, unreadable target, etc.)
996
- // Without this branch, exit-2 errors used to silently map to
997
- // "No files found." — the agent then treats a tooling failure
998
- // as a real absence of matches.
999
- if (result.timedOut ||
1000
- (result.exitCode != null && result.exitCode > 1)) {
1001
- const detail = result.stderr.trim() || `rg exited ${result.exitCode}`;
1002
- return [
1003
- `glob_search failed: ${detail}`,
1004
- {
1005
- files: [],
1006
- engine: 'ripgrep',
1007
- error: detail,
1008
- exitCode: result.exitCode,
1009
- },
1010
- ];
1011
- }
1012
- const lines = result.stdout
1013
- .split('\n')
1014
- .filter(Boolean)
1015
- .slice(0, maxResults);
1016
- return [
1017
- lines.length > 0 ? lines.join('\n') : 'No files found.',
1018
- { files: lines, engine: 'ripgrep' },
1019
- ];
1020
- }
1021
- const files = await fallbackGlob(target, input.pattern, maxResults, fs);
1022
- return [
1023
- files.length > 0 ? files.join('\n') : 'No files found.',
1024
- { files, engine: 'node-fallback' },
1025
- ];
1026
- }, {
1027
- name: LocalGlobSearchToolName,
1028
- description: 'Find local files matching a glob pattern (ripgrep when available, Node fallback otherwise).',
1029
- schema: LocalGlobSearchToolSchema,
1030
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
1031
- });
738
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
739
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
740
+ const input = rawInput;
741
+ const target = await require_LocalExecutionEngine.resolveWorkspacePathSafe(input.path ?? ".", config, "read");
742
+ const maxResults = Math.max(input.max_results ?? DEFAULT_MAX_RESULTS, 1);
743
+ if (await isRipgrepAvailable(config)) {
744
+ const result = await require_LocalExecutionEngine.spawnLocalProcess("rg", [
745
+ "--files",
746
+ "--hidden",
747
+ "--glob",
748
+ "!.git/**",
749
+ "--glob",
750
+ input.pattern,
751
+ target
752
+ ], {
753
+ ...config,
754
+ timeoutMs: config.timeoutMs ?? 3e4
755
+ });
756
+ if (result.timedOut || result.exitCode != null && result.exitCode > 1) {
757
+ const detail = result.stderr.trim() || `rg exited ${result.exitCode}`;
758
+ return [`glob_search failed: ${detail}`, {
759
+ files: [],
760
+ engine: "ripgrep",
761
+ error: detail,
762
+ exitCode: result.exitCode
763
+ }];
764
+ }
765
+ const lines = result.stdout.split("\n").filter(Boolean).slice(0, maxResults);
766
+ return [lines.length > 0 ? lines.join("\n") : "No files found.", {
767
+ files: lines,
768
+ engine: "ripgrep"
769
+ }];
770
+ }
771
+ const files = await fallbackGlob(target, input.pattern, maxResults, fs);
772
+ return [files.length > 0 ? files.join("\n") : "No files found.", {
773
+ files,
774
+ engine: "node-fallback"
775
+ }];
776
+ }, {
777
+ name: LocalGlobSearchToolName,
778
+ description: "Find local files matching a glob pattern (ripgrep when available, Node fallback otherwise).",
779
+ schema: LocalGlobSearchToolSchema,
780
+ responseFormat: "content_and_artifact"
781
+ });
1032
782
  }
1033
783
  function createLocalListDirectoryTool(config = {}) {
1034
- const fs = LocalExecutionEngine.getWorkspaceFS(config);
1035
- return tools.tool(async (rawInput) => {
1036
- const input = rawInput;
1037
- const path = await LocalExecutionEngine.resolveWorkspacePathSafe(input.path ?? '.', config, 'read');
1038
- const entries = await fs.readdir(path, { withFileTypes: true });
1039
- const output = entries
1040
- .map((entry) => `${entry.isDirectory() ? 'dir ' : 'file'}\t${entry.name}`)
1041
- .join('\n');
1042
- return [output || 'Directory is empty.', { path, count: entries.length }];
1043
- }, {
1044
- name: LocalListDirectoryToolName,
1045
- description: 'List files and directories in a local directory.',
1046
- schema: LocalListDirectoryToolSchema,
1047
- responseFormat: _enum.Constants.CONTENT_AND_ARTIFACT,
1048
- });
784
+ const fs = require_LocalExecutionEngine.getWorkspaceFS(config);
785
+ return (0, _langchain_core_tools.tool)(async (rawInput) => {
786
+ const path$7 = await require_LocalExecutionEngine.resolveWorkspacePathSafe(rawInput.path ?? ".", config, "read");
787
+ const entries = await fs.readdir(path$7, { withFileTypes: true });
788
+ return [entries.map((entry) => `${entry.isDirectory() ? "dir " : "file"}\t${entry.name}`).join("\n") || "Directory is empty.", {
789
+ path: path$7,
790
+ count: entries.length
791
+ }];
792
+ }, {
793
+ name: LocalListDirectoryToolName,
794
+ description: "List files and directories in a local directory.",
795
+ schema: LocalListDirectoryToolSchema,
796
+ responseFormat: "content_and_artifact"
797
+ });
1049
798
  }
1050
799
  function createLocalCodingTools(config = {}, options = {}) {
1051
- const checkpointer = options.checkpointer ??
1052
- (config.fileCheckpointing === true
1053
- ? FileCheckpointer.createLocalFileCheckpointer({ fs: config.exec?.fs })
1054
- : undefined);
1055
- return [
1056
- createLocalReadFileTool(config),
1057
- createLocalWriteFileTool(config, checkpointer),
1058
- createLocalEditFileTool(config, checkpointer),
1059
- createLocalGrepSearchTool(config),
1060
- createLocalGlobSearchTool(config),
1061
- createLocalListDirectoryTool(config),
1062
- CompileCheckTool.createCompileCheckTool(config),
1063
- LocalExecutionTools.createLocalBashExecutionTool({ config }),
1064
- LocalExecutionTools.createLocalCodeExecutionTool(config),
1065
- LocalProgrammaticToolCalling.createLocalProgrammaticToolCallingTool(config),
1066
- LocalProgrammaticToolCalling.createLocalBashProgrammaticToolCallingTool(config),
1067
- ];
800
+ const checkpointer = options.checkpointer ?? (config.fileCheckpointing === true ? require_FileCheckpointer.createLocalFileCheckpointer({ fs: config.exec?.fs }) : void 0);
801
+ return [
802
+ createLocalReadFileTool(config),
803
+ createLocalWriteFileTool(config, checkpointer),
804
+ createLocalEditFileTool(config, checkpointer),
805
+ createLocalGrepSearchTool(config),
806
+ createLocalGlobSearchTool(config),
807
+ createLocalListDirectoryTool(config),
808
+ require_CompileCheckTool.createCompileCheckTool(config),
809
+ require_LocalExecutionTools.createLocalBashExecutionTool({ config }),
810
+ require_LocalExecutionTools.createLocalCodeExecutionTool(config),
811
+ require_LocalProgrammaticToolCalling.createLocalProgrammaticToolCallingTool(config),
812
+ require_LocalProgrammaticToolCalling.createLocalBashProgrammaticToolCallingTool(config)
813
+ ];
1068
814
  }
1069
815
  /**
1070
- * Variant of `createLocalCodingTools` that returns the bundle alongside
1071
- * the file checkpointer so callers can later call
1072
- * `bundle.checkpointer?.rewind()`.
1073
- */
816
+ * Variant of `createLocalCodingTools` that returns the bundle alongside
817
+ * the file checkpointer so callers can later call
818
+ * `bundle.checkpointer?.rewind()`.
819
+ */
1074
820
  function createLocalCodingToolBundle(config = {}, options = {}) {
1075
- const checkpointer = options.checkpointer ??
1076
- (config.fileCheckpointing === true
1077
- ? FileCheckpointer.createLocalFileCheckpointer({ fs: config.exec?.fs })
1078
- : undefined);
1079
- return {
1080
- tools: createLocalCodingTools(config, { checkpointer }),
1081
- checkpointer,
1082
- };
821
+ const checkpointer = options.checkpointer ?? (config.fileCheckpointing === true ? require_FileCheckpointer.createLocalFileCheckpointer({ fs: config.exec?.fs }) : void 0);
822
+ return {
823
+ tools: createLocalCodingTools(config, { checkpointer }),
824
+ checkpointer
825
+ };
1083
826
  }
1084
827
  function createLocalCodingToolDefinitions() {
1085
- return [
1086
- toolDefinition(_enum.Constants.READ_FILE, 'Read a local text file from the configured working directory with line numbers.', LocalReadFileToolSchema),
1087
- toolDefinition(LocalWriteFileToolName, 'Create or overwrite a local text file in the configured working directory.', LocalWriteFileToolSchema),
1088
- toolDefinition(LocalEditFileToolName, 'Apply exact text replacements to a local file.', LocalEditFileToolSchema),
1089
- toolDefinition(LocalGrepSearchToolName, 'Search local files with ripgrep and return matching lines.', LocalGrepSearchToolSchema),
1090
- toolDefinition(LocalGlobSearchToolName, 'Find local files matching a glob pattern.', LocalGlobSearchToolSchema),
1091
- toolDefinition(LocalListDirectoryToolName, 'List files and directories in a local directory.', LocalListDirectoryToolSchema),
1092
- CompileCheckTool.createCompileCheckToolDefinition(),
1093
- ];
828
+ return [
829
+ toolDefinition("read_file", "Read a local text file from the configured working directory with line numbers.", LocalReadFileToolSchema),
830
+ toolDefinition(LocalWriteFileToolName, "Create or overwrite a local text file in the configured working directory.", LocalWriteFileToolSchema),
831
+ toolDefinition(LocalEditFileToolName, "Apply exact text replacements to a local file.", LocalEditFileToolSchema),
832
+ toolDefinition(LocalGrepSearchToolName, "Search local files with ripgrep and return matching lines.", LocalGrepSearchToolSchema),
833
+ toolDefinition(LocalGlobSearchToolName, "Find local files matching a glob pattern.", LocalGlobSearchToolSchema),
834
+ toolDefinition(LocalListDirectoryToolName, "List files and directories in a local directory.", LocalListDirectoryToolSchema),
835
+ require_CompileCheckTool.createCompileCheckToolDefinition()
836
+ ];
1094
837
  }
1095
838
  function createLocalCodingToolRegistry() {
1096
- return new Map(createLocalCodingToolDefinitions().map((definition) => [
1097
- definition.name,
1098
- definition,
1099
- ]));
839
+ return new Map(createLocalCodingToolDefinitions().map((definition) => [definition.name, definition]));
1100
840
  }
1101
-
841
+ //#endregion
1102
842
  exports.LocalEditFileToolName = LocalEditFileToolName;
1103
843
  exports.LocalEditFileToolSchema = LocalEditFileToolSchema;
1104
844
  exports.LocalGlobSearchToolName = LocalGlobSearchToolName;
@@ -1121,4 +861,5 @@ exports.createLocalGrepSearchTool = createLocalGrepSearchTool;
1121
861
  exports.createLocalListDirectoryTool = createLocalListDirectoryTool;
1122
862
  exports.createLocalReadFileTool = createLocalReadFileTool;
1123
863
  exports.createLocalWriteFileTool = createLocalWriteFileTool;
1124
- //# sourceMappingURL=LocalCodingTools.cjs.map
864
+
865
+ //# sourceMappingURL=LocalCodingTools.cjs.map