@vandeepunk/pi-coding-agent 0.0.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 (595) hide show
  1. package/CHANGELOG.md +2564 -0
  2. package/README.md +555 -0
  3. package/dist/cli/args.d.ts +47 -0
  4. package/dist/cli/args.d.ts.map +1 -0
  5. package/dist/cli/args.js +286 -0
  6. package/dist/cli/args.js.map +1 -0
  7. package/dist/cli/config-selector.d.ts +14 -0
  8. package/dist/cli/config-selector.d.ts.map +1 -0
  9. package/dist/cli/config-selector.js +31 -0
  10. package/dist/cli/config-selector.js.map +1 -0
  11. package/dist/cli/file-processor.d.ts +15 -0
  12. package/dist/cli/file-processor.d.ts.map +1 -0
  13. package/dist/cli/file-processor.js +79 -0
  14. package/dist/cli/file-processor.js.map +1 -0
  15. package/dist/cli/list-models.d.ts +9 -0
  16. package/dist/cli/list-models.d.ts.map +1 -0
  17. package/dist/cli/list-models.js +92 -0
  18. package/dist/cli/list-models.js.map +1 -0
  19. package/dist/cli/session-picker.d.ts +9 -0
  20. package/dist/cli/session-picker.d.ts.map +1 -0
  21. package/dist/cli/session-picker.js +34 -0
  22. package/dist/cli/session-picker.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +11 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/config.d.ts +68 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +203 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/core/agent-session.d.ts +574 -0
  32. package/dist/core/agent-session.d.ts.map +1 -0
  33. package/dist/core/agent-session.js +2260 -0
  34. package/dist/core/agent-session.js.map +1 -0
  35. package/dist/core/auth-storage.d.ts +102 -0
  36. package/dist/core/auth-storage.d.ts.map +1 -0
  37. package/dist/core/auth-storage.js +282 -0
  38. package/dist/core/auth-storage.js.map +1 -0
  39. package/dist/core/bash-executor.d.ts +47 -0
  40. package/dist/core/bash-executor.d.ts.map +1 -0
  41. package/dist/core/bash-executor.js +212 -0
  42. package/dist/core/bash-executor.js.map +1 -0
  43. package/dist/core/compaction/branch-summarization.d.ts +86 -0
  44. package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
  45. package/dist/core/compaction/branch-summarization.js +242 -0
  46. package/dist/core/compaction/branch-summarization.js.map +1 -0
  47. package/dist/core/compaction/compaction.d.ts +121 -0
  48. package/dist/core/compaction/compaction.d.ts.map +1 -0
  49. package/dist/core/compaction/compaction.js +607 -0
  50. package/dist/core/compaction/compaction.js.map +1 -0
  51. package/dist/core/compaction/index.d.ts +7 -0
  52. package/dist/core/compaction/index.d.ts.map +1 -0
  53. package/dist/core/compaction/index.js +7 -0
  54. package/dist/core/compaction/index.js.map +1 -0
  55. package/dist/core/compaction/utils.d.ts +35 -0
  56. package/dist/core/compaction/utils.d.ts.map +1 -0
  57. package/dist/core/compaction/utils.js +138 -0
  58. package/dist/core/compaction/utils.js.map +1 -0
  59. package/dist/core/defaults.d.ts +3 -0
  60. package/dist/core/defaults.d.ts.map +1 -0
  61. package/dist/core/defaults.js +2 -0
  62. package/dist/core/defaults.js.map +1 -0
  63. package/dist/core/diagnostics.d.ts +15 -0
  64. package/dist/core/diagnostics.d.ts.map +1 -0
  65. package/dist/core/diagnostics.js +2 -0
  66. package/dist/core/diagnostics.js.map +1 -0
  67. package/dist/core/event-bus.d.ts +9 -0
  68. package/dist/core/event-bus.d.ts.map +1 -0
  69. package/dist/core/event-bus.js +25 -0
  70. package/dist/core/event-bus.js.map +1 -0
  71. package/dist/core/exec.d.ts +29 -0
  72. package/dist/core/exec.d.ts.map +1 -0
  73. package/dist/core/exec.js +71 -0
  74. package/dist/core/exec.js.map +1 -0
  75. package/dist/core/export-html/ansi-to-html.d.ts +22 -0
  76. package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
  77. package/dist/core/export-html/ansi-to-html.js +249 -0
  78. package/dist/core/export-html/ansi-to-html.js.map +1 -0
  79. package/dist/core/export-html/index.d.ts +34 -0
  80. package/dist/core/export-html/index.d.ts.map +1 -0
  81. package/dist/core/export-html/index.js +222 -0
  82. package/dist/core/export-html/index.js.map +1 -0
  83. package/dist/core/export-html/template.css +909 -0
  84. package/dist/core/export-html/template.html +54 -0
  85. package/dist/core/export-html/template.js +1549 -0
  86. package/dist/core/export-html/tool-renderer.d.ts +35 -0
  87. package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
  88. package/dist/core/export-html/tool-renderer.js +57 -0
  89. package/dist/core/export-html/tool-renderer.js.map +1 -0
  90. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  91. package/dist/core/export-html/vendor/marked.min.js +6 -0
  92. package/dist/core/extensions/index.d.ts +11 -0
  93. package/dist/core/extensions/index.d.ts.map +1 -0
  94. package/dist/core/extensions/index.js +9 -0
  95. package/dist/core/extensions/index.js.map +1 -0
  96. package/dist/core/extensions/loader.d.ts +25 -0
  97. package/dist/core/extensions/loader.d.ts.map +1 -0
  98. package/dist/core/extensions/loader.js +400 -0
  99. package/dist/core/extensions/loader.js.map +1 -0
  100. package/dist/core/extensions/runner.d.ts +129 -0
  101. package/dist/core/extensions/runner.d.ts.map +1 -0
  102. package/dist/core/extensions/runner.js +576 -0
  103. package/dist/core/extensions/runner.js.map +1 -0
  104. package/dist/core/extensions/types.d.ts +928 -0
  105. package/dist/core/extensions/types.d.ts.map +1 -0
  106. package/dist/core/extensions/types.js +35 -0
  107. package/dist/core/extensions/types.js.map +1 -0
  108. package/dist/core/extensions/wrapper.d.ts +27 -0
  109. package/dist/core/extensions/wrapper.d.ts.map +1 -0
  110. package/dist/core/extensions/wrapper.js +102 -0
  111. package/dist/core/extensions/wrapper.js.map +1 -0
  112. package/dist/core/footer-data-provider.d.ts +32 -0
  113. package/dist/core/footer-data-provider.d.ts.map +1 -0
  114. package/dist/core/footer-data-provider.js +134 -0
  115. package/dist/core/footer-data-provider.js.map +1 -0
  116. package/dist/core/index.d.ts +9 -0
  117. package/dist/core/index.d.ts.map +1 -0
  118. package/dist/core/index.js +9 -0
  119. package/dist/core/index.js.map +1 -0
  120. package/dist/core/keybindings.d.ts +55 -0
  121. package/dist/core/keybindings.d.ts.map +1 -0
  122. package/dist/core/keybindings.js +153 -0
  123. package/dist/core/keybindings.js.map +1 -0
  124. package/dist/core/messages.d.ts +77 -0
  125. package/dist/core/messages.d.ts.map +1 -0
  126. package/dist/core/messages.js +123 -0
  127. package/dist/core/messages.js.map +1 -0
  128. package/dist/core/model-registry.d.ts +100 -0
  129. package/dist/core/model-registry.d.ts.map +1 -0
  130. package/dist/core/model-registry.js +419 -0
  131. package/dist/core/model-registry.js.map +1 -0
  132. package/dist/core/model-resolver.d.ts +76 -0
  133. package/dist/core/model-resolver.d.ts.map +1 -0
  134. package/dist/core/model-resolver.js +313 -0
  135. package/dist/core/model-resolver.js.map +1 -0
  136. package/dist/core/package-manager.d.ts +131 -0
  137. package/dist/core/package-manager.d.ts.map +1 -0
  138. package/dist/core/package-manager.js +1290 -0
  139. package/dist/core/package-manager.js.map +1 -0
  140. package/dist/core/prompt-templates.d.ts +50 -0
  141. package/dist/core/prompt-templates.d.ts.map +1 -0
  142. package/dist/core/prompt-templates.js +251 -0
  143. package/dist/core/prompt-templates.js.map +1 -0
  144. package/dist/core/resolve-config-value.d.ts +17 -0
  145. package/dist/core/resolve-config-value.d.ts.map +1 -0
  146. package/dist/core/resolve-config-value.js +59 -0
  147. package/dist/core/resolve-config-value.js.map +1 -0
  148. package/dist/core/resource-loader.d.ts +184 -0
  149. package/dist/core/resource-loader.d.ts.map +1 -0
  150. package/dist/core/resource-loader.js +673 -0
  151. package/dist/core/resource-loader.js.map +1 -0
  152. package/dist/core/sdk.d.ts +90 -0
  153. package/dist/core/sdk.d.ts.map +1 -0
  154. package/dist/core/sdk.js +234 -0
  155. package/dist/core/sdk.js.map +1 -0
  156. package/dist/core/session-manager.d.ts +323 -0
  157. package/dist/core/session-manager.d.ts.map +1 -0
  158. package/dist/core/session-manager.js +1091 -0
  159. package/dist/core/session-manager.js.map +1 -0
  160. package/dist/core/settings-manager.d.ts +187 -0
  161. package/dist/core/settings-manager.d.ts.map +1 -0
  162. package/dist/core/settings-manager.js +552 -0
  163. package/dist/core/settings-manager.js.map +1 -0
  164. package/dist/core/skills.d.ts +58 -0
  165. package/dist/core/skills.d.ts.map +1 -0
  166. package/dist/core/skills.js +310 -0
  167. package/dist/core/skills.js.map +1 -0
  168. package/dist/core/slash-commands.d.ts +15 -0
  169. package/dist/core/slash-commands.d.ts.map +1 -0
  170. package/dist/core/slash-commands.js +21 -0
  171. package/dist/core/slash-commands.js.map +1 -0
  172. package/dist/core/system-prompt.d.ts +24 -0
  173. package/dist/core/system-prompt.d.ts.map +1 -0
  174. package/dist/core/system-prompt.js +137 -0
  175. package/dist/core/system-prompt.js.map +1 -0
  176. package/dist/core/timings.d.ts +7 -0
  177. package/dist/core/timings.d.ts.map +1 -0
  178. package/dist/core/timings.js +25 -0
  179. package/dist/core/timings.js.map +1 -0
  180. package/dist/core/tools/bash.d.ts +55 -0
  181. package/dist/core/tools/bash.d.ts.map +1 -0
  182. package/dist/core/tools/bash.js +242 -0
  183. package/dist/core/tools/bash.js.map +1 -0
  184. package/dist/core/tools/edit-diff.d.ts +63 -0
  185. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  186. package/dist/core/tools/edit-diff.js +243 -0
  187. package/dist/core/tools/edit-diff.js.map +1 -0
  188. package/dist/core/tools/edit.d.ts +39 -0
  189. package/dist/core/tools/edit.d.ts.map +1 -0
  190. package/dist/core/tools/edit.js +146 -0
  191. package/dist/core/tools/edit.js.map +1 -0
  192. package/dist/core/tools/find.d.ts +39 -0
  193. package/dist/core/tools/find.d.ts.map +1 -0
  194. package/dist/core/tools/find.js +206 -0
  195. package/dist/core/tools/find.js.map +1 -0
  196. package/dist/core/tools/grep.d.ts +45 -0
  197. package/dist/core/tools/grep.d.ts.map +1 -0
  198. package/dist/core/tools/grep.js +239 -0
  199. package/dist/core/tools/grep.js.map +1 -0
  200. package/dist/core/tools/index.d.ts +73 -0
  201. package/dist/core/tools/index.d.ts.map +1 -0
  202. package/dist/core/tools/index.js +61 -0
  203. package/dist/core/tools/index.js.map +1 -0
  204. package/dist/core/tools/ls.d.ts +40 -0
  205. package/dist/core/tools/ls.d.ts.map +1 -0
  206. package/dist/core/tools/ls.js +118 -0
  207. package/dist/core/tools/ls.js.map +1 -0
  208. package/dist/core/tools/path-utils.d.ts +8 -0
  209. package/dist/core/tools/path-utils.d.ts.map +1 -0
  210. package/dist/core/tools/path-utils.js +81 -0
  211. package/dist/core/tools/path-utils.js.map +1 -0
  212. package/dist/core/tools/read.d.ts +39 -0
  213. package/dist/core/tools/read.d.ts.map +1 -0
  214. package/dist/core/tools/read.js +166 -0
  215. package/dist/core/tools/read.js.map +1 -0
  216. package/dist/core/tools/truncate.d.ts +70 -0
  217. package/dist/core/tools/truncate.d.ts.map +1 -0
  218. package/dist/core/tools/truncate.js +205 -0
  219. package/dist/core/tools/truncate.js.map +1 -0
  220. package/dist/core/tools/write.d.ts +29 -0
  221. package/dist/core/tools/write.d.ts.map +1 -0
  222. package/dist/core/tools/write.js +78 -0
  223. package/dist/core/tools/write.js.map +1 -0
  224. package/dist/index.d.ts +27 -0
  225. package/dist/index.d.ts.map +1 -0
  226. package/dist/index.js +42 -0
  227. package/dist/index.js.map +1 -0
  228. package/dist/main.d.ts +8 -0
  229. package/dist/main.d.ts.map +1 -0
  230. package/dist/main.js +623 -0
  231. package/dist/main.js.map +1 -0
  232. package/dist/migrations.d.ts +33 -0
  233. package/dist/migrations.d.ts.map +1 -0
  234. package/dist/migrations.js +261 -0
  235. package/dist/migrations.js.map +1 -0
  236. package/dist/modes/index.d.ts +9 -0
  237. package/dist/modes/index.d.ts.map +1 -0
  238. package/dist/modes/index.js +8 -0
  239. package/dist/modes/index.js.map +1 -0
  240. package/dist/modes/interactive/components/armin.d.ts +34 -0
  241. package/dist/modes/interactive/components/armin.d.ts.map +1 -0
  242. package/dist/modes/interactive/components/armin.js +333 -0
  243. package/dist/modes/interactive/components/armin.js.map +1 -0
  244. package/dist/modes/interactive/components/assistant-message.d.ts +16 -0
  245. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
  246. package/dist/modes/interactive/components/assistant-message.js +91 -0
  247. package/dist/modes/interactive/components/assistant-message.js.map +1 -0
  248. package/dist/modes/interactive/components/bash-execution.d.ts +35 -0
  249. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
  250. package/dist/modes/interactive/components/bash-execution.js +162 -0
  251. package/dist/modes/interactive/components/bash-execution.js.map +1 -0
  252. package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
  253. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
  254. package/dist/modes/interactive/components/bordered-loader.js +51 -0
  255. package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
  256. package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
  257. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
  258. package/dist/modes/interactive/components/branch-summary-message.js +44 -0
  259. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
  260. package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
  261. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
  262. package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
  263. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
  264. package/dist/modes/interactive/components/config-selector.d.ts +71 -0
  265. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
  266. package/dist/modes/interactive/components/config-selector.js +479 -0
  267. package/dist/modes/interactive/components/config-selector.js.map +1 -0
  268. package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
  269. package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
  270. package/dist/modes/interactive/components/countdown-timer.js +33 -0
  271. package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
  272. package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
  273. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
  274. package/dist/modes/interactive/components/custom-editor.js +70 -0
  275. package/dist/modes/interactive/components/custom-editor.js.map +1 -0
  276. package/dist/modes/interactive/components/custom-message.d.ts +20 -0
  277. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
  278. package/dist/modes/interactive/components/custom-message.js +79 -0
  279. package/dist/modes/interactive/components/custom-message.js.map +1 -0
  280. package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
  281. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
  282. package/dist/modes/interactive/components/daxnuts.js +140 -0
  283. package/dist/modes/interactive/components/daxnuts.js.map +1 -0
  284. package/dist/modes/interactive/components/diff.d.ts +12 -0
  285. package/dist/modes/interactive/components/diff.d.ts.map +1 -0
  286. package/dist/modes/interactive/components/diff.js +133 -0
  287. package/dist/modes/interactive/components/diff.js.map +1 -0
  288. package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
  289. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
  290. package/dist/modes/interactive/components/dynamic-border.js +21 -0
  291. package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
  292. package/dist/modes/interactive/components/extension-editor.d.ts +17 -0
  293. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
  294. package/dist/modes/interactive/components/extension-editor.js +102 -0
  295. package/dist/modes/interactive/components/extension-editor.js.map +1 -0
  296. package/dist/modes/interactive/components/extension-input.d.ts +23 -0
  297. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
  298. package/dist/modes/interactive/components/extension-input.js +61 -0
  299. package/dist/modes/interactive/components/extension-input.js.map +1 -0
  300. package/dist/modes/interactive/components/extension-selector.d.ts +24 -0
  301. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
  302. package/dist/modes/interactive/components/extension-selector.js +78 -0
  303. package/dist/modes/interactive/components/extension-selector.js.map +1 -0
  304. package/dist/modes/interactive/components/footer.d.ts +26 -0
  305. package/dist/modes/interactive/components/footer.d.ts.map +1 -0
  306. package/dist/modes/interactive/components/footer.js +220 -0
  307. package/dist/modes/interactive/components/footer.js.map +1 -0
  308. package/dist/modes/interactive/components/index.d.ts +32 -0
  309. package/dist/modes/interactive/components/index.d.ts.map +1 -0
  310. package/dist/modes/interactive/components/index.js +33 -0
  311. package/dist/modes/interactive/components/index.js.map +1 -0
  312. package/dist/modes/interactive/components/keybinding-hints.d.ts +41 -0
  313. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
  314. package/dist/modes/interactive/components/keybinding-hints.js +61 -0
  315. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
  316. package/dist/modes/interactive/components/login-dialog.d.ts +42 -0
  317. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
  318. package/dist/modes/interactive/components/login-dialog.js +145 -0
  319. package/dist/modes/interactive/components/login-dialog.js.map +1 -0
  320. package/dist/modes/interactive/components/model-selector.d.ts +47 -0
  321. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
  322. package/dist/modes/interactive/components/model-selector.js +266 -0
  323. package/dist/modes/interactive/components/model-selector.js.map +1 -0
  324. package/dist/modes/interactive/components/oauth-selector.d.ts +19 -0
  325. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
  326. package/dist/modes/interactive/components/oauth-selector.js +97 -0
  327. package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
  328. package/dist/modes/interactive/components/scoped-models-selector.d.ts +49 -0
  329. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
  330. package/dist/modes/interactive/components/scoped-models-selector.js +270 -0
  331. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
  332. package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
  333. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
  334. package/dist/modes/interactive/components/session-selector-search.js +155 -0
  335. package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
  336. package/dist/modes/interactive/components/session-selector.d.ts +95 -0
  337. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
  338. package/dist/modes/interactive/components/session-selector.js +851 -0
  339. package/dist/modes/interactive/components/session-selector.js.map +1 -0
  340. package/dist/modes/interactive/components/settings-selector.d.ts +53 -0
  341. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
  342. package/dist/modes/interactive/components/settings-selector.js +277 -0
  343. package/dist/modes/interactive/components/settings-selector.js.map +1 -0
  344. package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
  345. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
  346. package/dist/modes/interactive/components/show-images-selector.js +35 -0
  347. package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
  348. package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
  349. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
  350. package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
  351. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
  352. package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
  353. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
  354. package/dist/modes/interactive/components/theme-selector.js +46 -0
  355. package/dist/modes/interactive/components/theme-selector.js.map +1 -0
  356. package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
  357. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
  358. package/dist/modes/interactive/components/thinking-selector.js +47 -0
  359. package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
  360. package/dist/modes/interactive/components/tool-execution.d.ts +70 -0
  361. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
  362. package/dist/modes/interactive/components/tool-execution.js +621 -0
  363. package/dist/modes/interactive/components/tool-execution.js.map +1 -0
  364. package/dist/modes/interactive/components/tree-selector.d.ts +68 -0
  365. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
  366. package/dist/modes/interactive/components/tree-selector.js +934 -0
  367. package/dist/modes/interactive/components/tree-selector.js.map +1 -0
  368. package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
  369. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
  370. package/dist/modes/interactive/components/user-message-selector.js +113 -0
  371. package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
  372. package/dist/modes/interactive/components/user-message.d.ts +8 -0
  373. package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
  374. package/dist/modes/interactive/components/user-message.js +16 -0
  375. package/dist/modes/interactive/components/user-message.js.map +1 -0
  376. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  377. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  378. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  379. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  380. package/dist/modes/interactive/interactive-mode.d.ts +313 -0
  381. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
  382. package/dist/modes/interactive/interactive-mode.js +3664 -0
  383. package/dist/modes/interactive/interactive-mode.js.map +1 -0
  384. package/dist/modes/interactive/theme/dark.json +85 -0
  385. package/dist/modes/interactive/theme/light.json +84 -0
  386. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  387. package/dist/modes/interactive/theme/theme.d.ts +78 -0
  388. package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
  389. package/dist/modes/interactive/theme/theme.js +944 -0
  390. package/dist/modes/interactive/theme/theme.js.map +1 -0
  391. package/dist/modes/print-mode.d.ts +28 -0
  392. package/dist/modes/print-mode.d.ts.map +1 -0
  393. package/dist/modes/print-mode.js +98 -0
  394. package/dist/modes/print-mode.js.map +1 -0
  395. package/dist/modes/rpc/rpc-client.d.ts +217 -0
  396. package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
  397. package/dist/modes/rpc/rpc-client.js +405 -0
  398. package/dist/modes/rpc/rpc-client.js.map +1 -0
  399. package/dist/modes/rpc/rpc-mode.d.ts +20 -0
  400. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
  401. package/dist/modes/rpc/rpc-mode.js +500 -0
  402. package/dist/modes/rpc/rpc-mode.js.map +1 -0
  403. package/dist/modes/rpc/rpc-types.d.ts +409 -0
  404. package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
  405. package/dist/modes/rpc/rpc-types.js +8 -0
  406. package/dist/modes/rpc/rpc-types.js.map +1 -0
  407. package/dist/utils/changelog.d.ts +21 -0
  408. package/dist/utils/changelog.d.ts.map +1 -0
  409. package/dist/utils/changelog.js +87 -0
  410. package/dist/utils/changelog.js.map +1 -0
  411. package/dist/utils/clipboard-image.d.ts +11 -0
  412. package/dist/utils/clipboard-image.d.ts.map +1 -0
  413. package/dist/utils/clipboard-image.js +162 -0
  414. package/dist/utils/clipboard-image.js.map +1 -0
  415. package/dist/utils/clipboard-native.d.ts +7 -0
  416. package/dist/utils/clipboard-native.d.ts.map +1 -0
  417. package/dist/utils/clipboard-native.js +14 -0
  418. package/dist/utils/clipboard-native.js.map +1 -0
  419. package/dist/utils/clipboard.d.ts +2 -0
  420. package/dist/utils/clipboard.d.ts.map +1 -0
  421. package/dist/utils/clipboard.js +67 -0
  422. package/dist/utils/clipboard.js.map +1 -0
  423. package/dist/utils/frontmatter.d.ts +8 -0
  424. package/dist/utils/frontmatter.d.ts.map +1 -0
  425. package/dist/utils/frontmatter.js +26 -0
  426. package/dist/utils/frontmatter.js.map +1 -0
  427. package/dist/utils/git.d.ts +2 -0
  428. package/dist/utils/git.d.ts.map +1 -0
  429. package/dist/utils/git.js +6 -0
  430. package/dist/utils/git.js.map +1 -0
  431. package/dist/utils/image-convert.d.ts +9 -0
  432. package/dist/utils/image-convert.d.ts.map +1 -0
  433. package/dist/utils/image-convert.js +35 -0
  434. package/dist/utils/image-convert.js.map +1 -0
  435. package/dist/utils/image-resize.d.ts +36 -0
  436. package/dist/utils/image-resize.d.ts.map +1 -0
  437. package/dist/utils/image-resize.js +181 -0
  438. package/dist/utils/image-resize.js.map +1 -0
  439. package/dist/utils/mime.d.ts +2 -0
  440. package/dist/utils/mime.d.ts.map +1 -0
  441. package/dist/utils/mime.js +26 -0
  442. package/dist/utils/mime.js.map +1 -0
  443. package/dist/utils/photon.d.ts +21 -0
  444. package/dist/utils/photon.d.ts.map +1 -0
  445. package/dist/utils/photon.js +121 -0
  446. package/dist/utils/photon.js.map +1 -0
  447. package/dist/utils/shell.d.ts +26 -0
  448. package/dist/utils/shell.d.ts.map +1 -0
  449. package/dist/utils/shell.js +186 -0
  450. package/dist/utils/shell.js.map +1 -0
  451. package/dist/utils/sleep.d.ts +5 -0
  452. package/dist/utils/sleep.d.ts.map +1 -0
  453. package/dist/utils/sleep.js +17 -0
  454. package/dist/utils/sleep.js.map +1 -0
  455. package/dist/utils/tools-manager.d.ts +3 -0
  456. package/dist/utils/tools-manager.d.ts.map +1 -0
  457. package/dist/utils/tools-manager.js +201 -0
  458. package/dist/utils/tools-manager.js.map +1 -0
  459. package/docs/compaction.md +390 -0
  460. package/docs/custom-provider.md +539 -0
  461. package/docs/development.md +69 -0
  462. package/docs/extensions.md +1827 -0
  463. package/docs/images/doom-extension.png +0 -0
  464. package/docs/images/exy.png +0 -0
  465. package/docs/images/interactive-mode.png +0 -0
  466. package/docs/images/tree-view.png +0 -0
  467. package/docs/json.md +79 -0
  468. package/docs/keybindings.md +174 -0
  469. package/docs/models.md +254 -0
  470. package/docs/packages.md +191 -0
  471. package/docs/prompt-templates.md +67 -0
  472. package/docs/providers.md +168 -0
  473. package/docs/rpc.md +1311 -0
  474. package/docs/sdk.md +957 -0
  475. package/docs/session.md +412 -0
  476. package/docs/settings.md +221 -0
  477. package/docs/shell-aliases.md +13 -0
  478. package/docs/skills.md +227 -0
  479. package/docs/terminal-setup.md +70 -0
  480. package/docs/termux.md +127 -0
  481. package/docs/themes.md +295 -0
  482. package/docs/tree.md +219 -0
  483. package/docs/tui.md +887 -0
  484. package/docs/windows.md +17 -0
  485. package/examples/README.md +25 -0
  486. package/examples/extensions/README.md +202 -0
  487. package/examples/extensions/antigravity-image-gen.ts +413 -0
  488. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  489. package/examples/extensions/bash-spawn-hook.ts +30 -0
  490. package/examples/extensions/bookmark.ts +50 -0
  491. package/examples/extensions/claude-rules.ts +86 -0
  492. package/examples/extensions/commands.ts +72 -0
  493. package/examples/extensions/confirm-destructive.ts +59 -0
  494. package/examples/extensions/custom-compaction.ts +114 -0
  495. package/examples/extensions/custom-footer.ts +64 -0
  496. package/examples/extensions/custom-header.ts +73 -0
  497. package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
  498. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  499. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  500. package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
  501. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  502. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  503. package/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
  504. package/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
  505. package/examples/extensions/dirty-repo-guard.ts +56 -0
  506. package/examples/extensions/doom-overlay/README.md +46 -0
  507. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  508. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  509. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  510. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  511. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  512. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  513. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  514. package/examples/extensions/doom-overlay/index.ts +74 -0
  515. package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
  516. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  517. package/examples/extensions/dynamic-resources/dynamic.json +79 -0
  518. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  519. package/examples/extensions/dynamic-resources/index.ts +15 -0
  520. package/examples/extensions/event-bus.ts +43 -0
  521. package/examples/extensions/file-trigger.ts +41 -0
  522. package/examples/extensions/git-checkpoint.ts +53 -0
  523. package/examples/extensions/handoff.ts +150 -0
  524. package/examples/extensions/hello.ts +25 -0
  525. package/examples/extensions/inline-bash.ts +94 -0
  526. package/examples/extensions/input-transform.ts +43 -0
  527. package/examples/extensions/interactive-shell.ts +196 -0
  528. package/examples/extensions/mac-system-theme.ts +47 -0
  529. package/examples/extensions/message-renderer.ts +59 -0
  530. package/examples/extensions/minimal-mode.ts +426 -0
  531. package/examples/extensions/modal-editor.ts +85 -0
  532. package/examples/extensions/model-status.ts +31 -0
  533. package/examples/extensions/notify.ts +55 -0
  534. package/examples/extensions/overlay-qa-tests.ts +881 -0
  535. package/examples/extensions/overlay-test.ts +150 -0
  536. package/examples/extensions/permission-gate.ts +34 -0
  537. package/examples/extensions/pirate.ts +47 -0
  538. package/examples/extensions/plan-mode/README.md +65 -0
  539. package/examples/extensions/plan-mode/index.ts +340 -0
  540. package/examples/extensions/plan-mode/utils.ts +168 -0
  541. package/examples/extensions/preset.ts +398 -0
  542. package/examples/extensions/protected-paths.ts +30 -0
  543. package/examples/extensions/qna.ts +119 -0
  544. package/examples/extensions/question.ts +264 -0
  545. package/examples/extensions/questionnaire.ts +427 -0
  546. package/examples/extensions/rainbow-editor.ts +88 -0
  547. package/examples/extensions/rpc-demo.ts +124 -0
  548. package/examples/extensions/sandbox/index.ts +318 -0
  549. package/examples/extensions/sandbox/package-lock.json +92 -0
  550. package/examples/extensions/sandbox/package.json +19 -0
  551. package/examples/extensions/send-user-message.ts +97 -0
  552. package/examples/extensions/session-name.ts +27 -0
  553. package/examples/extensions/shutdown-command.ts +63 -0
  554. package/examples/extensions/snake.ts +343 -0
  555. package/examples/extensions/space-invaders.ts +560 -0
  556. package/examples/extensions/ssh.ts +220 -0
  557. package/examples/extensions/status-line.ts +40 -0
  558. package/examples/extensions/subagent/README.md +172 -0
  559. package/examples/extensions/subagent/agents/planner.md +37 -0
  560. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  561. package/examples/extensions/subagent/agents/scout.md +50 -0
  562. package/examples/extensions/subagent/agents/worker.md +24 -0
  563. package/examples/extensions/subagent/agents.ts +127 -0
  564. package/examples/extensions/subagent/index.ts +963 -0
  565. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  566. package/examples/extensions/subagent/prompts/implement.md +10 -0
  567. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  568. package/examples/extensions/summarize.ts +195 -0
  569. package/examples/extensions/system-prompt-header.ts +17 -0
  570. package/examples/extensions/timed-confirm.ts +70 -0
  571. package/examples/extensions/titlebar-spinner.ts +58 -0
  572. package/examples/extensions/todo.ts +299 -0
  573. package/examples/extensions/tool-override.ts +143 -0
  574. package/examples/extensions/tools.ts +146 -0
  575. package/examples/extensions/trigger-compact.ts +40 -0
  576. package/examples/extensions/truncated-tool.ts +192 -0
  577. package/examples/extensions/widget-placement.ts +17 -0
  578. package/examples/extensions/with-deps/index.ts +36 -0
  579. package/examples/extensions/with-deps/package-lock.json +31 -0
  580. package/examples/extensions/with-deps/package.json +22 -0
  581. package/examples/rpc-extension-ui.ts +632 -0
  582. package/examples/sdk/01-minimal.ts +22 -0
  583. package/examples/sdk/02-custom-model.ts +49 -0
  584. package/examples/sdk/03-custom-prompt.ts +55 -0
  585. package/examples/sdk/04-skills.ts +46 -0
  586. package/examples/sdk/05-tools.ts +56 -0
  587. package/examples/sdk/06-extensions.ts +88 -0
  588. package/examples/sdk/07-context-files.ts +40 -0
  589. package/examples/sdk/08-prompt-templates.ts +47 -0
  590. package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
  591. package/examples/sdk/10-settings.ts +38 -0
  592. package/examples/sdk/11-sessions.ts +48 -0
  593. package/examples/sdk/12-full-control.ts +82 -0
  594. package/examples/sdk/README.md +144 -0
  595. package/package.json +97 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/core/tools/grep.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { spawn } from \"child_process\";\nimport { readFileSync, statSync } from \"fs\";\nimport path from \"path\";\nimport { ensureTool } from \"../../utils/tools-manager.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tformatSize,\n\tGREP_MAX_LINE_LENGTH,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n} from \"./truncate.js\";\n\nconst grepSchema = Type.Object({\n\tpattern: Type.String({ description: \"Search pattern (regex or literal string)\" }),\n\tpath: Type.Optional(Type.String({ description: \"Directory or file to search (default: current directory)\" })),\n\tglob: Type.Optional(Type.String({ description: \"Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'\" })),\n\tignoreCase: Type.Optional(Type.Boolean({ description: \"Case-insensitive search (default: false)\" })),\n\tliteral: Type.Optional(\n\t\tType.Boolean({ description: \"Treat pattern as literal string instead of regex (default: false)\" }),\n\t),\n\tcontext: Type.Optional(\n\t\tType.Number({ description: \"Number of lines to show before and after each match (default: 0)\" }),\n\t),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of matches to return (default: 100)\" })),\n});\n\nexport type GrepToolInput = Static<typeof grepSchema>;\n\nconst DEFAULT_LIMIT = 100;\n\nexport interface GrepToolDetails {\n\ttruncation?: TruncationResult;\n\tmatchLimitReached?: number;\n\tlinesTruncated?: boolean;\n}\n\n/**\n * Pluggable operations for the grep tool.\n * Override these to delegate search to remote systems (e.g., SSH).\n */\nexport interface GrepOperations {\n\t/** Check if path is a directory. Throws if path doesn't exist. */\n\tisDirectory: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Read file contents for context lines */\n\treadFile: (absolutePath: string) => Promise<string> | string;\n}\n\nconst defaultGrepOperations: GrepOperations = {\n\tisDirectory: (p) => statSync(p).isDirectory(),\n\treadFile: (p) => readFileSync(p, \"utf-8\"),\n};\n\nexport interface GrepToolOptions {\n\t/** Custom operations for grep. Default: local filesystem + ripgrep */\n\toperations?: GrepOperations;\n}\n\nexport function createGrepTool(cwd: string, options?: GrepToolOptions): AgentTool<typeof grepSchema> {\n\tconst customOps = options?.operations;\n\n\treturn {\n\t\tname: \"grep\",\n\t\tlabel: \"grep\",\n\t\tdescription: `Search file contents for a pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} matches or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Long lines are truncated to ${GREP_MAX_LINE_LENGTH} chars.`,\n\t\tparameters: grepSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{\n\t\t\t\tpattern,\n\t\t\t\tpath: searchDir,\n\t\t\t\tglob,\n\t\t\t\tignoreCase,\n\t\t\t\tliteral,\n\t\t\t\tcontext,\n\t\t\t\tlimit,\n\t\t\t}: {\n\t\t\t\tpattern: string;\n\t\t\t\tpath?: string;\n\t\t\t\tglob?: string;\n\t\t\t\tignoreCase?: boolean;\n\t\t\t\tliteral?: boolean;\n\t\t\t\tcontext?: number;\n\t\t\t\tlimit?: number;\n\t\t\t},\n\t\t\tsignal?: AbortSignal,\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\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (!settled) {\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tfn();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst rgPath = await ensureTool(\"rg\", true);\n\t\t\t\t\t\tif (!rgPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"ripgrep (rg) 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\tconst searchPath = resolveToCwd(searchDir || \".\", cwd);\n\t\t\t\t\t\tconst ops = customOps ?? defaultGrepOperations;\n\n\t\t\t\t\t\tlet isDirectory: boolean;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tisDirectory = await ops.isDirectory(searchPath);\n\t\t\t\t\t\t} catch (_err) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst contextValue = context && context > 0 ? context : 0;\n\t\t\t\t\t\tconst effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);\n\n\t\t\t\t\t\tconst formatPath = (filePath: string): string => {\n\t\t\t\t\t\t\tif (isDirectory) {\n\t\t\t\t\t\t\t\tconst relative = path.relative(searchPath, filePath);\n\t\t\t\t\t\t\t\tif (relative && !relative.startsWith(\"..\")) {\n\t\t\t\t\t\t\t\t\treturn relative.replace(/\\\\/g, \"/\");\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 path.basename(filePath);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst fileCache = new Map<string, string[]>();\n\t\t\t\t\t\tconst getFileLines = async (filePath: string): Promise<string[]> => {\n\t\t\t\t\t\t\tlet lines = fileCache.get(filePath);\n\t\t\t\t\t\t\tif (!lines) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst content = await ops.readFile(filePath);\n\t\t\t\t\t\t\t\t\tlines = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\tlines = [];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfileCache.set(filePath, lines);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn lines;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst args: string[] = [\"--json\", \"--line-number\", \"--color=never\", \"--hidden\"];\n\n\t\t\t\t\t\tif (ignoreCase) {\n\t\t\t\t\t\t\targs.push(\"--ignore-case\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (literal) {\n\t\t\t\t\t\t\targs.push(\"--fixed-strings\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (glob) {\n\t\t\t\t\t\t\targs.push(\"--glob\", glob);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\targs.push(pattern, searchPath);\n\n\t\t\t\t\t\tconst child = spawn(rgPath, 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\tlet matchCount = 0;\n\t\t\t\t\t\tlet matchLimitReached = false;\n\t\t\t\t\t\tlet linesTruncated = false;\n\t\t\t\t\t\tlet aborted = false;\n\t\t\t\t\t\tlet killedDueToLimit = false;\n\t\t\t\t\t\tconst outputLines: string[] = [];\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\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst stopChild = (dueToLimit: boolean = false) => {\n\t\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\t\tkilledDueToLimit = dueToLimit;\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 onAbort = () => {\n\t\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\t\tstopChild();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\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\tconst formatBlock = async (filePath: string, lineNumber: number): Promise<string[]> => {\n\t\t\t\t\t\t\tconst relativePath = formatPath(filePath);\n\t\t\t\t\t\t\tconst lines = await getFileLines(filePath);\n\t\t\t\t\t\t\tif (!lines.length) {\n\t\t\t\t\t\t\t\treturn [`${relativePath}:${lineNumber}: (unable to read file)`];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst block: string[] = [];\n\t\t\t\t\t\t\tconst start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;\n\t\t\t\t\t\t\tconst end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;\n\n\t\t\t\t\t\t\tfor (let current = start; current <= end; current++) {\n\t\t\t\t\t\t\t\tconst lineText = lines[current - 1] ?? \"\";\n\t\t\t\t\t\t\t\tconst sanitized = lineText.replace(/\\r/g, \"\");\n\t\t\t\t\t\t\t\tconst isMatchLine = current === lineNumber;\n\n\t\t\t\t\t\t\t\t// Truncate long lines\n\t\t\t\t\t\t\t\tconst { text: truncatedText, wasTruncated } = truncateLine(sanitized);\n\t\t\t\t\t\t\t\tif (wasTruncated) {\n\t\t\t\t\t\t\t\t\tlinesTruncated = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (isMatchLine) {\n\t\t\t\t\t\t\t\t\tblock.push(`${relativePath}:${current}: ${truncatedText}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tblock.push(`${relativePath}-${current}- ${truncatedText}`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn block;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// Collect matches during streaming, format after\n\t\t\t\t\t\tconst matches: Array<{ filePath: string; lineNumber: number }> = [];\n\n\t\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\t\tif (!line.trim() || matchCount >= effectiveLimit) {\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\tlet event: any;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tevent = JSON.parse(line);\n\t\t\t\t\t\t\t} catch {\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\tif (event.type === \"match\") {\n\t\t\t\t\t\t\t\tmatchCount++;\n\t\t\t\t\t\t\t\tconst filePath = event.data?.path?.text;\n\t\t\t\t\t\t\t\tconst lineNumber = event.data?.line_number;\n\n\t\t\t\t\t\t\t\tif (filePath && typeof lineNumber === \"number\") {\n\t\t\t\t\t\t\t\t\tmatches.push({ filePath, lineNumber });\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (matchCount >= effectiveLimit) {\n\t\t\t\t\t\t\t\t\tmatchLimitReached = true;\n\t\t\t\t\t\t\t\t\tstopChild(true);\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\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 ripgrep: ${error.message}`)));\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"close\", async (code) => {\n\t\t\t\t\t\t\tcleanup();\n\n\t\t\t\t\t\t\tif (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\n\t\t\t\t\t\t\tif (!killedDueToLimit && code !== 0 && code !== 1) {\n\t\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\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\tif (matchCount === 0) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"No matches found\" }], details: undefined }),\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// Format matches (async to support remote file reading)\n\t\t\t\t\t\t\tfor (const match of matches) {\n\t\t\t\t\t\t\t\tconst block = await formatBlock(match.filePath, match.lineNumber);\n\t\t\t\t\t\t\t\toutputLines.push(...block);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Apply byte truncation (no line limit since we already have match limit)\n\t\t\t\t\t\t\tconst rawOutput = outputLines.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\n\t\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\t\tconst details: GrepToolDetails = {};\n\n\t\t\t\t\t\t\t// Build notices\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\n\t\t\t\t\t\t\tif (matchLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`${effectiveLimit} matches 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.matchLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\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\n\t\t\t\t\t\t\tif (linesTruncated) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.linesTruncated = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\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: output }],\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 (err) {\n\t\t\t\t\t\tsettle(() => reject(err as Error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default grep tool using process.cwd() - for backwards compatibility */\nexport const grepTool = createGrepTool(process.cwd());\n"]}
