@travisennis/acai 0.0.9 → 0.0.11

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 (403) hide show
  1. package/README.md +51 -760
  2. package/bin/acai +52 -0
  3. package/dist/agent/index.d.ts +12 -2
  4. package/dist/agent/index.d.ts.map +1 -1
  5. package/dist/agent/index.js +380 -199
  6. package/dist/agent/sub-agent.d.ts +23 -0
  7. package/dist/agent/sub-agent.d.ts.map +1 -0
  8. package/dist/agent/sub-agent.js +109 -0
  9. package/dist/cli/index.d.ts +26 -0
  10. package/dist/cli/index.d.ts.map +1 -0
  11. package/dist/{cli.js → cli/index.js} +84 -77
  12. package/dist/{stdin.d.ts → cli/stdin.d.ts} +2 -1
  13. package/dist/cli/stdin.d.ts.map +1 -0
  14. package/dist/{stdin.js → cli/stdin.js} +11 -0
  15. package/dist/commands/copy/index.js +2 -2
  16. package/dist/commands/copy/utils.d.ts.map +1 -1
  17. package/dist/commands/copy/utils.js +15 -13
  18. package/dist/commands/generate-rules/index.d.ts +1 -1
  19. package/dist/commands/generate-rules/index.d.ts.map +1 -1
  20. package/dist/commands/generate-rules/index.js +16 -101
  21. package/dist/commands/generate-rules/service.d.ts +22 -0
  22. package/dist/commands/generate-rules/service.d.ts.map +1 -0
  23. package/dist/commands/generate-rules/service.js +103 -0
  24. package/dist/commands/handoff/index.js +2 -2
  25. package/dist/commands/health/index.js +1 -1
  26. package/dist/commands/health/utils.d.ts +3 -2
  27. package/dist/commands/health/utils.d.ts.map +1 -1
  28. package/dist/commands/health/utils.js +6 -0
  29. package/dist/commands/history/index.d.ts +1 -1
  30. package/dist/commands/history/index.d.ts.map +1 -1
  31. package/dist/commands/history/index.js +17 -18
  32. package/dist/commands/history/types.d.ts +38 -0
  33. package/dist/commands/history/types.d.ts.map +1 -1
  34. package/dist/commands/history/utils.d.ts.map +1 -1
  35. package/dist/commands/history/utils.js +63 -58
  36. package/dist/commands/init/index.d.ts.map +1 -1
  37. package/dist/commands/init/index.js +3 -8
  38. package/dist/commands/init-project/index.d.ts.map +1 -1
  39. package/dist/commands/init-project/index.js +3 -3
  40. package/dist/commands/init-project/utils.d.ts +2 -1
  41. package/dist/commands/init-project/utils.d.ts.map +1 -1
  42. package/dist/commands/init-project/utils.js +10 -2
  43. package/dist/commands/list-tools/index.d.ts.map +1 -1
  44. package/dist/commands/list-tools/index.js +7 -31
  45. package/dist/commands/manager.d.ts +2 -2
  46. package/dist/commands/manager.d.ts.map +1 -1
  47. package/dist/commands/manager.js +55 -33
  48. package/dist/commands/model/index.d.ts.map +1 -1
  49. package/dist/commands/model/index.js +20 -151
  50. package/dist/commands/model/model-panel.d.ts +4 -0
  51. package/dist/commands/model/model-panel.d.ts.map +1 -0
  52. package/dist/commands/model/model-panel.js +144 -0
  53. package/dist/commands/paste/index.d.ts.map +1 -1
  54. package/dist/commands/paste/index.js +59 -62
  55. package/dist/commands/paste/utils.d.ts.map +1 -1
  56. package/dist/commands/paste/utils.js +88 -58
  57. package/dist/commands/pickup/index.d.ts.map +1 -1
  58. package/dist/commands/pickup/index.js +6 -3
  59. package/dist/commands/pickup/utils.js +3 -3
  60. package/dist/commands/resources/index.d.ts.map +1 -1
  61. package/dist/commands/resources/index.js +33 -50
  62. package/dist/commands/review/index.d.ts.map +1 -1
  63. package/dist/commands/review/index.js +3 -117
  64. package/dist/commands/review/review-panel.d.ts +3 -0
  65. package/dist/commands/review/review-panel.d.ts.map +1 -0
  66. package/dist/commands/review/review-panel.js +186 -0
  67. package/dist/commands/review/utils.d.ts +15 -1
  68. package/dist/commands/review/utils.d.ts.map +1 -1
  69. package/dist/commands/review/utils.js +127 -68
  70. package/dist/commands/session/index.d.ts +1 -1
  71. package/dist/commands/session/index.d.ts.map +1 -1
  72. package/dist/commands/session/index.js +124 -135
  73. package/dist/commands/shell/index.d.ts.map +1 -1
  74. package/dist/commands/shell/index.js +16 -1
  75. package/dist/commands/types.d.ts +2 -2
  76. package/dist/commands/types.d.ts.map +1 -1
  77. package/dist/{config.d.ts → config/index.d.ts} +20 -9
  78. package/dist/config/index.d.ts.map +1 -0
  79. package/dist/{config.js → config/index.js} +43 -42
  80. package/dist/execution/index.d.ts.map +1 -1
  81. package/dist/execution/index.js +75 -55
  82. package/dist/index.d.ts +1 -0
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +148 -141
  85. package/dist/middleware/cache.d.ts.map +1 -1
  86. package/dist/middleware/cache.js +18 -36
  87. package/dist/models/ai-config.d.ts +1 -0
  88. package/dist/models/ai-config.d.ts.map +1 -1
  89. package/dist/models/ai-config.js +4 -3
  90. package/dist/models/anthropic-provider.d.ts +2 -5
  91. package/dist/models/anthropic-provider.d.ts.map +1 -1
  92. package/dist/models/anthropic-provider.js +3 -70
  93. package/dist/models/deepseek-provider.d.ts +1 -0
  94. package/dist/models/deepseek-provider.d.ts.map +1 -1
  95. package/dist/models/google-provider.d.ts +2 -3
  96. package/dist/models/google-provider.d.ts.map +1 -1
  97. package/dist/models/google-provider.js +0 -26
  98. package/dist/models/groq-provider.d.ts +1 -0
  99. package/dist/models/groq-provider.d.ts.map +1 -1
  100. package/dist/models/manager.d.ts +13 -2
  101. package/dist/models/manager.d.ts.map +1 -1
  102. package/dist/models/manager.js +20 -8
  103. package/dist/models/openai-provider.d.ts +2 -5
  104. package/dist/models/openai-provider.d.ts.map +1 -1
  105. package/dist/models/openai-provider.js +0 -52
  106. package/dist/models/opencode-go-provider.d.ts +25 -0
  107. package/dist/models/opencode-go-provider.d.ts.map +1 -0
  108. package/dist/models/opencode-go-provider.js +78 -0
  109. package/dist/models/opencode-zen-provider.d.ts +7 -3
  110. package/dist/models/opencode-zen-provider.d.ts.map +1 -1
  111. package/dist/models/opencode-zen-provider.js +49 -10
  112. package/dist/models/openrouter-provider.d.ts +27 -31
  113. package/dist/models/openrouter-provider.d.ts.map +1 -1
  114. package/dist/models/openrouter-provider.js +121 -180
  115. package/dist/models/providers.d.ts +3 -3
  116. package/dist/models/providers.d.ts.map +1 -1
  117. package/dist/models/providers.js +6 -0
  118. package/dist/models/xai-provider.d.ts +4 -3
  119. package/dist/models/xai-provider.d.ts.map +1 -1
  120. package/dist/models/xai-provider.js +18 -18
  121. package/dist/modes/manager.d.ts +24 -0
  122. package/dist/modes/manager.d.ts.map +1 -0
  123. package/dist/modes/manager.js +77 -0
  124. package/dist/modes/prompts.d.ts +2 -0
  125. package/dist/modes/prompts.d.ts.map +1 -0
  126. package/dist/modes/prompts.js +142 -0
  127. package/dist/prompts/mentions.d.ts +11 -0
  128. package/dist/prompts/mentions.d.ts.map +1 -0
  129. package/dist/{mentions.js → prompts/mentions.js} +55 -85
  130. package/dist/{prompts.d.ts → prompts/system-prompt.d.ts} +7 -2
  131. package/dist/prompts/system-prompt.d.ts.map +1 -0
  132. package/dist/{prompts.js → prompts/system-prompt.js} +31 -16
  133. package/dist/repl/index.d.ts +174 -0
  134. package/dist/repl/index.d.ts.map +1 -0
  135. package/dist/{repl-new.js → repl/index.js} +397 -76
  136. package/dist/repl/project-status.d.ts +1 -0
  137. package/dist/repl/project-status.d.ts.map +1 -1
  138. package/dist/repl/project-status.js +4 -1
  139. package/dist/sessions/manager.d.ts +92 -0
  140. package/dist/sessions/manager.d.ts.map +1 -1
  141. package/dist/sessions/manager.js +262 -9
  142. package/dist/sessions/summary.d.ts +4 -0
  143. package/dist/sessions/summary.d.ts.map +1 -0
  144. package/dist/sessions/summary.js +30 -0
  145. package/dist/skills/index.d.ts +29 -0
  146. package/dist/skills/index.d.ts.map +1 -0
  147. package/dist/skills/index.js +294 -0
  148. package/dist/subagents/index.d.ts +16 -0
  149. package/dist/subagents/index.d.ts.map +1 -0
  150. package/dist/subagents/index.js +231 -0
  151. package/dist/terminal/control.d.ts +1 -1
  152. package/dist/terminal/control.d.ts.map +1 -1
  153. package/dist/terminal/control.js +3 -3
  154. package/dist/terminal/east-asian-width.d.ts.map +1 -1
  155. package/dist/terminal/east-asian-width.js +404 -351
  156. package/dist/terminal/keys.d.ts +17 -0
  157. package/dist/terminal/keys.d.ts.map +1 -1
  158. package/dist/terminal/keys.js +37 -0
  159. package/dist/terminal/select-prompt.d.ts.map +1 -1
  160. package/dist/terminal/select-prompt.js +24 -12
  161. package/dist/terminal/string-width.d.ts.map +1 -1
  162. package/dist/terminal/string-width.js +25 -27
  163. package/dist/terminal/style.d.ts.map +1 -1
  164. package/dist/terminal/style.js +4 -7
  165. package/dist/terminal/supports-color.d.ts.map +1 -1
  166. package/dist/terminal/supports-color.js +41 -27
  167. package/dist/terminal/table/cell.d.ts +12 -0
  168. package/dist/terminal/table/cell.d.ts.map +1 -1
  169. package/dist/terminal/table/cell.js +40 -25
  170. package/dist/terminal/table/layout-manager.d.ts.map +1 -1
  171. package/dist/terminal/table/layout-manager.js +100 -68
  172. package/dist/terminal/table/utils.d.ts +1 -1
  173. package/dist/terminal/table/utils.d.ts.map +1 -1
  174. package/dist/terminal/table/utils.js +17 -10
  175. package/dist/terminal/wrap-ansi.d.ts.map +1 -1
  176. package/dist/terminal/wrap-ansi.js +174 -105
  177. package/dist/tokens/tracker.d.ts +1 -0
  178. package/dist/tokens/tracker.d.ts.map +1 -1
  179. package/dist/tokens/tracker.js +3 -0
  180. package/dist/tools/agent.d.ts +27 -0
  181. package/dist/tools/agent.d.ts.map +1 -0
  182. package/dist/tools/agent.js +81 -0
  183. package/dist/tools/apply-patch.d.ts +62 -0
  184. package/dist/tools/apply-patch.d.ts.map +1 -0
  185. package/dist/tools/apply-patch.js +377 -0
  186. package/dist/tools/bash.d.ts +4 -3
  187. package/dist/tools/bash.d.ts.map +1 -1
  188. package/dist/tools/bash.js +349 -141
  189. package/dist/tools/directory-tree.d.ts +3 -3
  190. package/dist/tools/directory-tree.d.ts.map +1 -1
  191. package/dist/tools/directory-tree.js +8 -5
  192. package/dist/tools/dynamic-tool-loader.d.ts +3 -6
  193. package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
  194. package/dist/tools/dynamic-tool-loader.js +20 -4
  195. package/dist/tools/edit-file.d.ts +7 -7
  196. package/dist/tools/edit-file.d.ts.map +1 -1
  197. package/dist/tools/edit-file.js +292 -85
  198. package/dist/tools/glob.d.ts +6 -6
  199. package/dist/tools/glob.d.ts.map +1 -1
  200. package/dist/tools/glob.js +110 -63
  201. package/dist/tools/grep.d.ts +15 -12
  202. package/dist/tools/grep.d.ts.map +1 -1
  203. package/dist/tools/grep.js +315 -193
  204. package/dist/tools/index.d.ts +114 -9
  205. package/dist/tools/index.d.ts.map +1 -1
  206. package/dist/tools/index.js +39 -24
  207. package/dist/tools/ls.d.ts +2 -2
  208. package/dist/tools/ls.d.ts.map +1 -1
  209. package/dist/tools/ls.js +7 -5
  210. package/dist/tools/read-file.d.ts +4 -6
  211. package/dist/tools/read-file.d.ts.map +1 -1
  212. package/dist/tools/read-file.js +84 -39
  213. package/dist/tools/save-file.d.ts +3 -3
  214. package/dist/tools/save-file.d.ts.map +1 -1
  215. package/dist/tools/save-file.js +36 -31
  216. package/dist/tools/skill.d.ts +23 -0
  217. package/dist/tools/skill.d.ts.map +1 -0
  218. package/dist/tools/skill.js +65 -0
  219. package/dist/tools/think.d.ts.map +1 -1
  220. package/dist/tools/think.js +2 -9
  221. package/dist/tools/utils.d.ts +2 -0
  222. package/dist/tools/utils.d.ts.map +1 -1
  223. package/dist/tools/utils.js +12 -0
  224. package/dist/tools/web-fetch.d.ts +50 -0
  225. package/dist/tools/web-fetch.d.ts.map +1 -0
  226. package/dist/tools/web-fetch.js +446 -0
  227. package/dist/tools/web-search.d.ts +44 -0
  228. package/dist/tools/web-search.d.ts.map +1 -0
  229. package/dist/tools/web-search.js +226 -0
  230. package/dist/tui/autocomplete/attachment-provider.d.ts +3 -6
  231. package/dist/tui/autocomplete/attachment-provider.d.ts.map +1 -1
  232. package/dist/tui/autocomplete/attachment-provider.js +25 -78
  233. package/dist/tui/autocomplete/base-provider.d.ts +1 -0
  234. package/dist/tui/autocomplete/base-provider.d.ts.map +1 -1
  235. package/dist/tui/autocomplete/combined-provider.d.ts +1 -4
  236. package/dist/tui/autocomplete/combined-provider.d.ts.map +1 -1
  237. package/dist/tui/autocomplete/combined-provider.js +3 -17
  238. package/dist/tui/autocomplete/command-provider.d.ts +1 -0
  239. package/dist/tui/autocomplete/command-provider.d.ts.map +1 -1
  240. package/dist/tui/autocomplete/command-provider.js +3 -0
  241. package/dist/tui/autocomplete/file-search-provider.d.ts +2 -1
  242. package/dist/tui/autocomplete/file-search-provider.d.ts.map +1 -1
  243. package/dist/tui/autocomplete/file-search-provider.js +37 -17
  244. package/dist/tui/autocomplete/skill-provider.d.ts +17 -0
  245. package/dist/tui/autocomplete/skill-provider.d.ts.map +1 -0
  246. package/dist/tui/autocomplete/skill-provider.js +49 -0
  247. package/dist/tui/autocomplete/utils.d.ts +2 -1
  248. package/dist/tui/autocomplete/utils.d.ts.map +1 -1
  249. package/dist/tui/autocomplete/utils.js +25 -23
  250. package/dist/tui/autocomplete.d.ts +2 -2
  251. package/dist/tui/autocomplete.d.ts.map +1 -1
  252. package/dist/tui/autocomplete.js +3 -5
  253. package/dist/tui/components/assistant-message.d.ts.map +1 -1
  254. package/dist/tui/components/assistant-message.js +0 -4
  255. package/dist/tui/components/editor.d.ts +18 -3
  256. package/dist/tui/components/editor.d.ts.map +1 -1
  257. package/dist/tui/components/editor.js +211 -237
  258. package/dist/tui/components/footer.d.ts +6 -4
  259. package/dist/tui/components/footer.d.ts.map +1 -1
  260. package/dist/tui/components/footer.js +49 -25
  261. package/dist/tui/components/markdown.d.ts +10 -7
  262. package/dist/tui/components/markdown.d.ts.map +1 -1
  263. package/dist/tui/components/markdown.js +57 -39
  264. package/dist/tui/components/modal.d.ts.map +1 -1
  265. package/dist/tui/components/modal.js +35 -33
  266. package/dist/tui/components/notification.d.ts +13 -2
  267. package/dist/tui/components/notification.d.ts.map +1 -1
  268. package/dist/tui/components/notification.js +36 -2
  269. package/dist/tui/components/progress-bar.js +1 -1
  270. package/dist/tui/components/select-list.d.ts +1 -0
  271. package/dist/tui/components/select-list.d.ts.map +1 -1
  272. package/dist/tui/components/select-list.js +14 -11
  273. package/dist/tui/components/text.d.ts +16 -0
  274. package/dist/tui/components/text.d.ts.map +1 -1
  275. package/dist/tui/components/text.js +72 -57
  276. package/dist/tui/components/thinking-block.d.ts +9 -0
  277. package/dist/tui/components/thinking-block.d.ts.map +1 -1
  278. package/dist/tui/components/thinking-block.js +43 -11
  279. package/dist/tui/components/tool-execution.d.ts +5 -1
  280. package/dist/tui/components/tool-execution.d.ts.map +1 -1
  281. package/dist/tui/components/tool-execution.js +19 -10
  282. package/dist/tui/components/user-message.d.ts.map +1 -1
  283. package/dist/tui/components/user-message.js +0 -3
  284. package/dist/tui/components/welcome.d.ts +2 -1
  285. package/dist/tui/components/welcome.d.ts.map +1 -1
  286. package/dist/tui/components/welcome.js +2 -2
  287. package/dist/tui/editor-launcher.d.ts +3 -2
  288. package/dist/tui/editor-launcher.d.ts.map +1 -1
  289. package/dist/tui/index.d.ts +0 -1
  290. package/dist/tui/index.d.ts.map +1 -1
  291. package/dist/tui/terminal.d.ts.map +1 -1
  292. package/dist/tui/terminal.js +10 -2
  293. package/dist/tui/tui.d.ts +43 -0
  294. package/dist/tui/tui.d.ts.map +1 -1
  295. package/dist/tui/tui.js +166 -41
  296. package/dist/tui/utils.d.ts +1 -5
  297. package/dist/tui/utils.d.ts.map +1 -1
  298. package/dist/tui/utils.js +271 -44
  299. package/dist/utils/bash/parse.d.ts +19 -0
  300. package/dist/utils/bash/parse.d.ts.map +1 -0
  301. package/dist/utils/bash/parse.js +223 -0
  302. package/dist/utils/bash/quote.d.ts +6 -0
  303. package/dist/utils/bash/quote.d.ts.map +1 -0
  304. package/dist/utils/bash/quote.js +23 -0
  305. package/dist/utils/bash.d.ts.map +1 -1
  306. package/dist/utils/bash.js +211 -126
  307. package/dist/utils/command-protection.d.ts +28 -0
  308. package/dist/utils/command-protection.d.ts.map +1 -0
  309. package/dist/utils/command-protection.js +324 -0
  310. package/dist/utils/dedent.d.ts.map +1 -0
  311. package/dist/utils/env-expand.d.ts +2 -0
  312. package/dist/utils/env-expand.d.ts.map +1 -0
  313. package/dist/utils/env-expand.js +8 -0
  314. package/dist/utils/filesystem/path-display.d.ts +11 -0
  315. package/dist/utils/filesystem/path-display.d.ts.map +1 -0
  316. package/dist/utils/filesystem/path-display.js +32 -0
  317. package/dist/utils/filesystem/security.d.ts +2 -2
  318. package/dist/utils/filesystem/security.d.ts.map +1 -1
  319. package/dist/utils/filesystem/security.js +28 -30
  320. package/dist/utils/formatting.d.ts.map +1 -0
  321. package/dist/{formatting.js → utils/formatting.js} +1 -1
  322. package/dist/utils/git.d.ts +4 -0
  323. package/dist/utils/git.d.ts.map +1 -1
  324. package/dist/utils/git.js +30 -0
  325. package/dist/utils/glob.d.ts +1 -1
  326. package/dist/utils/glob.d.ts.map +1 -1
  327. package/dist/utils/logger.d.ts.map +1 -0
  328. package/dist/{logger.js → utils/logger.js} +1 -1
  329. package/dist/utils/parsing.d.ts.map +1 -0
  330. package/dist/utils/process.d.ts.map +1 -1
  331. package/dist/utils/process.js +90 -37
  332. package/dist/utils/templates.d.ts +2 -0
  333. package/dist/utils/templates.d.ts.map +1 -0
  334. package/dist/utils/templates.js +24 -0
  335. package/dist/utils/version.d.ts.map +1 -0
  336. package/dist/{version.js → utils/version.js} +1 -1
  337. package/package.json +35 -26
  338. package/dist/cli.d.ts +0 -23
  339. package/dist/cli.d.ts.map +0 -1
  340. package/dist/commands/add-directory/types.d.ts +0 -6
  341. package/dist/commands/add-directory/types.d.ts.map +0 -1
  342. package/dist/commands/add-directory/types.js +0 -1
  343. package/dist/commands/copy/types.d.ts +0 -3
  344. package/dist/commands/copy/types.d.ts.map +0 -1
  345. package/dist/commands/copy/types.js +0 -1
  346. package/dist/commands/exit/index.d.ts +0 -10
  347. package/dist/commands/exit/index.d.ts.map +0 -1
  348. package/dist/commands/exit/index.js +0 -21
  349. package/dist/commands/exit/types.d.ts +0 -8
  350. package/dist/commands/exit/types.d.ts.map +0 -1
  351. package/dist/commands/exit/types.js +0 -1
  352. package/dist/commands/exit/utils.d.ts +0 -2
  353. package/dist/commands/exit/utils.d.ts.map +0 -1
  354. package/dist/commands/exit/utils.js +0 -13
  355. package/dist/commands/prompt/index.d.ts +0 -5
  356. package/dist/commands/prompt/index.d.ts.map +0 -1
  357. package/dist/commands/prompt/index.js +0 -122
  358. package/dist/commands/prompt/types.d.ts +0 -15
  359. package/dist/commands/prompt/types.d.ts.map +0 -1
  360. package/dist/commands/prompt/types.js +0 -1
  361. package/dist/commands/prompt/utils.d.ts +0 -12
  362. package/dist/commands/prompt/utils.d.ts.map +0 -1
  363. package/dist/commands/prompt/utils.js +0 -107
  364. package/dist/commands/reset/index.d.ts +0 -3
  365. package/dist/commands/reset/index.d.ts.map +0 -1
  366. package/dist/commands/reset/index.js +0 -25
  367. package/dist/commands/reset/types.d.ts +0 -1
  368. package/dist/commands/reset/types.d.ts.map +0 -1
  369. package/dist/commands/reset/types.js +0 -3
  370. package/dist/commands/review/types.d.ts +0 -12
  371. package/dist/commands/review/types.d.ts.map +0 -1
  372. package/dist/commands/review/types.js +0 -1
  373. package/dist/commands/save/index.d.ts +0 -3
  374. package/dist/commands/save/index.d.ts.map +0 -1
  375. package/dist/commands/save/index.js +0 -19
  376. package/dist/config.d.ts.map +0 -1
  377. package/dist/dedent.d.ts.map +0 -1
  378. package/dist/formatting.d.ts.map +0 -1
  379. package/dist/logger.d.ts.map +0 -1
  380. package/dist/mentions.d.ts +0 -14
  381. package/dist/mentions.d.ts.map +0 -1
  382. package/dist/parsing.d.ts.map +0 -1
  383. package/dist/prompts.d.ts.map +0 -1
  384. package/dist/repl-new.d.ts +0 -65
  385. package/dist/repl-new.d.ts.map +0 -1
  386. package/dist/skills.d.ts +0 -16
  387. package/dist/skills.d.ts.map +0 -1
  388. package/dist/skills.js +0 -233
  389. package/dist/stdin.d.ts.map +0 -1
  390. package/dist/tui/autocomplete/path-provider.d.ts +0 -21
  391. package/dist/tui/autocomplete/path-provider.d.ts.map +0 -1
  392. package/dist/tui/autocomplete/path-provider.js +0 -164
  393. package/dist/utils/iterables.d.ts +0 -2
  394. package/dist/utils/iterables.d.ts.map +0 -1
  395. package/dist/utils/iterables.js +0 -6
  396. package/dist/version.d.ts.map +0 -1
  397. /package/dist/{dedent.d.ts → utils/dedent.d.ts} +0 -0
  398. /package/dist/{dedent.js → utils/dedent.js} +0 -0
  399. /package/dist/{formatting.d.ts → utils/formatting.d.ts} +0 -0
  400. /package/dist/{logger.d.ts → utils/logger.d.ts} +0 -0
  401. /package/dist/{parsing.d.ts → utils/parsing.d.ts} +0 -0
  402. /package/dist/{parsing.js → utils/parsing.js} +0 -0
  403. /package/dist/{version.d.ts → utils/version.d.ts} +0 -0
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Command Protection Module
3
+ * Detects and blocks destructive commands that could cause data loss
4
+ */
5
+ /**
6
+ * Detects if a command is destructive and should be blocked
7
+ * @param command - The full command string to check
8
+ * @returns BlockedCommandResult if destructive, SafeCommandResult if safe
9
+ */
10
+ export function detectDestructiveCommand(command) {
11
+ const trimmed = command.trim();
12
+ // Check for dangerous inline scripts first (bash -c, python -c, etc.)
13
+ const inlineScriptResult = detectDangerousInlineScripts(trimmed);
14
+ if (inlineScriptResult.blocked) {
15
+ return inlineScriptResult;
16
+ }
17
+ // Check for dangerous heredocs
18
+ const heredocResult = detectDangerousHeredocs(trimmed);
19
+ if (heredocResult.blocked) {
20
+ return heredocResult;
21
+ }
22
+ // Check for destructive git commands
23
+ const gitResult = detectDestructiveGitCommands(trimmed);
24
+ if (gitResult.blocked) {
25
+ return gitResult;
26
+ }
27
+ // Check for dangerous rm -rf commands
28
+ const rmResult = detectDangerousRmRf(trimmed);
29
+ if (rmResult.blocked) {
30
+ return rmResult;
31
+ }
32
+ return { blocked: false };
33
+ }
34
+ /**
35
+ * Detect destructive git commands
36
+ */
37
+ function detectDestructiveGitCommands(command) {
38
+ const lowerCommand = command.toLowerCase();
39
+ // Block git reset --hard and --merge
40
+ if (lowerCommand.includes("git reset --hard") ||
41
+ lowerCommand.includes("git reset --merge")) {
42
+ return {
43
+ blocked: true,
44
+ reason: "git reset --hard or --merge destroys uncommitted changes",
45
+ command,
46
+ tip: "Consider using 'git stash' first to save your changes, or use 'git reset --soft' to preserve changes.",
47
+ };
48
+ }
49
+ // Block git checkout -- <file> (discarding local changes)
50
+ if (lowerCommand.match(/git\s+checkout\s+--\s+\S+/)) {
51
+ return {
52
+ blocked: true,
53
+ reason: "git checkout -- <file> discards uncommitted file changes",
54
+ command,
55
+ tip: "Use 'git restore --staged <file>' to unstage changes, or 'git stash' to save changes temporarily.",
56
+ };
57
+ }
58
+ // Block git restore without --staged (discards uncommitted changes)
59
+ if (lowerCommand.startsWith("git restore") &&
60
+ !lowerCommand.includes(" --staged")) {
61
+ // Check if it's restoring files (not branches)
62
+ const afterRestore = lowerCommand.substring("git restore".length).trim();
63
+ if (afterRestore && !afterRestore.startsWith("-b")) {
64
+ return {
65
+ blocked: true,
66
+ reason: "git restore <file> (without --staged) discards uncommitted changes",
67
+ command,
68
+ tip: "Use 'git restore --staged <file>' to only unstage, or 'git stash' to save changes.",
69
+ };
70
+ }
71
+ }
72
+ // Block git clean -f (force deletes untracked files)
73
+ if (lowerCommand.includes("git clean -f") ||
74
+ lowerCommand.includes("git clean --force")) {
75
+ return {
76
+ blocked: true,
77
+ reason: "git clean -f permanently deletes untracked files",
78
+ command,
79
+ tip: "Use 'git clean -n' to preview what would be deleted, or 'git clean -f -d' to only delete untracked directories.",
80
+ };
81
+ }
82
+ // Block force push (but allow --force-with-lease which is safer)
83
+ if ((lowerCommand.includes("git push --force") &&
84
+ !lowerCommand.includes("--force-with-lease")) ||
85
+ lowerCommand.match(/git\s+push\s+-f\b/)) {
86
+ return {
87
+ blocked: true,
88
+ reason: "git push --force overwrites remote commit history",
89
+ command,
90
+ tip: "Use 'git push --force-with-lease' for safer force pushes, or prefer creating a new branch instead.",
91
+ };
92
+ }
93
+ // Block git branch -D (force delete without merge check)
94
+ if (lowerCommand.match(/git\s+branch\s+-[a-z]/)) {
95
+ // Check if it's an uppercase letter (force delete)
96
+ const match = lowerCommand.match(/git\s+branch\s+-[a-z]/);
97
+ if (match && match[0].slice(-1) !== match[0].slice(-1).toLowerCase()) {
98
+ // It's uppercase, block it
99
+ }
100
+ else if (match) {
101
+ const upperMatch = command.match(/git\s+branch\s+-[A-Z]/);
102
+ if (upperMatch) {
103
+ return {
104
+ blocked: true,
105
+ reason: "git branch -D force-deletes branches without checking if they're merged",
106
+ command,
107
+ tip: "Use 'git branch -d' (lowercase) to safely delete branches that are merged.",
108
+ };
109
+ }
110
+ }
111
+ }
112
+ // Block git stash drop and git stash clear
113
+ if (lowerCommand.includes("git stash drop") ||
114
+ lowerCommand.includes("git stash clear")) {
115
+ return {
116
+ blocked: true,
117
+ reason: "git stash drop/clear permanently deletes stashed changes",
118
+ command,
119
+ tip: "Use 'git stash list' to see stashes, or 'git stash pop' to apply and remove a stash.",
120
+ };
121
+ }
122
+ return { blocked: false };
123
+ }
124
+ /**
125
+ * Detect dangerous rm -rf commands outside of temporary directories
126
+ */
127
+ function detectDangerousRmRf(command) {
128
+ // Check for rm -rf pattern (case insensitive)
129
+ const rmMatch = command.match(/rm\s+-rf\s+/i);
130
+ if (!rmMatch || rmMatch.index === undefined) {
131
+ return { blocked: false };
132
+ }
133
+ // Extract the path argument
134
+ const matchIndex = rmMatch.index + rmMatch[0].length;
135
+ const afterRmRf = command.substring(matchIndex).trim();
136
+ // If no path specified, don't block (will fail naturally)
137
+ if (!afterRmRf) {
138
+ return { blocked: false };
139
+ }
140
+ // Get temporary directory paths
141
+ const tempDirs = ["/tmp", "/var/tmp", process.env["TMPDIR"] || "/tmp"];
142
+ // Check if the path is explicitly targeting only temp directories
143
+ // This handles: rm -rf /tmp/*, rm -rf /var/tmp/*, rm -rf $TMPDIR/*, and any subpaths
144
+ const isTempDirectoryOnly = tempDirs.some((tempDir) => {
145
+ // Check if path starts with temp directory (e.g., /tmp/foo, /tmp/*)
146
+ if (afterRmRf === tempDir || afterRmRf.startsWith(`${tempDir}/`)) {
147
+ return true;
148
+ }
149
+ return false;
150
+ });
151
+ // Also check for $TMPDIR/* pattern (literal strings)
152
+ // Using string concatenation to avoid lint warnings about template-like strings
153
+ const tmpDirVar = "$" + "TMPDIR";
154
+ const tmpDirVarBraces = "$" + "{TMPDIR}";
155
+ if (afterRmRf === tmpDirVar ||
156
+ afterRmRf.startsWith(`${tmpDirVar}/`) ||
157
+ afterRmRf === tmpDirVarBraces ||
158
+ afterRmRf.startsWith(`${tmpDirVarBraces}/`)) {
159
+ return { blocked: false };
160
+ }
161
+ if (isTempDirectoryOnly) {
162
+ return { blocked: false };
163
+ }
164
+ // Block any other rm -rf
165
+ return {
166
+ blocked: true,
167
+ reason: "rm -rf outside of temporary directories can cause permanent data loss",
168
+ command,
169
+ tip: "Only rm -rf is allowed for /tmp/*, /var/tmp/*, or $TMPDIR/* to clean temporary files.",
170
+ };
171
+ }
172
+ /**
173
+ * Detect dangerous patterns in inline scripts (-c flags)
174
+ */
175
+ function detectDangerousInlineScripts(command) {
176
+ // Check for common inline script patterns and scan the content after -c for destructive commands
177
+ const languagePatterns = [
178
+ { pattern: /\bbash\s+-c\s+\S+/i, language: "bash" },
179
+ { pattern: /\bsh\s+-c\s+\S+/i, language: "sh" },
180
+ { pattern: /\bpython\d?\s+-c\s+\S+/i, language: "Python" },
181
+ { pattern: /\bnode\s+-e\s+\S+/i, language: "Node.js" },
182
+ { pattern: /\bnpx\s+-c\s+\S+/i, language: "npx" },
183
+ { pattern: /\bruby\s+-e\s+\S+/i, language: "Ruby" },
184
+ { pattern: /\bperl\s+-e\s+\S+/i, language: "Perl" },
185
+ ];
186
+ for (const { pattern, language } of languagePatterns) {
187
+ if (pattern.test(command)) {
188
+ // Found an inline script, scan the command for destructive patterns
189
+ // Look for patterns after -c flag, handling nested quotes
190
+ const destructivePatterns = [
191
+ /git\s+reset\s+--hard/i,
192
+ /git\s+reset\s+--merge/i,
193
+ /git\s+clean\s+-f/i,
194
+ /git\s+checkout\s+--\s+\S+/i,
195
+ /git\s+push\s+(-f|--force)/i,
196
+ /git\s+branch\s+-[A-Z]/i,
197
+ /git\s+stash\s+(drop|clear)/i,
198
+ /rm\s+-rf\s+\/home/i,
199
+ /rm\s+-rf\s+\/usr/i,
200
+ /rm\s+-rf\s+~/i,
201
+ ];
202
+ // Check if any destructive pattern is present in the command
203
+ for (const destructivePattern of destructivePatterns) {
204
+ if (destructivePattern.test(command)) {
205
+ return {
206
+ blocked: true,
207
+ reason: `Inline ${language} script contains destructive operation`,
208
+ command,
209
+ tip: "Review the script content for destructive commands.",
210
+ };
211
+ }
212
+ }
213
+ }
214
+ }
215
+ return { blocked: false };
216
+ }
217
+ /**
218
+ * Detect dangerous patterns in heredocs and here-strings
219
+ */
220
+ function detectDangerousHeredocs(command) {
221
+ // Match heredoc patterns: <<EOF ... EOF
222
+ const heredocPattern = /<<-?\s*['"]?(\w+)['"]?\s*([\s\S]*?)\n\1\b/gi;
223
+ let match = null;
224
+ match = heredocPattern.exec(command);
225
+ while (match !== null) {
226
+ const heredocContent = match[2];
227
+ const heredocResult = detectDangerousScriptContent(heredocContent);
228
+ if (heredocResult.blocked) {
229
+ return {
230
+ blocked: true,
231
+ reason: "Heredoc contains destructive operation",
232
+ command,
233
+ tip: heredocResult.tip ||
234
+ "Review the heredoc content for destructive commands.",
235
+ };
236
+ }
237
+ match = heredocPattern.exec(command);
238
+ }
239
+ // Match here-string patterns (<<<)
240
+ const hereStringPattern = /<<<\s*(['"])([^"']+)\1/gi;
241
+ match = null;
242
+ match = hereStringPattern.exec(command);
243
+ while (match !== null) {
244
+ const stringContent = match[2];
245
+ const stringResult = detectDangerousScriptContent(stringContent);
246
+ if (stringResult.blocked) {
247
+ return {
248
+ blocked: true,
249
+ reason: "Here-string contains destructive operation",
250
+ command,
251
+ tip: stringResult.tip ||
252
+ "Review the here-string content for destructive commands.",
253
+ };
254
+ }
255
+ match = hereStringPattern.exec(command);
256
+ }
257
+ return { blocked: false };
258
+ }
259
+ /**
260
+ * Check script content for dangerous patterns
261
+ */
262
+ function detectDangerousScriptContent(content) {
263
+ const lowerContent = content.toLowerCase();
264
+ // Check for destructive git commands within scripts
265
+ const dangerousGitPatterns = [
266
+ /\bgit\s+reset\s+(--hard|--merge|--keep)\b/i,
267
+ /\bgit\s+clean\s+-f\b/i,
268
+ /\bgit\s+checkout\s+--\s+\S+/i,
269
+ /\bgit\s+restore\s+(?!--staged)\s+\S+/i,
270
+ /\bgit\s+push\s+(-f|--force)\b/i,
271
+ /\bgit\s+branch\s+-[D]\b/i,
272
+ /\bgit\s+stash\s+(drop|clear)\b/i,
273
+ ];
274
+ for (const pattern of dangerousGitPatterns) {
275
+ if (pattern.test(lowerContent)) {
276
+ return {
277
+ blocked: true,
278
+ tip: "The script contains a destructive git command. Review the script content.",
279
+ };
280
+ }
281
+ }
282
+ // Check for dangerous rm -rf patterns (more permissive for scripts, block obvious dangers)
283
+ const dangerousRmPatterns = [
284
+ /\brm\s+-rf\s+\/[^\s*]*[a-z]/i, // rm -rf /something (but allow /tmp/* patterns)
285
+ /\brm\s+-rf\s+\/home/i,
286
+ /\brm\s+-rf\s+\/usr/i,
287
+ /\brm\s+-rf\s+\/etc/i,
288
+ /\brm\s+-rf\s+\/var\s*$/i, // Block /var alone but allow /var/tmp
289
+ /\brm\s+-rf\s+~(?!\/)/i, // rm -rf ~ but allow ~/tmp
290
+ ];
291
+ for (const pattern of dangerousRmPatterns) {
292
+ if (pattern.test(content)) {
293
+ return {
294
+ blocked: true,
295
+ tip: "The script contains a dangerous rm -rf command.",
296
+ };
297
+ }
298
+ }
299
+ // Check for format string attacks and other dangerous patterns
300
+ const dangerousPatterns = [
301
+ /\brm\s+-rf\s+\$\w+/i, // rm -rf $VAR (variable expansion could be dangerous)
302
+ ];
303
+ for (const pattern of dangerousPatterns) {
304
+ if (pattern.test(content)) {
305
+ return {
306
+ blocked: true,
307
+ tip: "The script contains a potentially dangerous rm command with variable expansion.",
308
+ };
309
+ }
310
+ }
311
+ return { blocked: false };
312
+ }
313
+ /**
314
+ * Generate a user-friendly blocked command message
315
+ */
316
+ export function formatBlockedCommandMessage(result) {
317
+ return `BLOCKED
318
+
319
+ Reason: ${result.reason}
320
+
321
+ Command: ${result.command}
322
+
323
+ Tip: ${result.tip}`;
324
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedent.d.ts","sourceRoot":"","sources":["../../source/utils/dedent.ts"],"names":[],"mappings":"AAAA,KAAK,MAAM,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC;AAI9E,eAAO,MAAM,MAAM,EAAE,MA+CpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function expandEnvVars(vars: Record<string, string>): Record<string, string>;
2
+ //# sourceMappingURL=env-expand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-expand.d.ts","sourceRoot":"","sources":["../../source/utils/env-expand.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxB"}
@@ -0,0 +1,8 @@
1
+ const ENV_VAR_PATTERN = /\$\{([^}]+)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g;
2
+ export function expandEnvVars(vars) {
3
+ const result = {};
4
+ for (const [key, value] of Object.entries(vars)) {
5
+ result[key] = value.replace(ENV_VAR_PATTERN, (_match, bracedName, plainName) => process.env[bracedName ?? plainName ?? ""] ?? "");
6
+ }
7
+ return result;
8
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Converts an absolute path to a relative path for display purposes.
3
+ * If the path is within the current working directory, returns the relative path.
4
+ * Otherwise, returns the absolute path unchanged.
5
+ *
6
+ * @param absolutePath - The absolute path to convert
7
+ * @param cwd - The current working directory (defaults to process.cwd())
8
+ * @returns The display-ready path (relative if within cwd, absolute otherwise)
9
+ */
10
+ export declare function toDisplayPath(absolutePath: string | undefined | null, cwd?: string): string;
11
+ //# sourceMappingURL=path-display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-display.d.ts","sourceRoot":"","sources":["../../../source/utils/filesystem/path-display.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EACvC,GAAG,GAAE,MAAsB,GAC1B,MAAM,CA0BR"}
@@ -0,0 +1,32 @@
1
+ import path from "node:path";
2
+ /**
3
+ * Converts an absolute path to a relative path for display purposes.
4
+ * If the path is within the current working directory, returns the relative path.
5
+ * Otherwise, returns the absolute path unchanged.
6
+ *
7
+ * @param absolutePath - The absolute path to convert
8
+ * @param cwd - The current working directory (defaults to process.cwd())
9
+ * @returns The display-ready path (relative if within cwd, absolute otherwise)
10
+ */
11
+ export function toDisplayPath(absolutePath, cwd = process.cwd()) {
12
+ if (!absolutePath) {
13
+ return ".";
14
+ }
15
+ // If path is already relative, return as-is
16
+ if (!path.isAbsolute(absolutePath)) {
17
+ return absolutePath;
18
+ }
19
+ // Try to get relative path
20
+ const relativePath = path.relative(cwd, absolutePath);
21
+ // If relative path starts with '..', it means the path is outside cwd
22
+ // Return absolute path in that case
23
+ if (relativePath.startsWith("..")) {
24
+ return absolutePath;
25
+ }
26
+ // If relative path is empty (path equals cwd), return '.'
27
+ if (relativePath === "") {
28
+ return ".";
29
+ }
30
+ // Return relative path
31
+ return relativePath;
32
+ }
@@ -1,9 +1,9 @@
1
- import type { ProjectConfig } from "../../config.ts";
1
+ import type { Config } from "../../config/index.ts";
2
2
  export declare function joinWorkingDir(userPath: string, workingDir: string): string;
3
3
  export declare function isPathWithinAllowedDirs(requestedPath: string, allowedDirs: string[]): boolean;
4
4
  export declare function validatePath(requestedPath: string, allowedDirectory: string | string[], options?: {
5
5
  requireExistence?: boolean;
6
6
  abortSignal?: AbortSignal;
7
7
  }): Promise<string>;
8
- export declare function validateFileNotReadOnly(filePath: string, config: ProjectConfig, workingDir: string): void;
8
+ export declare function validateFileNotReadOnly(filePath: string, config: Config, workingDir: string): void;
9
9
  //# sourceMappingURL=security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../source/utils/filesystem/security.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAsCrD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK3E;AAoCD,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAIT;AAGD,wBAAsB,YAAY,CAChC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,EACnC,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAO,GACtE,OAAO,CAAC,MAAM,CAAC,CAiIjB;AA8BD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,GACjB,IAAI,CAIN"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../source/utils/filesystem/security.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAsCpD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAK3E;AAoCD,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAIT;AAsCD,wBAAsB,YAAY,CAChC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,GAAG,MAAM,EAAE,EACnC,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,WAAW,CAAA;CAAO,GACtE,OAAO,CAAC,MAAM,CAAC,CAmGjB;AA8BD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,IAAI,CAIN"}
@@ -77,6 +77,33 @@ function isPathWithinBaseDir(requestedPath, baseDir) {
77
77
  export function isPathWithinAllowedDirs(requestedPath, allowedDirs) {
78
78
  return allowedDirs.some((allowedDir) => isPathWithinBaseDir(requestedPath, allowedDir));
79
79
  }
80
+ async function resolveValidAncestor(startDir, isWithinAllowed) {
81
+ let current = startDir;
82
+ while (true) {
83
+ try {
84
+ const stat = await fs.stat(current);
85
+ if (!stat.isDirectory()) {
86
+ throw new Error(`Nearest existing ancestor is not a directory: ${current}`);
87
+ }
88
+ const realAncestor = await fs.realpath(current);
89
+ const normalizedAncestor = normalizePath(realAncestor);
90
+ if (!isWithinAllowed(normalizedAncestor)) {
91
+ throw new Error("Access denied - ancestor directory resolves outside allowed directories");
92
+ }
93
+ return true;
94
+ }
95
+ catch (err) {
96
+ if (err instanceof Error && err.message.startsWith("Access denied")) {
97
+ throw err;
98
+ }
99
+ const parent = path.dirname(current);
100
+ if (parent === current) {
101
+ return false;
102
+ }
103
+ current = parent;
104
+ }
105
+ }
106
+ }
80
107
  // Security utilities
81
108
  export async function validatePath(requestedPath, allowedDirectory, options = {}) {
82
109
  const { requireExistence = true, abortSignal } = options;
@@ -136,36 +163,7 @@ export async function validatePath(requestedPath, allowedDirectory, options = {}
136
163
  catch (_error) {
137
164
  // For new files or paths where some directories don't exist yet:
138
165
  // Walk up to the nearest existing ancestor directory and validate it.
139
- let current = path.dirname(absolute);
140
- let foundValidAncestor = false;
141
- while (true) {
142
- try {
143
- const stat = await fs.stat(current);
144
- if (!stat.isDirectory()) {
145
- throw new Error(`Nearest existing ancestor is not a directory: ${current}`);
146
- }
147
- const realAncestor = await fs.realpath(current);
148
- const normalizedAncestor = normalizePath(realAncestor);
149
- if (!isWithinAllowed(normalizedAncestor)) {
150
- throw new Error("Access denied - ancestor directory resolves outside allowed directories");
151
- }
152
- // Ancestor is within allowed; allow creation below it.
153
- foundValidAncestor = true;
154
- break;
155
- }
156
- catch (err) {
157
- // If it's a security denial, rethrow
158
- if (err instanceof Error && err.message.startsWith("Access denied")) {
159
- throw err;
160
- }
161
- // If we reached the filesystem root, break to fallback check
162
- const parent = path.dirname(current);
163
- if (parent === current) {
164
- break;
165
- }
166
- current = parent;
167
- }
168
- }
166
+ const foundValidAncestor = await resolveValidAncestor(path.dirname(absolute), isWithinAllowed);
169
167
  if (!foundValidAncestor) {
170
168
  // Rely on intended path check
171
169
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../source/utils/formatting.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;AAExD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,GACjB,MAAM,CAaR;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,UAAU,GACjB,MAAM,CAWR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GACjB,MAAM,CAWR;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,MACG,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,MAAM,KAAG,MASjD,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GAAI,cAAc,MAAM,KAAG,MAuCrD,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAwC1C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GAAI,MAAM,IAAI,KAAG,MASvC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAGvD,CAAC"}
@@ -5,7 +5,7 @@
5
5
  * @module formatting
6
6
  */
7
7
  import path from "node:path";
8
- import { getCodeblockFromFilePath } from "./utils/filetype-detection.js";
8
+ import { getCodeblockFromFilePath } from "./filetype-detection.js";
9
9
  const MD_TRIPLE_QUOTE = "```";
10
10
  /**
11
11
  * Formats file content with metadata in the specified format.
@@ -18,4 +18,8 @@ export declare function hasUncommittedChanges(): Promise<boolean>;
18
18
  * Get the current git branch name
19
19
  */
20
20
  export declare function getCurrentBranch(): Promise<string | null>;
21
+ /**
22
+ * Count commits that exist locally but haven't been pushed to the remote branch
23
+ */
24
+ export declare function getUnpushedCommitsCount(): Promise<number>;
21
25
  //# sourceMappingURL=git.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../source/utils/git.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW;;;;GAyDhC;AAED,wBAAsB,YAAY;;;;;GAmCjC;AAED,eAAO,MAAM,cAAc,QAAqB,OAAO,CAAC,OAAO,CAS7D,CAAC;AAEH;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAY9D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkB/D"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../source/utils/git.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW;;;;GAyDhC;AAED,wBAAsB,YAAY;;;;;GAmCjC;AAED,eAAO,MAAM,cAAc,QAAqB,OAAO,CAAC,OAAO,CAS7D,CAAC;AAEH;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAY9D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkB/D;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC,CAmC/D"}
package/dist/utils/git.js CHANGED
@@ -133,3 +133,33 @@ export async function getCurrentBranch() {
133
133
  return null;
134
134
  }
135
135
  }
136
+ /**
137
+ * Count commits that exist locally but haven't been pushed to the remote branch
138
+ */
139
+ export async function getUnpushedCommitsCount() {
140
+ try {
141
+ // First, check if there's a remote configured
142
+ const remoteResult = await executeCommand(["git", "rev-parse", "--abbrev-ref", "@{u}"], {
143
+ cwd: process.cwd(),
144
+ throwOnError: false,
145
+ });
146
+ if (remoteResult.code !== 0) {
147
+ // No upstream configured or no remote
148
+ return 0;
149
+ }
150
+ // Count unpushed commits using git rev-list
151
+ // @{u}..HEAD gives commits in HEAD but not in upstream (unpushed commits)
152
+ const result = await executeCommand(["git", "rev-list", "--count", "@{u}..HEAD"], {
153
+ cwd: process.cwd(),
154
+ throwOnError: false,
155
+ });
156
+ if (result.code !== 0 || !result.stdout.trim()) {
157
+ return 0;
158
+ }
159
+ const count = Number.parseInt(result.stdout.trim(), 10);
160
+ return Number.isNaN(count) ? 0 : count;
161
+ }
162
+ catch {
163
+ return 0;
164
+ }
165
+ }
@@ -4,7 +4,7 @@ type ExpandDirectoriesOption = boolean | readonly string[] | {
4
4
  extensions?: readonly string[];
5
5
  };
6
6
  type FastGlobOptionsWithoutCwd = Omit<FastGlobOptions, "cwd">;
7
- type Options = {
7
+ export type Options = {
8
8
  /**
9
9
  * If set to `true`, `glob` will automatically glob directories for you. If you define an `Array` it will only glob files that matches the patterns inside the `Array`. You can also define an `Object` with `files` and `extensions` like in the example below.
10
10
  *
@@ -1 +1 @@
1
- {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../source/utils/glob.ts"],"names":[],"mappings":"AAIA,OAAW,EAAc,KAAK,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAC;AAgB5E,KAAK,uBAAuB,GACxB,OAAO,GACP,SAAS,MAAM,EAAE,GACjB;IAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAElE,KAAK,yBAAyB,GAAG,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AAE9D,KAAK,OAAO,GAAG;IACb;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAErD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC;CAC7B,GAAG,yBAAyB,CAAC;AA6U9B;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,8DAtLa,OAAO,sBAoMpC,CAAC"}
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../source/utils/glob.ts"],"names":[],"mappings":"AAIA,OAAW,EAAc,KAAK,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAC;AAgB5E,KAAK,uBAAuB,GACxB,OAAO,GACP,SAAS,MAAM,EAAE,GACjB;IAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAElE,KAAK,yBAAyB,GAAG,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AAE9D,MAAM,MAAM,OAAO,GAAG;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAErD;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IAElD;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC;CAC7B,GAAG,yBAAyB,CAAC;AA6U9B;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI,8DAtLa,OAAO,sBAoMpC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../source/utils/logger.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAgDxB,eAAO,MAAM,MAAM,6BAIjB,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { join } from "node:path";
2
2
  import pino from "pino";
3
- import { config } from "./config.js";
3
+ import { config } from "../config/index.js";
4
4
  // Create a lazy logger factory that only initializes when first used
5
5
  let loggerInstance = null;
6
6
  function createLogger() {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsing.d.ts","sourceRoot":"","sources":["../../source/utils/parsing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,CAAC,EAAE,MAAM,KAAK,CAAC;AAiBtC,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,8CAE1D"}
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../source/utils/process.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mGAAmG;IACnG,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CACzB;AAED,KAAK,WAAW,GACZ;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAGjC,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CA2EpD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACvC,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,aAAa,CAAC,CAqGxB"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../source/utils/process.ts"],"names":[],"mappings":"AAOA,UAAU,cAAc;IACtB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mGAAmG;IACnG,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,aAAa;IACrB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CACzB;AAED,KAAK,WAAW,GACZ;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAwGjC,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CA8DpD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACvC,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,aAAa,CAAC,CAqGxB"}