@bastani/atomic 0.9.2-alpha.1 → 0.9.3-alpha.1

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 (455) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +2 -2
  3. package/dist/builtin/cursor/CHANGELOG.md +6 -0
  4. package/dist/builtin/cursor/package.json +2 -2
  5. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  6. package/dist/builtin/intercom/package.json +1 -1
  7. package/dist/builtin/mcp/CHANGELOG.md +12 -0
  8. package/dist/builtin/mcp/direct-tools.ts +4 -2
  9. package/dist/builtin/mcp/package.json +1 -1
  10. package/dist/builtin/mcp/proxy-call.ts +3 -1
  11. package/dist/builtin/mcp/utils.ts +18 -7
  12. package/dist/builtin/subagents/CHANGELOG.md +17 -0
  13. package/dist/builtin/subagents/README.md +6 -6
  14. package/dist/builtin/subagents/agents/code-simplifier.md +7 -6
  15. package/dist/builtin/subagents/agents/codebase-analyzer.md +5 -4
  16. package/dist/builtin/subagents/agents/codebase-locator.md +3 -3
  17. package/dist/builtin/subagents/agents/codebase-online-researcher.md +10 -10
  18. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +4 -4
  19. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +3 -3
  20. package/dist/builtin/subagents/agents/codebase-research-locator.md +4 -4
  21. package/dist/builtin/subagents/agents/debugger.md +5 -5
  22. package/dist/builtin/subagents/agents/worker.md +56 -0
  23. package/dist/builtin/subagents/package.json +1 -1
  24. package/dist/builtin/subagents/skills/subagent/SKILL.md +11 -11
  25. package/dist/builtin/subagents/src/agents/agent-loaders.ts +3 -5
  26. package/dist/builtin/subagents/src/agents/agent-management-helpers.ts +3 -3
  27. package/dist/builtin/subagents/src/extension/schemas.ts +2 -2
  28. package/dist/builtin/subagents/src/intercom/result-intercom.ts +4 -3
  29. package/dist/builtin/subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +1 -1
  30. package/dist/builtin/subagents/src/runs/shared/nested-render.ts +2 -2
  31. package/dist/builtin/subagents/src/runs/shared/pi-args.ts +2 -1
  32. package/dist/builtin/subagents/src/shared/types-depth.ts +5 -5
  33. package/dist/builtin/subagents/src/shared/types-runtime.ts +2 -1
  34. package/dist/builtin/subagents/src/tui/render-event-formatting.ts +2 -2
  35. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  36. package/dist/builtin/web-access/package.json +1 -1
  37. package/dist/builtin/workflows/CHANGELOG.md +21 -0
  38. package/dist/builtin/workflows/README.md +2 -2
  39. package/dist/builtin/workflows/builtin/goal-artifacts.ts +11 -6
  40. package/dist/builtin/workflows/builtin/goal-ledger.ts +33 -1
  41. package/dist/builtin/workflows/builtin/goal-prompts.ts +23 -28
  42. package/dist/builtin/workflows/builtin/goal-reducer.ts +2 -2
  43. package/dist/builtin/workflows/builtin/goal-reports.ts +2 -5
  44. package/dist/builtin/workflows/builtin/goal-review.ts +1 -1
  45. package/dist/builtin/workflows/builtin/goal-runner.ts +10 -17
  46. package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +3 -3
  47. package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +1 -3
  48. package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +1 -1
  49. package/dist/builtin/workflows/builtin/ralph-core.ts +7 -17
  50. package/dist/builtin/workflows/builtin/ralph-runner.ts +11 -18
  51. package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
  52. package/dist/builtin/workflows/package.json +1 -1
  53. package/dist/builtin/workflows/src/extension/config-loader.ts +35 -15
  54. package/dist/builtin/workflows/src/extension/discovery.ts +20 -8
  55. package/dist/builtin/workflows/src/extension/extension-runtime-state.ts +1 -2
  56. package/dist/builtin/workflows/src/extension/wiring.ts +1 -1
  57. package/dist/builtin/workflows/src/tui/dispatch-confirm.ts +11 -10
  58. package/dist/cli/args.d.ts.map +1 -1
  59. package/dist/cli/args.js +9 -9
  60. package/dist/cli/args.js.map +1 -1
  61. package/dist/config-self-update.d.ts.map +1 -1
  62. package/dist/config-self-update.js +3 -4
  63. package/dist/config-self-update.js.map +1 -1
  64. package/dist/config.d.ts.map +1 -1
  65. package/dist/config.js +4 -5
  66. package/dist/config.js.map +1 -1
  67. package/dist/core/agent-session-bash.d.ts +1 -0
  68. package/dist/core/agent-session-bash.d.ts.map +1 -1
  69. package/dist/core/agent-session-bash.js +1 -0
  70. package/dist/core/agent-session-bash.js.map +1 -1
  71. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  72. package/dist/core/agent-session-tool-registry.js +23 -0
  73. package/dist/core/agent-session-tool-registry.js.map +1 -1
  74. package/dist/core/bash-executor.d.ts +2 -0
  75. package/dist/core/bash-executor.d.ts.map +1 -1
  76. package/dist/core/bash-executor.js +1 -0
  77. package/dist/core/bash-executor.js.map +1 -1
  78. package/dist/core/compaction/compaction.d.ts +29 -0
  79. package/dist/core/compaction/compaction.d.ts.map +1 -1
  80. package/dist/core/compaction/compaction.js +36 -1
  81. package/dist/core/compaction/compaction.js.map +1 -1
  82. package/dist/core/compaction/context-compaction-metrics.d.ts +14 -2
  83. package/dist/core/compaction/context-compaction-metrics.d.ts.map +1 -1
  84. package/dist/core/compaction/context-compaction-metrics.js +50 -1
  85. package/dist/core/compaction/context-compaction-metrics.js.map +1 -1
  86. package/dist/core/compaction/context-compaction-prompt.d.ts.map +1 -1
  87. package/dist/core/compaction/context-compaction-prompt.js +2 -0
  88. package/dist/core/compaction/context-compaction-prompt.js.map +1 -1
  89. package/dist/core/compaction/context-compaction-runner.d.ts.map +1 -1
  90. package/dist/core/compaction/context-compaction-runner.js +1 -1
  91. package/dist/core/compaction/context-compaction-runner.js.map +1 -1
  92. package/dist/core/compaction/context-deletion-application.d.ts.map +1 -1
  93. package/dist/core/compaction/context-deletion-application.js +5 -5
  94. package/dist/core/compaction/context-deletion-application.js.map +1 -1
  95. package/dist/core/compaction/context-deletion-targets.d.ts +2 -0
  96. package/dist/core/compaction/context-deletion-targets.d.ts.map +1 -1
  97. package/dist/core/compaction/context-deletion-targets.js +23 -3
  98. package/dist/core/compaction/context-deletion-targets.js.map +1 -1
  99. package/dist/core/compaction/context-deletion-tool-definitions.d.ts +6 -0
  100. package/dist/core/compaction/context-deletion-tool-definitions.d.ts.map +1 -1
  101. package/dist/core/compaction/context-deletion-tool-definitions.js.map +1 -1
  102. package/dist/core/compaction/context-deletion-tools.d.ts.map +1 -1
  103. package/dist/core/compaction/context-deletion-tools.js +18 -10
  104. package/dist/core/compaction/context-deletion-tools.js.map +1 -1
  105. package/dist/core/compaction/context-transcript-analysis.d.ts.map +1 -1
  106. package/dist/core/compaction/context-transcript-analysis.js +2 -4
  107. package/dist/core/compaction/context-transcript-analysis.js.map +1 -1
  108. package/dist/core/copilot-gemini-tool-arguments.d.ts.map +1 -1
  109. package/dist/core/copilot-gemini-tool-arguments.js +2 -60
  110. package/dist/core/copilot-gemini-tool-arguments.js.map +1 -1
  111. package/dist/core/extensions/context-types.d.ts +2 -0
  112. package/dist/core/extensions/context-types.d.ts.map +1 -1
  113. package/dist/core/extensions/context-types.js.map +1 -1
  114. package/dist/core/extensions/index.d.ts +2 -2
  115. package/dist/core/extensions/index.d.ts.map +1 -1
  116. package/dist/core/extensions/index.js +1 -1
  117. package/dist/core/extensions/index.js.map +1 -1
  118. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  119. package/dist/core/extensions/loader-virtual-modules.js +11 -3
  120. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  121. package/dist/core/extensions/runner-context.d.ts.map +1 -1
  122. package/dist/core/extensions/runner-context.js +11 -0
  123. package/dist/core/extensions/runner-context.js.map +1 -1
  124. package/dist/core/extensions/tool-events.d.ts +13 -13
  125. package/dist/core/extensions/tool-events.d.ts.map +1 -1
  126. package/dist/core/extensions/tool-events.js +3 -3
  127. package/dist/core/extensions/tool-events.js.map +1 -1
  128. package/dist/core/extensions/types.d.ts +1 -1
  129. package/dist/core/extensions/types.d.ts.map +1 -1
  130. package/dist/core/extensions/types.js +1 -1
  131. package/dist/core/extensions/types.js.map +1 -1
  132. package/dist/core/flattened-tool-arguments.d.ts +18 -0
  133. package/dist/core/flattened-tool-arguments.d.ts.map +1 -1
  134. package/dist/core/flattened-tool-arguments.js +104 -0
  135. package/dist/core/flattened-tool-arguments.js.map +1 -1
  136. package/dist/core/sdk-exports.d.ts +1 -1
  137. package/dist/core/sdk-exports.d.ts.map +1 -1
  138. package/dist/core/sdk-exports.js +1 -1
  139. package/dist/core/sdk-exports.js.map +1 -1
  140. package/dist/core/sdk-types.d.ts +2 -2
  141. package/dist/core/sdk-types.d.ts.map +1 -1
  142. package/dist/core/sdk-types.js.map +1 -1
  143. package/dist/core/settings-manager-basic-accessors.d.ts +4 -0
  144. package/dist/core/settings-manager-basic-accessors.d.ts.map +1 -1
  145. package/dist/core/settings-manager-basic-accessors.js +18 -0
  146. package/dist/core/settings-manager-basic-accessors.js.map +1 -1
  147. package/dist/core/settings-manager-resource-accessors.d.ts +4 -0
  148. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  149. package/dist/core/settings-manager-resource-accessors.js +15 -0
  150. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  151. package/dist/core/settings-types.d.ts +11 -0
  152. package/dist/core/settings-types.d.ts.map +1 -1
  153. package/dist/core/settings-types.js.map +1 -1
  154. package/dist/core/system-prompt.d.ts +1 -1
  155. package/dist/core/system-prompt.d.ts.map +1 -1
  156. package/dist/core/system-prompt.js +3 -2
  157. package/dist/core/system-prompt.js.map +1 -1
  158. package/dist/core/tools/artifact-protocol.d.ts +11 -0
  159. package/dist/core/tools/artifact-protocol.d.ts.map +1 -0
  160. package/dist/core/tools/artifact-protocol.js +76 -0
  161. package/dist/core/tools/artifact-protocol.js.map +1 -0
  162. package/dist/core/tools/artifacts.d.ts +18 -0
  163. package/dist/core/tools/artifacts.d.ts.map +1 -0
  164. package/dist/core/tools/artifacts.js +90 -0
  165. package/dist/core/tools/artifacts.js.map +1 -0
  166. package/dist/core/tools/bash-async-jobs.d.ts +20 -0
  167. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -0
  168. package/dist/core/tools/bash-async-jobs.js +59 -0
  169. package/dist/core/tools/bash-async-jobs.js.map +1 -0
  170. package/dist/core/tools/bash-async-output.d.ts +10 -0
  171. package/dist/core/tools/bash-async-output.d.ts.map +1 -0
  172. package/dist/core/tools/bash-async-output.js +80 -0
  173. package/dist/core/tools/bash-async-output.js.map +1 -0
  174. package/dist/core/tools/bash-interceptor.d.ts +10 -0
  175. package/dist/core/tools/bash-interceptor.d.ts.map +1 -0
  176. package/dist/core/tools/bash-interceptor.js +39 -0
  177. package/dist/core/tools/bash-interceptor.js.map +1 -0
  178. package/dist/core/tools/bash-leading-cd.d.ts +7 -0
  179. package/dist/core/tools/bash-leading-cd.d.ts.map +1 -0
  180. package/dist/core/tools/bash-leading-cd.js +59 -0
  181. package/dist/core/tools/bash-leading-cd.js.map +1 -0
  182. package/dist/core/tools/bash-pty-native.d.ts +14 -0
  183. package/dist/core/tools/bash-pty-native.d.ts.map +1 -0
  184. package/dist/core/tools/bash-pty-native.js +71 -0
  185. package/dist/core/tools/bash-pty-native.js.map +1 -0
  186. package/dist/core/tools/bash.d.ts +28 -17
  187. package/dist/core/tools/bash.d.ts.map +1 -1
  188. package/dist/core/tools/bash.js +152 -35
  189. package/dist/core/tools/bash.js.map +1 -1
  190. package/dist/core/tools/block-resolver.d.ts +16 -0
  191. package/dist/core/tools/block-resolver.d.ts.map +1 -0
  192. package/dist/core/tools/block-resolver.js +74 -0
  193. package/dist/core/tools/block-resolver.js.map +1 -0
  194. package/dist/core/tools/conflict-registry.d.ts +16 -0
  195. package/dist/core/tools/conflict-registry.d.ts.map +1 -0
  196. package/dist/core/tools/conflict-registry.js +44 -0
  197. package/dist/core/tools/conflict-registry.js.map +1 -0
  198. package/dist/core/tools/directory-tree.d.ts +13 -0
  199. package/dist/core/tools/directory-tree.d.ts.map +1 -0
  200. package/dist/core/tools/directory-tree.js +81 -0
  201. package/dist/core/tools/directory-tree.js.map +1 -0
  202. package/dist/core/tools/edit.d.ts +4 -29
  203. package/dist/core/tools/edit.d.ts.map +1 -1
  204. package/dist/core/tools/edit.js +136 -228
  205. package/dist/core/tools/edit.js.map +1 -1
  206. package/dist/core/tools/fetch-url.d.ts +74 -0
  207. package/dist/core/tools/fetch-url.d.ts.map +1 -0
  208. package/dist/core/tools/fetch-url.js +518 -0
  209. package/dist/core/tools/fetch-url.js.map +1 -0
  210. package/dist/core/tools/find.d.ts +27 -9
  211. package/dist/core/tools/find.d.ts.map +1 -1
  212. package/dist/core/tools/find.js +400 -176
  213. package/dist/core/tools/find.js.map +1 -1
  214. package/dist/core/tools/glob-path-utils.d.ts +8 -0
  215. package/dist/core/tools/glob-path-utils.d.ts.map +1 -0
  216. package/dist/core/tools/glob-path-utils.js +26 -0
  217. package/dist/core/tools/glob-path-utils.js.map +1 -0
  218. package/dist/core/tools/grep.d.ts +12 -0
  219. package/dist/core/tools/grep.d.ts.map +1 -1
  220. package/dist/core/tools/grep.js +141 -17
  221. package/dist/core/tools/grep.js.map +1 -1
  222. package/dist/core/tools/hashline-engine/apply.d.ts +11 -0
  223. package/dist/core/tools/hashline-engine/apply.d.ts.map +1 -0
  224. package/dist/core/tools/hashline-engine/apply.js +752 -0
  225. package/dist/core/tools/hashline-engine/apply.js.map +1 -0
  226. package/dist/core/tools/hashline-engine/block.d.ts +40 -0
  227. package/dist/core/tools/hashline-engine/block.d.ts.map +1 -0
  228. package/dist/core/tools/hashline-engine/block.js +117 -0
  229. package/dist/core/tools/hashline-engine/block.js.map +1 -0
  230. package/dist/core/tools/hashline-engine/diff-preview.d.ts +15 -0
  231. package/dist/core/tools/hashline-engine/diff-preview.d.ts.map +1 -0
  232. package/dist/core/tools/hashline-engine/diff-preview.js +98 -0
  233. package/dist/core/tools/hashline-engine/diff-preview.js.map +1 -0
  234. package/dist/core/tools/hashline-engine/format.d.ts +71 -0
  235. package/dist/core/tools/hashline-engine/format.d.ts.map +1 -0
  236. package/dist/core/tools/hashline-engine/format.js +178 -0
  237. package/dist/core/tools/hashline-engine/format.js.map +1 -0
  238. package/dist/core/tools/hashline-engine/fs.d.ts +81 -0
  239. package/dist/core/tools/hashline-engine/fs.d.ts.map +1 -0
  240. package/dist/core/tools/hashline-engine/fs.js +143 -0
  241. package/dist/core/tools/hashline-engine/fs.js.map +1 -0
  242. package/dist/core/tools/hashline-engine/index.d.ts +18 -0
  243. package/dist/core/tools/hashline-engine/index.d.ts.map +1 -0
  244. package/dist/core/tools/hashline-engine/index.js +20 -0
  245. package/dist/core/tools/hashline-engine/index.js.map +1 -0
  246. package/dist/core/tools/hashline-engine/input.d.ts +101 -0
  247. package/dist/core/tools/hashline-engine/input.d.ts.map +1 -0
  248. package/dist/core/tools/hashline-engine/input.js +398 -0
  249. package/dist/core/tools/hashline-engine/input.js.map +1 -0
  250. package/dist/core/tools/hashline-engine/messages.d.ts +99 -0
  251. package/dist/core/tools/hashline-engine/messages.d.ts.map +1 -0
  252. package/dist/core/tools/hashline-engine/messages.js +144 -0
  253. package/dist/core/tools/hashline-engine/messages.js.map +1 -0
  254. package/dist/core/tools/hashline-engine/mismatch.d.ts +45 -0
  255. package/dist/core/tools/hashline-engine/mismatch.d.ts.map +1 -0
  256. package/dist/core/tools/hashline-engine/mismatch.js +90 -0
  257. package/dist/core/tools/hashline-engine/mismatch.js.map +1 -0
  258. package/dist/core/tools/hashline-engine/normalize.d.ts +21 -0
  259. package/dist/core/tools/hashline-engine/normalize.d.ts.map +1 -0
  260. package/dist/core/tools/hashline-engine/normalize.js +33 -0
  261. package/dist/core/tools/hashline-engine/normalize.js.map +1 -0
  262. package/dist/core/tools/hashline-engine/parser.d.ts +24 -0
  263. package/dist/core/tools/hashline-engine/parser.d.ts.map +1 -0
  264. package/dist/core/tools/hashline-engine/parser.js +381 -0
  265. package/dist/core/tools/hashline-engine/parser.js.map +1 -0
  266. package/dist/core/tools/hashline-engine/patcher.d.ts +118 -0
  267. package/dist/core/tools/hashline-engine/patcher.d.ts.map +1 -0
  268. package/dist/core/tools/hashline-engine/patcher.js +341 -0
  269. package/dist/core/tools/hashline-engine/patcher.js.map +1 -0
  270. package/dist/core/tools/hashline-engine/prefixes.d.ts +43 -0
  271. package/dist/core/tools/hashline-engine/prefixes.d.ts.map +1 -0
  272. package/dist/core/tools/hashline-engine/prefixes.js +135 -0
  273. package/dist/core/tools/hashline-engine/prefixes.js.map +1 -0
  274. package/dist/core/tools/hashline-engine/recovery.d.ts +41 -0
  275. package/dist/core/tools/hashline-engine/recovery.d.ts.map +1 -0
  276. package/dist/core/tools/hashline-engine/recovery.js +168 -0
  277. package/dist/core/tools/hashline-engine/recovery.js.map +1 -0
  278. package/dist/core/tools/hashline-engine/snapshots.d.ts +65 -0
  279. package/dist/core/tools/hashline-engine/snapshots.d.ts.map +1 -0
  280. package/dist/core/tools/hashline-engine/snapshots.js +108 -0
  281. package/dist/core/tools/hashline-engine/snapshots.js.map +1 -0
  282. package/dist/core/tools/hashline-engine/stream.d.ts +3 -0
  283. package/dist/core/tools/hashline-engine/stream.d.ts.map +1 -0
  284. package/dist/core/tools/hashline-engine/stream.js +111 -0
  285. package/dist/core/tools/hashline-engine/stream.js.map +1 -0
  286. package/dist/core/tools/hashline-engine/tokenizer.d.ts +69 -0
  287. package/dist/core/tools/hashline-engine/tokenizer.d.ts.map +1 -0
  288. package/dist/core/tools/hashline-engine/tokenizer.js +430 -0
  289. package/dist/core/tools/hashline-engine/tokenizer.js.map +1 -0
  290. package/dist/core/tools/hashline-engine/types.d.ts +166 -0
  291. package/dist/core/tools/hashline-engine/types.d.ts.map +1 -0
  292. package/dist/core/tools/hashline-engine/types.js +9 -0
  293. package/dist/core/tools/hashline-engine/types.js.map +1 -0
  294. package/dist/core/tools/hashline.d.ts +29 -0
  295. package/dist/core/tools/hashline.d.ts.map +1 -0
  296. package/dist/core/tools/hashline.js +110 -0
  297. package/dist/core/tools/hashline.js.map +1 -0
  298. package/dist/core/tools/index.d.ts +6 -4
  299. package/dist/core/tools/index.d.ts.map +1 -1
  300. package/dist/core/tools/index.js +52 -35
  301. package/dist/core/tools/index.js.map +1 -1
  302. package/dist/core/tools/notebook.d.ts +38 -0
  303. package/dist/core/tools/notebook.d.ts.map +1 -0
  304. package/dist/core/tools/notebook.js +125 -0
  305. package/dist/core/tools/notebook.js.map +1 -0
  306. package/dist/core/tools/read-document-extract.d.ts +9 -0
  307. package/dist/core/tools/read-document-extract.d.ts.map +1 -0
  308. package/dist/core/tools/read-document-extract.js +212 -0
  309. package/dist/core/tools/read-document-extract.js.map +1 -0
  310. package/dist/core/tools/read-selectors.d.ts +24 -0
  311. package/dist/core/tools/read-selectors.d.ts.map +1 -0
  312. package/dist/core/tools/read-selectors.js +277 -0
  313. package/dist/core/tools/read-selectors.js.map +1 -0
  314. package/dist/core/tools/read-url.d.ts +37 -0
  315. package/dist/core/tools/read-url.d.ts.map +1 -0
  316. package/dist/core/tools/read-url.js +39 -0
  317. package/dist/core/tools/read-url.js.map +1 -0
  318. package/dist/core/tools/read.d.ts +11 -11
  319. package/dist/core/tools/read.d.ts.map +1 -1
  320. package/dist/core/tools/read.js +224 -94
  321. package/dist/core/tools/read.js.map +1 -1
  322. package/dist/core/tools/resource-selectors.d.ts +44 -0
  323. package/dist/core/tools/resource-selectors.d.ts.map +1 -0
  324. package/dist/core/tools/resource-selectors.js +808 -0
  325. package/dist/core/tools/resource-selectors.js.map +1 -0
  326. package/dist/core/tools/search-details.d.ts +26 -0
  327. package/dist/core/tools/search-details.d.ts.map +1 -0
  328. package/dist/core/tools/search-details.js +24 -0
  329. package/dist/core/tools/search-details.js.map +1 -0
  330. package/dist/core/tools/search-line-ranges.d.ts +11 -0
  331. package/dist/core/tools/search-line-ranges.d.ts.map +1 -0
  332. package/dist/core/tools/search-line-ranges.js +65 -0
  333. package/dist/core/tools/search-line-ranges.js.map +1 -0
  334. package/dist/core/tools/search-native.d.ts +97 -0
  335. package/dist/core/tools/search-native.d.ts.map +1 -0
  336. package/dist/core/tools/search-native.js +27 -0
  337. package/dist/core/tools/search-native.js.map +1 -0
  338. package/dist/core/tools/search.d.ts +24 -0
  339. package/dist/core/tools/search.d.ts.map +1 -0
  340. package/dist/core/tools/search.js +573 -0
  341. package/dist/core/tools/search.js.map +1 -0
  342. package/dist/core/tools/truncate.d.ts +4 -4
  343. package/dist/core/tools/truncate.d.ts.map +1 -1
  344. package/dist/core/tools/truncate.js +3 -3
  345. package/dist/core/tools/truncate.js.map +1 -1
  346. package/dist/core/tools/url-ip-guards.d.ts +4 -0
  347. package/dist/core/tools/url-ip-guards.d.ts.map +1 -0
  348. package/dist/core/tools/url-ip-guards.js +126 -0
  349. package/dist/core/tools/url-ip-guards.js.map +1 -0
  350. package/dist/core/tools/write.d.ts +12 -2
  351. package/dist/core/tools/write.d.ts.map +1 -1
  352. package/dist/core/tools/write.js +166 -14
  353. package/dist/core/tools/write.js.map +1 -1
  354. package/dist/core/trust-manager.d.ts.map +1 -1
  355. package/dist/core/trust-manager.js +2 -3
  356. package/dist/core/trust-manager.js.map +1 -1
  357. package/dist/index-extensions.d.ts +2 -2
  358. package/dist/index-extensions.d.ts.map +1 -1
  359. package/dist/index-extensions.js +1 -1
  360. package/dist/index-extensions.js.map +1 -1
  361. package/dist/index.d.ts +3 -3
  362. package/dist/index.d.ts.map +1 -1
  363. package/dist/index.js +3 -3
  364. package/dist/index.js.map +1 -1
  365. package/dist/modes/interactive/components/custom-editor.d.ts +1 -0
  366. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/custom-editor.js +9 -2
  368. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  369. package/dist/modes/interactive/components/settings-selector-handlers.d.ts.map +1 -1
  370. package/dist/modes/interactive/components/settings-selector-handlers.js +3 -0
  371. package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
  372. package/dist/modes/interactive/components/settings-selector-items.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/settings-selector-items.js +7 -0
  374. package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
  375. package/dist/modes/interactive/components/settings-selector-types.d.ts +2 -0
  376. package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
  378. package/dist/modes/interactive/components/tree-selector-content.d.ts.map +1 -1
  379. package/dist/modes/interactive/components/tree-selector-content.js +0 -5
  380. package/dist/modes/interactive/components/tree-selector-content.js.map +1 -1
  381. package/dist/modes/interactive/interactive-auth-login.d.ts.map +1 -1
  382. package/dist/modes/interactive/interactive-auth-login.js +1 -0
  383. package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
  384. package/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
  385. package/dist/modes/interactive/interactive-autocomplete.js +80 -2
  386. package/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
  387. package/dist/modes/interactive/interactive-hotkeys-debug.d.ts.map +1 -1
  388. package/dist/modes/interactive/interactive-hotkeys-debug.js +3 -0
  389. package/dist/modes/interactive/interactive-hotkeys-debug.js.map +1 -1
  390. package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
  391. package/dist/modes/interactive/interactive-input-handling.js +51 -0
  392. package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
  393. package/dist/modes/interactive/interactive-mode-base.d.ts +5 -0
  394. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  395. package/dist/modes/interactive/interactive-mode-base.js +5 -0
  396. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  397. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  398. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  399. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  400. package/dist/modes/interactive/interactive-mode-surface.d.ts +12 -0
  401. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  402. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  403. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  404. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  405. package/dist/modes/interactive/interactive-mode.js +1 -0
  406. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  407. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  408. package/dist/modes/interactive/interactive-model-routing.js +4 -1
  409. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  410. package/dist/modes/interactive/interactive-onboarding.d.ts +11 -0
  411. package/dist/modes/interactive/interactive-onboarding.d.ts.map +1 -0
  412. package/dist/modes/interactive/interactive-onboarding.js +220 -0
  413. package/dist/modes/interactive/interactive-onboarding.js.map +1 -0
  414. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  415. package/dist/modes/interactive/interactive-selectors.js +4 -0
  416. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  417. package/dist/modes/interactive/interactive-session-routing.d.ts.map +1 -1
  418. package/dist/modes/interactive/interactive-session-routing.js +6 -0
  419. package/dist/modes/interactive/interactive-session-routing.js.map +1 -1
  420. package/dist/modes/interactive/interactive-slash-commands.d.ts.map +1 -1
  421. package/dist/modes/interactive/interactive-slash-commands.js +9 -4
  422. package/dist/modes/interactive/interactive-slash-commands.js.map +1 -1
  423. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  424. package/dist/modes/interactive/interactive-startup.js +28 -0
  425. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  426. package/dist/utils/child-process.d.ts.map +1 -1
  427. package/dist/utils/child-process.js +21 -1
  428. package/dist/utils/child-process.js.map +1 -1
  429. package/dist/utils/markit.d.ts +8 -0
  430. package/dist/utils/markit.d.ts.map +1 -0
  431. package/dist/utils/markit.js +53 -0
  432. package/dist/utils/markit.js.map +1 -0
  433. package/dist/utils/paths.d.ts +2 -1
  434. package/dist/utils/paths.d.ts.map +1 -1
  435. package/dist/utils/paths.js +14 -1
  436. package/dist/utils/paths.js.map +1 -1
  437. package/docs/compaction.md +16 -1
  438. package/docs/containerization.md +1 -1
  439. package/docs/docs.json +1 -0
  440. package/docs/extensions.md +25 -36
  441. package/docs/quickstart.md +11 -6
  442. package/docs/sdk.md +5 -5
  443. package/docs/settings.md +7 -0
  444. package/docs/subagents.md +3 -2
  445. package/docs/tools.md +49 -0
  446. package/docs/usage.md +3 -3
  447. package/docs/workflows.md +7 -5
  448. package/examples/extensions/subagent/README.md +5 -5
  449. package/examples/extensions/subagent/agents/planner.md +1 -1
  450. package/examples/extensions/subagent/agents/reviewer.md +1 -1
  451. package/examples/extensions/subagent/agents/scout.md +2 -2
  452. package/examples/extensions/subagent/display.ts +3 -3
  453. package/examples/sdk/05-tools.ts +3 -3
  454. package/examples/sdk/README.md +1 -1
  455. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-url.js","sourceRoot":"","sources":["../../../src/core/tools/fetch-url.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,eAAe,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,OAAO,IAAI,aAAa,EAAmB,MAAM,QAAQ,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGrF,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,uBAAuB,GAAG,MAAM,CAAC;AACvC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,sBAAsB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAChD,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAoC/B,MAAM,YAAY,GAAG,IAAI,QAAQ,CAA4B,EAAE,GAAG,EAAE,0BAA0B,EAAE,CAAC,CAAC;AAClG,IAAI,QAAqC,CAAC;AAC1C,SAAS,WAAW;IACnB,IAAI,CAAC,QAAQ;QAAE,QAAQ,GAAG,IAAI,eAAe,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC;IACxH,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAChD,OAAO,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IACjD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACjD,OAAO,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACxC,MAAM,QAAQ,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/D,OAAO,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,QAAQ,EAAE,CAAC;AAC1E,CAAC;AACD,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAClE,MAAM,cAAc,GAAG,8BAA8B,CAAC;AAEtD,SAAS,kBAAkB,CAAC,KAAa;IACxC,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzF,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QACnF,OAAO,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;IAC/E,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACpD,IAAI,KAAK,EAAE,CAAC;QAAC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAAC,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAAC,OAAO,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAAC,CAAC;IACtK,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,MAAM,EAAE,CAAC;QAAC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAAC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IAAC,CAAC;IACxG,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAAC,CAAC;IAC5G,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,6BAA6B,CAAC,QAAgB;IACtD,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,SAAS,CAAC;QACT,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACjD,IAAI,cAAc,IAAI,CAAC;YAAE,MAAM;QAC/B,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACpD,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC;YAAE,MAAM;QAC3E,IAAI,CAAC;YAAC,IAAI,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,MAAM;QAAC,CAAC;QAC3I,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxB,QAAQ,GAAG,SAAS,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IAClD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,6BAA6B,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAC;IAC3C,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,IAAI,MAA+B,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,GAAG,GAAG,IAAI,CAAC;YAAC,SAAS;QAAC,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;QACpI,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;QAClE,MAAM,GAAG,MAAM,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACjE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAC7G,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,YAAoB,EAAE,GAAY;IACnF,OAAO,GAAG,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,oBAAoB,CAAC,YAAY,CAAC,EAAE,CAAC;AACvF,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IAClC,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,gCAAgC,CAAC,WAAmB;IAC5D,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5C,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,IAAI,wCAAwC,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/E,IAAI,8CAA8C,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAC;IACrF,IAAI,mCAAmC,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC;IACzE,IAAI,4CAA4C,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAC;IACnF,IAAI,yBAAyB,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/D,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,OAAO,CAAC;IAC9C,IAAI,yBAAyB,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,QAAQ,CAAC;IACjE,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5C,OAAO,SAAS,CAAC;AAClB,CAAC;AAKD,SAAS,sBAAsB,CAAC,MAAwB;IACvD,OAAO,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,SAAiB,EAAE,OAA0B,EAAE,QAAwB,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG;gBAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;;gBAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC5N,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,UAA6B;IACjE,MAAM,KAAK,GAAI,UAAiE,EAAE,KAAK,CAAC;IACxF,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC/D,CAAC;AACD;;;;;;;GAOG;AACH,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,UAAsB,EAAE,OAAkE;IACjI,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACzH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC;IACjC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAwD,CAAC,EAAE,CAAC;QAC5G,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;QACjC,KAAK,CAAC,UAAU,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAc,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7M,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;KAC5B,CAAC,CAAC;IACH,OAAO,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAClD,CAAC;AAGD,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjI,IAAI,OAAO,CAAC,GAAG,CAAC,8BAA8B,KAAK,GAAG;QAAE,OAAO,SAAS,CAAC;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1F,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,KAAK,0BAA0B;QAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;IACjL,MAAM,cAAc,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,cAAc,EAAE,CAAC;QAAC,IAAI,kBAAkB,CAAC,cAAc,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,CAAC;IAC1N,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7M,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,yBAAyB,CAAC,CAAC;IAC7G,KAAK,MAAM,OAAO,IAAI,SAAS;QAAE,IAAI,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;IAC/I,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC;IAC5B,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACrF,CAAC;AAED,KAAK,UAAU,yBAAyB,CAAC,QAAkB;IAC1D,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAAC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QAAC,IAAI,MAAM,CAAC,MAAM,GAAG,sBAAsB;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,sBAAsB,aAAa,CAAC,CAAC;QAAC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAAC,CAAC;IAC3O,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,SAAS,CAAC;QACT,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI;YAAE,MAAM;QAChB,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC;QAC/B,IAAI,UAAU,GAAG,sBAAsB,EAAE,CAAC;YAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,wBAAwB,sBAAsB,aAAa,CAAC,CAAC;QAAC,CAAC;QACjJ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,SAAiB,EAAE,MAAoB,EAAE,MAAe;IACnG,GAAG,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACjG,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC/C,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC;QACJ,IAAI,UAAU,GAAG,GAAG,CAAC;QACrB,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,IAAI,iBAAiB,EAAE,SAAS,EAAE,EAAE,CAAC;YACrE,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,UAAU,CAAC,CAAC;YACpD,mEAAmE;YACnE,mEAAmE;YACnE,+DAA+D;YAC/D,MAAM,UAAU,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC/E,IAAI,CAAC;gBACJ,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBACxD,iEAAiE;gBACjE,kEAAkE;gBAClE,yDAAyD;gBACzD,MAAM,QAAQ,GAAG,UAAU;oBAC1B,CAAC,CAAC,MAAM,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;oBACnF,CAAC,CAAC,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACvF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;oBAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBAAC,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAE,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC;oBAAC,SAAS;gBAAC,CAAC;gBAC/N,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;gBACzF,IAAI,aAAa,GAAG,sBAAsB;oBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,sBAAsB,gBAAgB,UAAU,EAAE,CAAC,CAAC;gBACxI,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC/D,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,QAAQ,CAAC,CAAC;gBAC1D,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;YACjH,CAAC;oBAAS,CAAC;gBACV,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAChE,CAAC;QACF,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACrD,CAAC;AACF,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,2GAA2G,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI;QAAE,OAAO,IAAI,CAAC;IACzK,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC9E,IAAI,QAAQ,CAAC,MAAM,GAAG,EAAE,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,IAAI,CAAC;IAC3H,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,GAAW;IAC9C,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,SAAS,CAAC;IAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,IAAI,MAAM,CAAC,QAAQ,KAAK,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE;QAAE,OAAO,CAAC,GAAG,MAAM,uBAAuB,EAAE,GAAG,MAAM,WAAW,EAAE,GAAG,MAAM,UAAU,CAAC,CAAC;IAC5I,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACjG,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACxE,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/D,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,WAAW,EAAE,GAAG,IAAI,UAAU,CAAC,CAAC;IACxD,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,GAAG,MAAM,WAAW,EAAE,GAAG,MAAM,UAAU,CAAC,CAAC;IAC3D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,MAAoB;IAC/D,KAAK,MAAM,QAAQ,IAAI,0BAA0B,CAAC,GAAG,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YACpD,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;QAC5I,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,SAAS,0BAA0B,CAAC,IAAY,EAAE,OAAe;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,IAAI,GAAG,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9D,MAAM,IAAI,GAAG,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;YAAE,SAAS;QAC/C,IAAI,8CAA8C,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QACxE,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC;gBAAC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACrD,CAAC;IACF,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,MAAoB;IAC3D,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC;SACvD,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;;QACxD,UAAU,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,EAAE,GAAG,GAAG,gBAAgB,CAAC,CAAC;IAC1D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YACrD,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAC,OAAO,CAAC;QACrH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,qBAAqB,CAAC,GAAW,EAAE,MAAoB;IACrE,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,kDAAkD,CAAC,CAAC;QACnG,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC;IACnL,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,IAAI,CAAC;AACb,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,GAAY,EAAE,MAAoB;IAC9E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,IAAI,QAAgB,CAAC;IACrB,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,uBAAuB,EAAE,MAAM,CAAC,CAAC;IAClE,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IACzB,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,+BAA+B,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAClK,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACzG,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,gCAAgC,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjJ,IAAI,MAAM,EAAE,CAAC;QACZ,IAAI,CAAC;YAAC,IAAI,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC,CAAC;YAAC,MAAM,GAAG,UAAU,CAAC;QAAC,CAAC;QAClG,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,GAAG,gBAAgB,MAAM,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,GAAG,CAAC;YAAC,MAAM,GAAG,gBAAgB,CAAC;QAAC,CAAC;QACpJ,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxE,IAAI,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjE,IAAI,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;gBAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;oBAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;gBAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAAC,CAAC;QAC/W,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,EAAE;YAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACrK,MAAM,GAAG,GAAG,MAAM,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QAC5L,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3D,MAAM,GAAG,QAAQ,CAAC;QAClB,IAAI,QAAQ,CAAC,MAAM,IAAI,kBAAkB,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACrD,IAAI,IAAI,EAAE,CAAC;gBAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;YAAC,CAAC;YACpJ,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,GAAG,QAAQ,CAAC;IACjB,CAAC;SAAM,CAAC;QACP,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IACrD,MAAM,MAAM,GAAG,CAAC,QAAQ,MAAM,CAAC,QAAQ,EAAE,EAAE,iBAAiB,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChM,OAAO,GAAG,MAAM,cAAc,MAAM,CAAC,OAAO,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,sBAAsB,CAAC,YAAgC,EAAE,MAAc;IAC/E,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IACpC,OAAO,kBAAkB,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC9D,CAAC;AAeD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,MAAuC,EAAE,YAAgC,EAAE,MAAoB;IACrJ,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC;IACrC,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACvD,IAAI,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,sBAAsB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAChE,MAAM,OAAO,GAAuB,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QACtP,KAAK,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACxC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC;AAC5F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,MAAuC,EAAE,YAAgC,EAAE,MAAoB;IAClJ,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;IAChG,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAC7D,IAAI,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,oBAAoB,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,oBAAoB,GAAG,iBAAiB,CAAC;IAC/D,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,GAAG,uBAAuB,CAAC;IAC7D,IAAI,aAAa;QAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,aAAa,IAAI,aAAa,CAAC;IACjD,IAAI,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IAClC,IAAI,SAAS,IAAI,CAAC,UAAU;QAAE,UAAU,GAAG,sBAAsB,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9F,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC1E,MAAM,UAAU,GAAiC,SAAS,CAAC,CAAC,CAAC;QAC5D,OAAO;QACP,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;QAC9C,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;QACnD,WAAW;QACX,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;QAC/C,eAAe,EAAE,aAAa;QAC9B,qBAAqB,EAAE,KAAK;QAC5B,QAAQ,EAAE,uBAAuB;QACjC,QAAQ,EAAE,iBAAiB;KAC3B,CAAC,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,OAAO,GAAuB,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IAC3L,IAAI,SAAS;QAAE,OAAO,IAAI,sBAAsB,YAAY,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,UAAU,UAAU,CAAC,CAAC,CAAC,4BAA4B,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAC9J,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAChC,YAAY,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC","sourcesContent":["/// <reference path=\"../../utils/turndown.d.ts\" />\n/**\n * URL fetch / cache / artifact / markdown-discovery pipeline, mirrored from\n * oh-my-pi's `packages/coding-agent/src/tools/fetch.ts` at 15b5c1397fc.\n *\n * Responsibilities:\n * - parseReadUrlTarget: URL + line selectors (:raw, :N, :A-B, :A+B, :A-B,C-D),\n * collapsed-scheme repair, host-port protection.\n * - session-scoped LRU cache keyed by `<scope>::<raw|rendered>::<normalizedUrl>`,\n * cached under both requested and final (redirected) URLs.\n * - renderUrl: markdown discovery (alternate <link>, .md suffix, content\n * negotiation, llms.txt/llms.md endpoints) + native HTML-to-markdown, with\n * quality gating.\n * - artifact persistence of the rendered output, with artifactId surfaced in\n * truncation metadata when the visible output is head-truncated.\n */\nimport { lookup } from \"node:dns/promises\";\nimport { ipFamily, isPrivateIpAddress, normalizeIpLiteralHost } from \"./url-ip-guards.ts\";\nimport { LRUCache } from \"lru-cache\";\nimport TurndownService from \"turndown\";\nimport { Agent, request as undiciRequest, type Dispatcher } from \"undici\";\nimport { getArtifactManager } from \"./artifacts.ts\";\nimport { extractDocumentMarkdown, isDocumentPath } from \"./read-document-extract.ts\";\nimport type { TruncationResult } from \"./truncate.ts\";\n\nexport const FETCH_DEFAULT_MAX_LINES = 300;\nexport const READ_URL_CACHE_MAX_ENTRIES = 100;\nconst REMOTE_FETCH_TIMEOUT_MS = 10_000;\nconst MAX_URL_REDIRECTS = 5;\nconst MAX_URL_RESPONSE_BYTES = 10 * 1024 * 1024;\nconst MIN_CONTENT_LENGTH = 100;\n\nexport interface LineRange { start: number; end?: number }\n\nexport interface ParsedReadUrlTarget {\n\turl: string;\n\traw: boolean;\n\toffset?: number;\n\tlimit?: number;\n\tranges?: readonly LineRange[];\n}\n\nexport interface ReadUrlToolDetails {\n\turl: string;\n\tfinalUrl: string;\n\tcontentType: string;\n\tmethod: string;\n\ttruncated: boolean;\n\tnotes: string[];\n\tmeta?: { artifactId?: string; truncation?: TruncationResult };\n}\n\ninterface ReadUrlCacheEntry {\n\tartifactId?: string;\n\tdetails: ReadUrlToolDetails;\n\toutput: string;\n}\n\nexport interface LoadedPage {\n\tok: boolean;\n\tstatus: number;\n\tcontent: string;\n\tcontentType: string;\n\tfinalUrl: string;\n}\n\nconst readUrlCache = new LRUCache<string, ReadUrlCacheEntry>({ max: READ_URL_CACHE_MAX_ENTRIES });\nlet turndown: TurndownService | undefined;\nfunction getTurndown(): TurndownService {\n\tif (!turndown) turndown = new TurndownService({ headingStyle: \"atx\", codeBlockStyle: \"fenced\", bulletListMarker: \"-\" });\n\treturn turndown;\n}\n\nexport function repairCollapsedScheme(url: string): string {\n\treturn url.replace(/^(https?):\\/([^/])/i, \"$1://$2\");\n}\n\nexport function isReadableUrlPath(readPath: string): boolean {\n\tconst repaired = repairCollapsedScheme(readPath);\n\treturn /^https?:\\/\\//i.test(repaired) || /^www\\./i.test(readPath);\n}\n\nfunction normalizeUrlForCache(url: string): string {\n\tconst repaired = repairCollapsedScheme(url);\n\tif (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(repaired)) return repaired;\n\treturn /^https?:\\/\\//i.test(repaired) ? repaired : `https://${repaired}`;\n}\nconst RANGE_TOKEN_RE = /^(raw|\\d+(?:\\+(?:\\d+)|(?:-|\\.\\.)\\d+)?)$/i;\nconst MULTI_RANGE_RE = /^\\d+(?:(?:-|\\.\\.|,|\\+)\\d+)*$/;\n\nfunction isUrlSelectorToken(token: string): boolean {\n\treturn /^raw$/i.test(token) || RANGE_TOKEN_RE.test(token) || MULTI_RANGE_RE.test(token);\n}\n\nfunction parseSingleRange(token: string): LineRange | undefined {\n\tconst plus = token.match(/^(\\d+)\\+(\\d+)$/);\n\tif (plus) {\n\t\tconst start = Number.parseInt(plus[1]!, 10), count = Number.parseInt(plus[2]!, 10);\n\t\treturn start < 1 || count < 1 ? undefined : { start, end: start + count - 1 };\n\t}\n\tconst range = token.match(/^(\\d+)(?:-|\\.\\.)(\\d+)$/);\n\tif (range) { const start = Number.parseInt(range[1]!, 10); const end = Number.parseInt(range[2]!, 10); return start < 1 || end < start ? undefined : { start, end }; }\n\tconst single = token.match(/^(\\d+)$/);\n\tif (single) { const start = Number.parseInt(single[1]!, 10); return start < 1 ? undefined : { start }; }\n\treturn undefined;\n}\n\nfunction parseRangeGroup(token: string): LineRange[] | undefined {\n\tconst groups = token.split(\",\");\n\tconst ranges: LineRange[] = [];\n\tfor (const group of groups) { const r = parseSingleRange(group); if (!r) return undefined; ranges.push(r); }\n\treturn ranges;\n}\n\nfunction tryExtractEmbeddedUrlSelector(readPath: string): { path: string; sels: string[] } | null {\n\tlet basePath = readPath;\n\tconst sels: string[] = [];\n\tfor (;;) {\n\t\tconst lastColonIndex = basePath.lastIndexOf(\":\");\n\t\tif (lastColonIndex <= 0) break;\n\t\tconst candidate = basePath.slice(lastColonIndex + 1);\n\t\tconst remainder = basePath.slice(0, lastColonIndex);\n\t\tif (!isReadableUrlPath(remainder) || !isUrlSelectorToken(candidate)) break;\n\t\ttry { new URL(remainder.startsWith(\"http://\") || remainder.startsWith(\"https://\") ? remainder : `https://${remainder}`); } catch { break; }\n\t\tsels.unshift(candidate);\n\t\tbasePath = remainder;\n\t}\n\treturn sels.length === 0 ? null : { path: basePath, sels };\n}\n\nexport function parseReadUrlTarget(readPath: string): ParsedReadUrlTarget | null {\n\tconst repaired = repairCollapsedScheme(readPath);\n\tconst embedded = tryExtractEmbeddedUrlSelector(repaired);\n\tconst urlPath = embedded?.path ?? repaired;\n\tif (!isReadableUrlPath(urlPath)) return null;\n\tlet raw = false;\n\tlet ranges: LineRange[] | undefined;\n\tfor (const sel of embedded?.sels ?? []) {\n\t\tif (/^raw$/i.test(sel)) { raw = true; continue; }\n\t\tif (ranges !== undefined) throw new Error(\"URL selector has multiple range groups; combine them with commas (e.g. `:5-10,20-30`).\");\n\t\tconst parsed = parseRangeGroup(sel);\n\t\tif (!parsed) throw new Error(`Invalid URL line selector: ${sel}`);\n\t\tranges = parsed;\n\t}\n\tif (!ranges || ranges.length === 0) return { url: urlPath, raw };\n\tif (ranges.length === 1) {\n\t\tconst r = ranges[0]!;\n\t\treturn { url: urlPath, raw, offset: r.start, limit: r.end !== undefined ? r.end - r.start + 1 : undefined };\n\t}\n\treturn { url: urlPath, raw, ranges };\n}\n\nexport function getReadUrlCacheKey(scope: string, requestedUrl: string, raw: boolean): string {\n\treturn `${scope}::${raw ? \"raw\" : \"rendered\"}::${normalizeUrlForCache(requestedUrl)}`;\n}\n\nfunction looksLikeHtml(text: string): boolean {\n\treturn /<html[\\s>]/i.test(text) || (/<head[\\s>]/i.test(text) && /<body[\\s>]/i.test(text));\n}\n\nfunction documentExtensionFromContentType(contentType: string): string | undefined {\n\tif (/pdf/i.test(contentType)) return \".pdf\";\n\tif (/msword/i.test(contentType)) return \".doc\";\n\tif (/wordprocessingml|officedocument\\.word/i.test(contentType)) return \".docx\";\n\tif (/presentationml|officedocument\\.presentation/i.test(contentType)) return \".pptx\";\n\tif (/ms-powerpoint|vnd\\.ms-powerpoint/i.test(contentType)) return \".ppt\";\n\tif (/spreadsheetml|officedocument\\.spreadsheet/i.test(contentType)) return \".xlsx\";\n\tif (/ms-excel|vnd\\.ms-excel/i.test(contentType)) return \".xls\";\n\tif (/epub/i.test(contentType)) return \".epub\";\n\tif (/\\bjson\\b|ipynb|jupyter/i.test(contentType)) return \".ipynb\";\n\tif (/rtf/i.test(contentType)) return \".rtf\";\n\treturn undefined;\n}\n\ninterface SafeFetchAddress { address: string; family: 4 | 6; /** True only when the address came from DNS resolution and must be pinned to prevent rebinding at connect time. */ pinned: boolean }\ntype LookupCallback = (error: NodeJS.ErrnoException | null, address: string | SafeFetchAddress[], family?: number) => void;\n\nfunction createPinnedDispatcher(pinned: SafeFetchAddress): Agent {\n\treturn new Agent({ connect: { lookup: (_hostname: string, options: { all?: boolean }, callback: LookupCallback) => { if (options.all) callback(null, [pinned]); else callback(null, pinned.address, pinned.family); } } });\n}\n\nasync function closePinnedDispatcher(dispatcher: Agent | undefined): Promise<void> {\n\tconst close = (dispatcher as { close?: () => Promise<void> | void } | undefined)?.close;\n\tif (typeof close === \"function\") await close.call(dispatcher);\n}\n/**\n * Fetch a URL through undici with the pinned dispatcher so the validated\n * address is the one actually connected to. Unlike `globalThis.fetch`, which\n * silently ignores the undici `dispatcher` option under Bun's compiled binary\n * (reopening a DNS-rebinding TOCTOU window for hostname targets), undici's own\n * client honors the dispatcher's custom `lookup` regardless of host runtime.\n * Adapts the undici response to the WHATWG-Response shape loadPage consumes.\n */\nasync function pinnedFetch(url: string, dispatcher: Dispatcher, options: { signal: AbortSignal; headers?: Record<string, string> }): Promise<Response> {\n\tconst result = await undiciRequest(url, { method: \"GET\", dispatcher, signal: options.signal, headers: options.headers });\n\tconst body = result.body;\n\tconst status = result.statusCode;\n\tconst headers = new Headers();\n\tfor (const [key, value] of Object.entries(result.headers as Record<string, string | string[] | undefined>)) {\n\t\tif (value === undefined) continue;\n\t\tconst values = Array.isArray(value) ? value : [value];\n\t\tfor (const entry of values) headers.append(key, entry);\n\t}\n\tconst stream = new ReadableStream({\n\t\tstart(controller) { body.on(\"data\", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk))); body.on(\"end\", () => controller.close()); body.on(\"error\", (error: unknown) => controller.error(error)); },\n\t\tcancel() { body.destroy(); },\n\t});\n\treturn new Response(stream, { status, headers });\n}\n\n\nasync function assertSafeFetchUrl(url: string): Promise<SafeFetchAddress | undefined> {\n\tconst parsed = new URL(url);\n\tif (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") throw new Error(`Unsupported URL protocol: ${parsed.protocol}`);\n\tif (process.env.ATOMIC_ALLOW_PRIVATE_URL_READS === \"1\") return undefined;\n\tconst hostname = parsed.hostname.replace(/^\\[|\\]$/g, \"\").replace(/\\.$/, \"\").toLowerCase();\n\tif (hostname === \"localhost\" || hostname.endsWith(\".localhost\") || hostname === \"metadata.google.internal\") throw new Error(`Refusing to fetch private or metadata URL: ${url}`);\n\tconst literalAddress = normalizeIpLiteralHost(hostname);\n\tif (literalAddress) { if (isPrivateIpAddress(literalAddress)) throw new Error(`Refusing to fetch private or metadata URL: ${url}`); return { address: literalAddress, family: ipFamily(literalAddress), pinned: false }; }\n\tconst addresses = await lookup(hostname, { all: true }).catch((error: unknown) => { throw new Error(`Could not resolve URL host ${hostname}: ${error instanceof Error ? error.message : String(error)}`); });\n\tif (addresses.length === 0) throw new Error(`Could not resolve URL host ${hostname}: no addresses returned`);\n\tfor (const address of addresses) if (isPrivateIpAddress(address.address)) throw new Error(`Refusing to fetch private or metadata URL: ${url}`);\n\tconst first = addresses[0]!;\n\treturn { address: first.address, family: first.family === 6 ? 6 : 4, pinned: true };\n}\n\nasync function readResponseTextWithLimit(response: Response): Promise<string> {\n\tif (!response.body) { const buffer = Buffer.from(await response.arrayBuffer()); if (buffer.length > MAX_URL_RESPONSE_BYTES) throw new Error(`URL response exceeds ${MAX_URL_RESPONSE_BYTES} byte limit`); return buffer.toString(\"utf8\"); }\n\tconst reader = response.body.getReader();\n\tconst decoder = new TextDecoder();\n\tconst chunks: string[] = [];\n\tlet totalBytes = 0;\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\ttotalBytes += value.byteLength;\n\t\tif (totalBytes > MAX_URL_RESPONSE_BYTES) { await reader.cancel(); throw new Error(`URL response exceeds ${MAX_URL_RESPONSE_BYTES} byte limit`); }\n\t\tchunks.push(decoder.decode(value, { stream: true }));\n\t}\n\tchunks.push(decoder.decode());\n\treturn chunks.join(\"\");\n}\nexport async function loadPage(url: string, timeoutMs: number, signal?: AbortSignal, accept?: string): Promise<LoadedPage> {\n\turl = normalizeUrlForCache(url);\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), Math.min(timeoutMs, REMOTE_FETCH_TIMEOUT_MS));\n\tconst onParentAbort = () => controller.abort();\n\tsignal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\ttry {\n\t\tlet currentUrl = url;\n\t\tfor (let redirects = 0; redirects <= MAX_URL_REDIRECTS; redirects++) {\n\t\t\tconst pinned = await assertSafeFetchUrl(currentUrl);\n\t\t\t// Only a DNS-resolved hostname needs pinning: a literal-IP host is\n\t\t\t// validated directly and cannot be re-resolved at connect time, so\n\t\t\t// global fetch is sufficient and stays redirect/mock-friendly.\n\t\t\tconst dispatcher = pinned?.pinned ? createPinnedDispatcher(pinned) : undefined;\n\t\t\ttry {\n\t\t\t\tconst headers = accept ? { Accept: accept } : undefined;\n\t\t\t\t// Route pinned (hostname) fetches through undici directly so the\n\t\t\t\t// dispatcher's custom lookup is honored even under Bun's compiled\n\t\t\t\t// fetch, which silently ignores the `dispatcher` option.\n\t\t\t\tconst response = dispatcher\n\t\t\t\t\t? await pinnedFetch(currentUrl, dispatcher, { signal: controller.signal, headers })\n\t\t\t\t\t: await fetch(currentUrl, { signal: controller.signal, headers, redirect: \"manual\" });\n\t\t\t\tif (response.status >= 300 && response.status < 400 && response.headers.get(\"location\")) { await response.body?.cancel().catch(() => {}); currentUrl = new URL(response.headers.get(\"location\")!, currentUrl).href; continue; }\n\t\t\t\tconst contentLength = Number.parseInt(response.headers.get(\"content-length\") ?? \"0\", 10);\n\t\t\t\tif (contentLength > MAX_URL_RESPONSE_BYTES) throw new Error(`URL response exceeds ${MAX_URL_RESPONSE_BYTES} byte limit: ${currentUrl}`);\n\t\t\t\tconst contentType = response.headers.get(\"content-type\") ?? \"\";\n\t\t\t\tconst content = await readResponseTextWithLimit(response);\n\t\t\t\treturn { ok: response.ok, status: response.status, content, contentType, finalUrl: response.url || currentUrl };\n\t\t\t} finally {\n\t\t\t\tawait closePinnedDispatcher(dispatcher).catch(() => undefined);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(`Too many redirects while fetching URL: ${url}`);\n\t} finally {\n\t\tclearTimeout(timer);\n\t\tsignal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n\nfunction isLowQuality(content: string): boolean {\n\tconst lower = content.toLowerCase();\n\tif (/(enable javascript|javascript required|turn on javascript|please enable javascript|browser not supported)/.test(lower) && content.trim().length < 2000) return true;\n\tconst nonblank = content.split(\"\\n\").filter((line) => line.trim().length > 0);\n\tif (nonblank.length > 10 && nonblank.filter((line) => line.trim().length < 40).length / nonblank.length > 0.7) return true;\n\treturn false;\n}\n\nfunction buildLlmEndpointCandidates(url: string): string[] {\n\tconst parsed = (() => { try { return new URL(url); } catch { return undefined; } })();\n\tif (!parsed) return [];\n\tconst origin = parsed.origin;\n\tif (parsed.pathname === \"/\" || parsed.pathname === \"\") return [`${origin}/.well-known/llms.txt`, `${origin}/llms.txt`, `${origin}/llms.md`];\n\tconst trimmed = parsed.pathname.replace(/\\/+$/, \"\");\n\tconst segments = trimmed.split(\"/\").filter(Boolean);\n\tconst candidates: string[] = [];\n\tconst depth = parsed.pathname.endsWith(\"/\") ? segments.length : Math.max(segments.length - 1, 1);\n\tfor (let scope = Math.min(depth, segments.length); scope >= 1; scope--) {\n\t\tconst base = `${origin}/${segments.slice(0, scope).join(\"/\")}`;\n\t\tcandidates.push(`${base}/llms.txt`, `${base}/llms.md`);\n\t}\n\tcandidates.push(`${origin}/llms.txt`, `${origin}/llms.md`);\n\treturn [...new Set(candidates)];\n}\n\nasync function tryLlmEndpoints(url: string, signal?: AbortSignal): Promise<{ content: string; endpoint: string } | null> {\n\tfor (const endpoint of buildLlmEndpointCandidates(url)) {\n\t\ttry {\n\t\t\tconst page = await loadPage(endpoint, 5000, signal);\n\t\t\tif (page.ok && page.content.trim().length > MIN_CONTENT_LENGTH && !looksLikeHtml(page.content)) return { content: page.content, endpoint };\n\t\t} catch {}\n\t}\n\treturn null;\n}\n\nfunction parseAlternateMarkdownLink(html: string, pageUrl: string): string | undefined {\n\tconst headEnd = html.toLowerCase().indexOf(\"</head>\");\n\tconst head = html.slice(0, headEnd >= 0 ? headEnd + 7 : html.length);\n\tconst links = [...head.matchAll(/<link\\b[^>]*>/gi)].map((m) => m[0] ?? \"\");\n\tfor (const tag of links) {\n\t\tconst rel = /rel=[\"']?([^\"'>]+)[\"']?/i.exec(tag)?.[1] ?? \"\";\n\t\tconst type = /type=[\"']?([^\"'>]+)[\"']?/i.exec(tag)?.[1] ?? \"\";\n\t\tconst href = /href=[\"']?([^\"'>]+)[\"']?/i.exec(tag)?.[1] ?? \"\";\n\t\tif (!/alternate/i.test(rel) || !href) continue;\n\t\tif (/RecentChanges|Special:|\\/feed\\/|action=feed/i.test(href)) continue;\n\t\tif (type.includes(\"markdown\") || href.endsWith(\".md\")) {\n\t\t\ttry { return new URL(href, pageUrl).href; } catch {}\n\t\t}\n\t}\n\treturn undefined;\n}\n\nasync function tryMdSuffix(url: string, signal?: AbortSignal): Promise<string | null> {\n\tconst candidates: string[] = [];\n\tif (/\\/$/.test(url)) candidates.push(`${url}index.html.md`);\n\telse if (/\\.\\w+\\/?$/.test(url)) candidates.push(`${url}.md`);\n\telse candidates.push(`${url}.md`, `${url}/index.html.md`);\n\tfor (const candidate of candidates) {\n\t\ttry {\n\t\t\tconst page = await loadPage(candidate, 5000, signal);\n\t\t\tif (page.ok && page.content.trim().length > MIN_CONTENT_LENGTH && !looksLikeHtml(page.content)) return page.content;\n\t\t} catch {}\n\t}\n\treturn null;\n}\n\nasync function tryContentNegotiation(url: string, signal?: AbortSignal): Promise<string | null> {\n\ttry {\n\t\tconst page = await loadPage(url, 5000, signal, \"text/markdown, text/plain;q=0.9, text/html;q=0.8\");\n\t\tconst mime = page.contentType.toLowerCase();\n\t\tif (page.ok && page.content.trim().length > MIN_CONTENT_LENGTH && !looksLikeHtml(page.content) && (mime.includes(\"markdown\") || mime.includes(\"text/plain\"))) return page.content;\n\t} catch {}\n\treturn null;\n}\n\nexport interface RenderedUrl {\n\tcontent: string;\n\tfinalUrl: string;\n\tcontentType: string;\n\tmethod: string;\n\tnotes: string[];\n\ttruncated: boolean;\n}\n\nexport async function renderUrl(url: string, raw: boolean, signal?: AbortSignal): Promise<RenderedUrl> {\n\tconst notes: string[] = [];\n\tlet method = \"text\";\n\tlet contentType = \"\";\n\tlet finalUrl: string;\n\tlet body = \"\";\n\tconst page = await loadPage(url, REMOTE_FETCH_TIMEOUT_MS, signal);\n\tfinalUrl = page.finalUrl;\n\tcontentType = page.contentType;\n\tif (!page.ok) return { content: page.content || `(request failed with status ${page.status})`, finalUrl, contentType, method: \"failed\", notes, truncated: false };\n\tif (raw) return { content: page.content, finalUrl, contentType, method: \"raw\", notes, truncated: false };\n\tconst buffer = Buffer.from(page.content, \"utf8\");\n\tconst docExt = documentExtensionFromContentType(contentType) ?? (isDocumentPath(finalUrl) ? (finalUrl.match(/\\.\\w+(?:$|[?#])/)?.[0] ?? \"\") : \"\");\n\tif (docExt) {\n\t\ttry { body = await extractDocumentMarkdown(buffer, `${finalUrl}${docExt}`); method = \"document\"; }\n\t\tcatch (error) { body = `[Cannot read ${docExt} file: ${error instanceof Error ? error.message : \"conversion failed\"}]`; method = \"document-error\"; }\n\t\treturn { content: body, finalUrl, contentType, method, notes, truncated: false };\n\t}\n\tconst isHtml = /html/i.test(contentType) || looksLikeHtml(page.content);\n\tif (isHtml) {\n\t\tconst altMd = parseAlternateMarkdownLink(page.content, finalUrl);\n\t\tif (altMd) { try { const alt = await loadPage(altMd, 5000, signal); if (alt.ok && alt.content.trim().length > MIN_CONTENT_LENGTH && !looksLikeHtml(alt.content)) { return { content: alt.content, finalUrl: alt.finalUrl, contentType: alt.contentType, method: \"alternate-markdown\", notes, truncated: false }; } } catch {} notes.push(\"alternate markdown link unusable\"); }\n\t\tconst md = await tryMdSuffix(finalUrl, signal); if (md) return { content: md, finalUrl, contentType: \"text/markdown\", method: \"md-suffix\", notes, truncated: false };\n\t\tconst neg = await tryContentNegotiation(finalUrl, signal); if (neg) return { content: neg, finalUrl, contentType: \"text/markdown\", method: \"content-negotiation\", notes, truncated: false };\n\t\tlet rendered = getTurndown().turndown(page.content).trim();\n\t\tmethod = \"native\";\n\t\tif (rendered.length <= MIN_CONTENT_LENGTH || isLowQuality(rendered)) {\n\t\t\tconst llms = await tryLlmEndpoints(finalUrl, signal);\n\t\t\tif (llms) { return { content: llms.content, finalUrl, contentType: \"text/plain\", method: `llms-txt (${llms.endpoint})`, notes, truncated: false }; }\n\t\t\tnotes.push(\"rendered content low quality; no markdown source discovered\");\n\t\t}\n\t\tbody = rendered;\n\t} else {\n\t\tbody = page.content;\n\t}\n\treturn { content: body, finalUrl, contentType, method, notes, truncated: false };\n}\n\nexport function buildUrlReadOutput(result: RenderedUrl): string {\n\tconst header = [`URL: ${result.finalUrl}`, `Content-Type: ${result.contentType}`, `Method: ${result.method}`, ...(result.notes.length ? [`Notes: ${result.notes.join(\"; \")}`] : [])].join(\"\\n\");\n\treturn `${header}\\n\\n---\\n\\n${result.content}`;\n}\n\nfunction persistReadUrlArtifact(artifactsDir: string | undefined, output: string): string | undefined {\n\tif (!artifactsDir) return undefined;\n\treturn getArtifactManager(artifactsDir).save(output, \"read\");\n}\n\nexport interface ExecuteReadUrlResult {\n\tcontent: string;\n\tdetails: ReadUrlToolDetails;\n\tartifactId?: string;\n}\n\nexport interface LoadedReadUrl {\n\toutput: string;\n\tdetails: ReadUrlToolDetails;\n\tartifactId?: string;\n\traw: boolean;\n}\n\n/**\n * Resolve a URL to its full rendered (or raw) output, using the session-scoped\n * cache and persisting the rendered body as a `read` artifact. Returns the\n * complete untruncated output so callers can apply their own line selection.\n */\nexport async function loadReadUrlOutput(scope: string, params: { path: string; raw?: boolean }, artifactsDir: string | undefined, signal?: AbortSignal): Promise<LoadedReadUrl> {\n\tconst parsed = parseReadUrlTarget(params.path);\n\tif (!parsed) throw new Error(`Not a readable URL: ${params.path}`);\n\tconst raw = params.raw ?? parsed.raw;\n\tconst key = getReadUrlCacheKey(scope, parsed.url, raw);\n\tlet entry = readUrlCache.get(key);\n\tif (!entry) {\n\t\tconst rendered = await renderUrl(parsed.url, raw, signal);\n\t\tconst output = raw ? rendered.content : buildUrlReadOutput(rendered);\n\t\tconst artifactId = persistReadUrlArtifact(artifactsDir, output);\n\t\tconst details: ReadUrlToolDetails = { url: parsed.url, finalUrl: rendered.finalUrl, contentType: rendered.contentType, method: rendered.method, truncated: rendered.truncated, notes: rendered.notes, meta: artifactId ? { artifactId } : undefined };\n\t\tentry = { artifactId, details, output };\n\t\treadUrlCache.set(key, entry);\n\t\treadUrlCache.set(getReadUrlCacheKey(scope, rendered.finalUrl, raw), entry);\n\t}\n\treturn { output: entry.output, details: entry.details, artifactId: entry.artifactId, raw };\n}\n\nexport async function executeReadUrl(scope: string, params: { path: string; raw?: boolean }, artifactsDir: string | undefined, signal?: AbortSignal): Promise<ExecuteReadUrlResult> {\n\tconst loaded = await loadReadUrlOutput(scope, params, artifactsDir, signal);\n\tconst entry = { output: loaded.output, details: loaded.details, artifactId: loaded.artifactId };\n\tconst fetchDefaultBytes = 50 * 1024;\n\tconst lines = entry.output.split(\"\\n\");\n\tconst visibleLines = lines.slice(0, FETCH_DEFAULT_MAX_LINES);\n\tlet content = visibleLines.join(\"\\n\");\n\tconst bytesBeforeByteClamp = Buffer.byteLength(content, \"utf8\");\n\tconst byteTruncated = bytesBeforeByteClamp > fetchDefaultBytes;\n\tconst lineTruncated = lines.length > FETCH_DEFAULT_MAX_LINES;\n\tif (byteTruncated) content = content.slice(0, fetchDefaultBytes);\n\tconst truncated = lineTruncated || byteTruncated;\n\tlet artifactId = entry.artifactId;\n\tif (truncated && !artifactId) artifactId = persistReadUrlArtifact(artifactsDir, entry.output);\n\tconst outputLines = content.length === 0 ? 0 : content.split(\"\\n\").length;\n\tconst truncation: TruncationResult | undefined = truncated ? {\n\t\tcontent,\n\t\ttruncated: true,\n\t\ttruncatedBy: byteTruncated ? \"bytes\" : \"lines\",\n\t\ttotalLines: lines.length,\n\t\ttotalBytes: Buffer.byteLength(entry.output, \"utf8\"),\n\t\toutputLines,\n\t\toutputBytes: Buffer.byteLength(content, \"utf8\"),\n\t\tlastLinePartial: byteTruncated,\n\t\tfirstLineExceedsLimit: false,\n\t\tmaxLines: FETCH_DEFAULT_MAX_LINES,\n\t\tmaxBytes: fetchDefaultBytes,\n\t} : undefined;\n\tconst details: ReadUrlToolDetails = { ...entry.details, truncated, meta: { ...(entry.details.meta ?? {}), ...(artifactId ? { artifactId } : {}), ...(truncation ? { truncation } : {}) } };\n\tif (truncated) content += `\\n\\n[Showing first ${visibleLines.length} of ${lines.length} lines.${artifactId ? ` Full output: artifact://${artifactId}` : \"\"}]`;\n\treturn { content, details, artifactId };\n}\n\nexport function resetReadUrlCache(): void {\n\treadUrlCache.clear();\n}\n"]}
