task-o-matic-core 0.1.0
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/README.md +646 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/lib/ai-service/ai-operations.d.ts +45 -0
- package/dist/lib/ai-service/ai-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/ai-operations.js +60 -0
- package/dist/lib/ai-service/base-operations.d.ts +43 -0
- package/dist/lib/ai-service/base-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/base-operations.js +119 -0
- package/dist/lib/ai-service/documentation-operations.d.ts +18 -0
- package/dist/lib/ai-service/documentation-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/documentation-operations.js +308 -0
- package/dist/lib/ai-service/filesystem-tools.d.ts +69 -0
- package/dist/lib/ai-service/filesystem-tools.d.ts.map +1 -0
- package/dist/lib/ai-service/filesystem-tools.js +70 -0
- package/dist/lib/ai-service/json-parser.d.ts +34 -0
- package/dist/lib/ai-service/json-parser.d.ts.map +1 -0
- package/dist/lib/ai-service/json-parser.js +177 -0
- package/dist/lib/ai-service/mcp-client.d.ts +9 -0
- package/dist/lib/ai-service/mcp-client.d.ts.map +1 -0
- package/dist/lib/ai-service/mcp-client.js +48 -0
- package/dist/lib/ai-service/model-provider.d.ts +12 -0
- package/dist/lib/ai-service/model-provider.d.ts.map +1 -0
- package/dist/lib/ai-service/model-provider.js +146 -0
- package/dist/lib/ai-service/prd-operations.d.ts +25 -0
- package/dist/lib/ai-service/prd-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/prd-operations.js +592 -0
- package/dist/lib/ai-service/research-tools.d.ts +4 -0
- package/dist/lib/ai-service/research-tools.d.ts.map +1 -0
- package/dist/lib/ai-service/research-tools.js +8 -0
- package/dist/lib/ai-service/retry-handler.d.ts +8 -0
- package/dist/lib/ai-service/retry-handler.d.ts.map +1 -0
- package/dist/lib/ai-service/retry-handler.js +63 -0
- package/dist/lib/ai-service/task-operations.d.ts +13 -0
- package/dist/lib/ai-service/task-operations.d.ts.map +1 -0
- package/dist/lib/ai-service/task-operations.js +220 -0
- package/dist/lib/benchmark/registry.d.ts +11 -0
- package/dist/lib/benchmark/registry.d.ts.map +1 -0
- package/dist/lib/benchmark/registry.js +212 -0
- package/dist/lib/benchmark/runner.d.ts +6 -0
- package/dist/lib/benchmark/runner.d.ts.map +1 -0
- package/dist/lib/benchmark/runner.js +150 -0
- package/dist/lib/benchmark/storage.d.ts +13 -0
- package/dist/lib/benchmark/storage.d.ts.map +1 -0
- package/dist/lib/benchmark/storage.js +100 -0
- package/dist/lib/benchmark/types.d.ts +104 -0
- package/dist/lib/benchmark/types.d.ts.map +1 -0
- package/dist/lib/benchmark/types.js +2 -0
- package/dist/lib/better-t-stack-cli.d.ts +50 -0
- package/dist/lib/better-t-stack-cli.d.ts.map +1 -0
- package/dist/lib/better-t-stack-cli.js +428 -0
- package/dist/lib/bootstrap/cli-bootstrap.d.ts +14 -0
- package/dist/lib/bootstrap/cli-bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap/cli-bootstrap.js +322 -0
- package/dist/lib/bootstrap/index.d.ts +3 -0
- package/dist/lib/bootstrap/index.d.ts.map +1 -0
- package/dist/lib/bootstrap/index.js +18 -0
- package/dist/lib/bootstrap/medusa-bootstrap.d.ts +14 -0
- package/dist/lib/bootstrap/medusa-bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap/medusa-bootstrap.js +215 -0
- package/dist/lib/config-validation.d.ts +215 -0
- package/dist/lib/config-validation.d.ts.map +1 -0
- package/dist/lib/config-validation.js +254 -0
- package/dist/lib/config.d.ts +55 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +351 -0
- package/dist/lib/context-builder.d.ts +66 -0
- package/dist/lib/context-builder.d.ts.map +1 -0
- package/dist/lib/context-builder.js +322 -0
- package/dist/lib/executors/claude-code-executor.d.ts +9 -0
- package/dist/lib/executors/claude-code-executor.d.ts.map +1 -0
- package/dist/lib/executors/claude-code-executor.js +69 -0
- package/dist/lib/executors/codex-executor.d.ts +9 -0
- package/dist/lib/executors/codex-executor.d.ts.map +1 -0
- package/dist/lib/executors/codex-executor.js +73 -0
- package/dist/lib/executors/executor-factory.d.ts +5 -0
- package/dist/lib/executors/executor-factory.d.ts.map +1 -0
- package/dist/lib/executors/executor-factory.js +27 -0
- package/dist/lib/executors/gemini-executor.d.ts +9 -0
- package/dist/lib/executors/gemini-executor.d.ts.map +1 -0
- package/dist/lib/executors/gemini-executor.js +67 -0
- package/dist/lib/executors/kilo-executor.d.ts +9 -0
- package/dist/lib/executors/kilo-executor.d.ts.map +1 -0
- package/dist/lib/executors/kilo-executor.js +69 -0
- package/dist/lib/executors/opencode-executor.d.ts +9 -0
- package/dist/lib/executors/opencode-executor.d.ts.map +1 -0
- package/dist/lib/executors/opencode-executor.js +67 -0
- package/dist/lib/git-utils.d.ts +88 -0
- package/dist/lib/git-utils.d.ts.map +1 -0
- package/dist/lib/git-utils.js +242 -0
- package/dist/lib/hooks.d.ts +73 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +62 -0
- package/dist/lib/index.d.ts +100 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +143 -0
- package/dist/lib/logger.d.ts +20 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +32 -0
- package/dist/lib/notifications.d.ts +7 -0
- package/dist/lib/notifications.d.ts.map +1 -0
- package/dist/lib/notifications.js +81 -0
- package/dist/lib/prompt-builder.d.ts +70 -0
- package/dist/lib/prompt-builder.d.ts.map +1 -0
- package/dist/lib/prompt-builder.js +344 -0
- package/dist/lib/prompt-registry.d.ts +22 -0
- package/dist/lib/prompt-registry.d.ts.map +1 -0
- package/dist/lib/prompt-registry.js +409 -0
- package/dist/lib/provider-defaults.json +32 -0
- package/dist/lib/storage/file-system.d.ts +57 -0
- package/dist/lib/storage/file-system.d.ts.map +1 -0
- package/dist/lib/storage/file-system.js +638 -0
- package/dist/lib/storage/storage-callbacks.d.ts +17 -0
- package/dist/lib/storage/storage-callbacks.d.ts.map +1 -0
- package/dist/lib/storage/storage-callbacks.js +94 -0
- package/dist/lib/storage/types.d.ts +43 -0
- package/dist/lib/storage/types.d.ts.map +1 -0
- package/dist/lib/storage/types.js +2 -0
- package/dist/lib/task-execution-core.d.ts +7 -0
- package/dist/lib/task-execution-core.d.ts.map +1 -0
- package/dist/lib/task-execution-core.js +381 -0
- package/dist/lib/task-execution.d.ts +7 -0
- package/dist/lib/task-execution.d.ts.map +1 -0
- package/dist/lib/task-execution.js +40 -0
- package/dist/lib/task-loop-execution.d.ts +7 -0
- package/dist/lib/task-loop-execution.d.ts.map +1 -0
- package/dist/lib/task-loop-execution.js +156 -0
- package/dist/lib/task-planning.d.ts +29 -0
- package/dist/lib/task-planning.d.ts.map +1 -0
- package/dist/lib/task-planning.js +103 -0
- package/dist/lib/task-review.d.ts +27 -0
- package/dist/lib/task-review.d.ts.map +1 -0
- package/dist/lib/task-review.js +103 -0
- package/dist/lib/validation.d.ts +26 -0
- package/dist/lib/validation.d.ts.map +1 -0
- package/dist/lib/validation.js +98 -0
- package/dist/prompts/documentation-detection.d.ts +2 -0
- package/dist/prompts/documentation-detection.d.ts.map +1 -0
- package/dist/prompts/documentation-detection.js +24 -0
- package/dist/prompts/documentation-recap.d.ts +3 -0
- package/dist/prompts/documentation-recap.d.ts.map +1 -0
- package/dist/prompts/documentation-recap.js +13 -0
- package/dist/prompts/index.d.ts +15 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +30 -0
- package/dist/prompts/prd-combination.d.ts +2 -0
- package/dist/prompts/prd-combination.d.ts.map +1 -0
- package/dist/prompts/prd-combination.js +35 -0
- package/dist/prompts/prd-generation.d.ts +2 -0
- package/dist/prompts/prd-generation.d.ts.map +1 -0
- package/dist/prompts/prd-generation.js +49 -0
- package/dist/prompts/prd-parsing.d.ts +3 -0
- package/dist/prompts/prd-parsing.d.ts.map +1 -0
- package/dist/prompts/prd-parsing.js +172 -0
- package/dist/prompts/prd-question-answer.d.ts +3 -0
- package/dist/prompts/prd-question-answer.d.ts.map +1 -0
- package/dist/prompts/prd-question-answer.js +27 -0
- package/dist/prompts/prd-question.d.ts +3 -0
- package/dist/prompts/prd-question.d.ts.map +1 -0
- package/dist/prompts/prd-question.js +40 -0
- package/dist/prompts/prd-rework.d.ts +3 -0
- package/dist/prompts/prd-rework.d.ts.map +1 -0
- package/dist/prompts/prd-rework.js +81 -0
- package/dist/prompts/prd-suggest-stack.d.ts +3 -0
- package/dist/prompts/prd-suggest-stack.d.ts.map +1 -0
- package/dist/prompts/prd-suggest-stack.js +99 -0
- package/dist/prompts/task-breakdown.d.ts +3 -0
- package/dist/prompts/task-breakdown.d.ts.map +1 -0
- package/dist/prompts/task-breakdown.js +151 -0
- package/dist/prompts/task-enhancement.d.ts +3 -0
- package/dist/prompts/task-enhancement.d.ts.map +1 -0
- package/dist/prompts/task-enhancement.js +140 -0
- package/dist/prompts/task-execution.d.ts +3 -0
- package/dist/prompts/task-execution.d.ts.map +1 -0
- package/dist/prompts/task-execution.js +24 -0
- package/dist/prompts/task-planning.d.ts +3 -0
- package/dist/prompts/task-planning.d.ts.map +1 -0
- package/dist/prompts/task-planning.js +66 -0
- package/dist/prompts/workflow-assistance.d.ts +32 -0
- package/dist/prompts/workflow-assistance.d.ts.map +1 -0
- package/dist/prompts/workflow-assistance.js +130 -0
- package/dist/prompts/workflow-prompts.d.ts +9 -0
- package/dist/prompts/workflow-prompts.d.ts.map +1 -0
- package/dist/prompts/workflow-prompts.js +93 -0
- package/dist/services/benchmark.d.ts +26 -0
- package/dist/services/benchmark.d.ts.map +1 -0
- package/dist/services/benchmark.js +343 -0
- package/dist/services/prd.d.ts +136 -0
- package/dist/services/prd.d.ts.map +1 -0
- package/dist/services/prd.js +550 -0
- package/dist/services/tasks.d.ts +388 -0
- package/dist/services/tasks.d.ts.map +1 -0
- package/dist/services/tasks.js +1150 -0
- package/dist/services/workflow-ai-assistant.d.ts +74 -0
- package/dist/services/workflow-ai-assistant.d.ts.map +1 -0
- package/dist/services/workflow-ai-assistant.js +175 -0
- package/dist/services/workflow-benchmark.d.ts +34 -0
- package/dist/services/workflow-benchmark.d.ts.map +1 -0
- package/dist/services/workflow-benchmark.js +318 -0
- package/dist/services/workflow.d.ts +107 -0
- package/dist/services/workflow.d.ts.map +1 -0
- package/dist/services/workflow.js +580 -0
- package/dist/test/hooks.test.d.ts +2 -0
- package/dist/test/hooks.test.d.ts.map +1 -0
- package/dist/test/hooks.test.js +67 -0
- package/dist/test/integration/callbacks.test.d.ts +2 -0
- package/dist/test/integration/callbacks.test.d.ts.map +1 -0
- package/dist/test/integration/callbacks.test.js +64 -0
- package/dist/test/lib/ai-service/task-operations.test.d.ts +2 -0
- package/dist/test/lib/ai-service/task-operations.test.d.ts.map +1 -0
- package/dist/test/lib/ai-service/task-operations.test.js +362 -0
- package/dist/test/lib/config.test.d.ts +2 -0
- package/dist/test/lib/config.test.d.ts.map +1 -0
- package/dist/test/lib/config.test.js +128 -0
- package/dist/test/lib/git-utils.test.d.ts +2 -0
- package/dist/test/lib/git-utils.test.d.ts.map +1 -0
- package/dist/test/lib/git-utils.test.js +168 -0
- package/dist/test/mocks/mock-ai-operations.d.ts +15 -0
- package/dist/test/mocks/mock-ai-operations.d.ts.map +1 -0
- package/dist/test/mocks/mock-ai-operations.js +107 -0
- package/dist/test/mocks/mock-context-builder.d.ts +10 -0
- package/dist/test/mocks/mock-context-builder.d.ts.map +1 -0
- package/dist/test/mocks/mock-context-builder.js +81 -0
- package/dist/test/mocks/mock-model-provider.d.ts +7 -0
- package/dist/test/mocks/mock-model-provider.d.ts.map +1 -0
- package/dist/test/mocks/mock-model-provider.js +21 -0
- package/dist/test/mocks/mock-service-factory.d.ts +11 -0
- package/dist/test/mocks/mock-service-factory.d.ts.map +1 -0
- package/dist/test/mocks/mock-service-factory.js +61 -0
- package/dist/test/mocks/mock-storage.d.ts +50 -0
- package/dist/test/mocks/mock-storage.d.ts.map +1 -0
- package/dist/test/mocks/mock-storage.js +145 -0
- package/dist/test/model-parsing.test.d.ts +2 -0
- package/dist/test/model-parsing.test.d.ts.map +1 -0
- package/dist/test/model-parsing.test.js +73 -0
- package/dist/test/services/task-service.test.d.ts +2 -0
- package/dist/test/services/task-service.test.d.ts.map +1 -0
- package/dist/test/services/task-service.test.js +459 -0
- package/dist/test/storage.test.d.ts +2 -0
- package/dist/test/storage.test.d.ts.map +1 -0
- package/dist/test/storage.test.js +207 -0
- package/dist/test/task-loop-git.test.d.ts +2 -0
- package/dist/test/task-loop-git.test.d.ts.map +1 -0
- package/dist/test/task-loop-git.test.js +95 -0
- package/dist/test/test-mock-setup.d.ts +26 -0
- package/dist/test/test-mock-setup.d.ts.map +1 -0
- package/dist/test/test-mock-setup.js +41 -0
- package/dist/test/test-setup.d.ts +9 -0
- package/dist/test/test-setup.d.ts.map +1 -0
- package/dist/test/test-setup.js +44 -0
- package/dist/test/test-utils.d.ts +22 -0
- package/dist/test/test-utils.d.ts.map +1 -0
- package/dist/test/test-utils.js +37 -0
- package/dist/test/utils/ai-operation-utility.test.d.ts +2 -0
- package/dist/test/utils/ai-operation-utility.test.d.ts.map +1 -0
- package/dist/test/utils/ai-operation-utility.test.js +290 -0
- package/dist/test/utils/error-handling.test.d.ts +2 -0
- package/dist/test/utils/error-handling.test.d.ts.map +1 -0
- package/dist/test/utils/error-handling.test.js +231 -0
- package/dist/test/utils/file-utils.test.d.ts +2 -0
- package/dist/test/utils/file-utils.test.d.ts.map +1 -0
- package/dist/test/utils/file-utils.test.js +76 -0
- package/dist/test/utils/id-generator.test.d.ts +2 -0
- package/dist/test/utils/id-generator.test.d.ts.map +1 -0
- package/dist/test/utils/id-generator.test.js +41 -0
- package/dist/test/utils/model-parser.test.d.ts +2 -0
- package/dist/test/utils/model-parser.test.d.ts.map +1 -0
- package/dist/test/utils/model-parser.test.js +65 -0
- package/dist/test/validation.test.d.ts +2 -0
- package/dist/test/validation.test.d.ts.map +1 -0
- package/dist/test/validation.test.js +22 -0
- package/dist/types/callbacks.d.ts +30 -0
- package/dist/types/callbacks.d.ts.map +1 -0
- package/dist/types/callbacks.js +2 -0
- package/dist/types/index.d.ts +435 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +30 -0
- package/dist/types/mcp.d.ts +3 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +3 -0
- package/dist/types/options.d.ts +112 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/options.js +2 -0
- package/dist/types/results.d.ts +200 -0
- package/dist/types/results.d.ts.map +1 -0
- package/dist/types/results.js +2 -0
- package/dist/types/workflow-options.d.ts +82 -0
- package/dist/types/workflow-options.d.ts.map +1 -0
- package/dist/types/workflow-options.js +2 -0
- package/dist/types/workflow-results.d.ts +82 -0
- package/dist/types/workflow-results.d.ts.map +1 -0
- package/dist/types/workflow-results.js +2 -0
- package/dist/utils/ai-config-builder.d.ts +14 -0
- package/dist/utils/ai-config-builder.d.ts.map +1 -0
- package/dist/utils/ai-config-builder.js +22 -0
- package/dist/utils/ai-operation-utility.d.ts +142 -0
- package/dist/utils/ai-operation-utility.d.ts.map +1 -0
- package/dist/utils/ai-operation-utility.js +303 -0
- package/dist/utils/ai-service-factory.d.ts +34 -0
- package/dist/utils/ai-service-factory.d.ts.map +1 -0
- package/dist/utils/ai-service-factory.js +99 -0
- package/dist/utils/error-utils.d.ts +70 -0
- package/dist/utils/error-utils.d.ts.map +1 -0
- package/dist/utils/error-utils.js +104 -0
- package/dist/utils/file-utils.d.ts +107 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +171 -0
- package/dist/utils/id-generator.d.ts +92 -0
- package/dist/utils/id-generator.d.ts.map +1 -0
- package/dist/utils/id-generator.js +146 -0
- package/dist/utils/metadata-utils.d.ts +40 -0
- package/dist/utils/metadata-utils.d.ts.map +1 -0
- package/dist/utils/metadata-utils.js +43 -0
- package/dist/utils/model-executor-parser.d.ts +38 -0
- package/dist/utils/model-executor-parser.d.ts.map +1 -0
- package/dist/utils/model-executor-parser.js +69 -0
- package/dist/utils/model-parser.d.ts +6 -0
- package/dist/utils/model-parser.d.ts.map +1 -0
- package/dist/utils/model-parser.js +49 -0
- package/dist/utils/stack-formatter.d.ts +12 -0
- package/dist/utils/stack-formatter.d.ts.map +1 -0
- package/dist/utils/stack-formatter.js +36 -0
- package/dist/utils/storage-utils.d.ts +49 -0
- package/dist/utils/storage-utils.d.ts.map +1 -0
- package/dist/utils/storage-utils.js +80 -0
- package/dist/utils/streaming-utils.d.ts +38 -0
- package/dist/utils/streaming-utils.d.ts.map +1 -0
- package/dist/utils/streaming-utils.js +64 -0
- package/dist/utils/task-o-matic-error.d.ts +206 -0
- package/dist/utils/task-o-matic-error.d.ts.map +1 -0
- package/dist/utils/task-o-matic-error.js +304 -0
- package/package.json +40 -0
- package/src/index.ts +36 -0
- package/src/lib/ai-service/ai-operations.ts +310 -0
- package/src/lib/ai-service/base-operations.ts +139 -0
- package/src/lib/ai-service/documentation-operations.ts +438 -0
- package/src/lib/ai-service/filesystem-tools.ts +73 -0
- package/src/lib/ai-service/gemini-proxy.ts.bak +52 -0
- package/src/lib/ai-service/json-parser.ts +203 -0
- package/src/lib/ai-service/mcp-client.ts +54 -0
- package/src/lib/ai-service/model-provider.ts +192 -0
- package/src/lib/ai-service/prd-operations.ts +854 -0
- package/src/lib/ai-service/research-tools.ts +207 -0
- package/src/lib/ai-service/retry-handler.ts +89 -0
- package/src/lib/ai-service/task-operations.ts +342 -0
- package/src/lib/benchmark/registry.ts +307 -0
- package/src/lib/benchmark/runner.ts +190 -0
- package/src/lib/benchmark/storage.ts +140 -0
- package/src/lib/benchmark/types.ts +121 -0
- package/src/lib/better-t-stack-cli.ts +524 -0
- package/src/lib/bootstrap/cli-bootstrap.ts +397 -0
- package/src/lib/bootstrap/index.ts +2 -0
- package/src/lib/bootstrap/medusa-bootstrap.ts +261 -0
- package/src/lib/config-validation.ts +278 -0
- package/src/lib/config.ts +435 -0
- package/src/lib/context-builder.ts +383 -0
- package/src/lib/executors/claude-code-executor.ts +83 -0
- package/src/lib/executors/codex-executor.ts +85 -0
- package/src/lib/executors/executor-factory.ts +28 -0
- package/src/lib/executors/gemini-executor.ts +80 -0
- package/src/lib/executors/kilo-executor.ts +83 -0
- package/src/lib/executors/opencode-executor.ts +81 -0
- package/src/lib/git-utils.ts +334 -0
- package/src/lib/hooks.ts +121 -0
- package/src/lib/index.ts +166 -0
- package/src/lib/logger.ts +43 -0
- package/src/lib/notifications.ts +103 -0
- package/src/lib/prompt-builder.ts +471 -0
- package/src/lib/prompt-registry.ts +491 -0
- package/src/lib/provider-defaults.json +32 -0
- package/src/lib/storage/file-system.ts +864 -0
- package/src/lib/storage/storage-callbacks.ts +120 -0
- package/src/lib/storage/types.ts +58 -0
- package/src/lib/task-execution-core.ts +591 -0
- package/src/lib/task-execution.ts +59 -0
- package/src/lib/task-loop-execution.ts +214 -0
- package/src/lib/task-planning.ts +157 -0
- package/src/lib/task-review.ts +138 -0
- package/src/lib/validation.ts +140 -0
- package/src/prompts/documentation-detection.ts +21 -0
- package/src/prompts/documentation-recap.ts +11 -0
- package/src/prompts/index.ts +14 -0
- package/src/prompts/prd-combination.ts +32 -0
- package/src/prompts/prd-generation.ts +46 -0
- package/src/prompts/prd-parsing.ts +170 -0
- package/src/prompts/prd-question-answer.ts +25 -0
- package/src/prompts/prd-question.ts +38 -0
- package/src/prompts/prd-rework.ts +79 -0
- package/src/prompts/prd-suggest-stack.ts +97 -0
- package/src/prompts/task-breakdown.ts +149 -0
- package/src/prompts/task-enhancement.ts +138 -0
- package/src/prompts/task-execution.ts +22 -0
- package/src/prompts/task-planning.ts +64 -0
- package/src/prompts/workflow-assistance.ts +151 -0
- package/src/prompts/workflow-prompts.ts +97 -0
- package/src/services/benchmark.ts +433 -0
- package/src/services/prd.ts +845 -0
- package/src/services/tasks.ts +1515 -0
- package/src/services/workflow-ai-assistant.ts +298 -0
- package/src/services/workflow-benchmark.ts +339 -0
- package/src/services/workflow.ts +779 -0
- package/src/test/hooks.test.ts +77 -0
- package/src/test/integration/callbacks.test.ts +39 -0
- package/src/test/lib/ai-service/task-operations.test.ts +430 -0
- package/src/test/lib/config.test.ts +150 -0
- package/src/test/lib/git-utils.test.ts +198 -0
- package/src/test/mocks/mock-ai-operations.ts +205 -0
- package/src/test/mocks/mock-context-builder.ts +84 -0
- package/src/test/mocks/mock-model-provider.ts +21 -0
- package/src/test/mocks/mock-service-factory.ts +64 -0
- package/src/test/mocks/mock-storage.ts +204 -0
- package/src/test/model-parsing.test.ts +78 -0
- package/src/test/services/task-service.test.ts +551 -0
- package/src/test/storage.test.ts +206 -0
- package/src/test/task-loop-git.test.ts +142 -0
- package/src/test/test-mock-setup.ts +46 -0
- package/src/test/test-setup.ts +48 -0
- package/src/test/test-utils.ts +45 -0
- package/src/test/utils/ai-operation-utility.test.ts +306 -0
- package/src/test/utils/error-handling.test.ts +241 -0
- package/src/test/utils/file-utils.test.ts +80 -0
- package/src/test/utils/id-generator.test.ts +44 -0
- package/src/test/utils/model-parser.test.ts +67 -0
- package/src/test/validation.test.ts +19 -0
- package/src/types/callbacks.ts +14 -0
- package/src/types/index.ts +628 -0
- package/src/types/mcp.ts +5 -0
- package/src/types/options.ts +165 -0
- package/src/types/results.ts +216 -0
- package/src/types/workflow-options.ts +113 -0
- package/src/types/workflow-results.ts +87 -0
- package/src/utils/ai-config-builder.ts +33 -0
- package/src/utils/ai-operation-utility.ts +380 -0
- package/src/utils/ai-service-factory.ts +125 -0
- package/src/utils/error-utils.ts +124 -0
- package/src/utils/file-utils.ts +197 -0
- package/src/utils/id-generator.ts +168 -0
- package/src/utils/metadata-utils.ts +48 -0
- package/src/utils/model-executor-parser.ts +80 -0
- package/src/utils/model-parser.ts +58 -0
- package/src/utils/stack-formatter.ts +53 -0
- package/src/utils/storage-utils.ts +94 -0
- package/src/utils/streaming-utils.ts +91 -0
- package/src/utils/task-o-matic-error.ts +393 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
import { streamText } from "ai";
|
|
2
|
+
import type { ToolSet } from "ai";
|
|
3
|
+
import { AIConfig, StreamingOptions, RetryConfig } from "../types";
|
|
4
|
+
import { BaseOperations } from "../lib/ai-service/base-operations";
|
|
5
|
+
import { TaskOMaticError } from "./task-o-matic-error";
|
|
6
|
+
|
|
7
|
+
export interface AIOperationResult<T> {
|
|
8
|
+
result: T;
|
|
9
|
+
metrics: {
|
|
10
|
+
duration: number;
|
|
11
|
+
tokenUsage?: {
|
|
12
|
+
prompt: number;
|
|
13
|
+
completion: number;
|
|
14
|
+
total: number;
|
|
15
|
+
};
|
|
16
|
+
timeToFirstToken?: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface AIOperationOptions {
|
|
21
|
+
streamingOptions?: StreamingOptions;
|
|
22
|
+
retryConfig?: Partial<RetryConfig>;
|
|
23
|
+
aiConfig?: Partial<AIConfig>;
|
|
24
|
+
enableFilesystemTools?: boolean;
|
|
25
|
+
context?: Record<string, unknown>;
|
|
26
|
+
maxRetries?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* AIOperationUtility - Centralized utility for AI operations with metrics and error handling
|
|
31
|
+
*
|
|
32
|
+
* Extends BaseOperations to inherit core AI functionality (streamText, model provider, etc.)
|
|
33
|
+
* and adds standardized metrics collection, error handling, and retry logic.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const utility = new AIOperationUtility();
|
|
38
|
+
*
|
|
39
|
+
* // Execute operation with metrics
|
|
40
|
+
* const result = await utility.executeAIOperation(
|
|
41
|
+
* "Task breakdown",
|
|
42
|
+
* async () => performBreakdown(task),
|
|
43
|
+
* {
|
|
44
|
+
* maxRetries: 3,
|
|
45
|
+
* streamingOptions: { onChunk: console.log }
|
|
46
|
+
* }
|
|
47
|
+
* );
|
|
48
|
+
*
|
|
49
|
+
* console.log(result.metrics.duration);
|
|
50
|
+
* console.log(result.metrics.timeToFirstToken);
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export class AIOperationUtility extends BaseOperations {
|
|
54
|
+
/**
|
|
55
|
+
* Execute an AI operation with standardized metrics, error handling, and streaming support
|
|
56
|
+
*
|
|
57
|
+
* This method wraps AI operations to provide:
|
|
58
|
+
* - Automatic retry logic with configurable attempts
|
|
59
|
+
* - Metrics collection (duration, token usage, time to first token)
|
|
60
|
+
* - Error handling with TaskOMaticError wrapping
|
|
61
|
+
* - Streaming support with metrics capture
|
|
62
|
+
*
|
|
63
|
+
* @param operationName - Human-readable name for the operation (used in errors)
|
|
64
|
+
* @param operation - The async operation to execute
|
|
65
|
+
* @param options - Configuration options for retry, streaming, and AI config
|
|
66
|
+
* @returns Promise resolving to AIOperationResult with result and metrics
|
|
67
|
+
* @throws {TaskOMaticError} If operation fails after all retry attempts
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* try {
|
|
72
|
+
* const result = await utility.executeAIOperation(
|
|
73
|
+
* "Task enhancement",
|
|
74
|
+
* async () => enhanceTask(task),
|
|
75
|
+
* { maxRetries: 2 }
|
|
76
|
+
* );
|
|
77
|
+
* console.log(`Operation took ${result.metrics.duration}ms`);
|
|
78
|
+
* } catch (error) {
|
|
79
|
+
* if (error instanceof TaskOMaticError) {
|
|
80
|
+
* console.error(error.getDetails());
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
async executeAIOperation<T>(
|
|
86
|
+
operationName: string,
|
|
87
|
+
operation: () => Promise<T>,
|
|
88
|
+
options: AIOperationOptions = {}
|
|
89
|
+
): Promise<AIOperationResult<T>> {
|
|
90
|
+
const startTime = Date.now();
|
|
91
|
+
let timeToFirstToken: number | undefined;
|
|
92
|
+
|
|
93
|
+
// Create wrapped streaming options to capture metrics
|
|
94
|
+
const wrappedStreamingOptions = this.wrapStreamingOptions(
|
|
95
|
+
options.streamingOptions,
|
|
96
|
+
startTime,
|
|
97
|
+
(time) => {
|
|
98
|
+
timeToFirstToken = time;
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
// Execute with retry logic
|
|
104
|
+
const result = await this.retryHandler.executeWithRetry(
|
|
105
|
+
async () => {
|
|
106
|
+
// Execute operation - note: operations should use the streaming options
|
|
107
|
+
// passed through the closure, not directly from options
|
|
108
|
+
return await operation();
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
maxAttempts:
|
|
112
|
+
options.maxRetries || options.retryConfig?.maxAttempts || 2,
|
|
113
|
+
...options.retryConfig,
|
|
114
|
+
},
|
|
115
|
+
operationName
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const duration = Date.now() - startTime;
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
result,
|
|
122
|
+
metrics: {
|
|
123
|
+
duration,
|
|
124
|
+
timeToFirstToken,
|
|
125
|
+
tokenUsage: this.extractTokenUsageFromResult(result),
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const duration = Date.now() - startTime;
|
|
130
|
+
const typedError =
|
|
131
|
+
error instanceof Error ? error : new Error(String(error));
|
|
132
|
+
|
|
133
|
+
// THROW error instead of returning it
|
|
134
|
+
throw new TaskOMaticError(
|
|
135
|
+
`AI operation failed: ${operationName} - ${this.getErrorMessage(
|
|
136
|
+
typedError
|
|
137
|
+
)}`,
|
|
138
|
+
{
|
|
139
|
+
code: "AI_OPERATION_FAILED",
|
|
140
|
+
context: JSON.stringify({
|
|
141
|
+
operation: operationName,
|
|
142
|
+
duration,
|
|
143
|
+
error: this.getErrorMessage(typedError),
|
|
144
|
+
}),
|
|
145
|
+
cause: typedError,
|
|
146
|
+
suggestions: [
|
|
147
|
+
"Check AI configuration",
|
|
148
|
+
"Verify network connectivity",
|
|
149
|
+
"Review operation parameters",
|
|
150
|
+
"Check API keys and endpoints",
|
|
151
|
+
],
|
|
152
|
+
metadata: {
|
|
153
|
+
operationName,
|
|
154
|
+
duration,
|
|
155
|
+
attemptedRetries: options.maxRetries || 2,
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Standardized streaming text operation with tool support
|
|
164
|
+
*
|
|
165
|
+
* This method provides a unified interface for AI text generation with:
|
|
166
|
+
* - Optional tool integration (filesystem, MCP, etc.)
|
|
167
|
+
* - Streaming support with callbacks
|
|
168
|
+
* - Context7 documentation caching
|
|
169
|
+
* - Metrics collection
|
|
170
|
+
* - Error handling
|
|
171
|
+
*
|
|
172
|
+
* @param systemPrompt - System prompt for the AI
|
|
173
|
+
* @param userMessage - User message/prompt
|
|
174
|
+
* @param config - Optional AI configuration overrides
|
|
175
|
+
* @param streamingOptions - Optional streaming callbacks
|
|
176
|
+
* @param tools - Optional tool set to provide to the AI
|
|
177
|
+
* @returns Promise resolving to the generated text
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* const result = await utility.streamTextWithTools(
|
|
182
|
+
* "You are a helpful assistant",
|
|
183
|
+
* "Explain quantum computing",
|
|
184
|
+
* undefined,
|
|
185
|
+
* { onChunk: (chunk) => console.log(chunk) },
|
|
186
|
+
* filesystemTools
|
|
187
|
+
* );
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
async streamTextWithTools(
|
|
191
|
+
systemPrompt: string,
|
|
192
|
+
userMessage: string,
|
|
193
|
+
config?: Partial<AIConfig>,
|
|
194
|
+
streamingOptions?: StreamingOptions,
|
|
195
|
+
tools?: ToolSet
|
|
196
|
+
): Promise<string> {
|
|
197
|
+
const aiConfig = this.mergeAIConfig(config);
|
|
198
|
+
const model = this.modelProvider.getModel(aiConfig);
|
|
199
|
+
|
|
200
|
+
// Create streaming configuration with Context7 handling and callbacks
|
|
201
|
+
const streamConfig = this.createStreamingConfig(streamingOptions);
|
|
202
|
+
|
|
203
|
+
let accumulatedText = "";
|
|
204
|
+
const originalOnChunk = streamConfig.onChunk;
|
|
205
|
+
|
|
206
|
+
// Wrap onChunk to accumulate text locally
|
|
207
|
+
streamConfig.onChunk = (event: any) => {
|
|
208
|
+
// Debug log for chunk structure
|
|
209
|
+
// console.log(
|
|
210
|
+
// `[DEBUG] Chunk type: ${event.chunk?.type} | keys: ${Object.keys(
|
|
211
|
+
// event.chunk || {}
|
|
212
|
+
// ).join(",")}`
|
|
213
|
+
// );
|
|
214
|
+
|
|
215
|
+
if (
|
|
216
|
+
event.chunk?.type === "text-delta" &&
|
|
217
|
+
typeof event.chunk.text === "string"
|
|
218
|
+
) {
|
|
219
|
+
accumulatedText += event.chunk.text;
|
|
220
|
+
// } else {
|
|
221
|
+
// console.log(
|
|
222
|
+
// `[DEBUG] Ignored chunk content:`,
|
|
223
|
+
// JSON.stringify(event.chunk)
|
|
224
|
+
// );
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (originalOnChunk) {
|
|
228
|
+
originalOnChunk(event);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
const result = await streamText({
|
|
233
|
+
model,
|
|
234
|
+
tools: tools || {},
|
|
235
|
+
system: systemPrompt,
|
|
236
|
+
messages: [{ role: "user", content: userMessage }],
|
|
237
|
+
maxRetries: 0,
|
|
238
|
+
...streamConfig,
|
|
239
|
+
...(aiConfig.provider === "openrouter" &&
|
|
240
|
+
aiConfig.reasoning &&
|
|
241
|
+
aiConfig.reasoning.maxTokens
|
|
242
|
+
? {
|
|
243
|
+
providerOptions: {
|
|
244
|
+
openrouter: {
|
|
245
|
+
reasoning: {
|
|
246
|
+
max_tokens: aiConfig.reasoning.maxTokens,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
}
|
|
251
|
+
: {}),
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const fullText = await result.text;
|
|
255
|
+
return fullText || accumulatedText;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Wrap streaming options to capture metrics
|
|
260
|
+
*
|
|
261
|
+
* @private
|
|
262
|
+
*/
|
|
263
|
+
private wrapStreamingOptions(
|
|
264
|
+
streamingOptions: StreamingOptions | undefined,
|
|
265
|
+
startTime: number,
|
|
266
|
+
onFirstToken: (time: number) => void
|
|
267
|
+
): StreamingOptions | undefined {
|
|
268
|
+
if (!streamingOptions) {
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let firstTokenCaptured = false;
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
...streamingOptions,
|
|
276
|
+
onChunk: (chunk: string) => {
|
|
277
|
+
if (!firstTokenCaptured && chunk.trim()) {
|
|
278
|
+
onFirstToken(Date.now() - startTime);
|
|
279
|
+
firstTokenCaptured = true;
|
|
280
|
+
}
|
|
281
|
+
streamingOptions.onChunk?.(chunk);
|
|
282
|
+
},
|
|
283
|
+
onFinish: (result: any) => {
|
|
284
|
+
streamingOptions.onFinish?.(result);
|
|
285
|
+
},
|
|
286
|
+
onReasoning: (reasoning: string) => {
|
|
287
|
+
streamingOptions.onReasoning?.(reasoning);
|
|
288
|
+
},
|
|
289
|
+
onError: (error: unknown) => {
|
|
290
|
+
streamingOptions.onError?.(error as Error);
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Create streaming configuration with Context7 handling and callbacks
|
|
297
|
+
*
|
|
298
|
+
* This method creates a unified streaming configuration that:
|
|
299
|
+
* - Always handles Context7 tool-result events (even without streaming UI)
|
|
300
|
+
* - Forwards text-delta events to onChunk callback
|
|
301
|
+
* - Forwards reasoning-delta events to onReasoning callback
|
|
302
|
+
* - Handles errors with onError callback
|
|
303
|
+
* - Provides onFinish callback with completion data
|
|
304
|
+
*
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
private createStreamingConfig(streamingOptions?: StreamingOptions) {
|
|
308
|
+
return {
|
|
309
|
+
onChunk:
|
|
310
|
+
streamingOptions?.onChunk || streamingOptions?.onReasoning
|
|
311
|
+
? (event: any) => {
|
|
312
|
+
// Handle Context7 tool results ALWAYS (critical for caching)
|
|
313
|
+
this.handleContext7ToolResult(event.chunk);
|
|
314
|
+
|
|
315
|
+
// Forward text deltas to user callback
|
|
316
|
+
if (event.chunk?.type === "text-delta") {
|
|
317
|
+
streamingOptions?.onChunk?.(event.chunk.text);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Forward reasoning deltas to user callback
|
|
321
|
+
if (event.chunk?.type === "reasoning-delta") {
|
|
322
|
+
streamingOptions?.onReasoning?.(event.chunk.text);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
: undefined,
|
|
326
|
+
onFinish: streamingOptions?.onFinish
|
|
327
|
+
? (event: any) => {
|
|
328
|
+
streamingOptions.onFinish!({
|
|
329
|
+
text: event.text,
|
|
330
|
+
finishReason: event.finishReason,
|
|
331
|
+
usage: event.usage,
|
|
332
|
+
isAborted: false,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
: undefined,
|
|
336
|
+
onError: streamingOptions?.onError
|
|
337
|
+
? (event: any) => {
|
|
338
|
+
streamingOptions.onError!(event.error);
|
|
339
|
+
}
|
|
340
|
+
: undefined,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Extract token usage from AI result
|
|
346
|
+
*
|
|
347
|
+
* @private
|
|
348
|
+
*/
|
|
349
|
+
private extractTokenUsageFromResult(result: any):
|
|
350
|
+
| {
|
|
351
|
+
prompt: number;
|
|
352
|
+
completion: number;
|
|
353
|
+
total: number;
|
|
354
|
+
}
|
|
355
|
+
| undefined {
|
|
356
|
+
if (result && result.usage) {
|
|
357
|
+
return {
|
|
358
|
+
prompt: result.usage.prompt_tokens || 0,
|
|
359
|
+
completion: result.usage.completion_tokens || 0,
|
|
360
|
+
total: result.usage.total_tokens || 0,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Get error message from any error type
|
|
368
|
+
*
|
|
369
|
+
* @private
|
|
370
|
+
*/
|
|
371
|
+
private getErrorMessage(error: unknown): string {
|
|
372
|
+
if (error instanceof Error) {
|
|
373
|
+
return error.message;
|
|
374
|
+
} else if (typeof error === "string") {
|
|
375
|
+
return error;
|
|
376
|
+
} else {
|
|
377
|
+
return "Unknown error";
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { FileSystemStorage } from "../lib/storage/file-system";
|
|
2
|
+
import { TaskRepository } from "../lib/storage/types";
|
|
3
|
+
import { ContextBuilder, ContextCallbacks } from "../lib/context-builder";
|
|
4
|
+
import { existsSync } from "fs";
|
|
5
|
+
import { configManager, ConfigCallbacks } from "../lib/config";
|
|
6
|
+
import { AIOperations } from "../lib/ai-service/ai-operations";
|
|
7
|
+
import { ModelProvider } from "../lib/ai-service/model-provider";
|
|
8
|
+
import { StorageCallbacks } from "../lib/storage/storage-callbacks";
|
|
9
|
+
import {
|
|
10
|
+
createStandardError,
|
|
11
|
+
TaskOMaticErrorCodes,
|
|
12
|
+
} from "./task-o-matic-error";
|
|
13
|
+
|
|
14
|
+
export interface ServiceOptions {
|
|
15
|
+
storageCallbacks?: StorageCallbacks;
|
|
16
|
+
configCallbacks?: ConfigCallbacks;
|
|
17
|
+
contextCallbacks?: ContextCallbacks;
|
|
18
|
+
workingDirectory?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let aiOperations: AIOperations | null = null;
|
|
22
|
+
let modelProvider: ModelProvider | null = null;
|
|
23
|
+
let storage: TaskRepository | null = null;
|
|
24
|
+
let contextBuilder: ContextBuilder | null = null;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Initialize services with optional custom callbacks.
|
|
28
|
+
* This is the entry point for web applications or custom environments.
|
|
29
|
+
* It also ensures configuration is loaded asynchronously.
|
|
30
|
+
*/
|
|
31
|
+
export async function initializeServices(
|
|
32
|
+
options: ServiceOptions = {}
|
|
33
|
+
): Promise<void> {
|
|
34
|
+
if (options.workingDirectory) {
|
|
35
|
+
configManager.setWorkingDirectory(options.workingDirectory);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (options.configCallbacks) {
|
|
39
|
+
configManager.setCallbacks(options.configCallbacks);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Ensure config is loaded (async)
|
|
43
|
+
await configManager.load();
|
|
44
|
+
|
|
45
|
+
// Initialize storage
|
|
46
|
+
// If storageCallbacks provided, use them.
|
|
47
|
+
// If not, FileSystemStorage will use default callbacks (which use configManager.getTaskOMaticDir)
|
|
48
|
+
storage = new FileSystemStorage(options.storageCallbacks);
|
|
49
|
+
|
|
50
|
+
// Initialize context builder
|
|
51
|
+
contextBuilder = new ContextBuilder(storage, options.contextCallbacks);
|
|
52
|
+
|
|
53
|
+
// Reset other services to ensure they use fresh dependencies if needed
|
|
54
|
+
aiOperations = null;
|
|
55
|
+
modelProvider = null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getAIOperations(): AIOperations {
|
|
59
|
+
if (!aiOperations) {
|
|
60
|
+
aiOperations = new AIOperations();
|
|
61
|
+
}
|
|
62
|
+
return aiOperations;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getModelProvider(): ModelProvider {
|
|
66
|
+
if (!modelProvider) {
|
|
67
|
+
modelProvider = new ModelProvider();
|
|
68
|
+
}
|
|
69
|
+
return modelProvider;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getStorage(): TaskRepository {
|
|
73
|
+
if (!storage) {
|
|
74
|
+
// Default behavior for CLI (if initializeServices wasn't called)
|
|
75
|
+
|
|
76
|
+
// Ensure we're in a task-o-matic project before creating storage
|
|
77
|
+
// We use configManager (sync path) to check existence.
|
|
78
|
+
const taskOMaticDir = configManager.getTaskOMaticDir();
|
|
79
|
+
|
|
80
|
+
// Note: This check relies on FS. Web apps should call initializeServices first.
|
|
81
|
+
if (!existsSync(taskOMaticDir)) {
|
|
82
|
+
throw createStandardError(
|
|
83
|
+
TaskOMaticErrorCodes.CONFIGURATION_ERROR,
|
|
84
|
+
"Not a task-o-matic project. Run 'task-o-matic init' first.",
|
|
85
|
+
{
|
|
86
|
+
suggestions: ["Run `task-o-matic init` in your project root."],
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
storage = new FileSystemStorage();
|
|
92
|
+
}
|
|
93
|
+
return storage;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getContextBuilder(): ContextBuilder {
|
|
97
|
+
if (!contextBuilder) {
|
|
98
|
+
const storage = getStorage();
|
|
99
|
+
contextBuilder = new ContextBuilder(storage);
|
|
100
|
+
}
|
|
101
|
+
return contextBuilder;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function resetServiceInstances(): void {
|
|
105
|
+
aiOperations = null;
|
|
106
|
+
modelProvider = null;
|
|
107
|
+
storage = null;
|
|
108
|
+
contextBuilder = null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* FOR TESTING ONLY: Inject mock instances
|
|
113
|
+
* This allows tests to provide mock implementations without complex module mocking
|
|
114
|
+
*/
|
|
115
|
+
export function injectTestInstances(instances: {
|
|
116
|
+
storage?: TaskRepository;
|
|
117
|
+
aiOperations?: AIOperations;
|
|
118
|
+
modelProvider?: ModelProvider;
|
|
119
|
+
contextBuilder?: ContextBuilder;
|
|
120
|
+
}): void {
|
|
121
|
+
if (instances.storage) storage = instances.storage;
|
|
122
|
+
if (instances.aiOperations) aiOperations = instances.aiOperations;
|
|
123
|
+
if (instances.modelProvider) modelProvider = instances.modelProvider;
|
|
124
|
+
if (instances.contextBuilder) contextBuilder = instances.contextBuilder;
|
|
125
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createStandardError,
|
|
3
|
+
TaskOMaticErrorCodes,
|
|
4
|
+
} from "./task-o-matic-error";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Extracts a readable error message from an unknown error value.
|
|
8
|
+
* Handles Error objects, strings, objects with message property, and unknown types.
|
|
9
|
+
*
|
|
10
|
+
* @param error - The error value to extract message from
|
|
11
|
+
* @returns A string error message
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* try {
|
|
16
|
+
* throw new Error("Something went wrong");
|
|
17
|
+
* } catch (error) {
|
|
18
|
+
* console.log(getErrorMessage(error)); // "Something went wrong"
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function getErrorMessage(error: unknown): string {
|
|
23
|
+
// Error instance
|
|
24
|
+
if (error instanceof Error) {
|
|
25
|
+
return error.message;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// String error
|
|
29
|
+
if (typeof error === "string") {
|
|
30
|
+
return error;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Object with message property
|
|
34
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
35
|
+
return String(error.message);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Unknown type - convert to string
|
|
39
|
+
return "Unknown error occurred";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Formats an error with optional context information.
|
|
44
|
+
* Useful for adding context to error messages when rethrowing.
|
|
45
|
+
*
|
|
46
|
+
* @param error - The error value
|
|
47
|
+
* @param context - Optional context string to prepend to the error message
|
|
48
|
+
* @returns Formatted error message
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* try {
|
|
53
|
+
* await fetchData();
|
|
54
|
+
* } catch (error) {
|
|
55
|
+
* throw new Error(formatError(error, "Failed to fetch data"));
|
|
56
|
+
* // Result: "Failed to fetch data: Connection timeout"
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function formatError(error: unknown, context?: string): string {
|
|
61
|
+
const message = getErrorMessage(error);
|
|
62
|
+
return context ? `${context}: ${message}` : message;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates an error with a formatted message including context.
|
|
67
|
+
*
|
|
68
|
+
* @param error - The original error
|
|
69
|
+
* @param context - Context to add to the error
|
|
70
|
+
* @returns A new TaskOMaticError instance with formatted message
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* try {
|
|
75
|
+
* await operation();
|
|
76
|
+
* } catch (error) {
|
|
77
|
+
* throw createContextError(error, "Operation failed");
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function createContextError(
|
|
82
|
+
error: unknown,
|
|
83
|
+
context: string
|
|
84
|
+
): import("./task-o-matic-error").TaskOMaticError {
|
|
85
|
+
return createStandardError(
|
|
86
|
+
TaskOMaticErrorCodes.UNEXPECTED_ERROR,
|
|
87
|
+
formatError(error, context),
|
|
88
|
+
{ cause: error instanceof Error ? error : undefined }
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Type guard to check if an error is an Error instance.
|
|
94
|
+
*
|
|
95
|
+
* @param error - Value to check
|
|
96
|
+
* @returns true if error is an Error instance
|
|
97
|
+
*/
|
|
98
|
+
export function isError(error: unknown): error is Error {
|
|
99
|
+
return error instanceof Error;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Safely converts any value to an Error instance.
|
|
104
|
+
* If the value is already an Error, returns it unchanged.
|
|
105
|
+
* Otherwise, creates a new Error with the string representation.
|
|
106
|
+
*
|
|
107
|
+
* @param error - Value to convert
|
|
108
|
+
* @returns An Error instance
|
|
109
|
+
*/
|
|
110
|
+
export function toError(
|
|
111
|
+
error: unknown
|
|
112
|
+
): import("./task-o-matic-error").TaskOMaticError {
|
|
113
|
+
if (error instanceof Error) {
|
|
114
|
+
return createStandardError(
|
|
115
|
+
TaskOMaticErrorCodes.UNEXPECTED_ERROR,
|
|
116
|
+
error.message,
|
|
117
|
+
{ cause: error }
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return createStandardError(
|
|
121
|
+
TaskOMaticErrorCodes.UNEXPECTED_ERROR,
|
|
122
|
+
getErrorMessage(error)
|
|
123
|
+
);
|
|
124
|
+
}
|