@travisennis/acai 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 (439) hide show
  1. package/.acai/acai.json +9 -0
  2. package/.acai/prompts/add-openrouter-model.md +13 -0
  3. package/.acai/prompts/project-status.md +4 -0
  4. package/.acai/prompts/update-architecture-document.md +9 -0
  5. package/.acai/rules/learned-rules.md +9 -0
  6. package/.ai/docs/available-tools.txt +3 -0
  7. package/.ai/docs/cognitive_complexity_refactoring_progress.md +65 -0
  8. package/.ai/docs/deleted_tools.md +168 -0
  9. package/.ai/docs/deleted_tools_88ced9ef.md +56 -0
  10. package/.ai/docs/image-pasting.md +46 -0
  11. package/.ai/docs/initialize-app.md +117 -0
  12. package/.ai/docs/issue-4-plan.md +44 -0
  13. package/.ai/docs/marked-renderer-debug.md +15 -0
  14. package/.ai/docs/marked-renderer-refactor-plan.md +64 -0
  15. package/.ai/docs/memory-use-cases.md +55 -0
  16. package/.ai/docs/prompt-consistency.md +31 -0
  17. package/.ai/docs/refactoring-tools.md +98 -0
  18. package/.ai/docs/system-prompt-update.md +174 -0
  19. package/.ai/docs/system_prompt.txt +210 -0
  20. package/.ai/docs/tasks.md +49 -0
  21. package/.ai/plan.md +131 -0
  22. package/.ai/prompt.md +1 -0
  23. package/.ai/scripts/fetch_models.js +27 -0
  24. package/.ai/scripts/generateSystemPrompt.ts +15 -0
  25. package/.ai/scripts/list-tools.mjs +4 -0
  26. package/.ai/scripts/p5_geometric_shapes.js +149 -0
  27. package/.husky/commit-msg +1 -0
  28. package/.husky/pre-commit +3 -0
  29. package/.husky/pre-push +1 -0
  30. package/.ignore +4 -0
  31. package/AGENTS.md +25 -0
  32. package/ARCHITECTURE.md +304 -0
  33. package/LICENSE +21 -0
  34. package/README.md +392 -0
  35. package/TODO.md +2 -0
  36. package/biome.json +61 -0
  37. package/commitlint.config.js +3 -0
  38. package/dist/cli.d.ts +19 -0
  39. package/dist/cli.js +116 -0
  40. package/dist/commands/application-log-command.d.ts +2 -0
  41. package/dist/commands/application-log-command.js +43 -0
  42. package/dist/commands/clear-command.d.ts +2 -0
  43. package/dist/commands/clear-command.js +12 -0
  44. package/dist/commands/compact-command.d.ts +2 -0
  45. package/dist/commands/compact-command.js +51 -0
  46. package/dist/commands/copy-command.d.ts +2 -0
  47. package/dist/commands/copy-command.js +51 -0
  48. package/dist/commands/edit-command.d.ts +2 -0
  49. package/dist/commands/edit-command.js +53 -0
  50. package/dist/commands/edit-prompt-command.d.ts +2 -0
  51. package/dist/commands/edit-prompt-command.js +25 -0
  52. package/dist/commands/exit-command.d.ts +2 -0
  53. package/dist/commands/exit-command.js +14 -0
  54. package/dist/commands/files-command.d.ts +2 -0
  55. package/dist/commands/files-command.js +63 -0
  56. package/dist/commands/generate-rules-command.d.ts +2 -0
  57. package/dist/commands/generate-rules-command.js +61 -0
  58. package/dist/commands/help-command.d.ts +2 -0
  59. package/dist/commands/help-command.js +19 -0
  60. package/dist/commands/init-command.d.ts +2 -0
  61. package/dist/commands/init-command.js +40 -0
  62. package/dist/commands/last-log-command.d.ts +2 -0
  63. package/dist/commands/last-log-command.js +76 -0
  64. package/dist/commands/manager.d.ts +22 -0
  65. package/dist/commands/manager.js +123 -0
  66. package/dist/commands/model-command.d.ts +2 -0
  67. package/dist/commands/model-command.js +84 -0
  68. package/dist/commands/paste-command.d.ts +2 -0
  69. package/dist/commands/paste-command.js +40 -0
  70. package/dist/commands/prompt-command.d.ts +2 -0
  71. package/dist/commands/prompt-command.js +111 -0
  72. package/dist/commands/reset-command.d.ts +2 -0
  73. package/dist/commands/reset-command.js +16 -0
  74. package/dist/commands/rules-command.d.ts +2 -0
  75. package/dist/commands/rules-command.js +68 -0
  76. package/dist/commands/save-command.d.ts +2 -0
  77. package/dist/commands/save-command.js +14 -0
  78. package/dist/commands/types.d.ts +26 -0
  79. package/dist/commands/types.js +1 -0
  80. package/dist/commands/usage-command.d.ts +2 -0
  81. package/dist/commands/usage-command.js +21 -0
  82. package/dist/config.d.ts +60 -0
  83. package/dist/config.js +193 -0
  84. package/dist/conversation-analyzer.d.ts +10 -0
  85. package/dist/conversation-analyzer.js +88 -0
  86. package/dist/dedent.d.ts +3 -0
  87. package/dist/dedent.js +38 -0
  88. package/dist/formatting.d.ts +17 -0
  89. package/dist/formatting.js +103 -0
  90. package/dist/index.d.ts +18 -0
  91. package/dist/index.js +213 -0
  92. package/dist/logger.d.ts +2 -0
  93. package/dist/logger.js +24 -0
  94. package/dist/mentions.d.ts +9 -0
  95. package/dist/mentions.js +182 -0
  96. package/dist/messages.d.ts +69 -0
  97. package/dist/messages.js +261 -0
  98. package/dist/middleware/audit-message.d.ts +5 -0
  99. package/dist/middleware/audit-message.js +95 -0
  100. package/dist/middleware/index.d.ts +2 -0
  101. package/dist/middleware/index.js +2 -0
  102. package/dist/middleware/rate-limit.d.ts +4 -0
  103. package/dist/middleware/rate-limit.js +17 -0
  104. package/dist/models/ai-config.d.ts +12 -0
  105. package/dist/models/ai-config.js +87 -0
  106. package/dist/models/anthropic-provider.d.ts +25 -0
  107. package/dist/models/anthropic-provider.js +184 -0
  108. package/dist/models/deepseek-provider.d.ts +20 -0
  109. package/dist/models/deepseek-provider.js +42 -0
  110. package/dist/models/google-provider.d.ts +19 -0
  111. package/dist/models/google-provider.js +56 -0
  112. package/dist/models/manager.d.ts +15 -0
  113. package/dist/models/manager.js +48 -0
  114. package/dist/models/openai-provider.d.ts +22 -0
  115. package/dist/models/openai-provider.js +70 -0
  116. package/dist/models/openrouter-provider.d.ts +36 -0
  117. package/dist/models/openrouter-provider.js +276 -0
  118. package/dist/models/providers.d.ts +33 -0
  119. package/dist/models/providers.js +116 -0
  120. package/dist/models/xai-provider.d.ts +20 -0
  121. package/dist/models/xai-provider.js +47 -0
  122. package/dist/parsing.d.ts +2 -0
  123. package/dist/parsing.js +18 -0
  124. package/dist/prompts/manager.d.ts +19 -0
  125. package/dist/prompts/manager.js +71 -0
  126. package/dist/prompts.d.ts +4 -0
  127. package/dist/prompts.js +158 -0
  128. package/dist/repl-prompt.d.ts +14 -0
  129. package/dist/repl-prompt.js +147 -0
  130. package/dist/repl.d.ts +27 -0
  131. package/dist/repl.js +431 -0
  132. package/dist/source/cli.d.ts +19 -0
  133. package/dist/source/cli.js +116 -0
  134. package/dist/source/commands/application-log-command.d.ts +2 -0
  135. package/dist/source/commands/application-log-command.js +43 -0
  136. package/dist/source/commands/clear-command.d.ts +2 -0
  137. package/dist/source/commands/clear-command.js +12 -0
  138. package/dist/source/commands/compact-command.d.ts +2 -0
  139. package/dist/source/commands/compact-command.js +51 -0
  140. package/dist/source/commands/copy-command.d.ts +2 -0
  141. package/dist/source/commands/copy-command.js +51 -0
  142. package/dist/source/commands/edit-command.d.ts +2 -0
  143. package/dist/source/commands/edit-command.js +53 -0
  144. package/dist/source/commands/edit-prompt-command.d.ts +2 -0
  145. package/dist/source/commands/edit-prompt-command.js +25 -0
  146. package/dist/source/commands/exit-command.d.ts +2 -0
  147. package/dist/source/commands/exit-command.js +14 -0
  148. package/dist/source/commands/files-command.d.ts +2 -0
  149. package/dist/source/commands/files-command.js +63 -0
  150. package/dist/source/commands/generate-rules-command.d.ts +2 -0
  151. package/dist/source/commands/generate-rules-command.js +61 -0
  152. package/dist/source/commands/help-command.d.ts +2 -0
  153. package/dist/source/commands/help-command.js +19 -0
  154. package/dist/source/commands/init-command.d.ts +2 -0
  155. package/dist/source/commands/init-command.js +40 -0
  156. package/dist/source/commands/last-log-command.d.ts +2 -0
  157. package/dist/source/commands/last-log-command.js +76 -0
  158. package/dist/source/commands/manager.d.ts +22 -0
  159. package/dist/source/commands/manager.js +123 -0
  160. package/dist/source/commands/model-command.d.ts +2 -0
  161. package/dist/source/commands/model-command.js +84 -0
  162. package/dist/source/commands/paste-command.d.ts +2 -0
  163. package/dist/source/commands/paste-command.js +40 -0
  164. package/dist/source/commands/prompt-command.d.ts +2 -0
  165. package/dist/source/commands/prompt-command.js +111 -0
  166. package/dist/source/commands/reset-command.d.ts +2 -0
  167. package/dist/source/commands/reset-command.js +16 -0
  168. package/dist/source/commands/rules-command.d.ts +2 -0
  169. package/dist/source/commands/rules-command.js +68 -0
  170. package/dist/source/commands/save-command.d.ts +2 -0
  171. package/dist/source/commands/save-command.js +14 -0
  172. package/dist/source/commands/types.d.ts +26 -0
  173. package/dist/source/commands/types.js +1 -0
  174. package/dist/source/commands/usage-command.d.ts +2 -0
  175. package/dist/source/commands/usage-command.js +21 -0
  176. package/dist/source/config.d.ts +60 -0
  177. package/dist/source/config.js +193 -0
  178. package/dist/source/conversation-analyzer.d.ts +10 -0
  179. package/dist/source/conversation-analyzer.js +88 -0
  180. package/dist/source/dedent.d.ts +3 -0
  181. package/dist/source/dedent.js +38 -0
  182. package/dist/source/formatting.d.ts +17 -0
  183. package/dist/source/formatting.js +103 -0
  184. package/dist/source/index.d.ts +18 -0
  185. package/dist/source/index.js +213 -0
  186. package/dist/source/logger.d.ts +2 -0
  187. package/dist/source/logger.js +24 -0
  188. package/dist/source/mentions.d.ts +9 -0
  189. package/dist/source/mentions.js +182 -0
  190. package/dist/source/messages.d.ts +69 -0
  191. package/dist/source/messages.js +261 -0
  192. package/dist/source/middleware/audit-message.d.ts +5 -0
  193. package/dist/source/middleware/audit-message.js +95 -0
  194. package/dist/source/middleware/index.d.ts +2 -0
  195. package/dist/source/middleware/index.js +2 -0
  196. package/dist/source/middleware/rate-limit.d.ts +4 -0
  197. package/dist/source/middleware/rate-limit.js +17 -0
  198. package/dist/source/models/ai-config.d.ts +12 -0
  199. package/dist/source/models/ai-config.js +87 -0
  200. package/dist/source/models/anthropic-provider.d.ts +25 -0
  201. package/dist/source/models/anthropic-provider.js +184 -0
  202. package/dist/source/models/deepseek-provider.d.ts +20 -0
  203. package/dist/source/models/deepseek-provider.js +42 -0
  204. package/dist/source/models/google-provider.d.ts +19 -0
  205. package/dist/source/models/google-provider.js +56 -0
  206. package/dist/source/models/manager.d.ts +15 -0
  207. package/dist/source/models/manager.js +48 -0
  208. package/dist/source/models/openai-provider.d.ts +22 -0
  209. package/dist/source/models/openai-provider.js +70 -0
  210. package/dist/source/models/openrouter-provider.d.ts +36 -0
  211. package/dist/source/models/openrouter-provider.js +276 -0
  212. package/dist/source/models/providers.d.ts +33 -0
  213. package/dist/source/models/providers.js +116 -0
  214. package/dist/source/models/xai-provider.d.ts +20 -0
  215. package/dist/source/models/xai-provider.js +47 -0
  216. package/dist/source/parsing.d.ts +2 -0
  217. package/dist/source/parsing.js +18 -0
  218. package/dist/source/prompts/manager.d.ts +19 -0
  219. package/dist/source/prompts/manager.js +71 -0
  220. package/dist/source/prompts.d.ts +4 -0
  221. package/dist/source/prompts.js +158 -0
  222. package/dist/source/repl-prompt.d.ts +14 -0
  223. package/dist/source/repl-prompt.js +147 -0
  224. package/dist/source/repl.d.ts +27 -0
  225. package/dist/source/repl.js +431 -0
  226. package/dist/source/terminal/formatting.d.ts +37 -0
  227. package/dist/source/terminal/formatting.js +106 -0
  228. package/dist/source/terminal/index.d.ts +94 -0
  229. package/dist/source/terminal/index.js +420 -0
  230. package/dist/source/terminal/markdown-utils.d.ts +2 -0
  231. package/dist/source/terminal/markdown-utils.js +81 -0
  232. package/dist/source/terminal/markdown.d.ts +1 -0
  233. package/dist/source/terminal/markdown.js +111 -0
  234. package/dist/source/terminal/types.d.ts +71 -0
  235. package/dist/source/terminal/types.js +1 -0
  236. package/dist/source/terminal-output.d.ts +8 -0
  237. package/dist/source/terminal-output.js +213 -0
  238. package/dist/source/terminal-output.test.d.ts +8 -0
  239. package/dist/source/terminal-output.test.js +213 -0
  240. package/dist/source/token-tracker.d.ts +14 -0
  241. package/dist/source/token-tracker.js +53 -0
  242. package/dist/source/token-utils.d.ts +7 -0
  243. package/dist/source/token-utils.js +13 -0
  244. package/dist/source/tools/agent.d.ts +17 -0
  245. package/dist/source/tools/agent.js +87 -0
  246. package/dist/source/tools/bash.d.ts +19 -0
  247. package/dist/source/tools/bash.js +294 -0
  248. package/dist/source/tools/code-interpreter.d.ts +12 -0
  249. package/dist/source/tools/code-interpreter.js +131 -0
  250. package/dist/source/tools/command-validation.d.ts +8 -0
  251. package/dist/source/tools/command-validation.js +69 -0
  252. package/dist/source/tools/delete-file.d.ts +12 -0
  253. package/dist/source/tools/delete-file.js +56 -0
  254. package/dist/source/tools/directory-tree.d.ts +12 -0
  255. package/dist/source/tools/directory-tree.js +38 -0
  256. package/dist/source/tools/edit-file.d.ts +19 -0
  257. package/dist/source/tools/edit-file.js +107 -0
  258. package/dist/source/tools/filesystem-utils.d.ts +22 -0
  259. package/dist/source/tools/filesystem-utils.js +191 -0
  260. package/dist/source/tools/git-utils.d.ts +14 -0
  261. package/dist/source/tools/git-utils.js +64 -0
  262. package/dist/source/tools/grep.d.ts +17 -0
  263. package/dist/source/tools/grep.js +138 -0
  264. package/dist/source/tools/index.d.ts +161 -0
  265. package/dist/source/tools/index.js +209 -0
  266. package/dist/source/tools/memory-read.d.ts +13 -0
  267. package/dist/source/tools/memory-read.js +135 -0
  268. package/dist/source/tools/memory-write.d.ts +12 -0
  269. package/dist/source/tools/memory-write.js +83 -0
  270. package/dist/source/tools/move-file.d.ts +13 -0
  271. package/dist/source/tools/move-file.js +44 -0
  272. package/dist/source/tools/read-file.d.ts +17 -0
  273. package/dist/source/tools/read-file.js +86 -0
  274. package/dist/source/tools/read-multiple-files.d.ts +14 -0
  275. package/dist/source/tools/read-multiple-files.js +55 -0
  276. package/dist/source/tools/save-file.d.ts +17 -0
  277. package/dist/source/tools/save-file.js +98 -0
  278. package/dist/source/tools/think.d.ts +11 -0
  279. package/dist/source/tools/think.js +45 -0
  280. package/dist/source/tools/types.d.ts +29 -0
  281. package/dist/source/tools/types.js +14 -0
  282. package/dist/source/tools/web-fetch.d.ts +47 -0
  283. package/dist/source/tools/web-fetch.js +246 -0
  284. package/dist/source/tools/web-search.d.ts +13 -0
  285. package/dist/source/tools/web-search.js +80 -0
  286. package/dist/source/utils/process.d.ts +36 -0
  287. package/dist/source/utils/process.js +75 -0
  288. package/dist/source/version.d.ts +1 -0
  289. package/dist/source/version.js +21 -0
  290. package/dist/terminal/formatting.d.ts +37 -0
  291. package/dist/terminal/formatting.js +106 -0
  292. package/dist/terminal/index.d.ts +94 -0
  293. package/dist/terminal/index.js +420 -0
  294. package/dist/terminal/markdown-utils.d.ts +2 -0
  295. package/dist/terminal/markdown-utils.js +81 -0
  296. package/dist/terminal/markdown.d.ts +1 -0
  297. package/dist/terminal/markdown.js +111 -0
  298. package/dist/terminal/types.d.ts +71 -0
  299. package/dist/terminal/types.js +1 -0
  300. package/dist/terminal-output.d.ts +8 -0
  301. package/dist/terminal-output.js +213 -0
  302. package/dist/token-tracker.d.ts +14 -0
  303. package/dist/token-tracker.js +53 -0
  304. package/dist/token-utils.d.ts +7 -0
  305. package/dist/token-utils.js +13 -0
  306. package/dist/tools/agent.d.ts +17 -0
  307. package/dist/tools/agent.js +87 -0
  308. package/dist/tools/bash.d.ts +19 -0
  309. package/dist/tools/bash.js +294 -0
  310. package/dist/tools/code-interpreter.d.ts +12 -0
  311. package/dist/tools/code-interpreter.js +131 -0
  312. package/dist/tools/command-validation.d.ts +8 -0
  313. package/dist/tools/command-validation.js +69 -0
  314. package/dist/tools/delete-file.d.ts +12 -0
  315. package/dist/tools/delete-file.js +56 -0
  316. package/dist/tools/directory-tree.d.ts +12 -0
  317. package/dist/tools/directory-tree.js +38 -0
  318. package/dist/tools/edit-file.d.ts +19 -0
  319. package/dist/tools/edit-file.js +107 -0
  320. package/dist/tools/filesystem-utils.d.ts +22 -0
  321. package/dist/tools/filesystem-utils.js +191 -0
  322. package/dist/tools/git-utils.d.ts +14 -0
  323. package/dist/tools/git-utils.js +64 -0
  324. package/dist/tools/grep.d.ts +17 -0
  325. package/dist/tools/grep.js +138 -0
  326. package/dist/tools/index.d.ts +161 -0
  327. package/dist/tools/index.js +209 -0
  328. package/dist/tools/memory-read.d.ts +13 -0
  329. package/dist/tools/memory-read.js +135 -0
  330. package/dist/tools/memory-write.d.ts +12 -0
  331. package/dist/tools/memory-write.js +83 -0
  332. package/dist/tools/move-file.d.ts +13 -0
  333. package/dist/tools/move-file.js +44 -0
  334. package/dist/tools/read-file.d.ts +17 -0
  335. package/dist/tools/read-file.js +86 -0
  336. package/dist/tools/read-multiple-files.d.ts +14 -0
  337. package/dist/tools/read-multiple-files.js +55 -0
  338. package/dist/tools/save-file.d.ts +17 -0
  339. package/dist/tools/save-file.js +98 -0
  340. package/dist/tools/think.d.ts +11 -0
  341. package/dist/tools/think.js +45 -0
  342. package/dist/tools/types.d.ts +29 -0
  343. package/dist/tools/types.js +14 -0
  344. package/dist/tools/web-fetch.d.ts +47 -0
  345. package/dist/tools/web-fetch.js +246 -0
  346. package/dist/tools/web-search.d.ts +13 -0
  347. package/dist/tools/web-search.js +80 -0
  348. package/dist/utils/process.d.ts +36 -0
  349. package/dist/utils/process.js +75 -0
  350. package/dist/version.d.ts +1 -0
  351. package/dist/version.js +21 -0
  352. package/knip.json +5 -0
  353. package/package.json +83 -0
  354. package/source/cli.ts +172 -0
  355. package/source/commands/application-log-command.ts +53 -0
  356. package/source/commands/clear-command.ts +14 -0
  357. package/source/commands/compact-command.ts +64 -0
  358. package/source/commands/copy-command.ts +55 -0
  359. package/source/commands/edit-command.ts +63 -0
  360. package/source/commands/edit-prompt-command.ts +31 -0
  361. package/source/commands/exit-command.ts +18 -0
  362. package/source/commands/files-command.ts +85 -0
  363. package/source/commands/generate-rules-command.ts +82 -0
  364. package/source/commands/help-command.ts +27 -0
  365. package/source/commands/init-command.ts +48 -0
  366. package/source/commands/last-log-command.ts +88 -0
  367. package/source/commands/manager.ts +151 -0
  368. package/source/commands/model-command.ts +123 -0
  369. package/source/commands/paste-command.ts +62 -0
  370. package/source/commands/prompt-command.ts +150 -0
  371. package/source/commands/reset-command.ts +22 -0
  372. package/source/commands/rules-command.ts +76 -0
  373. package/source/commands/save-command.ts +20 -0
  374. package/source/commands/types.ts +28 -0
  375. package/source/commands/usage-command.ts +26 -0
  376. package/source/config.ts +223 -0
  377. package/source/conversation-analyzer.ts +115 -0
  378. package/source/dedent.ts +53 -0
  379. package/source/formatting.ts +132 -0
  380. package/source/index.ts +240 -0
  381. package/source/logger.ts +29 -0
  382. package/source/mentions.ts +227 -0
  383. package/source/messages.ts +360 -0
  384. package/source/middleware/audit-message.ts +133 -0
  385. package/source/middleware/index.ts +2 -0
  386. package/source/middleware/rate-limit.ts +24 -0
  387. package/source/models/ai-config.ts +109 -0
  388. package/source/models/anthropic-provider.ts +199 -0
  389. package/source/models/deepseek-provider.ts +53 -0
  390. package/source/models/google-provider.ts +68 -0
  391. package/source/models/manager.ts +84 -0
  392. package/source/models/openai-provider.ts +81 -0
  393. package/source/models/openrouter-provider.ts +288 -0
  394. package/source/models/providers.ts +197 -0
  395. package/source/models/xai-provider.ts +59 -0
  396. package/source/parsing.ts +20 -0
  397. package/source/prompts/manager.ts +90 -0
  398. package/source/prompts.ts +172 -0
  399. package/source/repl-prompt.ts +196 -0
  400. package/source/repl.ts +572 -0
  401. package/source/terminal/formatting.ts +121 -0
  402. package/source/terminal/index.ts +518 -0
  403. package/source/terminal/markdown-utils.ts +89 -0
  404. package/source/terminal/markdown.ts +155 -0
  405. package/source/terminal/types.ts +84 -0
  406. package/source/terminal-output.test.ts +266 -0
  407. package/source/token-tracker.ts +78 -0
  408. package/source/token-utils.ts +17 -0
  409. package/source/tools/agent.ts +107 -0
  410. package/source/tools/bash.ts +367 -0
  411. package/source/tools/code-interpreter.ts +172 -0
  412. package/source/tools/command-validation.ts +81 -0
  413. package/source/tools/delete-file.ts +71 -0
  414. package/source/tools/directory-tree.ts +54 -0
  415. package/source/tools/edit-file.ts +155 -0
  416. package/source/tools/filesystem-utils.ts +265 -0
  417. package/source/tools/git-utils.ts +70 -0
  418. package/source/tools/grep.ts +184 -0
  419. package/source/tools/index.ts +278 -0
  420. package/source/tools/memory-read.ts +174 -0
  421. package/source/tools/memory-write.ts +105 -0
  422. package/source/tools/move-file.ts +59 -0
  423. package/source/tools/read-file.ts +129 -0
  424. package/source/tools/read-multiple-files.ts +80 -0
  425. package/source/tools/save-file.ts +147 -0
  426. package/source/tools/think.ts +51 -0
  427. package/source/tools/types.ts +58 -0
  428. package/source/tools/web-fetch.ts +327 -0
  429. package/source/tools/web-search.ts +101 -0
  430. package/source/utils/process.ts +121 -0
  431. package/source/version.ts +21 -0
  432. package/test/commands/copy-command.test.ts +69 -0
  433. package/test/config.test.ts +200 -0
  434. package/test/terminal/markdown-utils.test.ts +124 -0
  435. package/test/tools/bash-tool.test.ts +58 -0
  436. package/test/tools/code-interpreter.test.ts +91 -0
  437. package/test/tools/command-validation.test.ts +48 -0
  438. package/tsconfig.build.json +9 -0
  439. package/tsconfig.json +30 -0