@@ -3,26 +3,44 @@ import { type Static, Type } from "typebox";
3
3
  import type { ToolDefinition } from "../extensions/types.ts";
4
4
  import { type TruncationResult } from "./truncate.ts";
5
5
  declare const findSchema: Type.TObject<{
6
- pattern: Type.TString;
7
- path: Type.TOptional<Type.TString>;
6
+ paths: Type.TArray<Type.TString>;
7
+ hidden: Type.TOptional<Type.TBoolean>;
8
+ gitignore: Type.TOptional<Type.TBoolean>;
8
9
  limit: Type.TOptional<Type.TNumber>;
10
+ timeout: Type.TOptional<Type.TNumber>;
9
11
  }>;
10
12
  export type FindToolInput = Static<typeof findSchema>;
11
13
  export interface FindToolDetails {
12
14
  truncation?: TruncationResult;
13
15
  resultLimitReached?: number;
16
+ timedOut?: boolean;
17
+ truncated?: boolean;
18
+ skippedMissingPaths?: string[];
19
+ missingPaths?: string[];
20
+ scopePath?: string;
21
+ fileCount?: number;
22
+ files?: string[];
23
+ meta?: {
24
+ limits?: {
25
+ resultLimit?: number;
26
+ };
27
+ truncation?: TruncationResult;
28
+ };
14
29
  }
