@vybestack/llxprt-code-tools 0.10.0-nightly.260613.1adad3b34

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 (364) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +294 -0
  3. package/dist/.last_build +0 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.js +2 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.d.ts +29 -0
  8. package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.js +30 -0
  9. package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.js.map +1 -0
  10. package/dist/src/__tests__/fixtures/key-storage-fixtures.d.ts +39 -0
  11. package/dist/src/__tests__/fixtures/key-storage-fixtures.js +53 -0
  12. package/dist/src/__tests__/fixtures/key-storage-fixtures.js.map +1 -0
  13. package/dist/src/__tests__/fixtures/provider-formatting-fixtures.d.ts +140 -0
  14. package/dist/src/__tests__/fixtures/provider-formatting-fixtures.js +157 -0
  15. package/dist/src/__tests__/fixtures/provider-formatting-fixtures.js.map +1 -0
  16. package/dist/src/__tests__/red-test-helpers.d.ts +14 -0
  17. package/dist/src/__tests__/red-test-helpers.js +18 -0
  18. package/dist/src/__tests__/red-test-helpers.js.map +1 -0
  19. package/dist/src/formatters/IToolFormatter.d.ts +84 -0
  20. package/dist/src/formatters/IToolFormatter.js +6 -0
  21. package/dist/src/formatters/IToolFormatter.js.map +1 -0
  22. package/dist/src/formatters/ToolFormatter.d.ts +94 -0
  23. package/dist/src/formatters/ToolFormatter.js +379 -0
  24. package/dist/src/formatters/ToolFormatter.js.map +1 -0
  25. package/dist/src/formatters/ToolIdStrategy.d.ts +79 -0
  26. package/dist/src/formatters/ToolIdStrategy.js +173 -0
  27. package/dist/src/formatters/ToolIdStrategy.js.map +1 -0
  28. package/dist/src/formatters/doubleEscapeUtils.d.ts +46 -0
  29. package/dist/src/formatters/doubleEscapeUtils.js +223 -0
  30. package/dist/src/formatters/doubleEscapeUtils.js.map +1 -0
  31. package/dist/src/formatters/index.d.ts +21 -0
  32. package/dist/src/formatters/index.js +12 -0
  33. package/dist/src/formatters/index.js.map +1 -0
  34. package/dist/src/formatters/toolIdNormalization.d.ts +28 -0
  35. package/dist/src/formatters/toolIdNormalization.js +97 -0
  36. package/dist/src/formatters/toolIdNormalization.js.map +1 -0
  37. package/dist/src/formatters/toolNameUtils.d.ts +43 -0
  38. package/dist/src/formatters/toolNameUtils.js +143 -0
  39. package/dist/src/formatters/toolNameUtils.js.map +1 -0
  40. package/dist/src/index.d.ts +88 -0
  41. package/dist/src/index.js +68 -0
  42. package/dist/src/index.js.map +1 -0
  43. package/dist/src/interfaces/IAsyncTaskService.d.ts +57 -0
  44. package/dist/src/interfaces/IAsyncTaskService.js +6 -0
  45. package/dist/src/interfaces/IAsyncTaskService.js.map +1 -0
  46. package/dist/src/interfaces/IIdeService.d.ts +62 -0
  47. package/dist/src/interfaces/IIdeService.js +6 -0
  48. package/dist/src/interfaces/IIdeService.js.map +1 -0
  49. package/dist/src/interfaces/ILspService.d.ts +54 -0
  50. package/dist/src/interfaces/ILspService.js +6 -0
  51. package/dist/src/interfaces/ILspService.js.map +1 -0
  52. package/dist/src/interfaces/IMcpToolService.d.ts +47 -0
  53. package/dist/src/interfaces/IMcpToolService.js +6 -0
  54. package/dist/src/interfaces/IMcpToolService.js.map +1 -0
  55. package/dist/src/interfaces/IPromptRegistryService.d.ts +51 -0
  56. package/dist/src/interfaces/IPromptRegistryService.js +6 -0
  57. package/dist/src/interfaces/IPromptRegistryService.js.map +1 -0
  58. package/dist/src/interfaces/ISettingsService.d.ts +50 -0
  59. package/dist/src/interfaces/ISettingsService.js +6 -0
  60. package/dist/src/interfaces/ISettingsService.js.map +1 -0
  61. package/dist/src/interfaces/IShellExecutionService.d.ts +55 -0
  62. package/dist/src/interfaces/IShellExecutionService.js +6 -0
  63. package/dist/src/interfaces/IShellExecutionService.js.map +1 -0
  64. package/dist/src/interfaces/IShellToolHost.d.ts +176 -0
  65. package/dist/src/interfaces/IShellToolHost.js +6 -0
  66. package/dist/src/interfaces/IShellToolHost.js.map +1 -0
  67. package/dist/src/interfaces/ISkillService.d.ts +69 -0
  68. package/dist/src/interfaces/ISkillService.js +6 -0
  69. package/dist/src/interfaces/ISkillService.js.map +1 -0
  70. package/dist/src/interfaces/IStorageService.d.ts +42 -0
  71. package/dist/src/interfaces/IStorageService.js +6 -0
  72. package/dist/src/interfaces/IStorageService.js.map +1 -0
  73. package/dist/src/interfaces/ISubagentService.d.ts +112 -0
  74. package/dist/src/interfaces/ISubagentService.js +6 -0
  75. package/dist/src/interfaces/ISubagentService.js.map +1 -0
  76. package/dist/src/interfaces/ITaskToolHost.d.ts +185 -0
  77. package/dist/src/interfaces/ITaskToolHost.js +6 -0
  78. package/dist/src/interfaces/ITaskToolHost.js.map +1 -0
  79. package/dist/src/interfaces/ITodoService.d.ts +79 -0
  80. package/dist/src/interfaces/ITodoService.js +6 -0
  81. package/dist/src/interfaces/ITodoService.js.map +1 -0
  82. package/dist/src/interfaces/IToolHost.d.ts +91 -0
  83. package/dist/src/interfaces/IToolHost.js +6 -0
  84. package/dist/src/interfaces/IToolHost.js.map +1 -0
  85. package/dist/src/interfaces/IToolKeyStorage.d.ts +62 -0
  86. package/dist/src/interfaces/IToolKeyStorage.js +6 -0
  87. package/dist/src/interfaces/IToolKeyStorage.js.map +1 -0
  88. package/dist/src/interfaces/IToolMessageBus.d.ts +63 -0
  89. package/dist/src/interfaces/IToolMessageBus.js +6 -0
  90. package/dist/src/interfaces/IToolMessageBus.js.map +1 -0
  91. package/dist/src/interfaces/IToolRegistryHost.d.ts +43 -0
  92. package/dist/src/interfaces/IToolRegistryHost.js +6 -0
  93. package/dist/src/interfaces/IToolRegistryHost.js.map +1 -0
  94. package/dist/src/interfaces/IWebSearchService.d.ts +16 -0
  95. package/dist/src/interfaces/IWebSearchService.js +7 -0
  96. package/dist/src/interfaces/IWebSearchService.js.map +1 -0
  97. package/dist/src/interfaces/index.d.ts +33 -0
  98. package/dist/src/interfaces/index.js +6 -0
  99. package/dist/src/interfaces/index.js.map +1 -0
  100. package/dist/src/tools/activate-skill.d.ts +26 -0
  101. package/dist/src/tools/activate-skill.js +121 -0
  102. package/dist/src/tools/activate-skill.js.map +1 -0
  103. package/dist/src/tools/apply-patch.d.ts +65 -0
  104. package/dist/src/tools/apply-patch.js +528 -0
  105. package/dist/src/tools/apply-patch.js.map +1 -0
  106. package/dist/src/tools/ast-edit/ast-config.d.ts +67 -0
  107. package/dist/src/tools/ast-edit/ast-config.js +72 -0
  108. package/dist/src/tools/ast-edit/ast-config.js.map +1 -0
  109. package/dist/src/tools/ast-edit/ast-edit-invocation.d.ts +40 -0
  110. package/dist/src/tools/ast-edit/ast-edit-invocation.js +410 -0
  111. package/dist/src/tools/ast-edit/ast-edit-invocation.js.map +1 -0
  112. package/dist/src/tools/ast-edit/ast-query-extractor.d.ts +21 -0
  113. package/dist/src/tools/ast-edit/ast-query-extractor.js +178 -0
  114. package/dist/src/tools/ast-edit/ast-query-extractor.js.map +1 -0
  115. package/dist/src/tools/ast-edit/ast-read-file-invocation.d.ts +26 -0
  116. package/dist/src/tools/ast-edit/ast-read-file-invocation.js +149 -0
  117. package/dist/src/tools/ast-edit/ast-read-file-invocation.js.map +1 -0
  118. package/dist/src/tools/ast-edit/constants.d.ts +30 -0
  119. package/dist/src/tools/ast-edit/constants.js +36 -0
  120. package/dist/src/tools/ast-edit/constants.js.map +1 -0
  121. package/dist/src/tools/ast-edit/context-collector.d.ts +25 -0
  122. package/dist/src/tools/ast-edit/context-collector.js +115 -0
  123. package/dist/src/tools/ast-edit/context-collector.js.map +1 -0
  124. package/dist/src/tools/ast-edit/context-optimizer.d.ts +29 -0
  125. package/dist/src/tools/ast-edit/context-optimizer.js +86 -0
  126. package/dist/src/tools/ast-edit/context-optimizer.js.map +1 -0
  127. package/dist/src/tools/ast-edit/cross-file-analyzer.d.ts +41 -0
  128. package/dist/src/tools/ast-edit/cross-file-analyzer.js +294 -0
  129. package/dist/src/tools/ast-edit/cross-file-analyzer.js.map +1 -0
  130. package/dist/src/tools/ast-edit/edit-calculator.d.ts +71 -0
  131. package/dist/src/tools/ast-edit/edit-calculator.js +249 -0
  132. package/dist/src/tools/ast-edit/edit-calculator.js.map +1 -0
  133. package/dist/src/tools/ast-edit/edit-helpers.d.ts +22 -0
  134. package/dist/src/tools/ast-edit/edit-helpers.js +36 -0
  135. package/dist/src/tools/ast-edit/edit-helpers.js.map +1 -0
  136. package/dist/src/tools/ast-edit/language-analysis.d.ts +19 -0
  137. package/dist/src/tools/ast-edit/language-analysis.js +123 -0
  138. package/dist/src/tools/ast-edit/language-analysis.js.map +1 -0
  139. package/dist/src/tools/ast-edit/local-context-analyzer.d.ts +84 -0
  140. package/dist/src/tools/ast-edit/local-context-analyzer.js +267 -0
  141. package/dist/src/tools/ast-edit/local-context-analyzer.js.map +1 -0
  142. package/dist/src/tools/ast-edit/repository-context-provider.d.ts +22 -0
  143. package/dist/src/tools/ast-edit/repository-context-provider.js +139 -0
  144. package/dist/src/tools/ast-edit/repository-context-provider.js.map +1 -0
  145. package/dist/src/tools/ast-edit/types.d.ts +155 -0
  146. package/dist/src/tools/ast-edit/types.js +7 -0
  147. package/dist/src/tools/ast-edit/types.js.map +1 -0
  148. package/dist/src/tools/ast-edit/workspace-context-provider.d.ts +22 -0
  149. package/dist/src/tools/ast-edit/workspace-context-provider.js +39 -0
  150. package/dist/src/tools/ast-edit/workspace-context-provider.js.map +1 -0
  151. package/dist/src/tools/ast-edit.d.ts +43 -0
  152. package/dist/src/tools/ast-edit.js +183 -0
  153. package/dist/src/tools/ast-edit.js.map +1 -0
  154. package/dist/src/tools/ast-grep.d.ts +22 -0
  155. package/dist/src/tools/ast-grep.js +291 -0
  156. package/dist/src/tools/ast-grep.js.map +1 -0
  157. package/dist/src/tools/check-async-tasks.d.ts +46 -0
  158. package/dist/src/tools/check-async-tasks.js +241 -0
  159. package/dist/src/tools/check-async-tasks.js.map +1 -0
  160. package/dist/src/tools/codesearch.d.ts +25 -0
  161. package/dist/src/tools/codesearch.js +153 -0
  162. package/dist/src/tools/codesearch.js.map +1 -0
  163. package/dist/src/tools/delete_line_range.d.ts +41 -0
  164. package/dist/src/tools/delete_line_range.js +238 -0
  165. package/dist/src/tools/delete_line_range.js.map +1 -0
  166. package/dist/src/tools/direct-web-fetch.d.ts +22 -0
  167. package/dist/src/tools/direct-web-fetch.js +215 -0
  168. package/dist/src/tools/direct-web-fetch.js.map +1 -0
  169. package/dist/src/tools/edit-utils.d.ts +53 -0
  170. package/dist/src/tools/edit-utils.js +250 -0
  171. package/dist/src/tools/edit-utils.js.map +1 -0
  172. package/dist/src/tools/edit.d.ts +70 -0
  173. package/dist/src/tools/edit.js +816 -0
  174. package/dist/src/tools/edit.js.map +1 -0
  175. package/dist/src/tools/exa-web-search.d.ts +27 -0
  176. package/dist/src/tools/exa-web-search.js +153 -0
  177. package/dist/src/tools/exa-web-search.js.map +1 -0
  178. package/dist/src/tools/glob.d.ts +55 -0
  179. package/dist/src/tools/glob.js +284 -0
  180. package/dist/src/tools/glob.js.map +1 -0
  181. package/dist/src/tools/google-web-fetch.d.ts +34 -0
  182. package/dist/src/tools/google-web-fetch.js +417 -0
  183. package/dist/src/tools/google-web-fetch.js.map +1 -0
  184. package/dist/src/tools/google-web-search-invocation.d.ts +53 -0
  185. package/dist/src/tools/google-web-search-invocation.js +180 -0
  186. package/dist/src/tools/google-web-search-invocation.js.map +1 -0
  187. package/dist/src/tools/google-web-search.d.ts +16 -0
  188. package/dist/src/tools/google-web-search.js +34 -0
  189. package/dist/src/tools/google-web-search.js.map +1 -0
  190. package/dist/src/tools/grep.d.ts +56 -0
  191. package/dist/src/tools/grep.js +883 -0
  192. package/dist/src/tools/grep.js.map +1 -0
  193. package/dist/src/tools/insert_at_line.d.ts +41 -0
  194. package/dist/src/tools/insert_at_line.js +287 -0
  195. package/dist/src/tools/insert_at_line.js.map +1 -0
  196. package/dist/src/tools/list-subagents.d.ts +31 -0
  197. package/dist/src/tools/list-subagents.js +122 -0
  198. package/dist/src/tools/list-subagents.js.map +1 -0
  199. package/dist/src/tools/ls.d.ts +71 -0
  200. package/dist/src/tools/ls.js +238 -0
  201. package/dist/src/tools/ls.js.map +1 -0
  202. package/dist/src/tools/memoryTool.d.ts +66 -0
  203. package/dist/src/tools/memoryTool.js +435 -0
  204. package/dist/src/tools/memoryTool.js.map +1 -0
  205. package/dist/src/tools/modifiable-tool.d.ts +37 -0
  206. package/dist/src/tools/modifiable-tool.js +120 -0
  207. package/dist/src/tools/modifiable-tool.js.map +1 -0
  208. package/dist/src/tools/read-file.d.ts +49 -0
  209. package/dist/src/tools/read-file.js +279 -0
  210. package/dist/src/tools/read-file.js.map +1 -0
  211. package/dist/src/tools/read-many-files.d.ts +60 -0
  212. package/dist/src/tools/read-many-files.js +529 -0
  213. package/dist/src/tools/read-many-files.js.map +1 -0
  214. package/dist/src/tools/read_line_range.d.ts +47 -0
  215. package/dist/src/tools/read_line_range.js +248 -0
  216. package/dist/src/tools/read_line_range.js.map +1 -0
  217. package/dist/src/tools/ripGrep.d.ts +41 -0
  218. package/dist/src/tools/ripGrep.js +395 -0
  219. package/dist/src/tools/ripGrep.js.map +1 -0
  220. package/dist/src/tools/shell.d.ts +60 -0
  221. package/dist/src/tools/shell.js +735 -0
  222. package/dist/src/tools/shell.js.map +1 -0
  223. package/dist/src/tools/structural-analysis.d.ts +27 -0
  224. package/dist/src/tools/structural-analysis.js +1089 -0
  225. package/dist/src/tools/structural-analysis.js.map +1 -0
  226. package/dist/src/tools/stubs.d.ts +10 -0
  227. package/dist/src/tools/stubs.js +6 -0
  228. package/dist/src/tools/stubs.js.map +1 -0
  229. package/dist/src/tools/task.d.ts +41 -0
  230. package/dist/src/tools/task.js +195 -0
  231. package/dist/src/tools/task.js.map +1 -0
  232. package/dist/src/tools/todo-events.d.ts +22 -0
  233. package/dist/src/tools/todo-events.js +24 -0
  234. package/dist/src/tools/todo-events.js.map +1 -0
  235. package/dist/src/tools/todo-pause.d.ts +29 -0
  236. package/dist/src/tools/todo-pause.js +172 -0
  237. package/dist/src/tools/todo-pause.js.map +1 -0
  238. package/dist/src/tools/todo-read.d.ts +18 -0
  239. package/dist/src/tools/todo-read.js +98 -0
  240. package/dist/src/tools/todo-read.js.map +1 -0
  241. package/dist/src/tools/todo-store.d.ts +35 -0
  242. package/dist/src/tools/todo-store.js +124 -0
  243. package/dist/src/tools/todo-store.js.map +1 -0
  244. package/dist/src/tools/todo-write.d.ts +29 -0
  245. package/dist/src/tools/todo-write.js +366 -0
  246. package/dist/src/tools/todo-write.js.map +1 -0
  247. package/dist/src/tools/tool-registry.d.ts +156 -0
  248. package/dist/src/tools/tool-registry.js +623 -0
  249. package/dist/src/tools/tool-registry.js.map +1 -0
  250. package/dist/src/tools/tools.d.ts +403 -0
  251. package/dist/src/tools/tools.js +519 -0
  252. package/dist/src/tools/tools.js.map +1 -0
  253. package/dist/src/tools/write-file.d.ts +45 -0
  254. package/dist/src/tools/write-file.js +320 -0
  255. package/dist/src/tools/write-file.js.map +1 -0
  256. package/dist/src/types/index.d.ts +17 -0
  257. package/dist/src/types/index.js +9 -0
  258. package/dist/src/types/index.js.map +1 -0
  259. package/dist/src/types/provider-content-types.d.ts +56 -0
  260. package/dist/src/types/provider-content-types.js +6 -0
  261. package/dist/src/types/provider-content-types.js.map +1 -0
  262. package/dist/src/types/todo-schemas.d.ts +263 -0
  263. package/dist/src/types/todo-schemas.js +32 -0
  264. package/dist/src/types/todo-schemas.js.map +1 -0
  265. package/dist/src/types/tool-confirmation-types.d.ts +34 -0
  266. package/dist/src/types/tool-confirmation-types.js +29 -0
  267. package/dist/src/types/tool-confirmation-types.js.map +1 -0
  268. package/dist/src/types/tool-context.d.ts +31 -0
  269. package/dist/src/types/tool-context.js +6 -0
  270. package/dist/src/types/tool-context.js.map +1 -0
  271. package/dist/src/types/tool-error.d.ts +69 -0
  272. package/dist/src/types/tool-error.js +94 -0
  273. package/dist/src/types/tool-error.js.map +1 -0
  274. package/dist/src/types/tool-names.d.ts +57 -0
  275. package/dist/src/types/tool-names.js +64 -0
  276. package/dist/src/types/tool-names.js.map +1 -0
  277. package/dist/src/utils/EmojiFilter.d.ts +134 -0
  278. package/dist/src/utils/EmojiFilter.js +370 -0
  279. package/dist/src/utils/EmojiFilter.js.map +1 -0
  280. package/dist/src/utils/ast-grep-utils.d.ts +42 -0
  281. package/dist/src/utils/ast-grep-utils.js +140 -0
  282. package/dist/src/utils/ast-grep-utils.js.map +1 -0
  283. package/dist/src/utils/debugLogger.d.ts +11 -0
  284. package/dist/src/utils/debugLogger.js +16 -0
  285. package/dist/src/utils/debugLogger.js.map +1 -0
  286. package/dist/src/utils/diffOptions.d.ts +14 -0
  287. package/dist/src/utils/diffOptions.js +46 -0
  288. package/dist/src/utils/diffOptions.js.map +1 -0
  289. package/dist/src/utils/editor.d.ts +39 -0
  290. package/dist/src/utils/editor.js +212 -0
  291. package/dist/src/utils/editor.js.map +1 -0
  292. package/dist/src/utils/ensure-dirs.d.ts +10 -0
  293. package/dist/src/utils/ensure-dirs.js +16 -0
  294. package/dist/src/utils/ensure-dirs.js.map +1 -0
  295. package/dist/src/utils/errors.d.ts +59 -0
  296. package/dist/src/utils/errors.js +178 -0
  297. package/dist/src/utils/errors.js.map +1 -0
  298. package/dist/src/utils/fetch.d.ts +11 -0
  299. package/dist/src/utils/fetch.js +74 -0
  300. package/dist/src/utils/fetch.js.map +1 -0
  301. package/dist/src/utils/fileUtils.d.ts +32 -0
  302. package/dist/src/utils/fileUtils.js +363 -0
  303. package/dist/src/utils/fileUtils.js.map +1 -0
  304. package/dist/src/utils/fuzzy-replacer.d.ts +61 -0
  305. package/dist/src/utils/fuzzy-replacer.js +492 -0
  306. package/dist/src/utils/fuzzy-replacer.js.map +1 -0
  307. package/dist/src/utils/gitLineChanges.d.ts +12 -0
  308. package/dist/src/utils/gitLineChanges.js +171 -0
  309. package/dist/src/utils/gitLineChanges.js.map +1 -0
  310. package/dist/src/utils/gitUtils.d.ts +6 -0
  311. package/dist/src/utils/gitUtils.js +31 -0
  312. package/dist/src/utils/gitUtils.js.map +1 -0
  313. package/dist/src/utils/lsp-diagnostics-helper.d.ts +27 -0
  314. package/dist/src/utils/lsp-diagnostics-helper.js +62 -0
  315. package/dist/src/utils/lsp-diagnostics-helper.js.map +1 -0
  316. package/dist/src/utils/mediaUtils.d.ts +38 -0
  317. package/dist/src/utils/mediaUtils.js +22 -0
  318. package/dist/src/utils/mediaUtils.js.map +1 -0
  319. package/dist/src/utils/pathValidation.d.ts +7 -0
  320. package/dist/src/utils/pathValidation.js +39 -0
  321. package/dist/src/utils/pathValidation.js.map +1 -0
  322. package/dist/src/utils/paths.d.ts +7 -0
  323. package/dist/src/utils/paths.js +158 -0
  324. package/dist/src/utils/paths.js.map +1 -0
  325. package/dist/src/utils/resolveTextSearchTarget.d.ts +17 -0
  326. package/dist/src/utils/resolveTextSearchTarget.js +45 -0
  327. package/dist/src/utils/resolveTextSearchTarget.js.map +1 -0
  328. package/dist/src/utils/retry.d.ts +17 -0
  329. package/dist/src/utils/retry.js +185 -0
  330. package/dist/src/utils/retry.js.map +1 -0
  331. package/dist/src/utils/ripgrepPathResolver.d.ts +23 -0
  332. package/dist/src/utils/ripgrepPathResolver.js +179 -0
  333. package/dist/src/utils/ripgrepPathResolver.js.map +1 -0
  334. package/dist/src/utils/safeJsonStringify.d.ts +9 -0
  335. package/dist/src/utils/safeJsonStringify.js +21 -0
  336. package/dist/src/utils/safeJsonStringify.js.map +1 -0
  337. package/dist/src/utils/schemaValidator.d.ts +13 -0
  338. package/dist/src/utils/schemaValidator.js +275 -0
  339. package/dist/src/utils/schemaValidator.js.map +1 -0
  340. package/dist/src/utils/terminalSerializer.d.ts +33 -0
  341. package/dist/src/utils/terminalSerializer.js +6 -0
  342. package/dist/src/utils/terminalSerializer.js.map +1 -0
  343. package/dist/src/utils/todoContextTracker.d.ts +12 -0
  344. package/dist/src/utils/todoContextTracker.js +28 -0
  345. package/dist/src/utils/todoContextTracker.js.map +1 -0
  346. package/dist/src/utils/todoFormatter.d.ts +24 -0
  347. package/dist/src/utils/todoFormatter.js +157 -0
  348. package/dist/src/utils/todoFormatter.js.map +1 -0
  349. package/dist/src/utils/todoReminderService.d.ts +22 -0
  350. package/dist/src/utils/todoReminderService.js +43 -0
  351. package/dist/src/utils/todoReminderService.js.map +1 -0
  352. package/dist/src/utils/tool-key-storage-facade.d.ts +32 -0
  353. package/dist/src/utils/tool-key-storage-facade.js +56 -0
  354. package/dist/src/utils/tool-key-storage-facade.js.map +1 -0
  355. package/dist/src/utils/tool-key-storage-types.d.ts +56 -0
  356. package/dist/src/utils/tool-key-storage-types.js +56 -0
  357. package/dist/src/utils/tool-key-storage-types.js.map +1 -0
  358. package/dist/src/utils/toolOutputLimiter.d.ts +29 -0
  359. package/dist/src/utils/toolOutputLimiter.js +107 -0
  360. package/dist/src/utils/toolOutputLimiter.js.map +1 -0
  361. package/dist/src/utils/unicodeUtils.d.ts +55 -0
  362. package/dist/src/utils/unicodeUtils.js +129 -0
  363. package/dist/src/utils/unicodeUtils.js.map +1 -0
  364. package/package.json +75 -0
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { BaseTool, Kind } from './tools.js';
7
+ import { TodoStore } from './todo-store.js';
8
+ import { Type } from '@google/genai';
9
+ import { TodoReminderService } from '../utils/todoReminderService.js';
10
+ import { formatTodoListForDisplay } from '../utils/todoFormatter.js';
11
+ export class TodoRead extends BaseTool {
12
+ todoService;
13
+ static Name = 'todo_read';
14
+ reminderService = new TodoReminderService();
15
+ constructor(todoService) {
16
+ super(TodoRead.Name, 'TodoRead', 'Read the current todo list for the session. Returns all todos with their status and content.', Kind.Think, {
17
+ type: Type.OBJECT,
18
+ properties: {},
19
+ }, true, // isOutputMarkdown
20
+ false);
21
+ this.todoService = todoService;
22
+ }
23
+ getDescription(_params) {
24
+ return 'Read current todo list';
25
+ }
26
+ async execute(_params, _signal, _updateOutput) {
27
+ // Get session and agent IDs from context
28
+ const sessionId = this.context?.sessionId ?? 'default';
29
+ const agentId = this.context?.agentId;
30
+ const store = this.todoService?.getTodoStore(this.context);
31
+ const rawTodos = store?.readTodos
32
+ ? await store.readTodos()
33
+ : store?.getTodos
34
+ ? store.getTodos()
35
+ : await new TodoStore(sessionId, agentId).readTodos();
36
+ const todos = rawTodos;
37
+ const paused = store?.readPausedState
38
+ ? await store.readPausedState()
39
+ : false;
40
+ const output = formatTodoListForDisplay(todos) +
41
+ (paused ? '\\n\\nAI execution is paused.' : '');
42
+ if (todos.length === 0) {
43
+ const isComplexTask = false;
44
+ const reminder = this.reminderService.getReminderForEmptyTodos(isComplexTask);
45
+ return {
46
+ llmContent: output +
47
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional falsy coalescing: empty reminder string should not be concatenated
48
+ (reminder || ''),
49
+ returnDisplay: output,
50
+ };
51
+ }
52
+ // Calculate metadata
53
+ const statistics = this.calculateStatistics(todos);
54
+ const suggestedAction = this.determineSuggestedAction(todos);
55
+ return {
56
+ llmContent: output,
57
+ returnDisplay: output,
58
+ metadata: {
59
+ totalTasks: todos.length,
60
+ statistics,
61
+ suggestedAction,
62
+ },
63
+ };
64
+ }
65
+ calculateStatistics(todos) {
66
+ return {
67
+ total: todos.length,
68
+ inProgress: todos.filter((t) => t.status === 'in_progress').length,
69
+ pending: todos.filter((t) => t.status === 'pending').length,
70
+ completed: todos.filter((t) => t.status === 'completed').length,
71
+ };
72
+ }
73
+ determineSuggestedAction(todos) {
74
+ // Check if any tasks are in progress - return first one (preserves LLM order)
75
+ const inProgressTasks = todos.filter((t) => t.status === 'in_progress');
76
+ if (inProgressTasks.length > 0) {
77
+ const task = inProgressTasks[0];
78
+ return {
79
+ type: 'continue',
80
+ taskId: task.id,
81
+ taskContent: task.content,
82
+ };
83
+ }
84
+ // Check if any tasks are pending - return first one (preserves LLM order)
85
+ const pendingTasks = todos.filter((t) => t.status === 'pending');
86
+ if (pendingTasks.length > 0) {
87
+ const task = pendingTasks[0];
88
+ return {
89
+ type: 'start',
90
+ taskId: task.id,
91
+ taskContent: task.content,
92
+ };
93
+ }
94
+ // All tasks are completed
95
+ return { type: 'all-complete' };
96
+ }
97
+ }
98
+ //# sourceMappingURL=todo-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo-read.js","sourceRoot":"","sources":["../../../src/tools/todo-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type Todo } from '../types/todo-schemas.js';
7
+ export declare const DEFAULT_AGENT_ID = "primary";
8
+ export declare class TodoStore {
9
+ private readonly filePath;
10
+ constructor(sessionId: string, agentId?: string);
11
+ /**
12
+ * Parse file content handling both legacy (array) and new ({ todos, paused }) task formats.
13
+ */
14
+ private parseFileContent;
15
+ /**
16
+ * Read the full file data including todos and paused state.
17
+ */
18
+ private readFileData;
19
+ /**
20
+ * Write the full file data including todos and paused state.
21
+ */
22
+ private writeFileData;
23
+ readTodos(): Promise<Todo[]>;
24
+ writeTodos(todos: Todo[]): Promise<void>;
25
+ /**
26
+ * Read the paused state from the task file.
27
+ * Returns false if file doesn't exist or is in legacy format.
28
+ */
29
+ readPausedState(): Promise<boolean>;
30
+ /**
31
+ * Write the paused state to the task file.
32
+ * Preserves existing todos.
33
+ */
34
+ writePausedState(paused: boolean): Promise<void>;
35
+ }
@@ -0,0 +1,124 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { TodoArraySchema } from '../types/todo-schemas.js';
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as os from 'os';
10
+ export const DEFAULT_AGENT_ID = 'primary';
11
+ export class TodoStore {
12
+ filePath;
13
+ constructor(sessionId, agentId) {
14
+ const todoDir = path.join(os.homedir(), '.llxprt', 'todos');
15
+ // Ensure directory exists
16
+ fs.mkdirSync(todoDir, { recursive: true });
17
+ const scopedAgentId = agentId && agentId !== DEFAULT_AGENT_ID ? agentId : undefined;
18
+ // Create filename based on session and agent
19
+ const fileName = scopedAgentId
20
+ ? `todo-${sessionId}-${scopedAgentId}.json`
21
+ : `todo-${sessionId}.json`;
22
+ this.filePath = path.join(todoDir, fileName);
23
+ }
24
+ /**
25
+ * Parse file content handling both legacy (array) and new ({ todos, paused }) task formats.
26
+ */
27
+ parseFileContent(content) {
28
+ const rawData = JSON.parse(content);
29
+ // Check if it's the new format (object with todos property)
30
+ if (
31
+ // eslint-disable-next-line sonarjs/expression-complexity -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
32
+ rawData != null &&
33
+ rawData !== false &&
34
+ rawData !== 0 &&
35
+ rawData !== '' &&
36
+ !Number.isNaN(rawData) &&
37
+ typeof rawData === 'object' &&
38
+ !Array.isArray(rawData) &&
39
+ 'todos' in rawData) {
40
+ const todosResult = TodoArraySchema.safeParse(rawData.todos);
41
+ if (todosResult.success) {
42
+ return {
43
+ todos: todosResult.data,
44
+ paused: rawData.paused === true,
45
+ };
46
+ }
47
+ }
48
+ // Legacy format: just an array of todos
49
+ const todosResult = TodoArraySchema.safeParse(rawData);
50
+ if (todosResult.success) {
51
+ return {
52
+ todos: todosResult.data,
53
+ paused: false,
54
+ };
55
+ }
56
+ // Invalid format
57
+ return { todos: [], paused: false };
58
+ }
59
+ /**
60
+ * Read the full file data including todos and paused state.
61
+ */
62
+ async readFileData() {
63
+ try {
64
+ if (!fs.existsSync(this.filePath)) {
65
+ return { todos: [], paused: false };
66
+ }
67
+ const content = await fs.promises.readFile(this.filePath, 'utf8');
68
+ return this.parseFileContent(content);
69
+ }
70
+ catch {
71
+ // Reading persisted task-list data failed; return empty state.
72
+ return { todos: [], paused: false };
73
+ }
74
+ }
75
+ /**
76
+ * Write the full file data including todos and paused state.
77
+ */
78
+ async writeFileData(data) {
79
+ const todosResult = TodoArraySchema.safeParse(data.todos);
80
+ if (!todosResult.success) {
81
+ throw new Error('Invalid todo data');
82
+ }
83
+ const dir = path.dirname(this.filePath);
84
+ await fs.promises.mkdir(dir, { recursive: true });
85
+ const fileData = {
86
+ todos: todosResult.data,
87
+ paused: data.paused,
88
+ };
89
+ const content = JSON.stringify(fileData, null, 2);
90
+ await fs.promises.writeFile(this.filePath, content, 'utf8');
91
+ }
92
+ async readTodos() {
93
+ const data = await this.readFileData();
94
+ return data.todos;
95
+ }
96
+ async writeTodos(todos) {
97
+ // Preserve paused state when writing todos
98
+ const existingData = await this.readFileData();
99
+ await this.writeFileData({
100
+ todos,
101
+ paused: existingData.paused,
102
+ });
103
+ }
104
+ /**
105
+ * Read the paused state from the task file.
106
+ * Returns false if file doesn't exist or is in legacy format.
107
+ */
108
+ async readPausedState() {
109
+ const data = await this.readFileData();
110
+ return data.paused;
111
+ }
112
+ /**
113
+ * Write the paused state to the task file.
114
+ * Preserves existing todos.
115
+ */
116
+ async writePausedState(paused) {
117
+ const existingData = await this.readFileData();
118
+ await this.writeFileData({
119
+ todos: existingData.todos,
120
+ paused,
121
+ });
122
+ }
123
+ }
124
+ //# sourceMappingURL=todo-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo-store.js","sourceRoot":"","sources":["../../../src/tools/todo-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { BaseTool, type ToolResult } from './tools.js';
7
+ import { type Todo } from '../types/todo-schemas.js';
8
+ import type { ITodoService } from '../interfaces/ITodoService.js';
9
+ import type { IToolHost } from '../interfaces/IToolHost.js';
10
+ export interface TodoWriteParams {
11
+ todos: Todo[];
12
+ }
13
+ export declare class TodoWrite extends BaseTool<TodoWriteParams, ToolResult> {
14
+ private readonly todoService?;
15
+ private readonly toolHost?;
16
+ static readonly Name = "todo_write";
17
+ private static readonly SCHEMA;
18
+ constructor(todoService?: ITodoService | undefined, toolHost?: IToolHost | undefined);
19
+ getDescription(params: TodoWriteParams): string;
20
+ private trackInteractiveUpdate;
21
+ private emitTodoUpdated;
22
+ execute(params: TodoWriteParams, _signal: AbortSignal, _updateOutput?: (output: string) => void): Promise<ToolResult>;
23
+ private normalizeTodos;
24
+ private enforceOneInProgress;
25
+ private calculateStatistics;
26
+ private determineNextAction;
27
+ private getTodoEmojiFilter;
28
+ private applyEmojiFilter;
29
+ }
@@ -0,0 +1,366 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Vybestack LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Type } from '@google/genai';
7
+ import { BaseTool, Kind } from './tools.js';
8
+ import { TodoArraySchema } from '../types/todo-schemas.js';
9
+ import { TodoStore, DEFAULT_AGENT_ID } from './todo-store.js';
10
+ import { TodoReminderService } from '../utils/todoReminderService.js';
11
+ import { todoEvents } from './todo-events.js';
12
+ import { TodoContextTracker } from '../utils/todoContextTracker.js';
13
+ import { formatTodoListForDisplay } from '../utils/todoFormatter.js';
14
+ import { EmojiFilter, isEmojiFilterMode } from '../utils/EmojiFilter.js';
15
+ export class TodoWrite extends BaseTool {
16
+ todoService;
17
+ toolHost;
18
+ static Name = 'todo_write';
19
+ static SCHEMA = {
20
+ type: Type.OBJECT,
21
+ properties: {
22
+ todos: {
23
+ type: Type.ARRAY,
24
+ items: {
25
+ type: Type.OBJECT,
26
+ properties: {
27
+ id: {
28
+ type: Type.STRING,
29
+ description: 'Unique identifier for the todo item',
30
+ },
31
+ content: {
32
+ type: Type.STRING,
33
+ description: 'Description of the todo item',
34
+ minLength: 1,
35
+ },
36
+ status: {
37
+ type: Type.STRING,
38
+ enum: ['pending', 'in_progress', 'completed'],
39
+ description: 'Current status of the todo item',
40
+ },
41
+ subtasks: {
42
+ type: Type.ARRAY,
43
+ items: {
44
+ type: Type.OBJECT,
45
+ properties: {
46
+ id: {
47
+ type: Type.STRING,
48
+ description: 'Unique identifier for the subtask',
49
+ },
50
+ content: {
51
+ type: Type.STRING,
52
+ description: 'Description of the subtask',
53
+ minLength: 1,
54
+ },
55
+ toolCalls: {
56
+ type: Type.ARRAY,
57
+ items: {
58
+ type: Type.OBJECT,
59
+ properties: {
60
+ id: {
61
+ type: Type.STRING,
62
+ description: 'Unique identifier for the tool call',
63
+ },
64
+ name: {
65
+ type: Type.STRING,
66
+ description: 'Name of the tool being called',
67
+ },
68
+ parameters: {
69
+ type: Type.OBJECT,
70
+ description: 'Parameters for the tool call',
71
+ },
72
+ },
73
+ required: ['id', 'name', 'parameters'],
74
+ },
75
+ description: 'Tool calls associated with the subtask',
76
+ },
77
+ },
78
+ required: ['id', 'content'],
79
+ },
80
+ description: 'Subtasks associated with this todo',
81
+ },
82
+ },
83
+ required: ['id', 'content', 'status'],
84
+ },
85
+ description: 'The updated todo list',
86
+ },
87
+ },
88
+ required: ['todos'],
89
+ };
90
+ constructor(todoService, toolHost) {
91
+ super(TodoWrite.Name, 'TodoWrite', 'Create and manage a structured task list for the current coding session. Updates the entire todo list.', Kind.Think, TodoWrite.SCHEMA, true, // isOutputMarkdown
92
+ false);
93
+ this.todoService = todoService;
94
+ this.toolHost = toolHost;
95
+ }
96
+ getDescription(params) {
97
+ return `Update todo list with ${params.todos.length} items`;
98
+ }
99
+ // Emit an update event and track the active in-progress item.
100
+ trackInteractiveUpdate(todos, sessionId, agentId) {
101
+ const scopedAgentId = agentId ?? DEFAULT_AGENT_ID;
102
+ const inProgressTodo = todos.find((todo) => todo.status === 'in_progress');
103
+ const contextTracker = TodoContextTracker.forAgent(sessionId, scopedAgentId);
104
+ contextTracker.setActiveTodo(inProgressTodo ? inProgressTodo.id : null);
105
+ this.emitTodoUpdated(todos, sessionId, scopedAgentId);
106
+ }
107
+ emitTodoUpdated(todos, sessionId, agentId) {
108
+ const event = {
109
+ sessionId,
110
+ agentId,
111
+ todos,
112
+ timestamp: new Date(),
113
+ };
114
+ todoEvents.emitTodoUpdated(event);
115
+ }
116
+ async execute(params, _signal, _updateOutput) {
117
+ const normalizedTodos = this.normalizeTodos(params.todos);
118
+ // Validate todos with Zod schema
119
+ const result = TodoArraySchema.safeParse(normalizedTodos);
120
+ if (!result.success) {
121
+ const error = result.error.errors[0];
122
+ throw new Error(`Validation error: ${error.path.join('.')} - ${error.message}`);
123
+ }
124
+ const emojiResult = this.applyEmojiFilter(result.data);
125
+ if (emojiResult.blocked) {
126
+ return {
127
+ llmContent: emojiResult.errorMessage ?? 'Emojis detected in content',
128
+ returnDisplay: emojiResult.errorMessage ?? 'Emojis detected in content',
129
+ error: {
130
+ message: emojiResult.errorMessage ?? 'Emojis detected in content',
131
+ },
132
+ };
133
+ }
134
+ const revalidation = TodoArraySchema.safeParse(emojiResult.filtered);
135
+ if (!revalidation.success) {
136
+ const err = revalidation.error.errors[0];
137
+ const msg = `Emoji filtering produced invalid todo content: ${err.path.join('.')} - ${err.message}`;
138
+ return {
139
+ llmContent: msg,
140
+ returnDisplay: msg,
141
+ error: { message: msg },
142
+ };
143
+ }
144
+ const todos = revalidation.data;
145
+ // Get session and agent IDs from context
146
+ const sessionId = this.context?.sessionId ?? 'default';
147
+ const agentId = this.context?.agentId;
148
+ const serviceStore = this.todoService?.getTodoStore(this.context);
149
+ // Read old todos for diff tracking
150
+ const rawOldTodos = serviceStore?.readTodos
151
+ ? await serviceStore.readTodos()
152
+ : serviceStore?.getTodos
153
+ ? serviceStore.getTodos()
154
+ : await new TodoStore(sessionId, agentId).readTodos();
155
+ const oldTodos = rawOldTodos;
156
+ // Write new todos
157
+ if (serviceStore?.writeTodos) {
158
+ await serviceStore.writeTodos(todos);
159
+ }
160
+ else if (serviceStore?.setTodos) {
161
+ serviceStore.setTodos(todos);
162
+ }
163
+ else {
164
+ await new TodoStore(sessionId, agentId).writeTodos(todos);
165
+ }
166
+ const reminderService = this.todoService?.getReminderService();
167
+ const localReminderService = new TodoReminderService();
168
+ // Calculate state change
169
+ const stateChange = reminderService?.calculateStateChange?.(oldTodos, todos) ??
170
+ localReminderService.calculateStateChange(oldTodos, todos);
171
+ const shouldGenerateReminder = reminderService?.shouldGenerateReminder?.(stateChange) ??
172
+ localReminderService.shouldGenerateReminder(stateChange) ??
173
+ false;
174
+ // Generate reminder if needed
175
+ let reminder = null;
176
+ if (shouldGenerateReminder) {
177
+ reminder =
178
+ reminderService?.getReminderForStateChange?.(stateChange) ??
179
+ localReminderService.getReminderForStateChange(stateChange) ??
180
+ null;
181
+ }
182
+ // Set active task ID and emit event if in interactive mode
183
+ if (this.context?.interactiveMode === true) {
184
+ const scopedAgentId = agentId ?? this.todoService?.getDefaultAgentId() ?? DEFAULT_AGENT_ID;
185
+ const serviceTracker = this.todoService?.getContextTracker(this.context);
186
+ if (serviceTracker?.setActiveTodo) {
187
+ const inProgressTodo = todos.find((todo) => todo.status === 'in_progress');
188
+ serviceTracker.setActiveTodo(inProgressTodo ? inProgressTodo.id : null);
189
+ this.emitTodoUpdated(todos, sessionId, scopedAgentId);
190
+ }
191
+ else {
192
+ this.trackInteractiveUpdate(todos, sessionId, scopedAgentId);
193
+ }
194
+ }
195
+ const formattedOutput = formatTodoListForDisplay(todos);
196
+ const statistics = this.calculateStatistics(todos);
197
+ const nextAction = this.determineNextAction(todos);
198
+ let llmContent = formattedOutput;
199
+ if (emojiResult.systemFeedback) {
200
+ llmContent += `
201
+
202
+ <system-reminder>
203
+ ${emojiResult.systemFeedback}
204
+ </system-reminder>`;
205
+ }
206
+ return {
207
+ llmContent,
208
+ returnDisplay: formattedOutput,
209
+ metadata: {
210
+ stateChanged: shouldGenerateReminder,
211
+ todosAdded: stateChange.added.length,
212
+ todosRemoved: stateChange.removed.length,
213
+ statusChanged: stateChange.statusChanged.length,
214
+ statistics,
215
+ nextAction,
216
+ reminder: reminder ?? undefined,
217
+ },
218
+ };
219
+ }
220
+ normalizeTodos(rawTodos) {
221
+ const normalized = rawTodos.map((todo, index) => {
222
+ const normalizedId =
223
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Todo input payload data.
224
+ todo?.id !== undefined &&
225
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Todo input payload data.
226
+ todo?.id !== null &&
227
+ `${todo.id}`.trim() !== ''
228
+ ? String(todo.id)
229
+ : String(index + 1);
230
+ const rawSubtasks = todo?.subtasks;
231
+ const hasSubtasks = Array.isArray(rawSubtasks);
232
+ const normalizedSubtasks = hasSubtasks
233
+ ? rawSubtasks.map((subtask, subIndex) => {
234
+ const subtaskId =
235
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Todo input payload data.
236
+ subtask?.id !== undefined &&
237
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Todo input payload data.
238
+ subtask?.id !== null &&
239
+ `${subtask.id}`.trim() !== ''
240
+ ? String(subtask.id)
241
+ : `${normalizedId}-${subIndex + 1}`;
242
+ return {
243
+ ...subtask,
244
+ id: subtaskId,
245
+ };
246
+ })
247
+ : undefined;
248
+ const normalized = {
249
+ ...todo,
250
+ id: normalizedId,
251
+ status: todo.status ?? 'pending',
252
+ };
253
+ if (hasSubtasks) {
254
+ normalized.subtasks = normalizedSubtasks;
255
+ }
256
+ return normalized;
257
+ });
258
+ return this.enforceOneInProgress(normalized);
259
+ }
260
+ enforceOneInProgress(todos) {
261
+ const inProgressIndices = todos
262
+ .map((todo, index) => (todo.status === 'in_progress' ? index : -1))
263
+ .filter((index) => index !== -1);
264
+ if (inProgressIndices.length <= 1) {
265
+ return todos;
266
+ }
267
+ const lastInProgressIndex = inProgressIndices[inProgressIndices.length - 1];
268
+ return todos.map((todo, index) => {
269
+ if (todo.status === 'in_progress' && index !== lastInProgressIndex) {
270
+ return { ...todo, status: 'pending' };
271
+ }
272
+ return todo;
273
+ });
274
+ }
275
+ calculateStatistics(todos) {
276
+ return {
277
+ total: todos.length,
278
+ inProgress: todos.filter((t) => t.status === 'in_progress').length,
279
+ pending: todos.filter((t) => t.status === 'pending').length,
280
+ completed: todos.filter((t) => t.status === 'completed').length,
281
+ };
282
+ }
283
+ determineNextAction(todos) {
284
+ // Check if any tasks are in progress - return first one (preserves LLM order)
285
+ const inProgressTasks = todos.filter((t) => t.status === 'in_progress');
286
+ if (inProgressTasks.length > 0) {
287
+ const task = inProgressTasks[0];
288
+ return {
289
+ type: 'continue',
290
+ taskId: task.id,
291
+ taskContent: task.content,
292
+ };
293
+ }
294
+ // Check if any tasks are pending - return first one (preserves LLM order)
295
+ const pendingTasks = todos.filter((t) => t.status === 'pending');
296
+ if (pendingTasks.length > 0) {
297
+ const task = pendingTasks[0];
298
+ return {
299
+ type: 'start',
300
+ taskId: task.id,
301
+ taskContent: task.content,
302
+ };
303
+ }
304
+ // All tasks are completed
305
+ return { type: 'all-complete' };
306
+ }
307
+ getTodoEmojiFilter() {
308
+ if (!this.toolHost) {
309
+ return null;
310
+ }
311
+ const raw = this.toolHost.getEphemeralSettings?.().emojifilter;
312
+ const mode = isEmojiFilterMode(raw) ? raw : 'auto';
313
+ return new EmojiFilter({ mode });
314
+ }
315
+ applyEmojiFilter(todos) {
316
+ const filter = this.getTodoEmojiFilter();
317
+ if (!filter) {
318
+ return { filtered: todos, blocked: false };
319
+ }
320
+ let blocked = false;
321
+ let errorMessage;
322
+ const feedbackParts = new Set();
323
+ const filteredTodos = todos.map((todo) => {
324
+ const contentResult = filter.filterText(todo.content);
325
+ if (contentResult.blocked) {
326
+ blocked = true;
327
+ errorMessage = contentResult.error ?? 'Emojis detected in todo content';
328
+ }
329
+ if (contentResult.systemFeedback)
330
+ feedbackParts.add(contentResult.systemFeedback);
331
+ const filteredSubtasks = todo.subtasks?.map((subtask) => {
332
+ const subResult = filter.filterText(subtask.content);
333
+ if (subResult.blocked) {
334
+ blocked = true;
335
+ errorMessage =
336
+ subResult.error ?? 'Emojis detected in subtask content';
337
+ }
338
+ if (subResult.systemFeedback)
339
+ feedbackParts.add(subResult.systemFeedback);
340
+ const subFiltered = subResult.filtered;
341
+ return {
342
+ ...subtask,
343
+ content: typeof subFiltered === 'string' ? subFiltered : subtask.content,
344
+ };
345
+ });
346
+ const todoFiltered = contentResult.filtered;
347
+ const filteredTodo = {
348
+ ...todo,
349
+ content: typeof todoFiltered === 'string' ? todoFiltered : todo.content,
350
+ };
351
+ if (todo.subtasks) {
352
+ filteredTodo.subtasks = filteredSubtasks;
353
+ }
354
+ return filteredTodo;
355
+ });
356
+ return {
357
+ filtered: filteredTodos,
358
+ blocked,
359
+ errorMessage,
360
+ systemFeedback: feedbackParts.size > 0
361
+ ? Array.from(feedbackParts).join(' ')
362
+ : undefined,
363
+ };
364
+ }
365
+ }
366
+ //# sourceMappingURL=todo-write.js.map