@@ -0,0 +1,55 @@
1
+ import Clipboard from "@crosscopy/clipboard";
2
+ import type { ModelMessage, TextPart } from "ai";
3
+ import type { CommandOptions, ReplCommand } from "./types.ts";
4
+
5
+ function extractLastAssistantText(messages: ModelMessage[]): string | null {
6
+ for (let i = messages.length - 1; i >= 0; i--) {
7
+ const msg = messages[i] as ModelMessage | undefined;
8
+ if (!msg) continue;
9
+ if (msg.role !== "assistant") continue;
10
+ if (!("content" in msg) || !Array.isArray(msg.content)) continue;
11
+
12
+ // Find last text part
13
+ for (let j = msg.content.length - 1; j >= 0; j--) {
14
+ const part = msg.content[j];
15
+ if (
16
+ part &&
17
+ part.type === "text" &&
18
+ typeof (part as TextPart).text === "string"
19
+ ) {
20
+ const text = (part as TextPart).text;
21
+ if (text.trim().length > 0) return text;
22
+ }
23
+ }
24
+ }
25
+ return null;
26
+ }
27
+
28
+ export function copyCommand(options: CommandOptions): ReplCommand {
29
+ return {
30
+ command: "/copy",
31
+ description: "Copy the last assistant response to the clipboard",
32
+ result: "continue",
33
+ async getSubCommands() {
34
+ return [];
35
+ },
36
+ async execute(_args: string[]) {
37
+ const { messageHistory, terminal } = options;
38
+ const history = messageHistory.get();
39
+
40
+ const lastText = extractLastAssistantText(history);
41
+ if (!lastText) {
42
+ terminal.info("No assistant response to copy.");
43
+ return;
44
+ }
45
+
46
+ try {
47
+ await Clipboard.setText(lastText);
48
+ terminal.success("Copied last response to clipboard.");
49
+ } catch (err) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ terminal.error(`Could not copy to clipboard: ${message}`);
52
+ }
53
+ },
54
+ };
55
+ }
@@ -0,0 +1,63 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { extname, resolve } from "node:path";
3
+ import { editor, search } from "@inquirer/prompts";
4
+ import { globby } from "globby";
5
+ import type { CommandOptions, ReplCommand } from "./types.ts";
6
+
7
+ export const editCommand = ({ terminal }: CommandOptions): ReplCommand => {
8
+ return {
9
+ command: "/edit",
10
+ description: "Opens file in $EDITOR for editing. Usage: /edit [file-path]",
11
+ result: "continue" as const,
12
+ getSubCommands: () => Promise.resolve([]),
13
+ execute: async (args: string[]) => {
14
+ let fileToEdit: string;
15
+
16
+ if (args.length > 0) {
17
+ // File path provided as argument
18
+ const filePath = args.join(" "); // Handle file paths with spaces
19
+ const resolvedPath = resolve(filePath);
20
+
21
+ if (!existsSync(resolvedPath)) {
22
+ terminal.error(`File not found: ${filePath}`);
23
+ return;
24
+ }
25
+
26
+ fileToEdit = filePath;
27
+ } else {
28
+ // No file path provided, use search prompt
29
+ fileToEdit = await search({
30
+ message: "Search for file:",
31
+ source: async (input) => {
32
+ if (!input) {
33
+ return [];
34
+ }
35
+
36
+ const foundFiles = await globby(`**/*${input}*`, {
37
+ gitignore: true,
38
+ });
39
+
40
+ return foundFiles.map((file) => ({
41
+ name: file,
42
+ value: file,
43
+ }));
44
+ },
45
+ });
46
+ }
47
+
48
+ const content = readFileSync(fileToEdit, { encoding: "utf8" });
49
+
50
+ const edit = await editor({
51
+ message: `Edit ${fileToEdit}?`,
52
+ postfix: extname(fileToEdit),
53
+ default: content,
54
+ });
55
+
56
+ writeFileSync(fileToEdit, edit);
57
+
58
+ if (content !== edit) {
59
+ terminal.info(`File updated: ${fileToEdit}`);
60
+ }
61
+ },
62
+ };
63
+ };
@@ -0,0 +1,31 @@
1
+ import { editor } from "@inquirer/prompts";
2
+ import { syncTry } from "@travisennis/stdlib/try";
3
+ import type { CommandOptions, ReplCommand } from "./types.ts";
4
+
5
+ export const editPromptCommand = ({
6
+ terminal,
7
+ promptManager,
8
+ }: CommandOptions): ReplCommand => {
9
+ return {
10
+ command: "/edit-prompt",
11
+ description: "Edit the prompt.",
12
+ result: "use" as const,
13
+ getSubCommands: () => Promise.resolve([]),
14
+ execute: async () => {
15
+ try {
16
+ const prompt = syncTry(() => promptManager.get());
17
+ const updatedPrompt = await editor({
18
+ message: " Edit prompt?",
19
+ postfix: "md",
20
+ default: prompt.unwrapOr(""),
21
+ });
22
+
23
+ terminal.writeln(`> ${updatedPrompt}`);
24
+
25
+ promptManager.set(updatedPrompt);
26
+ } catch (error) {
27
+ terminal.error(`Error updating prompt: ${(error as Error).message}`);
28
+ }
29
+ },
30
+ };
31
+ };
@@ -0,0 +1,18 @@
1
+ import type { CommandOptions, ReplCommand } from "./types.ts";
2
+
3
+ export const exitCommand = ({
4
+ messageHistory,
5
+ }: CommandOptions): ReplCommand => {
6
+ return {
7
+ command: "/exit",
8
+ aliases: ["/bye", "/quit"],
9
+ description: "Exits and saves the chat history.",
10
+ result: "break" as const,
11
+ getSubCommands: () => Promise.resolve([]),
12
+ execute: async () => {
13
+ if (!messageHistory.isEmpty()) {
14
+ await messageHistory.save();
15
+ }
16
+ },
17
+ };
18
+ };
@@ -0,0 +1,85 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { checkbox } from "@inquirer/prompts";
3
+ import { globby } from "globby";
4
+ import { formatFile } from "../formatting.ts";
5
+ import { TokenCounter } from "../token-utils.ts";
6
+ import type { CommandOptions, ReplCommand } from "./types.ts";
7
+
8
+ export const filesCommand = ({
9
+ terminal,
10
+ promptManager,
11
+ modelManager,
12
+ }: CommandOptions): ReplCommand => {
13
+ return {
14
+ command: "/files",
15
+ description:
16
+ "Finds files matching the given patterns and adds their content to the next prompt. Usage: /files or /files src/**/*.ts",
17
+ result: "continue" as const,
18
+ getSubCommands: () => Promise.resolve([]),
19
+ execute: async (args: string[]) => {
20
+ try {
21
+ let workingFiles: string[] = [];
22
+ if (!args || args.length === 0) {
23
+ // Get all files in the current directory
24
+ const foundFiles = await globby("**/*", { gitignore: true });
25
+
26
+ const selectedFiles = await checkbox<string>({
27
+ message: "Select files to include:",
28
+ choices: foundFiles,
29
+ pageSize: 15,
30
+ });
31
+
32
+ if (selectedFiles.length === 0) {
33
+ terminal.warn("No files selected.");
34
+ return;
35
+ }
36
+
37
+ // Process the selected files
38
+ workingFiles = selectedFiles;
39
+ } else {
40
+ const patternList = args.filter(Boolean);
41
+ const foundFiles = await globby(patternList, { gitignore: true });
42
+
43
+ if (foundFiles.length === 0) {
44
+ terminal.warn("No files found matching the pattern(s)");
45
+ return;
46
+ }
47
+
48
+ // Process the selected files
49
+ workingFiles = foundFiles;
50
+ }
51
+
52
+ // Read the content of the files and format them for the next prompt
53
+ const format = modelManager.getModelMetadata("repl").promptFormat;
54
+ let tokenCount = 0;
55
+
56
+ const tokenCounter = new TokenCounter();
57
+
58
+ await Promise.all(
59
+ workingFiles.map(async (filePath) => {
60
+ try {
61
+ const content = await readFile(filePath, "utf-8");
62
+ const formattedFile = formatFile(filePath, content, format);
63
+ tokenCount += tokenCounter.count(formattedFile);
64
+ promptManager.addContext(formattedFile);
65
+ } catch (error) {
66
+ terminal.error(
67
+ `Error reading file ${filePath}: ${(error as Error).message}`,
68
+ );
69
+ }
70
+ }),
71
+ );
72
+
73
+ tokenCounter.free();
74
+
75
+ terminal.success(
76
+ `File contents will be added to your next prompt (${workingFiles.length} files, ${tokenCount} tokens)`,
77
+ );
78
+ } catch (error) {
79
+ terminal.error(
80
+ `Error processing file patterns: ${(error as Error).message}`,
81
+ );
82
+ }
83
+ },
84
+ };
85
+ };
@@ -0,0 +1,82 @@
1
+ import { checkbox } from "@inquirer/prompts";
2
+ import { analyzeConversation } from "../conversation-analyzer.ts";
3
+ import { logger } from "../logger.ts"; // Import logger
4
+ import type { CommandOptions, ReplCommand } from "./types.ts";
5
+
6
+ async function _processAndSaveRules(
7
+ newRules: string[] | null,
8
+ terminal: CommandOptions["terminal"],
9
+ config: CommandOptions["config"], // Simplified type
10
+ ) {
11
+ if (!newRules || newRules.length === 0) {
12
+ terminal.warn("No new generalizable rules were identified.");
13
+ return;
14
+ }
15
+
16
+ terminal.info("Generated potential rules:");
17
+ terminal.lineBreak();
18
+
19
+ const rulesToKeep = await checkbox({
20
+ message: "Select the rules you want to keep:",
21
+ choices: newRules.map((rule) => ({ name: rule, value: rule })),
22
+ });
23
+
24
+ if (rulesToKeep.length === 0) {
25
+ terminal.warn("No rules selected to save.");
26
+ return;
27
+ }
28
+
29
+ terminal.info("Saving selected rules...");
30
+ const existingRules = await config.readProjectLearnedRulesFile();
31
+ const rulesToAdd = rulesToKeep.join("\n");
32
+ const updatedProjectRules =
33
+ existingRules.endsWith("\n") || existingRules.length === 0
34
+ ? `${existingRules}${rulesToAdd}`
35
+ : `${existingRules}\n${rulesToAdd}`;
36
+
37
+ await config.writeProjectLearnedRulesFile(updatedProjectRules);
38
+ terminal.success("Selected rules saved to project learned rules.");
39
+ terminal.lineBreak();
40
+ terminal.display(rulesToAdd); // Display only the saved rules
41
+ }
42
+
43
+ export const generateRulesCommand = ({
44
+ terminal,
45
+ messageHistory,
46
+ modelManager,
47
+ tokenTracker,
48
+ config, // This is the config module from CommandOptions
49
+ }: CommandOptions): ReplCommand => {
50
+ return {
51
+ command: "/generate-rules",
52
+ description:
53
+ "Analyzes the current conversation to generate and save new interaction rules, then displays them.",
54
+ result: "continue" as const,
55
+ getSubCommands: () => Promise.resolve([]),
56
+ execute: async () => {
57
+ if (messageHistory.isEmpty()) {
58
+ terminal.writeln("Cannot generate rules from an empty conversation.");
59
+ return;
60
+ }
61
+
62
+ terminal.lineBreak();
63
+ terminal.info("Analyzing conversation to generate rules...");
64
+ try {
65
+ const newRules = await analyzeConversation({
66
+ modelManager,
67
+ messages: messageHistory.get(),
68
+ tokenTracker,
69
+ terminal,
70
+ });
71
+
72
+ // Pass the config object available in CommandOptions scope
73
+ await _processAndSaveRules(newRules, terminal, config);
74
+ } catch (error) {
75
+ const errorMessage =
76
+ error instanceof Error ? error.message : String(error);
77
+ terminal.error(`Error generating rules: ${errorMessage}`);
78
+ logger.error(error, "Error during rule generation:");
79
+ }
80
+ },
81
+ };
82
+ };
@@ -0,0 +1,27 @@
1
+ import type { CommandOptions, ReplCommand } from "./types.ts";
2
+
3
+ export const helpCommand = (
4
+ { terminal }: CommandOptions,
5
+ cmds: Map<string, ReplCommand>,
6
+ ): ReplCommand => {
7
+ return {
8
+ command: "/help",
9
+ description: "Shows available commands.",
10
+ result: "continue" as const,
11
+ getSubCommands: () => Promise.resolve([]),
12
+ execute: () => {
13
+ const commands = cmds;
14
+
15
+ const entries: [string, string][] = Array.from(commands.entries())
16
+ .sort(([a], [b]) => a.localeCompare(b))
17
+ .map(([key, cmd]) => [key, cmd.description]);
18
+
19
+ terminal.table(entries, {
20
+ header: ["Command", "Description"],
21
+ colWidths: [30, 70],
22
+ });
23
+
24
+ return Promise.resolve();
25
+ },
26
+ };
27
+ };
@@ -0,0 +1,48 @@
1
+ import { platform } from "node:os";
2
+ import { stepCountIs, streamText } from "ai";
3
+ import { inGitDirectory } from "../tools/git-utils.ts";
4
+ import { initTools } from "../tools/index.ts";
5
+ import type { CommandOptions, ReplCommand } from "./types.ts";
6
+
7
+ export const initCommand = ({
8
+ terminal,
9
+ modelManager,
10
+ tokenCounter,
11
+ toolEvents,
12
+ }: CommandOptions): ReplCommand => {
13
+ return {
14
+ command: "/init",
15
+ description: "Creates the AGENTS.md file.",
16
+ result: "continue" as const,
17
+ getSubCommands: () => Promise.resolve([]),
18
+ execute: async () => {
19
+ const result = streamText({
20
+ model: modelManager.getModel("init-project"),
21
+ temperature: 0.5,
22
+ prompt: `Please analyze this codebase and create a AGENTS.md file containing:
23
+ 1. Build/lint/test commands - especially for running a single test
24
+ 2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
25
+
26
+ The file you create will be given to agentic coding agents (such as yourself) that operate in this repository. Make it about 20 lines long.
27
+
28
+ If there's already a AGENTS.md, improve it.
29
+ If there are Cursor rules (in .cursor/rules/ or .cursorrules), Copilot rules (in .github/copilot-instructions.md), or Windsurf rules (in .windsurf/rules), make sure to include them.
30
+
31
+ Your current working directory is ${process.cwd()}
32
+ Is directory a git repo: ${(await inGitDirectory()) ? "Yes" : "No"}
33
+ Platform: ${platform()}`,
34
+ stopWhen: stepCountIs(40),
35
+ tools: await initTools({
36
+ terminal,
37
+ tokenCounter,
38
+ events: toolEvents,
39
+ autoAcceptAll: true,
40
+ }),
41
+ });
42
+
43
+ for await (const text of result.textStream) {
44
+ terminal.write(text);
45
+ }
46
+ },
47
+ };
48
+ };
@@ -0,0 +1,88 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { editor } from "@inquirer/prompts";
4
+ import chalk from "chalk";
5
+ import { globby } from "globby";
6
+ import { config } from "../config.ts";
7
+ import type { CommandOptions, ReplCommand } from "./types.ts";
8
+
9
+ const isoDateRegex = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)/;
10
+
11
+ // Function to find the most recent log file
12
+ async function findMostRecentLog(logDir: string): Promise<string | null> {
13
+ const logPattern = join(logDir, "*-repl-message.json");
14
+ const files = await globby(logPattern);
15
+
16
+ if (files.length === 0) {
17
+ return null;
18
+ }
19
+
20
+ const datedFiles = files
21
+ .map((file) => {
22
+ const filename = file.split("/").pop();
23
+ if (!filename) {
24
+ return null; // Skip if filename is somehow undefined
25
+ }
26
+ // Match the ISO date string at the beginning of the filename
27
+ const match = filename.match(isoDateRegex);
28
+ if (match?.[1]) {
29
+ try {
30
+ const date = new Date(match[1]);
31
+ // Check if the date is valid
32
+ if (!Number.isNaN(date.getTime())) {
33
+ return { file, date };
34
+ }
35
+ } catch (e) {
36
+ // Ignore files with invalid date strings
37
+ console.warn(`Could not parse date from filename: ${filename}`, e);
38
+ }
39
+ }
40
+ return null; // Exclude files that don't match the pattern or have invalid dates
41
+ })
42
+ .filter((item): item is { file: string; date: Date } => item !== null);
43
+
44
+ if (datedFiles.length === 0) {
45
+ return null; // No valid log files found
46
+ }
47
+
48
+ // Sort files by date (descending)
49
+ datedFiles.sort((a, b) => b.date.getTime() - a.date.getTime());
50
+
51
+ return datedFiles[0]?.file ?? null; // The first file is the most recent
52
+ }
53
+
54
+ export const lastLogCommand = ({ terminal }: CommandOptions): ReplCommand => {
55
+ return {
56
+ command: "/last-log",
57
+ description: "Opens the most recent REPL audit log in the editor.",
58
+ result: "continue" as const,
59
+ getSubCommands: () => Promise.resolve([]),
60
+ execute: async () => {
61
+ const logDir = config.app.ensurePathSync("audit");
62
+ const mostRecentLog = await findMostRecentLog(logDir);
63
+
64
+ if (!mostRecentLog) {
65
+ terminal.error(`No REPL audit logs found in '${logDir}'.`);
66
+ return;
67
+ }
68
+
69
+ try {
70
+ const content = await readFile(mostRecentLog, { encoding: "utf8" });
71
+
72
+ // Use the editor prompt to display the content (read-only)
73
+ await editor({
74
+ message: `Viewing ${chalk.green(mostRecentLog)}`,
75
+ postfix: ".json", // Set postfix for syntax highlighting if editor supports it
76
+ default: content,
77
+ // By not providing an onSubmit or similar handler to write the file,
78
+ // and not calling writeFileSync after, this effectively becomes read-only.
79
+ });
80
+ terminal.info("Closed log view");
81
+ } catch (error) {
82
+ terminal.error(
83
+ `Error reading or displaying log file ${mostRecentLog}: ${error}`,
84
+ );
85
+ }
86
+ },
87
+ };
88
+ };
@@ -0,0 +1,151 @@
1
+ import type { ConfigManager } from "../config.ts";
2
+ import type { MessageHistory } from "../messages.ts";
3
+ import type { ModelManager } from "../models/manager.ts";
4
+ import type { PromptManager } from "../prompts/manager.ts";
5
+ import type { Terminal } from "../terminal/index.ts";
6
+ import type { TokenTracker } from "../token-tracker.ts";
7
+ import type { TokenCounter } from "../token-utils.ts";
8
+ import type { Message } from "../tools/types.ts";
9
+ import { applicationLogCommand } from "./application-log-command.ts";
10
+ import { clearCommand } from "./clear-command.ts";
11
+ import { compactCommand } from "./compact-command.ts";
12
+ import { copyCommand } from "./copy-command.ts";
13
+ import { editCommand } from "./edit-command.ts";
14
+ import { editPromptCommand } from "./edit-prompt-command.ts";
15
+ import { exitCommand } from "./exit-command.ts";
16
+ import { filesCommand } from "./files-command.ts";
17
+ import { generateRulesCommand } from "./generate-rules-command.ts";
18
+ import { helpCommand } from "./help-command.ts";
19
+ import { initCommand } from "./init-command.ts";
20
+ import { lastLogCommand } from "./last-log-command.ts";
21
+ import { modelCommand } from "./model-command.ts";
22
+ import { pasteCommand } from "./paste-command.ts";
23
+ import { promptCommand } from "./prompt-command.ts";
24
+ import { resetCommand } from "./reset-command.ts";
25
+ import { rulesCommand } from "./rules-command.ts";
26
+ import { saveCommand } from "./save-command.ts";
27
+ import type { CommandOptions, ReplCommand } from "./types.ts";
28
+ import { usageCommand } from "./usage-command.ts";
29
+
30
+ export class CommandManager {
31
+ private commands: Map<string, ReplCommand>;
32
+ private promptManager: PromptManager;
33
+ private modelManager: ModelManager;
34
+ private messageHistory: MessageHistory;
35
+ private tokenTracker: TokenTracker;
36
+ private terminal: Terminal;
37
+ private config: ConfigManager;
38
+ private tokenCounter: TokenCounter;
39
+ private toolEvents: Map<string, Message[]>;
40
+
41
+ constructor({
42
+ promptManager,
43
+ modelManager,
44
+ terminal,
45
+ messageHistory,
46
+ tokenTracker,
47
+ config,
48
+ tokenCounter,
49
+ toolEvents,
50
+ }: CommandOptions) {
51
+ this.commands = new Map();
52
+ this.promptManager = promptManager;
53
+ this.modelManager = modelManager;
54
+ this.terminal = terminal;
55
+ this.messageHistory = messageHistory;
56
+ this.tokenTracker = tokenTracker;
57
+ this.config = config;
58
+ this.tokenCounter = tokenCounter;
59
+ this.toolEvents = toolEvents;
60
+ this.initializeCommmands();
61
+ }
62
+
63
+ initializeCommmands() {
64
+ // Import and register each command
65
+ const options: CommandOptions = {
66
+ promptManager: this.promptManager,
67
+ modelManager: this.modelManager,
68
+ terminal: this.terminal,
69
+ messageHistory: this.messageHistory,
70
+ tokenTracker: this.tokenTracker,
71
+ config: this.config,
72
+ tokenCounter: this.tokenCounter,
73
+ toolEvents: this.toolEvents,
74
+ };
75
+
76
+ // Register all commands
77
+ const cmds = [
78
+ clearCommand(options),
79
+ compactCommand(options),
80
+ editCommand(options),
81
+ editPromptCommand(options),
82
+ exitCommand(options),
83
+ filesCommand(options),
84
+ initCommand(options),
85
+ pasteCommand(options),
86
+ promptCommand(options),
87
+ resetCommand(options),
88
+ saveCommand(options),
89
+ rulesCommand(options),
90
+ modelCommand(options),
91
+ usageCommand(options),
92
+ lastLogCommand(options),
93
+ generateRulesCommand(options),
94
+ applicationLogCommand(options),
95
+ copyCommand(options),
96
+ ];
97
+
98
+ // Add help command with access to all commands
99
+ const helpCmd = helpCommand(options, this.commands);
100
+ cmds.push({
101
+ ...helpCmd,
102
+ execute: () => helpCmd.execute([]),
103
+ });
104
+
105
+ // Register all commands
106
+ for (const cmd of cmds) {
107
+ this.commands.set(cmd.command, cmd);
108
+ const aliases: string[] = cmd.aliases ?? [];
109
+ for (const alias of aliases) {
110
+ this.commands.set(alias, cmd);
111
+ }
112
+ }
113
+ }
114
+
115
+ getCommands() {
116
+ return Array.from(this.commands.keys()).sort();
117
+ }
118
+
119
+ async getSubCommands(command: string): Promise<string[]> {
120
+ return (await this.commands.get(command)?.getSubCommands()) ?? [];
121
+ }
122
+
123
+ async handle({ userInput }: { userInput: string }) {
124
+ const commandArgs = userInput.split(" ");
125
+ const command = commandArgs.at(0);
126
+ const args = commandArgs.slice(1);
127
+
128
+ if (command) {
129
+ const replCommand = this.commands.get(command);
130
+ if (replCommand) {
131
+ await replCommand.execute(args);
132
+ if (replCommand.result === "continue") {
133
+ return {
134
+ continue: true,
135
+ break: false,
136
+ };
137
+ }
138
+ if (replCommand.result === "break") {
139
+ return {
140
+ continue: false,
141
+ break: true,
142
+ };
143
+ }
144
+ }
145
+ }
146
+ return {
147
+ continue: false,
148
+ break: false,
149
+ };
150
+ }
151
+ }