15
- /**
16
- * Pluggable operations for the find tool.
17
- * Override these to delegate file search to remote systems (for example SSH).
18
- */
30
+ /** Pluggable operations for remote/container find backends. */
19
31
  export interface FindOperations {
20
- /** Check if path exists */
21
- exists: (absolutePath: string) => Promise<boolean> | boolean;
22
- /** Find files matching glob pattern. Returns relative or absolute paths. */
32
+ stat?: (path: string) => Promise<{
33
+ isFile: boolean;
34
+ isDirectory: boolean;
35
+ }> | {
36
+ isFile: boolean;
37
+ isDirectory: boolean;
38
+ } | undefined;
39
+ exists: (path: string) => Promise<boolean> | boolean;
23
40
  glob: (pattern: string, cwd: string, options: {
24
41
  ignore: string[];
25
42
  limit: number;
43
+ hidden: boolean;
26
44
  }) => Promise<string[]> | string[];
27
45
  }
28
46
  export interface FindToolOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAI/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAItF,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAMnG,QAAA,MAAM,UAAU;;;;EAMd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAItD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,4EAA4E;IAC5E,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACnH;AAQD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAuDD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CA2PhE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Text } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport path from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { ensureTool } from \"../../utils/tools-manager.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { getTextOutput, invalidArgText, shortenPath, str } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\n\nfunction toPosixPath(value: string): string {\n\treturn value.split(path.sep).join(\"/\");\n}\n\nconst findSchema = Type.Object({\n\tpattern: Type.String({\n\t\tdescription: \"Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'\",\n\t}),\n\tpath: Type.Optional(Type.String({ description: \"Directory to search in (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of results (default: 1000)\" })),\n});\n\nexport type FindToolInput = Static<typeof findSchema>;\n\nconst DEFAULT_LIMIT = 1000;\n\nexport interface FindToolDetails {\n\ttruncation?: TruncationResult;\n\tresultLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the find tool.\n * Override these to delegate file search to remote systems (for example SSH).\n */\nexport interface FindOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Find files matching glob pattern. Returns relative or absolute paths. */\n\tglob: (pattern: string, cwd: string, options: { ignore: string[]; limit: number }) => Promise<string[]> | string[];\n}\n\nconst defaultFindOperations: FindOperations = {\n\texists: pathExists,\n\t// This is a placeholder. Actual fd execution happens in execute() when no custom glob is provided.\n\tglob: () => [],\n};\n\nexport interface FindToolOptions {\n\t/** Custom operations for find. Default: local filesystem plus fd */\n\toperations?: FindOperations;\n}\n\nfunction formatFindCall(\n\targs: { pattern: string; path?: string; limit?: number } | undefined,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.ts\").theme,\n): string {\n\tconst pattern = str(args?.pattern);\n\tconst rawPath = str(args?.path);\n\tconst path = rawPath !== null ? shortenPath(rawPath || \".\") : null;\n\tconst limit = args?.limit;\n\tconst invalidArg = invalidArgText(theme);\n\tlet text =\n\t\ttheme.fg(\"toolTitle\", theme.bold(\"find\")) +\n\t\t\" \" +\n\t\t(pattern === null ? invalidArg : theme.fg(\"accent\", pattern || \"\")) +\n\t\ttheme.fg(\"toolOutput\", ` in ${path === null ? invalidArg : path}`);\n\tif (limit !== undefined) {\n\t\ttext += theme.fg(\"toolOutput\", ` (limit ${limit})`);\n\t}\n\treturn text;\n}\n\nfunction formatFindResult(\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: FindToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.ts\").theme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tlet text = \"\";\n\tif (output) {\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst maxLines = options.expanded ? lines.length : 20;\n\t\tconst displayLines = lines.slice(0, maxLines);\n\t\tconst remaining = lines.length - maxLines;\n\t\ttext += `\\n${displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t}\n\t}\n\n\tconst resultLimit = result.details?.resultLimitReached;\n\tconst truncation = result.details?.truncation;\n\tif (resultLimit || truncation?.truncated) {\n\t\tconst warnings: string[] = [];\n\t\tif (resultLimit) warnings.push(`${resultLimit} results limit`);\n\t\tif (truncation?.truncated) warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);\n\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${warnings.join(\", \")}]`)}`;\n\t}\n\treturn text;\n}\n\nexport function createFindToolDefinition(\n\tcwd: string,\n\toptions?: FindToolOptions,\n): ToolDefinition<typeof findSchema, FindToolDetails | undefined> {\n\tconst customOps = options?.operations;\n\treturn {\n\t\tname: \"find\",\n\t\tlabel: \"find\",\n\t\tdescription: `Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tpromptSnippet: \"Find files by glob pattern (respects .gitignore)\",\n\t\tparameters: findSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ pattern, path: searchDir, limit }: { pattern: string; path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet settled = false;\n\t\t\t\tlet stopChild: (() => void) | undefined;\n\t\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tstopChild = undefined;\n\t\t\t\t\tfn();\n\t\t\t\t};\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tstopChild?.();\n\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t};\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst searchPath = resolveToCwd(searchDir || \".\", cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\t\t\t\t\t\tconst ops = customOps ?? defaultFindOperations;\n\n\t\t\t\t\t\t// If custom operations provide glob(), use that instead of fd.\n\t\t\t\t\t\tif (customOps?.glob) {\n\t\t\t\t\t\t\tif (!(await ops.exists(searchPath))) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst results = await ops.glob(pattern, searchPath, {\n\t\t\t\t\t\t\t\tignore: [\"**/node_modules/**\", \"**/.git/**\"],\n\t\t\t\t\t\t\t\tlimit: effectiveLimit,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Relativize paths against the search root for stable output.\n\t\t\t\t\t\t\tconst relativized = results.map((p) => {\n\t\t\t\t\t\t\t\tif (p.startsWith(searchPath)) return toPosixPath(p.slice(searchPath.length + 1));\n\t\t\t\t\t\t\t\treturn toPosixPath(path.relative(searchPath, p));\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tlet resultOutput = truncation.content;\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} results limit reached`);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tresultOutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: resultOutput }],\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Default implementation uses fd.\n\t\t\t\t\t\tconst fdPath = await ensureTool(\"fd\", true);\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!fdPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"fd is not available and could not be downloaded\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Build fd arguments. --no-require-git makes fd apply hierarchical .gitignore\n\t\t\t\t\t\t// semantics whether or not the search path is inside a git repository, without\n\t\t\t\t\t\t// leaking sibling-directory rules the way --ignore-file (a global source) would.\n\t\t\t\t\t\tconst args: string[] = [\n\t\t\t\t\t\t\t\"--glob\",\n\t\t\t\t\t\t\t\"--color=never\",\n\t\t\t\t\t\t\t\"--hidden\",\n\t\t\t\t\t\t\t\"--no-require-git\",\n\t\t\t\t\t\t\t\"--max-results\",\n\t\t\t\t\t\t\tString(effectiveLimit),\n\t\t\t\t\t\t];\n\n\t\t\t\t\t\t// fd --glob matches against the basename unless --full-path is set; in --full-path\n\t\t\t\t\t\t// mode it matches against the absolute candidate path, so a path-containing\n\t\t\t\t\t\t// pattern like 'src/**/*.spec.ts' needs a leading '**/' to match anything.\n\t\t\t\t\t\tlet effectivePattern = pattern;\n\t\t\t\t\t\tif (pattern.includes(\"/\")) {\n\t\t\t\t\t\t\targs.push(\"--full-path\");\n\t\t\t\t\t\t\tif (!pattern.startsWith(\"/\") && !pattern.startsWith(\"**/\") && pattern !== \"**\") {\n\t\t\t\t\t\t\t\teffectivePattern = `**/${pattern}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\targs.push(\"--\", effectivePattern, searchPath);\n\n\t\t\t\t\t\tconst child = spawn(fdPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\t\tconst lines: string[] = [];\n\n\t\t\t\t\t\tstopChild = () => {\n\t\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\t\tchild.kill();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\t\trl.close();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\t\tlines.push(line);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Failed to run fd: ${error.message}`)));\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst output = lines.join(\"\\n\");\n\t\t\t\t\t\t\tif (code !== 0) {\n\t\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `fd exited with code ${code}`;\n\t\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!output) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: \"No files found matching pattern\" }],\n\t\t\t\t\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst relativized: string[] = [];\n\t\t\t\t\t\t\tfor (const rawLine of lines) {\n\t\t\t\t\t\t\t\tconst line = rawLine.replace(/\\r$/, \"\").trim();\n\t\t\t\t\t\t\t\tif (!line) continue;\n\t\t\t\t\t\t\t\tconst hadTrailingSlash = line.endsWith(\"/\") || line.endsWith(\"\\\\\");\n\t\t\t\t\t\t\t\tlet relativePath = line;\n\t\t\t\t\t\t\t\tif (line.startsWith(searchPath)) {\n\t\t\t\t\t\t\t\t\trelativePath = line.slice(searchPath.length + 1);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\trelativePath = path.relative(searchPath, line);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (hadTrailingSlash && !relativePath.endsWith(\"/\")) relativePath += \"/\";\n\t\t\t\t\t\t\t\trelativized.push(toPosixPath(relativePath));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst resultLimitReached = relativized.length >= effectiveLimit;\n\t\t\t\t\t\t\tconst rawOutput = relativized.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\t\t\t\t\t\t\tlet resultOutput = truncation.content;\n\t\t\t\t\t\t\tconst details: FindToolDetails = {};\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\t\t\t\t\t\t\tif (resultLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`${effectiveLimit} results limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.resultLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\tresultOutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: resultOutput }],\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst error = e instanceof Error ? e : new Error(String(e));\n\t\t\t\t\t\tsettle(() => reject(error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatFindCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatFindResult(result, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\n\nexport function createFindTool(cwd: string, options?: FindToolOptions): AgentTool<typeof findSchema> {\n\treturn wrapToolDefinition(createFindToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAI/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,wBAAwB,CAAC;AAOtF,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,UAAU;;;;;;EAMmB,CAAC;AACpC,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AA+FtD,MAAM,WAAW,eAAe;IAAG,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;KAAE,CAAA;CAAE;AAsCxU,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACpI,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACrD,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACpI;AAKD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AA6CD,wBAAgB,wBAAwB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACvB,cAAc,CAAC,OAAO,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC,CAmRhE;AACD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAEnG","sourcesContent":["import { statSync } from \"node:fs\";\nimport { stat as fsStat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Text } from \"@earendil-works/pi-tui\";\nimport { spawn } from \"child_process\";\nimport path from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { keyHint } from \"../../modes/interactive/components/keybinding-hints.ts\";\nimport { ensureTool } from \"../../utils/tools-manager.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../extensions/types.ts\";\nimport { normalizePathLikeInput, splitPathLikeGlob } from \"./glob-path-utils.ts\";\nimport { loadNativeSearchBinding } from \"./search-native.ts\";\nimport { pathExists, resolveToCwd } from \"./path-utils.ts\";\nimport { resolveInternalSelector, type InternalResourceContext } from \"./resource-selectors.ts\";\nimport { getTextOutput } from \"./render-utils.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.ts\";\nconst toPosixPath = (value: string): string => value.split(path.sep).join(\"/\");\nconst findSchema = Type.Object({\n\tpaths: Type.Array(Type.String({ description: \"File, directory, or glob path to find.\" }), { description: \"Paths or glob paths to find.\", minItems: 1 }),\n\thidden: Type.Optional(Type.Boolean({ description: \"Include hidden files. Defaults to true.\" })),\n\tgitignore: Type.Optional(Type.Boolean({ description: \"Respect gitignore. Defaults to true.\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of results, clamped to 1-200.\", minimum: 1, maximum: 200 })),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds; default 5, clamped to 0.5..60.\", minimum: 0.5, maximum: 60 })),\n}, { additionalProperties: false });\nexport type FindToolInput = Static<typeof findSchema>;\nconst DEFAULT_LIMIT = 200;\nconst MAX_LIMIT = 200;\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst MIN_TIMEOUT_MS = 500;\nconst MAX_TIMEOUT_MS = 60_000;\ninterface FindTarget { searchPath: string; pattern: string; exactPathInput: boolean; inputPath: string }\nfunction normalizeLimit(limit: number | undefined): number { return limit === undefined || !Number.isFinite(limit) ? DEFAULT_LIMIT : Math.max(1, Math.min(MAX_LIMIT, Math.floor(limit))); }\nfunction normalizeTimeoutMs(timeout: number | undefined): number { return timeout === undefined || !Number.isFinite(timeout) ? DEFAULT_TIMEOUT_MS : Math.max(MIN_TIMEOUT_MS, Math.min(MAX_TIMEOUT_MS, Math.floor(timeout * 1000))); }\nfunction formatTimeoutSeconds(timeoutMs: number): string { const seconds = timeoutMs / 1000; return Number.isInteger(seconds) ? String(seconds) : seconds.toFixed(1); }\nasync function resolveFindInternal(input: string, cwd: string, ctx?: InternalResourceContext): Promise<string> { const parsed = splitPathLikeGlob(input); if (!/^[a-z]+:\\/\\//i.test(parsed.basePath)) return input; for (const resolve of [ctx?.internalRouter?.resolve, ctx?.internalResourceRouter?.resolve, ctx?.resolveInternalUrl]) { const resolved = await resolve?.(parsed.basePath); if (typeof resolved === \"string\") return parsed.glob ? `${resolved}/${parsed.glob}` : resolved; } const fallback = resolveInternalSelector(parsed.basePath, cwd); return fallback ? parsed.glob ? `${fallback}/${parsed.glob}` : fallback : input; }\nfunction isWindowsAbsolutePath(value: string): boolean { return /^[A-Za-z]:[\\\\/]/.test(value) || value.startsWith(\"\\\\\\\\\"); }\nfunction resolveFindBackendPath(input: string, cwd: string, customBackend: boolean): string { if (!customBackend) return resolveToCwd(input, cwd); if (input === \".\" || input === \"\") return cwd; if (input.startsWith(\"/\") || isWindowsAbsolutePath(input)) return input; if (cwd.includes(\"\\\\\") || isWindowsAbsolutePath(cwd)) return path.resolve(cwd, input); return `${cwd.replace(/\\/+$/, \"\")}/${input}`; }\nasync function delimiterInExistingGlobRoot(value: string, cwd: string, ops: FindOperations, customBackend: boolean): Promise<boolean> { const parsed = splitPathLikeGlob(value); return !!parsed.glob && /[;,\\s]/.test(parsed.basePath) && await ops.exists(resolveFindBackendPath(parsed.basePath, cwd, customBackend)); }\nasync function expandDelimitedFindPaths(pathsValue: string[] | undefined, cwd: string, ops: FindOperations, ctx?: InternalResourceContext, customBackend = false): Promise<string[]> {\n\tif (!pathsValue?.length) throw new Error(\"find.paths must include at least one path or glob.\"); const expanded: string[] = [];\n\tfor (const input of pathsValue) { const raw = normalizePathLikeInput(input); if (raw === \"\") throw new Error(\"find.paths entries must not be empty.\"); const resolvedRaw = await resolveFindInternal(raw, cwd, ctx); const rawParsed = splitPathLikeGlob(resolvedRaw);\n\t\tif ((rawParsed.glob === undefined && await ops.exists(resolveFindBackendPath(rawParsed.basePath, cwd, customBackend))) || await delimiterInExistingGlobRoot(resolvedRaw, cwd, ops, customBackend)) { expanded.push(resolvedRaw); continue; }\n\t\tconst parts = await Promise.all(raw.split(/[;,\\s]+/).map(normalizePathLikeInput).filter(Boolean).map((part) => resolveFindInternal(part, cwd, ctx)));\n\t\tconst delimiterCanSplit = /[;,]/.test(raw) ? (await Promise.all(parts.map((part) => ops.exists(resolveFindBackendPath(splitPathLikeGlob(part).basePath, cwd, customBackend))))).some(Boolean) : (await Promise.all(parts.map((part) => ops.exists(resolveFindBackendPath(splitPathLikeGlob(part).basePath, cwd, customBackend))))).every(Boolean);\n\t\tif (parts.length > 1 && delimiterCanSplit) expanded.push(...parts); else expanded.push(resolvedRaw);\n\t}\n\treturn expanded;\n}\nfunction normalizeFindTargets(cwd: string, pathsValue: string[] | undefined, customBackend = false): FindTarget[] {\n\tif (!pathsValue || pathsValue.length === 0) throw new Error(\"find.paths must include at least one path or glob.\");\n\treturn pathsValue.map((searchPath) => {\n\t\tconst parsed = splitPathLikeGlob(searchPath);\n\t\tconst target = { searchPath: resolveFindBackendPath(parsed.basePath, cwd, customBackend), pattern: parsed.glob ?? \"**/*\", exactPathInput: parsed.glob === undefined, inputPath: searchPath };\n\t\tif (path.parse(target.searchPath).root === target.searchPath) throw new Error(\"Refusing to search filesystem root with find; provide a narrower path.\");\n\t\treturn target;\n\t});\n}\nfunction relativizeFoundPath(foundPath: string, searchPath: string): string {\n\tconst hadTrailingSlash = foundPath.endsWith(\"/\") || foundPath.endsWith(\"\\\\\");\n\tconst relativePath = path.relative(searchPath, foundPath) || path.basename(foundPath);\n\tconst outputPath = hadTrailingSlash && !relativePath.endsWith(\"/\") ? `${relativePath}/` : relativePath;\n\treturn toPosixPath(outputPath);\n}\nfunction formatExactFoundPath(foundPath: string, cwd: string): string { return toPosixPath(path.relative(cwd, foundPath) || path.basename(foundPath)); }\nfunction containsHiddenSegment(value: string): boolean { return toPosixPath(value).split(\"/\").some((part) => part.startsWith(\".\") && part.length > 1); }\nfunction findTargetMentionsNodeModules(target: FindTarget): boolean { return target.pattern.includes(\"node_modules\") || toPosixPath(target.searchPath).split(\"/\").includes(\"node_modules\"); }\nfunction formatFoundPath(foundPath: string, searchPath: string, searchPaths: string[], cwd: string): string {\n\tlet absoluteFoundPath = path.isAbsolute(foundPath) ? foundPath : path.resolve(searchPath, foundPath);\n\tif (foundPath.endsWith(\"/\") && !absoluteFoundPath.endsWith(\"/\")) absoluteFoundPath += \"/\";\n\tconst relative = relativizeFoundPath(absoluteFoundPath, searchPath);\n\tif (searchPaths.length <= 1) return relative;\n\tconst rootLabel = toPosixPath(path.relative(cwd, searchPath) || path.basename(searchPath) || \".\");\n\treturn `${rootLabel}/${relative}`;\n}\ninterface FindTreeNode {\n\tfiles: Set<string>;\n\tdirs: Map<string, FindTreeNode>;\n}\nfunction createFindTreeNode(): FindTreeNode { return { files: new Set(), dirs: new Map() }; }\nfunction formatFindTree(relativized: string[]): string {\n\tconst root = createFindTreeNode();\n\tfor (const item of relativized) {\n\t\tconst isDir = item.endsWith(\"/\");\n\t\tconst parts = item.replace(/\\/+$/g, \"\").split(\"/\").filter(Boolean);\n\t\tif (parts.length === 0) continue;\n\t\tlet node = root;\n\t\tconst dirParts = isDir ? parts : parts.slice(0, -1);\n\t\tfor (const dir of dirParts) {\n\t\t\tlet child = node.dirs.get(dir);\n\t\t\tif (!child) {\n\t\t\t\tchild = createFindTreeNode();\n\t\t\t\tnode.dirs.set(dir, child);\n\t\t\t}\n\t\t\tnode = child;\n\t\t}\n\t\tif (!isDir) node.files.add(parts[parts.length - 1]!);\n\t}\n\tconst lines: string[] = [];\n\tconst collapse = (dir: string, node: FindTreeNode): { label: string; node: FindTreeNode } => {\n\t\tconst parts = [dir];\n\t\tlet current = node;\n\t\twhile (current.files.size === 0 && current.dirs.size === 1) {\n\t\t\tconst [[nextDir, nextNode]] = [...current.dirs.entries()];\n\t\t\tparts.push(nextDir!);\n\t\t\tcurrent = nextNode!;\n\t\t}\n\t\treturn { label: parts.join(\"/\"), node: current };\n\t};\n\tconst render = (node: FindTreeNode, depth: number): void => {\n\t\tfor (const file of [...node.files].sort()) lines.push(file);\n\t\tfor (const [dir, child] of [...node.dirs.entries()].sort(([a], [b]) => a.localeCompare(b))) {\n\t\t\tconst folded = collapse(dir, child);\n\t\t\tlines.push(`${\"#\".repeat(depth + 1)} ${folded.label}/`);\n\t\t\trender(folded.node, depth + 1);\n\t\t}\n\t};\n\trender(root, 0);\n\treturn lines.join(\"\\n\");\n}\nexport interface FindToolDetails { truncation?: TruncationResult; resultLimitReached?: number; timedOut?: boolean; truncated?: boolean; skippedMissingPaths?: string[]; missingPaths?: string[]; scopePath?: string; fileCount?: number; files?: string[]; meta?: { limits?: { resultLimit?: number }; truncation?: TruncationResult } }\nfunction buildFindResult(\n\trelativized: string[],\n\teffectiveLimit: number,\n\ttimedOut: boolean,\n\ttimeoutMs: number,\n\tskippedMissingPaths: string[] = [],\n\tresultLimitReached = false,\n): {\n\tcontent: Array<{ type: \"text\"; text: string }>;\n\tdetails: FindToolDetails | undefined;\n} {\n\tconst rawOutput = relativized.length > 0 ? formatFindTree(relativized) : \"No files found matching pattern\";\n\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\tlet resultOutput = truncation.content;\n\tconst details: FindToolDetails = { scopePath: \".\", fileCount: relativized.length, files: relativized, meta: { limits: { resultLimit: effectiveLimit } } };\n\tconst notices: string[] = [];\n\tif (resultLimitReached) {\n\t\tnotices.push(`${effectiveLimit} results limit reached. Refine pattern or path to narrow results`);\n\t\tdetails.resultLimitReached = effectiveLimit;\n\t}\n\tif (timedOut) { notices.push(`find timed out after ${formatTimeoutSeconds(timeoutMs)}s; returning ${relativized.length} partial matches — increase timeout or narrow pattern`); details.timedOut = true; details.truncated = true; }\n\tif (skippedMissingPaths.length > 0) {\n\t\tnotices.push(`Skipped missing paths: ${skippedMissingPaths.join(\", \")}`);\n\t\tdetails.skippedMissingPaths = skippedMissingPaths;\n\t\tdetails.missingPaths = skippedMissingPaths;\n\t}\n\tif (truncation.truncated) {\n\t\tnotices.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit reached`);\n\t\tdetails.truncation = truncation;\n\t\tdetails.meta = { ...(details.meta ?? {}), truncation };\n\t\tdetails.truncated = true;\n\t}\n\tif (notices.length > 0) {\n\t\tresultOutput += `\\n\\n[${notices.join(\". \")}]`;\n\t}\n\treturn { content: [{ type: \"text\", text: resultOutput }], details };\n}\n/** Pluggable operations for remote/container find backends. */\nexport interface FindOperations {\n\tstat?: (path: string) => Promise<{ isFile: boolean; isDirectory: boolean }> | { isFile: boolean; isDirectory: boolean } | undefined;\n\texists: (path: string) => Promise<boolean> | boolean;\n\tglob: (pattern: string, cwd: string, options: { ignore: string[]; limit: number; hidden: boolean }) => Promise<string[]> | string[];\n}\nconst defaultFindOperations: FindOperations = {\n\texists: pathExists,\n\tglob: () => [],\n};\nexport interface FindToolOptions {\n\t/** Custom operations for find. Default: local filesystem plus fd */\n\toperations?: FindOperations;\n}\nfunction stripTrailingForwardSlashes(value: string): string { let end = value.length; while (end > 0 && value[end - 1] === \"/\") end--; return value.slice(0, end); }\n\nfunction formatFindCall(\n\targs: { paths?: string[]; limit?: number } | undefined,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.ts\").theme,\n): string {\n\tconst paths = Array.isArray(args?.paths) ? args.paths.map((item) => splitPathLikeGlob(item).glob ? item : `${stripTrailingForwardSlashes(item)}/**/*`).join(\", \") : \"<paths>\";\n\tlet text = `${theme.fg(\"toolTitle\", theme.bold(\"find\"))} ${theme.fg(\"accent\", paths)}`;\n\tif (args?.limit !== undefined) text += theme.fg(\"toolOutput\", ` (limit ${args.limit})`);\n\treturn text;\n}\nfunction formatFindResult(\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: FindToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\ttheme: typeof import(\"../../modes/interactive/theme/theme.ts\").theme,\n\tshowImages: boolean,\n): string {\n\tconst output = getTextOutput(result, showImages).trim();\n\tlet text = \"\";\n\tif (output) {\n\t\tconst lines = output.split(\"\\n\");\n\t\tconst maxLines = options.expanded ? lines.length : 20;\n\t\tconst displayLines = lines.slice(0, maxLines);\n\t\tconst remaining = lines.length - maxLines;\n\t\ttext += `\\n${displayLines.map((line) => theme.fg(\"toolOutput\", line)).join(\"\\n\")}`;\n\t\tif (remaining > 0) {\n\t\t\ttext += `${theme.fg(\"muted\", `\\n... (${remaining} more lines,`)} ${keyHint(\"app.tools.expand\", \"Expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t}\n\t}\n\tconst resultLimit = result.details?.resultLimitReached;\n\tconst truncation = result.details?.truncation;\n\tconst timedOut = result.details?.timedOut;\n\tif (resultLimit || truncation?.truncated || timedOut) {\n\t\tconst warnings: string[] = [];\n\t\tif (resultLimit) warnings.push(`${resultLimit} results limit`);\n\t\tif (timedOut) warnings.push(\"timeout\");\n\t\tif (truncation?.truncated) warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`);\n\t\ttext += `\\n${theme.fg(\"warning\", `[Truncated: ${warnings.join(\", \")}]`)}`;\n\t}\n\treturn text;\n}\nexport function createFindToolDefinition(\n\tcwd: string,\n\toptions?: FindToolOptions,\n): ToolDefinition<typeof findSchema, FindToolDetails | undefined> {\n\tconst customOps = options?.operations;\n\treturn {\n\t\tname: \"find\",\n\t\tlabel: \"find\",\n\t\tdescription: \"Find filesystem paths by glob; use search when you need content matches instead of path matches.\",\n\t\tpromptSnippet: \"Find filesystem paths by glob.\",\n\t\tparameters: findSchema,\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\tparams: FindToolInput,\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\t_ctx?,\n\t\t) {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet settled = false;\n\t\t\t\tlet stopChild: (() => void) | undefined;\n\t\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (settled) return;\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\tstopChild = undefined;\n\t\t\t\t\tfn();\n\t\t\t\t};\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\tstopChild?.();\n\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t};\n\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\tconst { limit, hidden, gitignore, timeout } = params;\n\t\t\t\tconst paths = params.paths;\n\t\t\t\tconst resourceCtx = _ctx as InternalResourceContext | undefined;\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst ops = customOps ?? defaultFindOperations;\n\t\t\t\t\t\tconst targets = normalizeFindTargets(cwd, await expandDelimitedFindPaths(paths, cwd, ops, resourceCtx, !!customOps), !!customOps);\n\t\t\t\t\t\tconst searchPaths = targets.map((target) => target.searchPath);\n\t\t\t\t\t\tconst effectiveLimit = normalizeLimit(limit);\n\t\t\t\t\t\tconst timeoutMs = normalizeTimeoutMs(timeout);\n\t\t\t\t\t\tconst emitUpdate = (files: string[]) => _onUpdate?.({ content: [{ type: \"text\", text: files.join(\"\\n\") || \"No files found matching pattern\" }], details: { scopePath: \".\", files, fileCount: files.length, truncated: false } });\n\t\t\t\t\t\tconst exactFileResults: string[] = [];\n\t\t\t\t\t\tconst searchableTargets: FindTarget[] = [];\n\t\t\t\t\t\tconst skippedMissingPaths: string[] = [];\n\t\t\t\t\t\tfor (const target of targets) {\n\t\t\t\t\t\t\tif (target.searchPath === path.parse(target.searchPath).root) throw new Error(\"Refusing to search filesystem root with find; provide a narrower path.\");\n\t\t\t\t\t\t\tconst stat = customOps ? await customOps.stat?.(target.searchPath) : await fsStat(target.searchPath).catch(() => undefined);\n\t\t\t\t\t\t\tif (!stat && targets.length > 1 && !customOps) {\n\t\t\t\t\t\t\t\tskippedMissingPaths.push(target.inputPath);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!stat && targets.length === 1 && !customOps) {\n\t\t\t\t\t\t\t\tthrow new Error(`ENOENT: Path not found: ${target.searchPath}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (target.exactPathInput) {\n\t\t\t\t\t\t\t\tconst isFile = typeof stat?.isFile === \"function\" ? stat.isFile() : stat?.isFile;\n\t\t\t\t\t\t\t\tif (isFile) {\n\t\t\t\t\t\t\t\t\texactFileResults.push(formatExactFoundPath(target.searchPath, cwd));\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsearchableTargets.push(target);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (exactFileResults.length > effectiveLimit || searchableTargets.length === 0) {\n\t\t\t\t\t\t\tconst resultLimitReached = exactFileResults.length > effectiveLimit;\n\t\t\t\t\t\t\tsettle(() => resolve(buildFindResult(exactFileResults.slice(0, effectiveLimit), effectiveLimit, false, timeoutMs, skippedMissingPaths, resultLimitReached)));\n\t\t\t\t\t\t\temitUpdate(exactFileResults.slice(0, effectiveLimit));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (customOps?.glob) {\n\t\t\t\t\t\t\tconst deadline = Date.now() + timeoutMs;\n\t\t\t\t\t\t\tlet timedOut = false;\n\t\t\t\t\t\t\tconst relativized: string[] = [...exactFileResults];\n\t\t\t\t\t\t\tlet customLimitReached = false;\n\t\t\t\t\t\t\tfor (const target of searchableTargets) {\n\t\t\t\t\t\t\t\tif (!(await ops.exists(target.searchPath))) {\n\t\t\t\t\t\t\t\t\tif (targets.length > 1) {\n\t\t\t\t\t\t\t\t\t\tskippedMissingPaths.push(target.inputPath);\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${target.searchPath}`)));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst remaining = effectiveLimit - relativized.length;\n\t\t\t\t\t\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\t\t\t\t\t\tif (remaining <= 0) {\n\t\t\t\t\t\t\t\t\tconst ignore = findTargetMentionsNodeModules(target) ? [\"**/.git/**\"] : [\"**/node_modules/**\", \"**/.git/**\"];\n\t\t\t\t\t\t\t\t\tconst probe = await Promise.resolve(ops.glob(target.pattern, target.searchPath, { ignore, limit: 1, hidden: hidden !== false }));\n\t\t\t\t\t\t\t\t\tif (probe.some((p) => hidden !== false || !containsHiddenSegment(p))) customLimitReached = true;\n\t\t\t\t\t\t\t\t\tif (customLimitReached) break;\n\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (remainingMs <= 0) {\n\t\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst timeoutResult = Symbol(\"find-timeout\");\n\t\t\t\t\t\t\t\tlet raceTimer: ReturnType<typeof setTimeout> | undefined;\n\t\t\t\t\t\t\t\tconst ignore = findTargetMentionsNodeModules(target) ? [\"**/.git/**\"] : [\"**/node_modules/**\", \"**/.git/**\"];\n\t\t\t\t\t\t\t\tconst results = await Promise.race<string[] | symbol>([\n\t\t\t\t\t\t\t\t\tPromise.resolve(ops.glob(target.pattern, target.searchPath, { ignore, limit: remaining + 1, hidden: hidden !== false })),\n\t\t\t\t\t\t\t\t\tnew Promise<typeof timeoutResult>((resolveTimeout) => {\n\t\t\t\t\t\t\t\t\t\traceTimer = setTimeout(() => resolveTimeout(timeoutResult), remainingMs);\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\tif (raceTimer) clearTimeout(raceTimer);\n\t\t\t\t\t\t\t\tif (!Array.isArray(results)) {\n\t\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (target.exactPathInput && results.length === 0) { const stat = await customOps.stat?.(target.searchPath); if (!stat?.isDirectory) relativized.push(formatExactFoundPath(target.searchPath, cwd)); continue; }\n\t\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconst visible = results.filter((p) => hidden !== false || !containsHiddenSegment(p));\n\t\t\t\t\t\t\t\tif (visible.length > remaining) customLimitReached = true;\n\t\t\t\t\t\t\t\trelativized.push(...visible.slice(0, remaining).map((p) => formatFoundPath(p, target.searchPath, searchPaths, cwd)));\n\t\t\t\t\t\t\t\temitUpdate(relativized);\n\t\t\t\t\t\t\t\tif (customLimitReached) break;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tsettle(() => resolve(buildFindResult(relativized, effectiveLimit, timedOut, timeoutMs, skippedMissingPaths, customLimitReached)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst nativeBinding = loadNativeSearchBinding();\n\t\t\t\t\t\tif (nativeBinding) {\n\t\t\t\t\t\t\tconst matches: { path: string; mtime: number }[] = exactFileResults.map((path) => ({ path, mtime: Number.POSITIVE_INFINITY }));\n\t\t\t\t\t\t\tlet timedOut = false;\n\t\t\t\t\t\t\tconst deadline = Date.now() + timeoutMs;\n\t\t\t\t\t\t\tfor (const target of searchableTargets) {\n\t\t\t\t\t\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\t\t\t\t\t\tif (remainingMs <= 0) {\n\t\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst result = await nativeBinding.glob({\n\t\t\t\t\t\t\t\t\t\tpattern: target.pattern,\n\t\t\t\t\t\t\t\t\t\tpath: target.searchPath,\n\t\t\t\t\t\t\t\t\t\trecursive: false,\n\t\t\t\t\t\t\t\t\t\thidden: hidden !== false,\n\t\t\t\t\t\t\t\t\t\tgitignore: gitignore !== false,\n\t\t\t\t\t\t\t\t\t\tincludeNodeModules: findTargetMentionsNodeModules(target),\n\t\t\t\t\t\t\t\t\t\tmaxResults: effectiveLimit + 1,\n\t\t\t\t\t\t\t\t\t\tcache: false,\n\t\t\t\t\t\t\t\t\t\tsortByMtime: true,\n\t\t\t\t\t\t\t\t\t\ttimeoutMs: remainingMs,\n\t\t\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tmatches.push(...result.matches.map((match) => { const fileType = match.fileType ?? (match as { file_type?: number }).file_type; const isDir = (fileType === 2 || fileType === \"Dir\" || (fileType === undefined && statSync(path.resolve(target.searchPath, match.path), { throwIfNoEntry: false })?.isDirectory())) && !match.path.endsWith(\"/\"); const matchPath = isDir ? `${match.path}/` : match.path; return { path: formatFoundPath(matchPath, target.searchPath, searchPaths, cwd), mtime: match.mtime ?? 0 }; }));\n\t\t\t\t\t\t\t\t\temitUpdate(matches.map((match) => match.path));\n\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\tif (String(error).toLowerCase().includes(\"timed out\")) {\n\t\t\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst uniqueMatches = [...matches.reduce((map, match) => { const previous = map.get(match.path); if (!previous || match.mtime > previous.mtime) map.set(match.path, match); return map; }, new Map<string, { path: string; mtime: number }>()).values()];\n\t\t\t\t\t\t\tuniqueMatches.sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));\n\t\t\t\t\t\t\tconst resultLimitReached = uniqueMatches.length > effectiveLimit;\n\t\t\t\t\t\t\tsettle(() => resolve(buildFindResult(uniqueMatches.slice(0, effectiveLimit).map((match) => match.path), effectiveLimit, timedOut, timeoutMs, skippedMissingPaths, resultLimitReached)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst fdPath = await ensureTool(\"fd\", true);\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!fdPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"fd is not available and could not be downloaded\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlet timedOut = false;\n\t\t\t\t\t\tconst relativized: string[] = [...exactFileResults];\n\t\t\t\t\t\tconst deadline = Date.now() + timeoutMs;\n\t\t\t\t\t\tconst runFdForTarget = async (target: FindTarget, remaining: number): Promise<boolean> => {\n\t\t\t\t\t\t\tconst args: string[] = [\"--glob\", \"--color=never\", \"--no-require-git\", \"--max-results\", String(remaining + 1)];\n\t\t\t\t\t\t\tif (hidden !== false) args.push(\"--hidden\");\n\t\t\t\t\t\t\tif (gitignore === false) args.push(\"--no-ignore\");\n\t\t\t\t\t\t\tif (!findTargetMentionsNodeModules(target)) args.push(\"--exclude\", \"node_modules\");\n\t\t\t\t\t\t\tlet fdPattern = target.pattern;\n\t\t\t\t\t\t\tif (target.pattern.includes(\"/\")) {\n\t\t\t\t\t\t\t\targs.push(\"--full-path\");\n\t\t\t\t\t\t\t\tif (!target.pattern.startsWith(\"/\") && !target.pattern.startsWith(\"**/\") && target.pattern !== \"**\") fdPattern = `**/${target.pattern}`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\targs.push(\"--\", fdPattern, target.searchPath);\n\t\t\t\t\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\t\t\t\t\tif (remainingMs <= 0) {\n\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn await new Promise<boolean>((resolveTarget, rejectTarget) => {\n\t\t\t\t\t\t\t\tconst child = spawn(fdPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\t\t\t\tconst lines: string[] = [];\n\t\t\t\t\t\t\t\tstopChild = () => {\n\t\t\t\t\t\t\t\t\tif (!child.killed) child.kill();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tconst targetTimer = setTimeout(() => {\n\t\t\t\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\t\t\t\tstopChild?.();\n\t\t\t\t\t\t\t\t}, remainingMs);\n\t\t\t\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\t\t\t\tclearTimeout(targetTimer);\n\t\t\t\t\t\t\t\t\trl.close();\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\trl.on(\"line\", (line) => lines.push(line));\n\t\t\t\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\t\t\trejectTarget(new Error(`Failed to run fd: ${error.message}`));\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\t\t\t\trejectTarget(new Error(\"Operation aborted\"));\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (!timedOut && code !== 0 && lines.length === 0) {\n\t\t\t\t\t\t\t\t\t\trejectTarget(new Error(stderr.trim() || `fd exited with code ${code}`));\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfor (const rawLine of lines.slice(0, remaining)) {\n\t\t\t\t\t\t\t\t\t\tconst line = rawLine.replace(/\\r$/, \"\").trim();\n\t\t\t\t\t\t\t\t\t\tif (line) { const found = statSync(path.resolve(target.searchPath, line), { throwIfNoEntry: false })?.isDirectory() && !line.endsWith(\"/\") ? `${line}/` : line; relativized.push(formatFoundPath(found, target.searchPath, searchPaths, cwd)); }\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\temitUpdate(relativized);\n\t\t\t\t\t\t\t\t\tresolveTarget(lines.length > Math.max(0, remaining));\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t};\n\t\t\t\t\t\tlet resultLimitReached = false;\n\t\t\t\t\t\tfor (const target of searchableTargets) {\n\t\t\t\t\t\t\tconst remaining = effectiveLimit - relativized.length;\n\t\t\t\t\t\t\tif (timedOut) break;\n\t\t\t\t\t\t\tif (remaining <= 0) { if (await runFdForTarget(target, 0)) { resultLimitReached = true; break; } continue; }\n\t\t\t\t\t\t\tconst targetLimitReached = await runFdForTarget(target, remaining);\n\t\t\t\t\t\t\tif (targetLimitReached) { resultLimitReached = true; break; }\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsettle(() => resolve(buildFindResult(relativized.slice(0, effectiveLimit), effectiveLimit, timedOut, timeoutMs, skippedMissingPaths, resultLimitReached)));\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst error = e instanceof Error ? e : new Error(String(e));\n\t\t\t\t\t\tsettle(() => reject(error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t\trenderCall(args, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatFindCall(args, theme));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, theme, context) {\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatFindResult(result, options, theme, context.showImages));\n\t\t\treturn text;\n\t\t},\n\t};\n}\nexport function createFindTool(cwd: string, options?: FindToolOptions): AgentTool<typeof findSchema> {\n\treturn wrapToolDefinition(createFindToolDefinition(cwd, options));\n}\n"]}