@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.
- package/LICENSE +202 -0
- package/README.md +294 -0
- package/dist/.last_build +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.d.ts +29 -0
- package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.js +30 -0
- package/dist/src/__tests__/fixtures/filesystem-tool-fixtures.js.map +1 -0
- package/dist/src/__tests__/fixtures/key-storage-fixtures.d.ts +39 -0
- package/dist/src/__tests__/fixtures/key-storage-fixtures.js +53 -0
- package/dist/src/__tests__/fixtures/key-storage-fixtures.js.map +1 -0
- package/dist/src/__tests__/fixtures/provider-formatting-fixtures.d.ts +140 -0
- package/dist/src/__tests__/fixtures/provider-formatting-fixtures.js +157 -0
- package/dist/src/__tests__/fixtures/provider-formatting-fixtures.js.map +1 -0
- package/dist/src/__tests__/red-test-helpers.d.ts +14 -0
- package/dist/src/__tests__/red-test-helpers.js +18 -0
- package/dist/src/__tests__/red-test-helpers.js.map +1 -0
- package/dist/src/formatters/IToolFormatter.d.ts +84 -0
- package/dist/src/formatters/IToolFormatter.js +6 -0
- package/dist/src/formatters/IToolFormatter.js.map +1 -0
- package/dist/src/formatters/ToolFormatter.d.ts +94 -0
- package/dist/src/formatters/ToolFormatter.js +379 -0
- package/dist/src/formatters/ToolFormatter.js.map +1 -0
- package/dist/src/formatters/ToolIdStrategy.d.ts +79 -0
- package/dist/src/formatters/ToolIdStrategy.js +173 -0
- package/dist/src/formatters/ToolIdStrategy.js.map +1 -0
- package/dist/src/formatters/doubleEscapeUtils.d.ts +46 -0
- package/dist/src/formatters/doubleEscapeUtils.js +223 -0
- package/dist/src/formatters/doubleEscapeUtils.js.map +1 -0
- package/dist/src/formatters/index.d.ts +21 -0
- package/dist/src/formatters/index.js +12 -0
- package/dist/src/formatters/index.js.map +1 -0
- package/dist/src/formatters/toolIdNormalization.d.ts +28 -0
- package/dist/src/formatters/toolIdNormalization.js +97 -0
- package/dist/src/formatters/toolIdNormalization.js.map +1 -0
- package/dist/src/formatters/toolNameUtils.d.ts +43 -0
- package/dist/src/formatters/toolNameUtils.js +143 -0
- package/dist/src/formatters/toolNameUtils.js.map +1 -0
- package/dist/src/index.d.ts +88 -0
- package/dist/src/index.js +68 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces/IAsyncTaskService.d.ts +57 -0
- package/dist/src/interfaces/IAsyncTaskService.js +6 -0
- package/dist/src/interfaces/IAsyncTaskService.js.map +1 -0
- package/dist/src/interfaces/IIdeService.d.ts +62 -0
- package/dist/src/interfaces/IIdeService.js +6 -0
- package/dist/src/interfaces/IIdeService.js.map +1 -0
- package/dist/src/interfaces/ILspService.d.ts +54 -0
- package/dist/src/interfaces/ILspService.js +6 -0
- package/dist/src/interfaces/ILspService.js.map +1 -0
- package/dist/src/interfaces/IMcpToolService.d.ts +47 -0
- package/dist/src/interfaces/IMcpToolService.js +6 -0
- package/dist/src/interfaces/IMcpToolService.js.map +1 -0
- package/dist/src/interfaces/IPromptRegistryService.d.ts +51 -0
- package/dist/src/interfaces/IPromptRegistryService.js +6 -0
- package/dist/src/interfaces/IPromptRegistryService.js.map +1 -0
- package/dist/src/interfaces/ISettingsService.d.ts +50 -0
- package/dist/src/interfaces/ISettingsService.js +6 -0
- package/dist/src/interfaces/ISettingsService.js.map +1 -0
- package/dist/src/interfaces/IShellExecutionService.d.ts +55 -0
- package/dist/src/interfaces/IShellExecutionService.js +6 -0
- package/dist/src/interfaces/IShellExecutionService.js.map +1 -0
- package/dist/src/interfaces/IShellToolHost.d.ts +176 -0
- package/dist/src/interfaces/IShellToolHost.js +6 -0
- package/dist/src/interfaces/IShellToolHost.js.map +1 -0
- package/dist/src/interfaces/ISkillService.d.ts +69 -0
- package/dist/src/interfaces/ISkillService.js +6 -0
- package/dist/src/interfaces/ISkillService.js.map +1 -0
- package/dist/src/interfaces/IStorageService.d.ts +42 -0
- package/dist/src/interfaces/IStorageService.js +6 -0
- package/dist/src/interfaces/IStorageService.js.map +1 -0
- package/dist/src/interfaces/ISubagentService.d.ts +112 -0
- package/dist/src/interfaces/ISubagentService.js +6 -0
- package/dist/src/interfaces/ISubagentService.js.map +1 -0
- package/dist/src/interfaces/ITaskToolHost.d.ts +185 -0
- package/dist/src/interfaces/ITaskToolHost.js +6 -0
- package/dist/src/interfaces/ITaskToolHost.js.map +1 -0
- package/dist/src/interfaces/ITodoService.d.ts +79 -0
- package/dist/src/interfaces/ITodoService.js +6 -0
- package/dist/src/interfaces/ITodoService.js.map +1 -0
- package/dist/src/interfaces/IToolHost.d.ts +91 -0
- package/dist/src/interfaces/IToolHost.js +6 -0
- package/dist/src/interfaces/IToolHost.js.map +1 -0
- package/dist/src/interfaces/IToolKeyStorage.d.ts +62 -0
- package/dist/src/interfaces/IToolKeyStorage.js +6 -0
- package/dist/src/interfaces/IToolKeyStorage.js.map +1 -0
- package/dist/src/interfaces/IToolMessageBus.d.ts +63 -0
- package/dist/src/interfaces/IToolMessageBus.js +6 -0
- package/dist/src/interfaces/IToolMessageBus.js.map +1 -0
- package/dist/src/interfaces/IToolRegistryHost.d.ts +43 -0
- package/dist/src/interfaces/IToolRegistryHost.js +6 -0
- package/dist/src/interfaces/IToolRegistryHost.js.map +1 -0
- package/dist/src/interfaces/IWebSearchService.d.ts +16 -0
- package/dist/src/interfaces/IWebSearchService.js +7 -0
- package/dist/src/interfaces/IWebSearchService.js.map +1 -0
- package/dist/src/interfaces/index.d.ts +33 -0
- package/dist/src/interfaces/index.js +6 -0
- package/dist/src/interfaces/index.js.map +1 -0
- package/dist/src/tools/activate-skill.d.ts +26 -0
- package/dist/src/tools/activate-skill.js +121 -0
- package/dist/src/tools/activate-skill.js.map +1 -0
- package/dist/src/tools/apply-patch.d.ts +65 -0
- package/dist/src/tools/apply-patch.js +528 -0
- package/dist/src/tools/apply-patch.js.map +1 -0
- package/dist/src/tools/ast-edit/ast-config.d.ts +67 -0
- package/dist/src/tools/ast-edit/ast-config.js +72 -0
- package/dist/src/tools/ast-edit/ast-config.js.map +1 -0
- package/dist/src/tools/ast-edit/ast-edit-invocation.d.ts +40 -0
- package/dist/src/tools/ast-edit/ast-edit-invocation.js +410 -0
- package/dist/src/tools/ast-edit/ast-edit-invocation.js.map +1 -0
- package/dist/src/tools/ast-edit/ast-query-extractor.d.ts +21 -0
- package/dist/src/tools/ast-edit/ast-query-extractor.js +178 -0
- package/dist/src/tools/ast-edit/ast-query-extractor.js.map +1 -0
- package/dist/src/tools/ast-edit/ast-read-file-invocation.d.ts +26 -0
- package/dist/src/tools/ast-edit/ast-read-file-invocation.js +149 -0
- package/dist/src/tools/ast-edit/ast-read-file-invocation.js.map +1 -0
- package/dist/src/tools/ast-edit/constants.d.ts +30 -0
- package/dist/src/tools/ast-edit/constants.js +36 -0
- package/dist/src/tools/ast-edit/constants.js.map +1 -0
- package/dist/src/tools/ast-edit/context-collector.d.ts +25 -0
- package/dist/src/tools/ast-edit/context-collector.js +115 -0
- package/dist/src/tools/ast-edit/context-collector.js.map +1 -0
- package/dist/src/tools/ast-edit/context-optimizer.d.ts +29 -0
- package/dist/src/tools/ast-edit/context-optimizer.js +86 -0
- package/dist/src/tools/ast-edit/context-optimizer.js.map +1 -0
- package/dist/src/tools/ast-edit/cross-file-analyzer.d.ts +41 -0
- package/dist/src/tools/ast-edit/cross-file-analyzer.js +294 -0
- package/dist/src/tools/ast-edit/cross-file-analyzer.js.map +1 -0
- package/dist/src/tools/ast-edit/edit-calculator.d.ts +71 -0
- package/dist/src/tools/ast-edit/edit-calculator.js +249 -0
- package/dist/src/tools/ast-edit/edit-calculator.js.map +1 -0
- package/dist/src/tools/ast-edit/edit-helpers.d.ts +22 -0
- package/dist/src/tools/ast-edit/edit-helpers.js +36 -0
- package/dist/src/tools/ast-edit/edit-helpers.js.map +1 -0
- package/dist/src/tools/ast-edit/language-analysis.d.ts +19 -0
- package/dist/src/tools/ast-edit/language-analysis.js +123 -0
- package/dist/src/tools/ast-edit/language-analysis.js.map +1 -0
- package/dist/src/tools/ast-edit/local-context-analyzer.d.ts +84 -0
- package/dist/src/tools/ast-edit/local-context-analyzer.js +267 -0
- package/dist/src/tools/ast-edit/local-context-analyzer.js.map +1 -0
- package/dist/src/tools/ast-edit/repository-context-provider.d.ts +22 -0
- package/dist/src/tools/ast-edit/repository-context-provider.js +139 -0
- package/dist/src/tools/ast-edit/repository-context-provider.js.map +1 -0
- package/dist/src/tools/ast-edit/types.d.ts +155 -0
- package/dist/src/tools/ast-edit/types.js +7 -0
- package/dist/src/tools/ast-edit/types.js.map +1 -0
- package/dist/src/tools/ast-edit/workspace-context-provider.d.ts +22 -0
- package/dist/src/tools/ast-edit/workspace-context-provider.js +39 -0
- package/dist/src/tools/ast-edit/workspace-context-provider.js.map +1 -0
- package/dist/src/tools/ast-edit.d.ts +43 -0
- package/dist/src/tools/ast-edit.js +183 -0
- package/dist/src/tools/ast-edit.js.map +1 -0
- package/dist/src/tools/ast-grep.d.ts +22 -0
- package/dist/src/tools/ast-grep.js +291 -0
- package/dist/src/tools/ast-grep.js.map +1 -0
- package/dist/src/tools/check-async-tasks.d.ts +46 -0
- package/dist/src/tools/check-async-tasks.js +241 -0
- package/dist/src/tools/check-async-tasks.js.map +1 -0
- package/dist/src/tools/codesearch.d.ts +25 -0
- package/dist/src/tools/codesearch.js +153 -0
- package/dist/src/tools/codesearch.js.map +1 -0
- package/dist/src/tools/delete_line_range.d.ts +41 -0
- package/dist/src/tools/delete_line_range.js +238 -0
- package/dist/src/tools/delete_line_range.js.map +1 -0
- package/dist/src/tools/direct-web-fetch.d.ts +22 -0
- package/dist/src/tools/direct-web-fetch.js +215 -0
- package/dist/src/tools/direct-web-fetch.js.map +1 -0
- package/dist/src/tools/edit-utils.d.ts +53 -0
- package/dist/src/tools/edit-utils.js +250 -0
- package/dist/src/tools/edit-utils.js.map +1 -0
- package/dist/src/tools/edit.d.ts +70 -0
- package/dist/src/tools/edit.js +816 -0
- package/dist/src/tools/edit.js.map +1 -0
- package/dist/src/tools/exa-web-search.d.ts +27 -0
- package/dist/src/tools/exa-web-search.js +153 -0
- package/dist/src/tools/exa-web-search.js.map +1 -0
- package/dist/src/tools/glob.d.ts +55 -0
- package/dist/src/tools/glob.js +284 -0
- package/dist/src/tools/glob.js.map +1 -0
- package/dist/src/tools/google-web-fetch.d.ts +34 -0
- package/dist/src/tools/google-web-fetch.js +417 -0
- package/dist/src/tools/google-web-fetch.js.map +1 -0
- package/dist/src/tools/google-web-search-invocation.d.ts +53 -0
- package/dist/src/tools/google-web-search-invocation.js +180 -0
- package/dist/src/tools/google-web-search-invocation.js.map +1 -0
- package/dist/src/tools/google-web-search.d.ts +16 -0
- package/dist/src/tools/google-web-search.js +34 -0
- package/dist/src/tools/google-web-search.js.map +1 -0
- package/dist/src/tools/grep.d.ts +56 -0
- package/dist/src/tools/grep.js +883 -0
- package/dist/src/tools/grep.js.map +1 -0
- package/dist/src/tools/insert_at_line.d.ts +41 -0
- package/dist/src/tools/insert_at_line.js +287 -0
- package/dist/src/tools/insert_at_line.js.map +1 -0
- package/dist/src/tools/list-subagents.d.ts +31 -0
- package/dist/src/tools/list-subagents.js +122 -0
- package/dist/src/tools/list-subagents.js.map +1 -0
- package/dist/src/tools/ls.d.ts +71 -0
- package/dist/src/tools/ls.js +238 -0
- package/dist/src/tools/ls.js.map +1 -0
- package/dist/src/tools/memoryTool.d.ts +66 -0
- package/dist/src/tools/memoryTool.js +435 -0
- package/dist/src/tools/memoryTool.js.map +1 -0
- package/dist/src/tools/modifiable-tool.d.ts +37 -0
- package/dist/src/tools/modifiable-tool.js +120 -0
- package/dist/src/tools/modifiable-tool.js.map +1 -0
- package/dist/src/tools/read-file.d.ts +49 -0
- package/dist/src/tools/read-file.js +279 -0
- package/dist/src/tools/read-file.js.map +1 -0
- package/dist/src/tools/read-many-files.d.ts +60 -0
- package/dist/src/tools/read-many-files.js +529 -0
- package/dist/src/tools/read-many-files.js.map +1 -0
- package/dist/src/tools/read_line_range.d.ts +47 -0
- package/dist/src/tools/read_line_range.js +248 -0
- package/dist/src/tools/read_line_range.js.map +1 -0
- package/dist/src/tools/ripGrep.d.ts +41 -0
- package/dist/src/tools/ripGrep.js +395 -0
- package/dist/src/tools/ripGrep.js.map +1 -0
- package/dist/src/tools/shell.d.ts +60 -0
- package/dist/src/tools/shell.js +735 -0
- package/dist/src/tools/shell.js.map +1 -0
- package/dist/src/tools/structural-analysis.d.ts +27 -0
- package/dist/src/tools/structural-analysis.js +1089 -0
- package/dist/src/tools/structural-analysis.js.map +1 -0
- package/dist/src/tools/stubs.d.ts +10 -0
- package/dist/src/tools/stubs.js +6 -0
- package/dist/src/tools/stubs.js.map +1 -0
- package/dist/src/tools/task.d.ts +41 -0
- package/dist/src/tools/task.js +195 -0
- package/dist/src/tools/task.js.map +1 -0
- package/dist/src/tools/todo-events.d.ts +22 -0
- package/dist/src/tools/todo-events.js +24 -0
- package/dist/src/tools/todo-events.js.map +1 -0
- package/dist/src/tools/todo-pause.d.ts +29 -0
- package/dist/src/tools/todo-pause.js +172 -0
- package/dist/src/tools/todo-pause.js.map +1 -0
- package/dist/src/tools/todo-read.d.ts +18 -0
- package/dist/src/tools/todo-read.js +98 -0
- package/dist/src/tools/todo-read.js.map +1 -0
- package/dist/src/tools/todo-store.d.ts +35 -0
- package/dist/src/tools/todo-store.js +124 -0
- package/dist/src/tools/todo-store.js.map +1 -0
- package/dist/src/tools/todo-write.d.ts +29 -0
- package/dist/src/tools/todo-write.js +366 -0
- package/dist/src/tools/todo-write.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +156 -0
- package/dist/src/tools/tool-registry.js +623 -0
- package/dist/src/tools/tool-registry.js.map +1 -0
- package/dist/src/tools/tools.d.ts +403 -0
- package/dist/src/tools/tools.js +519 -0
- package/dist/src/tools/tools.js.map +1 -0
- package/dist/src/tools/write-file.d.ts +45 -0
- package/dist/src/tools/write-file.js +320 -0
- package/dist/src/tools/write-file.js.map +1 -0
- package/dist/src/types/index.d.ts +17 -0
- package/dist/src/types/index.js +9 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/provider-content-types.d.ts +56 -0
- package/dist/src/types/provider-content-types.js +6 -0
- package/dist/src/types/provider-content-types.js.map +1 -0
- package/dist/src/types/todo-schemas.d.ts +263 -0
- package/dist/src/types/todo-schemas.js +32 -0
- package/dist/src/types/todo-schemas.js.map +1 -0
- package/dist/src/types/tool-confirmation-types.d.ts +34 -0
- package/dist/src/types/tool-confirmation-types.js +29 -0
- package/dist/src/types/tool-confirmation-types.js.map +1 -0
- package/dist/src/types/tool-context.d.ts +31 -0
- package/dist/src/types/tool-context.js +6 -0
- package/dist/src/types/tool-context.js.map +1 -0
- package/dist/src/types/tool-error.d.ts +69 -0
- package/dist/src/types/tool-error.js +94 -0
- package/dist/src/types/tool-error.js.map +1 -0
- package/dist/src/types/tool-names.d.ts +57 -0
- package/dist/src/types/tool-names.js +64 -0
- package/dist/src/types/tool-names.js.map +1 -0
- package/dist/src/utils/EmojiFilter.d.ts +134 -0
- package/dist/src/utils/EmojiFilter.js +370 -0
- package/dist/src/utils/EmojiFilter.js.map +1 -0
- package/dist/src/utils/ast-grep-utils.d.ts +42 -0
- package/dist/src/utils/ast-grep-utils.js +140 -0
- package/dist/src/utils/ast-grep-utils.js.map +1 -0
- package/dist/src/utils/debugLogger.d.ts +11 -0
- package/dist/src/utils/debugLogger.js +16 -0
- package/dist/src/utils/debugLogger.js.map +1 -0
- package/dist/src/utils/diffOptions.d.ts +14 -0
- package/dist/src/utils/diffOptions.js +46 -0
- package/dist/src/utils/diffOptions.js.map +1 -0
- package/dist/src/utils/editor.d.ts +39 -0
- package/dist/src/utils/editor.js +212 -0
- package/dist/src/utils/editor.js.map +1 -0
- package/dist/src/utils/ensure-dirs.d.ts +10 -0
- package/dist/src/utils/ensure-dirs.js +16 -0
- package/dist/src/utils/ensure-dirs.js.map +1 -0
- package/dist/src/utils/errors.d.ts +59 -0
- package/dist/src/utils/errors.js +178 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/fetch.d.ts +11 -0
- package/dist/src/utils/fetch.js +74 -0
- package/dist/src/utils/fetch.js.map +1 -0
- package/dist/src/utils/fileUtils.d.ts +32 -0
- package/dist/src/utils/fileUtils.js +363 -0
- package/dist/src/utils/fileUtils.js.map +1 -0
- package/dist/src/utils/fuzzy-replacer.d.ts +61 -0
- package/dist/src/utils/fuzzy-replacer.js +492 -0
- package/dist/src/utils/fuzzy-replacer.js.map +1 -0
- package/dist/src/utils/gitLineChanges.d.ts +12 -0
- package/dist/src/utils/gitLineChanges.js +171 -0
- package/dist/src/utils/gitLineChanges.js.map +1 -0
- package/dist/src/utils/gitUtils.d.ts +6 -0
- package/dist/src/utils/gitUtils.js +31 -0
- package/dist/src/utils/gitUtils.js.map +1 -0
- package/dist/src/utils/lsp-diagnostics-helper.d.ts +27 -0
- package/dist/src/utils/lsp-diagnostics-helper.js +62 -0
- package/dist/src/utils/lsp-diagnostics-helper.js.map +1 -0
- package/dist/src/utils/mediaUtils.d.ts +38 -0
- package/dist/src/utils/mediaUtils.js +22 -0
- package/dist/src/utils/mediaUtils.js.map +1 -0
- package/dist/src/utils/pathValidation.d.ts +7 -0
- package/dist/src/utils/pathValidation.js +39 -0
- package/dist/src/utils/pathValidation.js.map +1 -0
- package/dist/src/utils/paths.d.ts +7 -0
- package/dist/src/utils/paths.js +158 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/resolveTextSearchTarget.d.ts +17 -0
- package/dist/src/utils/resolveTextSearchTarget.js +45 -0
- package/dist/src/utils/resolveTextSearchTarget.js.map +1 -0
- package/dist/src/utils/retry.d.ts +17 -0
- package/dist/src/utils/retry.js +185 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/dist/src/utils/ripgrepPathResolver.d.ts +23 -0
- package/dist/src/utils/ripgrepPathResolver.js +179 -0
- package/dist/src/utils/ripgrepPathResolver.js.map +1 -0
- package/dist/src/utils/safeJsonStringify.d.ts +9 -0
- package/dist/src/utils/safeJsonStringify.js +21 -0
- package/dist/src/utils/safeJsonStringify.js.map +1 -0
- package/dist/src/utils/schemaValidator.d.ts +13 -0
- package/dist/src/utils/schemaValidator.js +275 -0
- package/dist/src/utils/schemaValidator.js.map +1 -0
- package/dist/src/utils/terminalSerializer.d.ts +33 -0
- package/dist/src/utils/terminalSerializer.js +6 -0
- package/dist/src/utils/terminalSerializer.js.map +1 -0
- package/dist/src/utils/todoContextTracker.d.ts +12 -0
- package/dist/src/utils/todoContextTracker.js +28 -0
- package/dist/src/utils/todoContextTracker.js.map +1 -0
- package/dist/src/utils/todoFormatter.d.ts +24 -0
- package/dist/src/utils/todoFormatter.js +157 -0
- package/dist/src/utils/todoFormatter.js.map +1 -0
- package/dist/src/utils/todoReminderService.d.ts +22 -0
- package/dist/src/utils/todoReminderService.js +43 -0
- package/dist/src/utils/todoReminderService.js.map +1 -0
- package/dist/src/utils/tool-key-storage-facade.d.ts +32 -0
- package/dist/src/utils/tool-key-storage-facade.js +56 -0
- package/dist/src/utils/tool-key-storage-facade.js.map +1 -0
- package/dist/src/utils/tool-key-storage-types.d.ts +56 -0
- package/dist/src/utils/tool-key-storage-types.js +56 -0
- package/dist/src/utils/tool-key-storage-types.js.map +1 -0
- package/dist/src/utils/toolOutputLimiter.d.ts +29 -0
- package/dist/src/utils/toolOutputLimiter.js +107 -0
- package/dist/src/utils/toolOutputLimiter.js.map +1 -0
- package/dist/src/utils/unicodeUtils.d.ts +55 -0
- package/dist/src/utils/unicodeUtils.js +129 -0
- package/dist/src/utils/unicodeUtils.js.map +1 -0
- 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":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAmB,IAAI,EAAE,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAKrE,MAAM,OAAO,QAAS,SAAQ,QAAoC;IAInC;IAH7B,MAAM,CAAU,IAAI,GAAG,WAAW,CAAC;IAC3B,eAAe,GAAG,IAAI,mBAAmB,EAAE,CAAC;IAEpD,YAA6B,WAA0B;QACrD,KAAK,CACH,QAAQ,CAAC,IAAI,EACb,UAAU,EACV,8FAA8F,EAC9F,IAAI,CAAC,KAAK,EACV;YACE,IAAI,EAAE,IAAI,CAAC,MAAM;YACjB,UAAU,EAAE,EAAE;SACf,EACD,IAAI,EAAE,mBAAmB;QACzB,KAAK,CACN,CAAC;QAZyB,gBAAW,GAAX,WAAW,CAAe;IAavD,CAAC;IAEQ,cAAc,CAAC,OAAuB;QAC7C,OAAO,wBAAwB,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAuB,EACvB,OAAoB,EACpB,aAAwC;QAExC,yCAAyC;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,IAAI,SAAS,CAAC;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;QAEtC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,KAAK,EAAE,SAAS;YAC/B,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE;YACzB,CAAC,CAAC,KAAK,EAAE,QAAQ;gBACf,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE;gBAClB,CAAC,CAAC,MAAM,IAAI,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,QAAkB,CAAC;QAEjC,MAAM,MAAM,GAAG,KAAK,EAAE,eAAe;YACnC,CAAC,CAAC,MAAM,KAAK,CAAC,eAAe,EAAE;YAC/B,CAAC,CAAC,KAAK,CAAC;QACV,MAAM,MAAM,GACV,wBAAwB,CAAC,KAAK,CAAC;YAC/B,CAAC,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAElD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,KAAK,CAAC;YAC5B,MAAM,QAAQ,GACZ,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,aAAa,CAAC,CAAC;YAC/D,OAAO;gBACL,UAAU,EACR,MAAM;oBACN,0JAA0J;oBAC1J,CAAC,QAAQ,IAAI,EAAE,CAAC;gBAClB,aAAa,EAAE,MAAM;aACtB,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,MAAM,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QACnD,MAAM,eAAe,GAAG,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAE7D,OAAO;YACL,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,MAAM;YACrB,QAAQ,EAAE;gBACR,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,UAAU;gBACV,eAAe;aAChB;SACF,CAAC;IACJ,CAAC;IAEO,mBAAmB,CAAC,KAAa;QAMvC,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,MAAM;YAClE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;YAC3D,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;SAChE,CAAC;IACJ,CAAC;IAEO,wBAAwB,CAAC,KAAa;QAK5C,8EAA8E;QAC9E,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;QACxE,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,IAAI,CAAC,OAAO;aAC1B,CAAC;QACJ,CAAC;QAED,0EAA0E;QAC1E,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QACjE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7B,OAAO;gBACL,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,IAAI,CAAC,EAAE;gBACf,WAAW,EAAE,IAAI,CAAC,OAAO;aAC1B,CAAC;QACJ,CAAC;QAED,0BAA0B;QAC1B,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAClC,CAAC"}
|
|
@@ -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
|