@@ -0,0 +1,73 @@
1
+ export { type BashOperations, type BashSpawnContext, type BashSpawnHook, type BashToolDetails, type BashToolInput, type BashToolOptions, bashTool, createBashTool, } from "./bash.js";
2
+ export { createEditTool, type EditOperations, type EditToolDetails, type EditToolInput, type EditToolOptions, editTool, } from "./edit.js";
3
+ export { createFindTool, type FindOperations, type FindToolDetails, type FindToolInput, type FindToolOptions, findTool, } from "./find.js";
4
+ export { createGrepTool, type GrepOperations, type GrepToolDetails, type GrepToolInput, type GrepToolOptions, grepTool, } from "./grep.js";
5
+ export { createLsTool, type LsOperations, type LsToolDetails, type LsToolInput, type LsToolOptions, lsTool, } from "./ls.js";
6
+ export { createReadTool, type ReadOperations, type ReadToolDetails, type ReadToolInput, type ReadToolOptions, readTool, } from "./read.js";
7
+ export { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationOptions, type TruncationResult, truncateHead, truncateLine, truncateTail, } from "./truncate.js";
8
+ export { createWriteTool, type WriteOperations, type WriteToolInput, type WriteToolOptions, writeTool, } from "./write.js";
9
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
10
+ import { type BashToolOptions } from "./bash.js";
11
+ import { type ReadToolOptions } from "./read.js";
12
+ /** Tool type (AgentTool from pi-ai) */
13
+ export type Tool = AgentTool<any>;
14
+ export declare const codingTools: Tool[];
15
+ export declare const readOnlyTools: Tool[];
16
+ export declare const allTools: {
17
+ read: AgentTool<import("@sinclair/typebox").TObject<{
18
+ path: import("@sinclair/typebox").TString;
19
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
20
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
21
+ }>, any>;
22
+ bash: AgentTool<import("@sinclair/typebox").TObject<{
23
+ command: import("@sinclair/typebox").TString;
24
+ timeout: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
25
+ }>, any>;
26
+ edit: AgentTool<import("@sinclair/typebox").TObject<{
27
+ path: import("@sinclair/typebox").TString;
28
+ oldText: import("@sinclair/typebox").TString;
29
+ newText: import("@sinclair/typebox").TString;
30
+ }>, any>;
31
+ write: AgentTool<import("@sinclair/typebox").TObject<{
32
+ path: import("@sinclair/typebox").TString;
33
+ content: import("@sinclair/typebox").TString;
34
+ }>, any>;
35
+ grep: AgentTool<import("@sinclair/typebox").TObject<{
36
+ pattern: import("@sinclair/typebox").TString;
37
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
38
+ glob: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
39
+ ignoreCase: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
40
+ literal: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
41
+ context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
42
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
43
+ }>, any>;
44
+ find: AgentTool<import("@sinclair/typebox").TObject<{
45
+ pattern: import("@sinclair/typebox").TString;
46
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
47
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
48
+ }>, any>;
49
+ ls: AgentTool<import("@sinclair/typebox").TObject<{
50
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
51
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
52
+ }>, any>;
53
+ };
54
+ export type ToolName = keyof typeof allTools;
55
+ export interface ToolsOptions {
56
+ /** Options for the read tool */
57
+ read?: ReadToolOptions;
58
+ /** Options for the bash tool */
59
+ bash?: BashToolOptions;
60
+ }
61
+ /**
62
+ * Create coding tools configured for a specific working directory.
63
+ */
64
+ export declare function createCodingTools(cwd: string, options?: ToolsOptions): Tool[];
65
+ /**
66
+ * Create read-only tools configured for a specific working directory.
67
+ */
68
+ export declare function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[];
69
+ /**
70
+ * Create all tools configured for a specific working directory.
71
+ */
72
+ export declare function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool>;
73
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,QAAQ,EACR,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,QAAQ,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,QAAQ,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,QAAQ,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,MAAM,GACN,MAAM,SAAS,CAAC;AACjB,OAAO,EACN,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,QAAQ,GACR,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,YAAY,EACZ,YAAY,EACZ,YAAY,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,SAAS,GACT,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,KAAK,eAAe,EAA4B,MAAM,WAAW,CAAC;AAK3E,OAAO,EAAkB,KAAK,eAAe,EAAY,MAAM,WAAW,CAAC;AAG3E,uCAAuC;AACvC,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;AAGlC,eAAO,MAAM,WAAW,EAAE,IAAI,EAA8C,CAAC;AAG7E,eAAO,MAAM,aAAa,EAAE,IAAI,EAA2C,CAAC;AAG5E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQpB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC5B,gCAAgC;IAChC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,gCAAgC;IAChC,IAAI,CAAC,EAAE,eAAe,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,EAAE,CAO7E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,EAAE,CAE/E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAU1F","sourcesContent":["export {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\tcreateBashTool,\n} from \"./bash.js\";\nexport {\n\tcreateEditTool,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n} from \"./edit.js\";\nexport {\n\tcreateFindTool,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n} from \"./find.js\";\nexport {\n\tcreateGrepTool,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n} from \"./grep.js\";\nexport {\n\tcreateLsTool,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n} from \"./ls.js\";\nexport {\n\tcreateReadTool,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n} from \"./read.js\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.js\";\nexport {\n\tcreateWriteTool,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n} from \"./write.js\";\n\nimport type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type BashToolOptions, bashTool, createBashTool } from \"./bash.js\";\nimport { createEditTool, editTool } from \"./edit.js\";\nimport { createFindTool, findTool } from \"./find.js\";\nimport { createGrepTool, grepTool } from \"./grep.js\";\nimport { createLsTool, lsTool } from \"./ls.js\";\nimport { createReadTool, type ReadToolOptions, readTool } from \"./read.js\";\nimport { createWriteTool, writeTool } from \"./write.js\";\n\n/** Tool type (AgentTool from pi-ai) */\nexport type Tool = AgentTool<any>;\n\n// Default tools for full access mode (using process.cwd())\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\n\n// Read-only tools for exploration without modification (using process.cwd())\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\n// All available tools (using process.cwd())\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n};\n\nexport type ToolName = keyof typeof allTools;\n\nexport interface ToolsOptions {\n\t/** Options for the read tool */\n\tread?: ReadToolOptions;\n\t/** Options for the bash tool */\n\tbash?: BashToolOptions;\n}\n\n/**\n * Create coding tools configured for a specific working directory.\n */\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd),\n\t\tcreateWriteTool(cwd),\n\t];\n}\n\n/**\n * Create read-only tools configured for a specific working directory.\n */\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [createReadTool(cwd, options?.read), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];\n}\n\n/**\n * Create all tools configured for a specific working directory.\n */\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool> {\n\treturn {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd),\n\t\twrite: createWriteTool(cwd),\n\t\tgrep: createGrepTool(cwd),\n\t\tfind: createFindTool(cwd),\n\t\tls: createLsTool(cwd),\n\t};\n}\n"]}
@@ -0,0 +1,61 @@
1
+ export { bashTool, createBashTool, } from "./bash.js";
2
+ export { createEditTool, editTool, } from "./edit.js";
3
+ export { createFindTool, findTool, } from "./find.js";
4
+ export { createGrepTool, grepTool, } from "./grep.js";
5
+ export { createLsTool, lsTool, } from "./ls.js";
6
+ export { createReadTool, readTool, } from "./read.js";
7
+ export { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateHead, truncateLine, truncateTail, } from "./truncate.js";
8
+ export { createWriteTool, writeTool, } from "./write.js";
9
+ import { bashTool, createBashTool } from "./bash.js";
10
+ import { createEditTool, editTool } from "./edit.js";
11
+ import { createFindTool, findTool } from "./find.js";
12
+ import { createGrepTool, grepTool } from "./grep.js";
13
+ import { createLsTool, lsTool } from "./ls.js";
14
+ import { createReadTool, readTool } from "./read.js";
15
+ import { createWriteTool, writeTool } from "./write.js";
16
+ // Default tools for full access mode (using process.cwd())
17
+ export const codingTools = [readTool, bashTool, editTool, writeTool];
18
+ // Read-only tools for exploration without modification (using process.cwd())
19
+ export const readOnlyTools = [readTool, grepTool, findTool, lsTool];
20
+ // All available tools (using process.cwd())
21
+ export const allTools = {
22
+ read: readTool,
23
+ bash: bashTool,
24
+ edit: editTool,
25
+ write: writeTool,
26
+ grep: grepTool,
27
+ find: findTool,
28
+ ls: lsTool,
29
+ };
30
+ /**
31
+ * Create coding tools configured for a specific working directory.
32
+ */
33
+ export function createCodingTools(cwd, options) {
34
+ return [
35
+ createReadTool(cwd, options?.read),
36
+ createBashTool(cwd, options?.bash),
37
+ createEditTool(cwd),
38
+ createWriteTool(cwd),
39
+ ];
40
+ }
41
+ /**
42
+ * Create read-only tools configured for a specific working directory.
43
+ */
44
+ export function createReadOnlyTools(cwd, options) {
45
+ return [createReadTool(cwd, options?.read), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];
46
+ }
47
+ /**
48
+ * Create all tools configured for a specific working directory.
49
+ */
50
+ export function createAllTools(cwd, options) {
51
+ return {
52
+ read: createReadTool(cwd, options?.read),
53
+ bash: createBashTool(cwd, options?.bash),
54
+ edit: createEditTool(cwd),
55
+ write: createWriteTool(cwd),
56
+ grep: createGrepTool(cwd),
57
+ find: createFindTool(cwd),
58
+ ls: createLsTool(cwd),
59
+ };
60
+ }
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"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","sourcesContent":["export {\n\ttype BashOperations,\n\ttype BashSpawnContext,\n\ttype BashSpawnHook,\n\ttype BashToolDetails,\n\ttype BashToolInput,\n\ttype BashToolOptions,\n\tbashTool,\n\tcreateBashTool,\n} from \"./bash.js\";\nexport {\n\tcreateEditTool,\n\ttype EditOperations,\n\ttype EditToolDetails,\n\ttype EditToolInput,\n\ttype EditToolOptions,\n\teditTool,\n} from \"./edit.js\";\nexport {\n\tcreateFindTool,\n\ttype FindOperations,\n\ttype FindToolDetails,\n\ttype FindToolInput,\n\ttype FindToolOptions,\n\tfindTool,\n} from \"./find.js\";\nexport {\n\tcreateGrepTool,\n\ttype GrepOperations,\n\ttype GrepToolDetails,\n\ttype GrepToolInput,\n\ttype GrepToolOptions,\n\tgrepTool,\n} from \"./grep.js\";\nexport {\n\tcreateLsTool,\n\ttype LsOperations,\n\ttype LsToolDetails,\n\ttype LsToolInput,\n\ttype LsToolOptions,\n\tlsTool,\n} from \"./ls.js\";\nexport {\n\tcreateReadTool,\n\ttype ReadOperations,\n\ttype ReadToolDetails,\n\ttype ReadToolInput,\n\ttype ReadToolOptions,\n\treadTool,\n} from \"./read.js\";\nexport {\n\tDEFAULT_MAX_BYTES,\n\tDEFAULT_MAX_LINES,\n\tformatSize,\n\ttype TruncationOptions,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n\ttruncateTail,\n} from \"./truncate.js\";\nexport {\n\tcreateWriteTool,\n\ttype WriteOperations,\n\ttype WriteToolInput,\n\ttype WriteToolOptions,\n\twriteTool,\n} from \"./write.js\";\n\nimport type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type BashToolOptions, bashTool, createBashTool } from \"./bash.js\";\nimport { createEditTool, editTool } from \"./edit.js\";\nimport { createFindTool, findTool } from \"./find.js\";\nimport { createGrepTool, grepTool } from \"./grep.js\";\nimport { createLsTool, lsTool } from \"./ls.js\";\nimport { createReadTool, type ReadToolOptions, readTool } from \"./read.js\";\nimport { createWriteTool, writeTool } from \"./write.js\";\n\n/** Tool type (AgentTool from pi-ai) */\nexport type Tool = AgentTool<any>;\n\n// Default tools for full access mode (using process.cwd())\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\n\n// Read-only tools for exploration without modification (using process.cwd())\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\n// All available tools (using process.cwd())\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n};\n\nexport type ToolName = keyof typeof allTools;\n\nexport interface ToolsOptions {\n\t/** Options for the read tool */\n\tread?: ReadToolOptions;\n\t/** Options for the bash tool */\n\tbash?: BashToolOptions;\n}\n\n/**\n * Create coding tools configured for a specific working directory.\n */\nexport function createCodingTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [\n\t\tcreateReadTool(cwd, options?.read),\n\t\tcreateBashTool(cwd, options?.bash),\n\t\tcreateEditTool(cwd),\n\t\tcreateWriteTool(cwd),\n\t];\n}\n\n/**\n * Create read-only tools configured for a specific working directory.\n */\nexport function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[] {\n\treturn [createReadTool(cwd, options?.read), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];\n}\n\n/**\n * Create all tools configured for a specific working directory.\n */\nexport function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool> {\n\treturn {\n\t\tread: createReadTool(cwd, options?.read),\n\t\tbash: createBashTool(cwd, options?.bash),\n\t\tedit: createEditTool(cwd),\n\t\twrite: createWriteTool(cwd),\n\t\tgrep: createGrepTool(cwd),\n\t\tfind: createFindTool(cwd),\n\t\tls: createLsTool(cwd),\n\t};\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
2
+ import { type Static } from "@sinclair/typebox";
3
+ import { type TruncationResult } from "./truncate.js";
4
+ declare const lsSchema: import("@sinclair/typebox").TObject<{
5
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
6
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
7
+ }>;
8
+ export type LsToolInput = Static<typeof lsSchema>;
9
+ export interface LsToolDetails {
10
+ truncation?: TruncationResult;
11
+ entryLimitReached?: number;
12
+ }
13
+ /**
14
+ * Pluggable operations for the ls tool.
15
+ * Override these to delegate directory listing to remote systems (e.g., SSH).
16
+ */
17
+ export interface LsOperations {
18
+ /** Check if path exists */
19
+ exists: (absolutePath: string) => Promise<boolean> | boolean;
20
+ /** Get file/directory stats. Throws if not found. */
21
+ stat: (absolutePath: string) => Promise<{
22
+ isDirectory: () => boolean;
23
+ }> | {
24
+ isDirectory: () => boolean;
25
+ };
26
+ /** Read directory entries */
27
+ readdir: (absolutePath: string) => Promise<string[]> | string[];
28
+ }
29
+ export interface LsToolOptions {
30
+ /** Custom operations for directory listing. Default: local filesystem */
31
+ operations?: LsOperations;
32
+ }
33
+ export declare function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema>;
34
+ /** Default ls tool using process.cwd() - for backwards compatibility */
35
+ export declare const lsTool: AgentTool<import("@sinclair/typebox").TObject<{
36
+ path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
37
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
38
+ }>, any>;
39
+ export {};
40
+ //# sourceMappingURL=ls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAItD,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,QAAQ;;;EAGZ,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAIlD,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,qDAAqD;IACrD,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC,GAAG;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IACzG,6BAA6B;IAC7B,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CAChE;AAQD,MAAM,WAAW,aAAa;IAC7B,yEAAyE;IACzE,UAAU,CAAC,EAAE,YAAY,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAyH7F;AAED,wEAAwE;AACxE,eAAO,MAAM,MAAM;;;QAA8B,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport nodePath from \"path\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst lsSchema = Type.Object({\n\tpath: Type.Optional(Type.String({ description: \"Directory to list (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of entries to return (default: 500)\" })),\n});\n\nexport type LsToolInput = Static<typeof lsSchema>;\n\nconst DEFAULT_LIMIT = 500;\n\nexport interface LsToolDetails {\n\ttruncation?: TruncationResult;\n\tentryLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the ls tool.\n * Override these to delegate directory listing to remote systems (e.g., SSH).\n */\nexport interface LsOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Get file/directory stats. Throws if not found. */\n\tstat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }> | { isDirectory: () => boolean };\n\t/** Read directory entries */\n\treaddir: (absolutePath: string) => Promise<string[]> | string[];\n}\n\nconst defaultLsOperations: LsOperations = {\n\texists: existsSync,\n\tstat: statSync,\n\treaddir: readdirSync,\n};\n\nexport interface LsToolOptions {\n\t/** Custom operations for directory listing. Default: local filesystem */\n\toperations?: LsOperations;\n}\n\nexport function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema> {\n\tconst ops = options?.operations ?? defaultLsOperations;\n\n\treturn {\n\t\tname: \"ls\",\n\t\tlabel: \"ls\",\n\t\tdescription: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tparameters: lsSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, limit }: { path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\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\tconst onAbort = () => reject(new Error(\"Operation aborted\"));\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 dirPath = resolveToCwd(path || \".\", cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\n\t\t\t\t\t\t// Check if path exists\n\t\t\t\t\t\tif (!(await ops.exists(dirPath))) {\n\t\t\t\t\t\t\treject(new Error(`Path not found: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path is a directory\n\t\t\t\t\t\tconst stat = await ops.stat(dirPath);\n\t\t\t\t\t\tif (!stat.isDirectory()) {\n\t\t\t\t\t\t\treject(new Error(`Not a directory: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read directory entries\n\t\t\t\t\t\tlet entries: string[];\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tentries = await ops.readdir(dirPath);\n\t\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t\treject(new Error(`Cannot read directory: ${e.message}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sort alphabetically (case-insensitive)\n\t\t\t\t\t\tentries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));\n\n\t\t\t\t\t\t// Format entries with directory indicators\n\t\t\t\t\t\tconst results: string[] = [];\n\t\t\t\t\t\tlet entryLimitReached = false;\n\n\t\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\t\tif (results.length >= effectiveLimit) {\n\t\t\t\t\t\t\t\tentryLimitReached = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst fullPath = nodePath.join(dirPath, entry);\n\t\t\t\t\t\t\tlet suffix = \"\";\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst entryStat = await ops.stat(fullPath);\n\t\t\t\t\t\t\t\tif (entryStat.isDirectory()) {\n\t\t\t\t\t\t\t\t\tsuffix = \"/\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip entries we can't stat\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresults.push(entry + suffix);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"(empty directory)\" }], details: undefined });\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Apply byte truncation (no line limit since we already have entry limit)\n\t\t\t\t\t\tconst rawOutput = results.join(\"\\n\");\n\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\n\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\tconst details: LsToolDetails = {};\n\n\t\t\t\t\t\t// Build notices\n\t\t\t\t\t\tconst notices: string[] = [];\n\n\t\t\t\t\t\tif (entryLimitReached) {\n\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);\n\t\t\t\t\t\t\tdetails.entryLimitReached = effectiveLimit;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(e);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default ls tool using process.cwd() - for backwards compatibility */\nexport const lsTool = createLsTool(process.cwd());\n"]}
@@ -0,0 +1,118 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { existsSync, readdirSync, statSync } from "fs";
3
+ import nodePath from "path";
4
+ import { resolveToCwd } from "./path-utils.js";
5
+ import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
6
+ const lsSchema = Type.Object({
7
+ path: Type.Optional(Type.String({ description: "Directory to list (default: current directory)" })),
8
+ limit: Type.Optional(Type.Number({ description: "Maximum number of entries to return (default: 500)" })),
9
+ });
10
+ const DEFAULT_LIMIT = 500;
11
+ const defaultLsOperations = {
12
+ exists: existsSync,
13
+ stat: statSync,
14
+ readdir: readdirSync,
15
+ };
16
+ export function createLsTool(cwd, options) {
17
+ const ops = options?.operations ?? defaultLsOperations;
18
+ return {
19
+ name: "ls",
20
+ label: "ls",
21
+ description: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,
22
+ parameters: lsSchema,
23
+ execute: async (_toolCallId, { path, limit }, signal) => {
24
+ return new Promise((resolve, reject) => {
25
+ if (signal?.aborted) {
26
+ reject(new Error("Operation aborted"));
27
+ return;
28
+ }
29
+ const onAbort = () => reject(new Error("Operation aborted"));
30
+ signal?.addEventListener("abort", onAbort, { once: true });
31
+ (async () => {
32
+ try {
33
+ const dirPath = resolveToCwd(path || ".", cwd);
34
+ const effectiveLimit = limit ?? DEFAULT_LIMIT;
35
+ // Check if path exists
36
+ if (!(await ops.exists(dirPath))) {
37
+ reject(new Error(`Path not found: ${dirPath}`));
38
+ return;
39
+ }
40
+ // Check if path is a directory
41
+ const stat = await ops.stat(dirPath);
42
+ if (!stat.isDirectory()) {
43
+ reject(new Error(`Not a directory: ${dirPath}`));
44
+ return;
45
+ }
46
+ // Read directory entries
47
+ let entries;
48
+ try {
49
+ entries = await ops.readdir(dirPath);
50
+ }
51
+ catch (e) {
52
+ reject(new Error(`Cannot read directory: ${e.message}`));
53
+ return;
54
+ }
55
+ // Sort alphabetically (case-insensitive)
56
+ entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
57
+ // Format entries with directory indicators
58
+ const results = [];
59
+ let entryLimitReached = false;
60
+ for (const entry of entries) {
61
+ if (results.length >= effectiveLimit) {
62
+ entryLimitReached = true;
63
+ break;
64
+ }
65
+ const fullPath = nodePath.join(dirPath, entry);
66
+ let suffix = "";
67
+ try {
68
+ const entryStat = await ops.stat(fullPath);
69
+ if (entryStat.isDirectory()) {
70
+ suffix = "/";
71
+ }
72
+ }
73
+ catch {
74
+ // Skip entries we can't stat
75
+ continue;
76
+ }
77
+ results.push(entry + suffix);
78
+ }
79
+ signal?.removeEventListener("abort", onAbort);
80
+ if (results.length === 0) {
81
+ resolve({ content: [{ type: "text", text: "(empty directory)" }], details: undefined });
82
+ return;
83
+ }
84
+ // Apply byte truncation (no line limit since we already have entry limit)
85
+ const rawOutput = results.join("\n");
86
+ const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
87
+ let output = truncation.content;
88
+ const details = {};
89
+ // Build notices
90
+ const notices = [];
91
+ if (entryLimitReached) {
92
+ notices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);
93
+ details.entryLimitReached = effectiveLimit;
94
+ }
95
+ if (truncation.truncated) {
96
+ notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
97
+ details.truncation = truncation;
98
+ }
99
+ if (notices.length > 0) {
100
+ output += `\n\n[${notices.join(". ")}]`;
101
+ }
102
+ resolve({
103
+ content: [{ type: "text", text: output }],
104
+ details: Object.keys(details).length > 0 ? details : undefined,
105
+ });
106
+ }
107
+ catch (e) {
108
+ signal?.removeEventListener("abort", onAbort);
109
+ reject(e);
110
+ }
111
+ })();
112
+ });
113
+ },
114
+ };
115
+ }
116
+ /** Default ls tool using process.cwd() - for backwards compatibility */
117
+ export const lsTool = createLsTool(process.cwd());
118
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { existsSync, readdirSync, statSync } from \"fs\";\nimport nodePath from \"path\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport { DEFAULT_MAX_BYTES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst lsSchema = Type.Object({\n\tpath: Type.Optional(Type.String({ description: \"Directory to list (default: current directory)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of entries to return (default: 500)\" })),\n});\n\nexport type LsToolInput = Static<typeof lsSchema>;\n\nconst DEFAULT_LIMIT = 500;\n\nexport interface LsToolDetails {\n\ttruncation?: TruncationResult;\n\tentryLimitReached?: number;\n}\n\n/**\n * Pluggable operations for the ls tool.\n * Override these to delegate directory listing to remote systems (e.g., SSH).\n */\nexport interface LsOperations {\n\t/** Check if path exists */\n\texists: (absolutePath: string) => Promise<boolean> | boolean;\n\t/** Get file/directory stats. Throws if not found. */\n\tstat: (absolutePath: string) => Promise<{ isDirectory: () => boolean }> | { isDirectory: () => boolean };\n\t/** Read directory entries */\n\treaddir: (absolutePath: string) => Promise<string[]> | string[];\n}\n\nconst defaultLsOperations: LsOperations = {\n\texists: existsSync,\n\tstat: statSync,\n\treaddir: readdirSync,\n};\n\nexport interface LsToolOptions {\n\t/** Custom operations for directory listing. Default: local filesystem */\n\toperations?: LsOperations;\n}\n\nexport function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema> {\n\tconst ops = options?.operations ?? defaultLsOperations;\n\n\treturn {\n\t\tname: \"ls\",\n\t\tlabel: \"ls\",\n\t\tdescription: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,\n\t\tparameters: lsSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, limit }: { path?: string; limit?: number },\n\t\t\tsignal?: AbortSignal,\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\tconst onAbort = () => reject(new Error(\"Operation aborted\"));\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 dirPath = resolveToCwd(path || \".\", cwd);\n\t\t\t\t\t\tconst effectiveLimit = limit ?? DEFAULT_LIMIT;\n\n\t\t\t\t\t\t// Check if path exists\n\t\t\t\t\t\tif (!(await ops.exists(dirPath))) {\n\t\t\t\t\t\t\treject(new Error(`Path not found: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if path is a directory\n\t\t\t\t\t\tconst stat = await ops.stat(dirPath);\n\t\t\t\t\t\tif (!stat.isDirectory()) {\n\t\t\t\t\t\t\treject(new Error(`Not a directory: ${dirPath}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read directory entries\n\t\t\t\t\t\tlet entries: string[];\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tentries = await ops.readdir(dirPath);\n\t\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\t\treject(new Error(`Cannot read directory: ${e.message}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sort alphabetically (case-insensitive)\n\t\t\t\t\t\tentries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));\n\n\t\t\t\t\t\t// Format entries with directory indicators\n\t\t\t\t\t\tconst results: string[] = [];\n\t\t\t\t\t\tlet entryLimitReached = false;\n\n\t\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\t\tif (results.length >= effectiveLimit) {\n\t\t\t\t\t\t\t\tentryLimitReached = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst fullPath = nodePath.join(dirPath, entry);\n\t\t\t\t\t\t\tlet suffix = \"\";\n\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst entryStat = await ops.stat(fullPath);\n\t\t\t\t\t\t\t\tif (entryStat.isDirectory()) {\n\t\t\t\t\t\t\t\t\tsuffix = \"/\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// Skip entries we can't stat\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresults.push(entry + suffix);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"(empty directory)\" }], details: undefined });\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Apply byte truncation (no line limit since we already have entry limit)\n\t\t\t\t\t\tconst rawOutput = results.join(\"\\n\");\n\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\n\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\tconst details: LsToolDetails = {};\n\n\t\t\t\t\t\t// Build notices\n\t\t\t\t\t\tconst notices: string[] = [];\n\n\t\t\t\t\t\tif (entryLimitReached) {\n\t\t\t\t\t\t\tnotices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);\n\t\t\t\t\t\t\tdetails.entryLimitReached = effectiveLimit;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e: any) {\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\treject(e);\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default ls tool using process.cwd() - for backwards compatibility */\nexport const lsTool = createLsTool(process.cwd());\n"]}
@@ -0,0 +1,8 @@
1
+ export declare function expandPath(filePath: string): string;
2
+ /**
3
+ * Resolve a path relative to the given cwd.
4
+ * Handles ~ expansion and absolute paths.
5
+ */
6
+ export declare function resolveToCwd(filePath: string, cwd: string): string;
7
+ export declare function resolveReadPath(filePath: string, cwd: string): string;
8
+ //# sourceMappingURL=path-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tools/path-utils.ts"],"names":[],"mappings":"AAsCA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASnD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAgCrE","sourcesContent":["import { accessSync, constants } from \"node:fs\";\nimport * as os from \"node:os\";\nimport { isAbsolute, resolve as resolvePath } from \"node:path\";\n\nconst UNICODE_SPACES = /[\\u00A0\\u2000-\\u200A\\u202F\\u205F\\u3000]/g;\nconst NARROW_NO_BREAK_SPACE = \"\\u202F\";\nfunction normalizeUnicodeSpaces(str: string): string {\n\treturn str.replace(UNICODE_SPACES, \" \");\n}\n\nfunction tryMacOSScreenshotPath(filePath: string): string {\n\treturn filePath.replace(/ (AM|PM)\\./g, `${NARROW_NO_BREAK_SPACE}$1.`);\n}\n\nfunction tryNFDVariant(filePath: string): string {\n\t// macOS stores filenames in NFD (decomposed) form, try converting user input to NFD\n\treturn filePath.normalize(\"NFD\");\n}\n\nfunction tryCurlyQuoteVariant(filePath: string): string {\n\t// macOS uses U+2019 (right single quotation mark) in screenshot names like \"Capture d'écran\"\n\t// Users typically type U+0027 (straight apostrophe)\n\treturn filePath.replace(/'/g, \"\\u2019\");\n}\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\taccessSync(filePath, constants.F_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction normalizeAtPrefix(filePath: string): string {\n\treturn filePath.startsWith(\"@\") ? filePath.slice(1) : filePath;\n}\n\nexport function expandPath(filePath: string): string {\n\tconst normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));\n\tif (normalized === \"~\") {\n\t\treturn os.homedir();\n\t}\n\tif (normalized.startsWith(\"~/\")) {\n\t\treturn os.homedir() + normalized.slice(1);\n\t}\n\treturn normalized;\n}\n\n/**\n * Resolve a path relative to the given cwd.\n * Handles ~ expansion and absolute paths.\n */\nexport function resolveToCwd(filePath: string, cwd: string): string {\n\tconst expanded = expandPath(filePath);\n\tif (isAbsolute(expanded)) {\n\t\treturn expanded;\n\t}\n\treturn resolvePath(cwd, expanded);\n}\n\nexport function resolveReadPath(filePath: string, cwd: string): string {\n\tconst resolved = resolveToCwd(filePath, cwd);\n\n\tif (fileExists(resolved)) {\n\t\treturn resolved;\n\t}\n\n\t// Try macOS AM/PM variant (narrow no-break space before AM/PM)\n\tconst amPmVariant = tryMacOSScreenshotPath(resolved);\n\tif (amPmVariant !== resolved && fileExists(amPmVariant)) {\n\t\treturn amPmVariant;\n\t}\n\n\t// Try NFD variant (macOS stores filenames in NFD form)\n\tconst nfdVariant = tryNFDVariant(resolved);\n\tif (nfdVariant !== resolved && fileExists(nfdVariant)) {\n\t\treturn nfdVariant;\n\t}\n\n\t// Try curly quote variant (macOS uses U+2019 in screenshot names)\n\tconst curlyVariant = tryCurlyQuoteVariant(resolved);\n\tif (curlyVariant !== resolved && fileExists(curlyVariant)) {\n\t\treturn curlyVariant;\n\t}\n\n\t// Try combined NFD + curly quote (for French macOS screenshots like \"Capture d'écran\")\n\tconst nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);\n\tif (nfdCurlyVariant !== resolved && fileExists(nfdCurlyVariant)) {\n\t\treturn nfdCurlyVariant;\n\t}\n\n\treturn resolved;\n}\n"]}
@@ -0,0 +1,81 @@
1
+ import { accessSync, constants } from "node:fs";
2
+ import * as os from "node:os";
3
+ import { isAbsolute, resolve as resolvePath } from "node:path";
4
+ const UNICODE_SPACES = /[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;
5
+ const NARROW_NO_BREAK_SPACE = "\u202F";
6
+ function normalizeUnicodeSpaces(str) {
7
+ return str.replace(UNICODE_SPACES, " ");
8
+ }
9
+ function tryMacOSScreenshotPath(filePath) {
10
+ return filePath.replace(/ (AM|PM)\./g, `${NARROW_NO_BREAK_SPACE}$1.`);
11
+ }
12
+ function tryNFDVariant(filePath) {
13
+ // macOS stores filenames in NFD (decomposed) form, try converting user input to NFD
14
+ return filePath.normalize("NFD");
15
+ }
16
+ function tryCurlyQuoteVariant(filePath) {
17
+ // macOS uses U+2019 (right single quotation mark) in screenshot names like "Capture d'écran"
18
+ // Users typically type U+0027 (straight apostrophe)
19
+ return filePath.replace(/'/g, "\u2019");
20
+ }
21
+ function fileExists(filePath) {
22
+ try {
23
+ accessSync(filePath, constants.F_OK);
24
+ return true;
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ function normalizeAtPrefix(filePath) {
31
+ return filePath.startsWith("@") ? filePath.slice(1) : filePath;
32
+ }
33
+ export function expandPath(filePath) {
34
+ const normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));
35
+ if (normalized === "~") {
36
+ return os.homedir();
37
+ }
38
+ if (normalized.startsWith("~/")) {
39
+ return os.homedir() + normalized.slice(1);
40
+ }
41
+ return normalized;
42
+ }
43
+ /**
44
+ * Resolve a path relative to the given cwd.
45
+ * Handles ~ expansion and absolute paths.
46
+ */
47
+ export function resolveToCwd(filePath, cwd) {
48
+ const expanded = expandPath(filePath);
49
+ if (isAbsolute(expanded)) {
50
+ return expanded;
51
+ }
52
+ return resolvePath(cwd, expanded);
53
+ }
54
+ export function resolveReadPath(filePath, cwd) {
55
+ const resolved = resolveToCwd(filePath, cwd);
56
+ if (fileExists(resolved)) {
57
+ return resolved;
58
+ }
59
+ // Try macOS AM/PM variant (narrow no-break space before AM/PM)
60
+ const amPmVariant = tryMacOSScreenshotPath(resolved);
61
+ if (amPmVariant !== resolved && fileExists(amPmVariant)) {
62
+ return amPmVariant;
63
+ }
64
+ // Try NFD variant (macOS stores filenames in NFD form)
65
+ const nfdVariant = tryNFDVariant(resolved);
66
+ if (nfdVariant !== resolved && fileExists(nfdVariant)) {
67
+ return nfdVariant;
68
+ }
69
+ // Try curly quote variant (macOS uses U+2019 in screenshot names)
70
+ const curlyVariant = tryCurlyQuoteVariant(resolved);
71
+ if (curlyVariant !== resolved && fileExists(curlyVariant)) {
72
+ return curlyVariant;
73
+ }
74
+ // Try combined NFD + curly quote (for French macOS screenshots like "Capture d'écran")
75
+ const nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);
76
+ if (nfdCurlyVariant !== resolved && fileExists(nfdCurlyVariant)) {
77
+ return nfdCurlyVariant;
78
+ }
79
+ return resolved;
80
+ }
81
+ //# sourceMappingURL=path-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../../src/core/tools/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AAE/D,MAAM,cAAc,GAAG,0CAA0C,CAAC;AAClE,MAAM,qBAAqB,GAAG,QAAQ,CAAC;AACvC,SAAS,sBAAsB,CAAC,GAAW,EAAU;IACpD,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;AAAA,CACxC;AAED,SAAS,sBAAsB,CAAC,QAAgB,EAAU;IACzD,OAAO,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,qBAAqB,KAAK,CAAC,CAAC;AAAA,CACtE;AAED,SAAS,aAAa,CAAC,QAAgB,EAAU;IAChD,oFAAoF;IACpF,OAAO,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAAA,CACjC;AAED,SAAS,oBAAoB,CAAC,QAAgB,EAAU;IACvD,8FAA6F;IAC7F,oDAAoD;IACpD,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,CACxC;AAED,SAAS,UAAU,CAAC,QAAgB,EAAW;IAC9C,IAAI,CAAC;QACJ,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AAAA,CACD;AAED,SAAS,iBAAiB,CAAC,QAAgB,EAAU;IACpD,OAAO,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAAA,CAC/D;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAU;IACpD,MAAM,UAAU,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvE,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,UAAU,CAAC;AAAA,CAClB;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,GAAW,EAAU;IACnE,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,OAAO,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAAA,CAClC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,GAAW,EAAU;IACtE,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE7C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,+DAA+D;IAC/D,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,WAAW,KAAK,QAAQ,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACzD,OAAO,WAAW,CAAC;IACpB,CAAC;IAED,uDAAuD;IACvD,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACvD,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,kEAAkE;IAClE,MAAM,YAAY,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACpD,IAAI,YAAY,KAAK,QAAQ,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3D,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,wFAAuF;IACvF,MAAM,eAAe,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACzD,IAAI,eAAe,KAAK,QAAQ,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACjE,OAAO,eAAe,CAAC;IACxB,CAAC;IAED,OAAO,QAAQ,CAAC;AAAA,CAChB","sourcesContent":["import { accessSync, constants } from \"node:fs\";\nimport * as os from \"node:os\";\nimport { isAbsolute, resolve as resolvePath } from \"node:path\";\n\nconst UNICODE_SPACES = /[\\u00A0\\u2000-\\u200A\\u202F\\u205F\\u3000]/g;\nconst NARROW_NO_BREAK_SPACE = \"\\u202F\";\nfunction normalizeUnicodeSpaces(str: string): string {\n\treturn str.replace(UNICODE_SPACES, \" \");\n}\n\nfunction tryMacOSScreenshotPath(filePath: string): string {\n\treturn filePath.replace(/ (AM|PM)\\./g, `${NARROW_NO_BREAK_SPACE}$1.`);\n}\n\nfunction tryNFDVariant(filePath: string): string {\n\t// macOS stores filenames in NFD (decomposed) form, try converting user input to NFD\n\treturn filePath.normalize(\"NFD\");\n}\n\nfunction tryCurlyQuoteVariant(filePath: string): string {\n\t// macOS uses U+2019 (right single quotation mark) in screenshot names like \"Capture d'écran\"\n\t// Users typically type U+0027 (straight apostrophe)\n\treturn filePath.replace(/'/g, \"\\u2019\");\n}\n\nfunction fileExists(filePath: string): boolean {\n\ttry {\n\t\taccessSync(filePath, constants.F_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction normalizeAtPrefix(filePath: string): string {\n\treturn filePath.startsWith(\"@\") ? filePath.slice(1) : filePath;\n}\n\nexport function expandPath(filePath: string): string {\n\tconst normalized = normalizeUnicodeSpaces(normalizeAtPrefix(filePath));\n\tif (normalized === \"~\") {\n\t\treturn os.homedir();\n\t}\n\tif (normalized.startsWith(\"~/\")) {\n\t\treturn os.homedir() + normalized.slice(1);\n\t}\n\treturn normalized;\n}\n\n/**\n * Resolve a path relative to the given cwd.\n * Handles ~ expansion and absolute paths.\n */\nexport function resolveToCwd(filePath: string, cwd: string): string {\n\tconst expanded = expandPath(filePath);\n\tif (isAbsolute(expanded)) {\n\t\treturn expanded;\n\t}\n\treturn resolvePath(cwd, expanded);\n}\n\nexport function resolveReadPath(filePath: string, cwd: string): string {\n\tconst resolved = resolveToCwd(filePath, cwd);\n\n\tif (fileExists(resolved)) {\n\t\treturn resolved;\n\t}\n\n\t// Try macOS AM/PM variant (narrow no-break space before AM/PM)\n\tconst amPmVariant = tryMacOSScreenshotPath(resolved);\n\tif (amPmVariant !== resolved && fileExists(amPmVariant)) {\n\t\treturn amPmVariant;\n\t}\n\n\t// Try NFD variant (macOS stores filenames in NFD form)\n\tconst nfdVariant = tryNFDVariant(resolved);\n\tif (nfdVariant !== resolved && fileExists(nfdVariant)) {\n\t\treturn nfdVariant;\n\t}\n\n\t// Try curly quote variant (macOS uses U+2019 in screenshot names)\n\tconst curlyVariant = tryCurlyQuoteVariant(resolved);\n\tif (curlyVariant !== resolved && fileExists(curlyVariant)) {\n\t\treturn curlyVariant;\n\t}\n\n\t// Try combined NFD + curly quote (for French macOS screenshots like \"Capture d'écran\")\n\tconst nfdCurlyVariant = tryCurlyQuoteVariant(nfdVariant);\n\tif (nfdCurlyVariant !== resolved && fileExists(nfdCurlyVariant)) {\n\t\treturn nfdCurlyVariant;\n\t}\n\n\treturn resolved;\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
2
+ import { type Static } from "@sinclair/typebox";
3
+ import { type TruncationResult } from "./truncate.js";
4
+ declare const readSchema: import("@sinclair/typebox").TObject<{
5
+ path: import("@sinclair/typebox").TString;
6
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
7
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
8
+ }>;
9
+ export type ReadToolInput = Static<typeof readSchema>;
10
+ export interface ReadToolDetails {
11
+ truncation?: TruncationResult;
12
+ }
13
+ /**
14
+ * Pluggable operations for the read tool.
15
+ * Override these to delegate file reading to remote systems (e.g., SSH).
16
+ */
17
+ export interface ReadOperations {
18
+ /** Read file contents as a Buffer */
19
+ readFile: (absolutePath: string) => Promise<Buffer>;
20
+ /** Check if file is readable (throw if not) */
21
+ access: (absolutePath: string) => Promise<void>;
22
+ /** Detect image MIME type, return null/undefined for non-images */
23
+ detectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;
24
+ }
25
+ export interface ReadToolOptions {
26
+ /** Whether to auto-resize images to 2000x2000 max. Default: true */
27
+ autoResizeImages?: boolean;
28
+ /** Custom operations for file reading. Default: local filesystem */
29
+ operations?: ReadOperations;
30
+ }
31
+ export declare function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema>;
32
+ /** Default read tool using process.cwd() - for backwards compatibility */
33
+ export declare const readTool: AgentTool<import("@sinclair/typebox").TObject<{
34
+ path: import("@sinclair/typebox").TString;
35
+ offset: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
36
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
37
+ }>, any>;
38
+ export {};
39
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/core/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAMtD,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEtH,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,+CAA+C;IAC/C,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACnF;AAQD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CA0KnG;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;;QAAgC,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@mariozechner/pi-ai\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile } from \"fs/promises\";\nimport { formatDimensionNote, resizeImage } from \"../../utils/image-resize.js\";\nimport { detectSupportedImageMimeTypeFromFile } from \"../../utils/mime.js\";\nimport { resolveReadPath } from \"./path-utils.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\nconst readSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\nexport type ReadToolInput = Static<typeof readSchema>;\n\nexport interface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\n/**\n * Pluggable operations for the read tool.\n * Override these to delegate file reading to remote systems (e.g., SSH).\n */\nexport interface ReadOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Check if file is readable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n\t/** Detect image MIME type, return null/undefined for non-images */\n\tdetectImageMimeType?: (absolutePath: string) => Promise<string | null | undefined>;\n}\n\nconst defaultReadOperations: ReadOperations = {\n\treadFile: (path) => fsReadFile(path),\n\taccess: (path) => fsAccess(path, constants.R_OK),\n\tdetectImageMimeType: detectSupportedImageMimeTypeFromFile,\n};\n\nexport interface ReadToolOptions {\n\t/** Whether to auto-resize images to 2000x2000 max. Default: true */\n\tautoResizeImages?: boolean;\n\t/** Custom operations for file reading. Default: local filesystem */\n\toperations?: ReadOperations;\n}\n\nexport function createReadTool(cwd: string, options?: ReadToolOptions): AgentTool<typeof readSchema> {\n\tconst autoResizeImages = options?.autoResizeImages ?? true;\n\tconst ops = options?.operations ?? defaultReadOperations;\n\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,\n\t\tparameters: readSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, offset, limit }: { path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tconst absolutePath = resolveReadPath(path, cwd);\n\n\t\t\treturn new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(\n\t\t\t\t(resolve, reject) => {\n\t\t\t\t\t// Check if already aborted\n\t\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet aborted = false;\n\n\t\t\t\t\t// Set up abort handler\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\t};\n\n\t\t\t\t\tif (signal) {\n\t\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t\t}\n\n\t\t\t\t\t// Perform the read operation\n\t\t\t\t\t(async () => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Check if file exists\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\n\t\t\t\t\t\t\t// Check if aborted before reading\n\t\t\t\t\t\t\tif (aborted) {\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 mimeType = ops.detectImageMimeType ? await ops.detectImageMimeType(absolutePath) : undefined;\n\n\t\t\t\t\t\t\t// Read the file based on type\n\t\t\t\t\t\t\tlet content: (TextContent | ImageContent)[];\n\t\t\t\t\t\t\tlet details: ReadToolDetails | undefined;\n\n\t\t\t\t\t\t\tif (mimeType) {\n\t\t\t\t\t\t\t\t// Read as image (binary)\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst base64 = buffer.toString(\"base64\");\n\n\t\t\t\t\t\t\t\tif (autoResizeImages) {\n\t\t\t\t\t\t\t\t\t// Resize image if needed\n\t\t\t\t\t\t\t\t\tconst resized = await resizeImage({ type: \"image\", data: base64, mimeType });\n\t\t\t\t\t\t\t\t\tconst dimensionNote = formatDimensionNote(resized);\n\n\t\t\t\t\t\t\t\t\tlet textNote = `Read image file [${resized.mimeType}]`;\n\t\t\t\t\t\t\t\t\tif (dimensionNote) {\n\t\t\t\t\t\t\t\t\t\ttextNote += `\\n${dimensionNote}`;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: resized.data, mimeType: resized.mimeType },\n\t\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tconst textNote = `Read image file [${mimeType}]`;\n\t\t\t\t\t\t\t\t\tcontent = [\n\t\t\t\t\t\t\t\t\t\t{ type: \"text\", text: textNote },\n\t\t\t\t\t\t\t\t\t\t{ type: \"image\", data: base64, mimeType },\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} else {\n\t\t\t\t\t\t\t\t// Read as text\n\t\t\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\t\t\tconst textContent = buffer.toString(\"utf-8\");\n\t\t\t\t\t\t\t\tconst allLines = textContent.split(\"\\n\");\n\t\t\t\t\t\t\t\tconst totalFileLines = allLines.length;\n\n\t\t\t\t\t\t\t\t// Apply offset if specified (1-indexed to 0-indexed)\n\t\t\t\t\t\t\t\tconst startLine = offset ? Math.max(0, offset - 1) : 0;\n\t\t\t\t\t\t\t\tconst startLineDisplay = startLine + 1; // For display (1-indexed)\n\n\t\t\t\t\t\t\t\t// Check if offset is out of bounds\n\t\t\t\t\t\t\t\tif (startLine >= allLines.length) {\n\t\t\t\t\t\t\t\t\tthrow new Error(`Offset ${offset} is beyond end of file (${allLines.length} lines total)`);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If limit is specified by user, use it; otherwise we'll let truncateHead decide\n\t\t\t\t\t\t\t\tlet selectedContent: string;\n\t\t\t\t\t\t\t\tlet userLimitedLines: number | undefined;\n\t\t\t\t\t\t\t\tif (limit !== undefined) {\n\t\t\t\t\t\t\t\t\tconst endLine = Math.min(startLine + limit, allLines.length);\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine, endLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t\tuserLimitedLines = endLine - startLine;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tselectedContent = allLines.slice(startLine).join(\"\\n\");\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Apply truncation (respects both line and byte limits)\n\t\t\t\t\t\t\t\tconst truncation = truncateHead(selectedContent);\n\n\t\t\t\t\t\t\t\tlet outputText: string;\n\n\t\t\t\t\t\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t\t\t\t\t\t// First line at offset exceeds 30KB - tell model to use bash\n\t\t\t\t\t\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(allLines[startLine], \"utf-8\"));\n\t\t\t\t\t\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (truncation.truncated) {\n\t\t\t\t\t\t\t\t\t// Truncation occurred - build actionable notice\n\t\t\t\t\t\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\t\t\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\n\t\t\t\t\t\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tdetails = { truncation };\n\t\t\t\t\t\t\t\t} else if (userLimitedLines !== undefined && startLine + userLimitedLines < allLines.length) {\n\t\t\t\t\t\t\t\t\t// User specified limit, there's more content, but no truncation\n\t\t\t\t\t\t\t\t\tconst remaining = allLines.length - (startLine + userLimitedLines);\n\t\t\t\t\t\t\t\t\tconst nextOffset = startLine + userLimitedLines + 1;\n\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t\toutputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// No truncation, no user limit exceeded\n\t\t\t\t\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcontent = [{ type: \"text\", text: outputText }];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check if aborted after reading\n\t\t\t\t\t\t\tif (aborted) {\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// Clean up abort handler\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tresolve({ content, details });\n\t\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!aborted) {\n\t\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})();\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t};\n}\n\n/** Default read tool using process.cwd() - for backwards compatibility */\nexport const readTool = createReadTool(process.cwd());\n"]}