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,550 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.prdService = exports.PRDService = void 0;
|
|
37
|
+
exports.getPRDService = getPRDService;
|
|
38
|
+
const task_o_matic_error_1 = require("../utils/task-o-matic-error");
|
|
39
|
+
const fs_1 = require("fs");
|
|
40
|
+
const path_1 = require("path");
|
|
41
|
+
const ai_service_factory_1 = require("../utils/ai-service-factory");
|
|
42
|
+
const ai_config_builder_1 = require("../utils/ai-config-builder");
|
|
43
|
+
const config_1 = require("../lib/config");
|
|
44
|
+
const validation_1 = require("../lib/validation");
|
|
45
|
+
const streaming_utils_1 = require("../utils/streaming-utils");
|
|
46
|
+
const file_utils_1 = require("../utils/file-utils");
|
|
47
|
+
/**
|
|
48
|
+
* PRDService - Business logic for PRD operations
|
|
49
|
+
* Handles PRD parsing, task extraction, and PRD improvement
|
|
50
|
+
*/
|
|
51
|
+
class PRDService {
|
|
52
|
+
storage;
|
|
53
|
+
aiOperations;
|
|
54
|
+
/**
|
|
55
|
+
* Create a new PRDService
|
|
56
|
+
*
|
|
57
|
+
* @param dependencies - Optional dependencies to inject (for testing)
|
|
58
|
+
*/
|
|
59
|
+
constructor(dependencies = {}) {
|
|
60
|
+
// Use injected dependencies or fall back to singletons
|
|
61
|
+
this.storage = dependencies.storage ?? (0, ai_service_factory_1.getStorage)();
|
|
62
|
+
this.aiOperations = dependencies.aiOperations ?? (0, ai_service_factory_1.getAIOperations)();
|
|
63
|
+
}
|
|
64
|
+
async parsePRD(input) {
|
|
65
|
+
const startTime = Date.now();
|
|
66
|
+
const steps = [];
|
|
67
|
+
input.callbacks?.onProgress?.({
|
|
68
|
+
type: "started",
|
|
69
|
+
message: "Starting PRD parsing...",
|
|
70
|
+
});
|
|
71
|
+
// Validate file exists (DRY fix 1.2)
|
|
72
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
73
|
+
// Ensure we're in a task-o-matic project
|
|
74
|
+
const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
|
|
75
|
+
if (!(0, fs_1.existsSync)(taskOMaticDir)) {
|
|
76
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.CONFIGURATION_ERROR, "Not a task-o-matic project. Run 'task-o-matic init init' first.", {
|
|
77
|
+
suggestions: ["Run `task-o-matic init init` in your project root."],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
81
|
+
const workingDir = input.workingDirectory || process.cwd();
|
|
82
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
83
|
+
input.callbacks?.onProgress?.({
|
|
84
|
+
type: "progress",
|
|
85
|
+
message: "Reading PRD file...",
|
|
86
|
+
});
|
|
87
|
+
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
88
|
+
// Save PRD file to .task-o-matic/prd directory
|
|
89
|
+
input.callbacks?.onProgress?.({
|
|
90
|
+
type: "progress",
|
|
91
|
+
message: "Saving PRD to project directory...",
|
|
92
|
+
});
|
|
93
|
+
const stepStart1 = Date.now();
|
|
94
|
+
const prdDir = (0, path_1.join)(taskOMaticDir, "prd");
|
|
95
|
+
const prdFileName = (0, path_1.basename)(input.file);
|
|
96
|
+
const savedPrdPath = (0, path_1.join)(prdDir, prdFileName);
|
|
97
|
+
// Ensure PRD directory exists
|
|
98
|
+
if (!(0, fs_1.existsSync)(prdDir)) {
|
|
99
|
+
(0, fs_1.mkdirSync)(prdDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
// Copy PRD file to project directory
|
|
102
|
+
(0, fs_1.copyFileSync)(input.file, savedPrdPath);
|
|
103
|
+
// Get relative path from .task-o-matic directory for storage
|
|
104
|
+
const relativePrdPath = (0, path_1.relative)(taskOMaticDir, savedPrdPath);
|
|
105
|
+
steps.push({
|
|
106
|
+
step: "Save PRD File",
|
|
107
|
+
status: "completed",
|
|
108
|
+
duration: Date.now() - stepStart1,
|
|
109
|
+
});
|
|
110
|
+
// Validate AI provider if specified
|
|
111
|
+
if (input.aiOptions?.aiProvider &&
|
|
112
|
+
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
113
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
114
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
118
|
+
input.callbacks?.onProgress?.({
|
|
119
|
+
type: "progress",
|
|
120
|
+
message: "Parsing PRD with AI...",
|
|
121
|
+
});
|
|
122
|
+
const stepStart2 = Date.now();
|
|
123
|
+
// Use utility to wrap streaming options and capture metrics (DRY fix 1.1)
|
|
124
|
+
const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, stepStart2);
|
|
125
|
+
const result = await this.aiOperations.parsePRD(prdContent, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
|
|
126
|
+
workingDir, // Pass working directory to AI operations
|
|
127
|
+
input.enableFilesystemTools);
|
|
128
|
+
// Extract metrics after AI call
|
|
129
|
+
const { tokenUsage, timeToFirstToken } = getMetrics();
|
|
130
|
+
steps.push({
|
|
131
|
+
step: "AI Parsing",
|
|
132
|
+
status: "completed",
|
|
133
|
+
duration: Date.now() - stepStart2,
|
|
134
|
+
details: { tasksFound: result.tasks.length },
|
|
135
|
+
});
|
|
136
|
+
input.callbacks?.onProgress?.({
|
|
137
|
+
type: "progress",
|
|
138
|
+
message: `Creating ${result.tasks.length} tasks...`,
|
|
139
|
+
});
|
|
140
|
+
// Create tasks
|
|
141
|
+
const stepStart3 = Date.now();
|
|
142
|
+
const createdTasks = [];
|
|
143
|
+
for (let i = 0; i < result.tasks.length; i++) {
|
|
144
|
+
const task = result.tasks[i];
|
|
145
|
+
input.callbacks?.onProgress?.({
|
|
146
|
+
type: "progress",
|
|
147
|
+
message: `Creating task ${i + 1}/${result.tasks.length}: ${task.title}`,
|
|
148
|
+
current: i + 1,
|
|
149
|
+
total: result.tasks.length,
|
|
150
|
+
});
|
|
151
|
+
const createdTask = await this.storage.createTask({
|
|
152
|
+
id: task.id, // Preserve AI-generated ID for dependencies
|
|
153
|
+
title: task.title,
|
|
154
|
+
description: task.description,
|
|
155
|
+
content: task.content,
|
|
156
|
+
estimatedEffort: task.estimatedEffort,
|
|
157
|
+
status: "todo",
|
|
158
|
+
dependencies: task.dependencies,
|
|
159
|
+
tags: task.tags,
|
|
160
|
+
prdFile: relativePrdPath, // Reference to the PRD file
|
|
161
|
+
});
|
|
162
|
+
createdTasks.push(createdTask);
|
|
163
|
+
// Update AI metadata with the actual task ID
|
|
164
|
+
const aiMetadata = {
|
|
165
|
+
taskId: createdTask.id,
|
|
166
|
+
aiGenerated: true,
|
|
167
|
+
aiPrompt: input.promptOverride || "Parse PRD and extract tasks",
|
|
168
|
+
confidence: result.confidence,
|
|
169
|
+
aiProvider: input.aiOptions?.aiProvider,
|
|
170
|
+
aiModel: input.aiOptions?.aiModel,
|
|
171
|
+
generatedAt: Date.now(),
|
|
172
|
+
};
|
|
173
|
+
await this.storage.saveTaskAIMetadata(aiMetadata);
|
|
174
|
+
}
|
|
175
|
+
steps.push({
|
|
176
|
+
step: "Create Tasks",
|
|
177
|
+
status: "completed",
|
|
178
|
+
duration: Date.now() - stepStart3,
|
|
179
|
+
details: { count: createdTasks.length },
|
|
180
|
+
});
|
|
181
|
+
input.callbacks?.onProgress?.({
|
|
182
|
+
type: "completed",
|
|
183
|
+
message: `Successfully created ${createdTasks.length} tasks from PRD`,
|
|
184
|
+
});
|
|
185
|
+
const duration = Date.now() - startTime;
|
|
186
|
+
// Calculate cost if token usage is available
|
|
187
|
+
let cost;
|
|
188
|
+
if (tokenUsage) {
|
|
189
|
+
// Cost calculation would depend on the model
|
|
190
|
+
// For now, we'll leave it undefined and can add pricing later
|
|
191
|
+
// This matches the benchmark pattern where cost calculation is done elsewhere
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
success: true,
|
|
195
|
+
prd: {
|
|
196
|
+
overview: result.summary || "",
|
|
197
|
+
objectives: [],
|
|
198
|
+
features: [],
|
|
199
|
+
},
|
|
200
|
+
tasks: createdTasks,
|
|
201
|
+
stats: {
|
|
202
|
+
tasksCreated: createdTasks.length,
|
|
203
|
+
duration,
|
|
204
|
+
aiProvider: input.aiOptions?.aiProvider || "default",
|
|
205
|
+
aiModel: input.aiOptions?.aiModel || "default",
|
|
206
|
+
tokenUsage,
|
|
207
|
+
timeToFirstToken,
|
|
208
|
+
cost,
|
|
209
|
+
},
|
|
210
|
+
steps,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
async generateQuestions(input) {
|
|
214
|
+
input.callbacks?.onProgress?.({
|
|
215
|
+
type: "started",
|
|
216
|
+
message: "Generating clarifying questions...",
|
|
217
|
+
});
|
|
218
|
+
// Validate file exists (DRY fix 1.2)
|
|
219
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
220
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
221
|
+
const workingDir = input.workingDirectory || process.cwd();
|
|
222
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
223
|
+
input.callbacks?.onProgress?.({
|
|
224
|
+
type: "progress",
|
|
225
|
+
message: "Reading PRD file...",
|
|
226
|
+
});
|
|
227
|
+
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
228
|
+
if (input.aiOptions?.aiProvider &&
|
|
229
|
+
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
230
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
231
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
235
|
+
input.callbacks?.onProgress?.({
|
|
236
|
+
type: "progress",
|
|
237
|
+
message: "Analyzing PRD with AI...",
|
|
238
|
+
});
|
|
239
|
+
const questions = await this.aiOperations.generatePRDQuestions(prdContent, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, workingDir, input.enableFilesystemTools);
|
|
240
|
+
input.callbacks?.onProgress?.({
|
|
241
|
+
type: "completed",
|
|
242
|
+
message: `Generated ${questions.length} questions`,
|
|
243
|
+
});
|
|
244
|
+
return questions;
|
|
245
|
+
}
|
|
246
|
+
async reworkPRD(input) {
|
|
247
|
+
input.callbacks?.onProgress?.({
|
|
248
|
+
type: "started",
|
|
249
|
+
message: "Starting PRD improvement...",
|
|
250
|
+
});
|
|
251
|
+
// Validate file exists (DRY fix 1.2)
|
|
252
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
253
|
+
// Set working directory and reload config (DRY fix 1.4)
|
|
254
|
+
const workingDir = input.workingDirectory || process.cwd();
|
|
255
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
256
|
+
input.callbacks?.onProgress?.({
|
|
257
|
+
type: "progress",
|
|
258
|
+
message: "Reading PRD file...",
|
|
259
|
+
});
|
|
260
|
+
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
261
|
+
// Validate AI provider if specified
|
|
262
|
+
if (input.aiOptions?.aiProvider &&
|
|
263
|
+
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
264
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
265
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
269
|
+
input.callbacks?.onProgress?.({
|
|
270
|
+
type: "progress",
|
|
271
|
+
message: "Calling AI to improve PRD...",
|
|
272
|
+
});
|
|
273
|
+
const improvedPRD = await this.aiOperations.reworkPRD(prdContent, input.feedback, aiConfig, input.promptOverride, input.messageOverride, input.streamingOptions, undefined, // retryConfig
|
|
274
|
+
workingDir, // Pass working directory to AI operations
|
|
275
|
+
input.enableFilesystemTools);
|
|
276
|
+
input.callbacks?.onProgress?.({
|
|
277
|
+
type: "progress",
|
|
278
|
+
message: "Saving improved PRD...",
|
|
279
|
+
});
|
|
280
|
+
const outputPath = input.output || input.file;
|
|
281
|
+
(0, fs_1.writeFileSync)(outputPath, improvedPRD);
|
|
282
|
+
input.callbacks?.onProgress?.({
|
|
283
|
+
type: "completed",
|
|
284
|
+
message: `PRD improved and saved to ${outputPath}`,
|
|
285
|
+
});
|
|
286
|
+
return outputPath;
|
|
287
|
+
}
|
|
288
|
+
async refinePRDWithQuestions(input) {
|
|
289
|
+
input.callbacks?.onProgress?.({
|
|
290
|
+
type: "started",
|
|
291
|
+
message: "Starting PRD question/refine process...",
|
|
292
|
+
});
|
|
293
|
+
// Step 1: Generate questions
|
|
294
|
+
input.callbacks?.onProgress?.({
|
|
295
|
+
type: "progress",
|
|
296
|
+
message: "Generating clarifying questions...",
|
|
297
|
+
});
|
|
298
|
+
const questions = await this.generateQuestions({
|
|
299
|
+
file: input.file,
|
|
300
|
+
workingDirectory: input.workingDirectory,
|
|
301
|
+
enableFilesystemTools: input.enableFilesystemTools,
|
|
302
|
+
aiOptions: input.aiOptions,
|
|
303
|
+
streamingOptions: input.streamingOptions,
|
|
304
|
+
callbacks: input.callbacks,
|
|
305
|
+
});
|
|
306
|
+
if (questions.length === 0) {
|
|
307
|
+
input.callbacks?.onProgress?.({
|
|
308
|
+
type: "completed",
|
|
309
|
+
message: "No questions generated - PRD appears complete",
|
|
310
|
+
});
|
|
311
|
+
return {
|
|
312
|
+
questions: [],
|
|
313
|
+
answers: {},
|
|
314
|
+
refinedPRDPath: input.file,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
// Step 2: Get stack info for context
|
|
318
|
+
const workingDir = input.workingDirectory || process.cwd();
|
|
319
|
+
const PromptBuilder = (await Promise.resolve().then(() => __importStar(require("../lib/prompt-builder")))).PromptBuilder;
|
|
320
|
+
let stackInfo = "";
|
|
321
|
+
try {
|
|
322
|
+
stackInfo = await PromptBuilder.detectStackInfo(workingDir);
|
|
323
|
+
if (stackInfo === "Not detected") {
|
|
324
|
+
stackInfo = "";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
catch (error) {
|
|
328
|
+
// Stack info not available
|
|
329
|
+
}
|
|
330
|
+
// Step 3: Get answers
|
|
331
|
+
let answers;
|
|
332
|
+
if (input.questionMode === "user") {
|
|
333
|
+
// User mode: return questions for CLI to prompt user
|
|
334
|
+
// Answers should be provided in input.answers
|
|
335
|
+
if (!input.answers || Object.keys(input.answers).length === 0) {
|
|
336
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "User mode selected but no answers provided. CLI layer should collect answers.");
|
|
337
|
+
}
|
|
338
|
+
answers = input.answers;
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
// AI mode: use AI to answer questions with context
|
|
342
|
+
input.callbacks?.onProgress?.({
|
|
343
|
+
type: "progress",
|
|
344
|
+
message: "AI is answering questions...",
|
|
345
|
+
});
|
|
346
|
+
const prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
347
|
+
// Use questionAIOptions if provided, otherwise use main aiOptions
|
|
348
|
+
const answeringAIConfig = (0, ai_config_builder_1.buildAIConfig)(input.questionAIOptions || input.aiOptions);
|
|
349
|
+
answers = await this.aiOperations.answerPRDQuestions(prdContent, questions, answeringAIConfig, {
|
|
350
|
+
stackInfo,
|
|
351
|
+
}, input.streamingOptions);
|
|
352
|
+
}
|
|
353
|
+
// Step 4: Format questions + answers as structured feedback
|
|
354
|
+
let feedback = "Please incorporate the following clarifications into the PRD:\n\n";
|
|
355
|
+
questions.forEach((q, i) => {
|
|
356
|
+
feedback += `Q${i + 1}: ${q}\nA: ${answers[q] || "No answer provided"}\n\n`;
|
|
357
|
+
});
|
|
358
|
+
// Step 5: Automatically call reworkPRD with formatted feedback
|
|
359
|
+
input.callbacks?.onProgress?.({
|
|
360
|
+
type: "progress",
|
|
361
|
+
message: "Refining PRD with answers...",
|
|
362
|
+
});
|
|
363
|
+
const refinedPRDPath = await this.reworkPRD({
|
|
364
|
+
file: input.file,
|
|
365
|
+
feedback,
|
|
366
|
+
workingDirectory: input.workingDirectory,
|
|
367
|
+
enableFilesystemTools: input.enableFilesystemTools,
|
|
368
|
+
aiOptions: input.aiOptions,
|
|
369
|
+
streamingOptions: input.streamingOptions,
|
|
370
|
+
callbacks: input.callbacks,
|
|
371
|
+
});
|
|
372
|
+
input.callbacks?.onProgress?.({
|
|
373
|
+
type: "completed",
|
|
374
|
+
message: `PRD refined with ${questions.length} questions answered`,
|
|
375
|
+
});
|
|
376
|
+
return {
|
|
377
|
+
questions,
|
|
378
|
+
answers,
|
|
379
|
+
refinedPRDPath,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
async generatePRD(input) {
|
|
383
|
+
const startTime = Date.now();
|
|
384
|
+
input.callbacks?.onProgress?.({
|
|
385
|
+
type: "started",
|
|
386
|
+
message: "Generating PRD...",
|
|
387
|
+
});
|
|
388
|
+
// Use utility to wrap streaming options and capture metrics
|
|
389
|
+
const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
|
|
390
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
391
|
+
const content = await this.aiOperations.generatePRD(input.description, aiConfig, undefined, undefined, metricsStreamingOptions);
|
|
392
|
+
// Get metrics after AI operation
|
|
393
|
+
const { tokenUsage, timeToFirstToken } = getMetrics();
|
|
394
|
+
// Calculate cost if needed
|
|
395
|
+
let cost;
|
|
396
|
+
if (tokenUsage && tokenUsage.total > 0) {
|
|
397
|
+
cost = tokenUsage.total * 0.000001; // Placeholder cost calculation
|
|
398
|
+
}
|
|
399
|
+
// Save file using utility
|
|
400
|
+
const path = (0, file_utils_1.savePRDFile)(content, input.filename, input.outputDir);
|
|
401
|
+
input.callbacks?.onProgress?.({
|
|
402
|
+
type: "completed",
|
|
403
|
+
message: `PRD generated and saved to ${path}`,
|
|
404
|
+
});
|
|
405
|
+
return {
|
|
406
|
+
path,
|
|
407
|
+
content,
|
|
408
|
+
stats: {
|
|
409
|
+
duration: Date.now() - startTime,
|
|
410
|
+
tokenUsage,
|
|
411
|
+
timeToFirstToken,
|
|
412
|
+
cost,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
async combinePRDs(input) {
|
|
417
|
+
const startTime = Date.now();
|
|
418
|
+
input.callbacks?.onProgress?.({
|
|
419
|
+
type: "started",
|
|
420
|
+
message: "Combining PRDs...",
|
|
421
|
+
});
|
|
422
|
+
// Use utility to wrap streaming options and capture metrics
|
|
423
|
+
const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
|
|
424
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
425
|
+
const content = await this.aiOperations.combinePRDs(input.prds, input.originalDescription, aiConfig, undefined, undefined, metricsStreamingOptions);
|
|
426
|
+
// Get metrics after AI operation
|
|
427
|
+
const { tokenUsage, timeToFirstToken } = getMetrics();
|
|
428
|
+
// Calculate cost if needed
|
|
429
|
+
let cost;
|
|
430
|
+
if (tokenUsage && tokenUsage.total > 0) {
|
|
431
|
+
cost = tokenUsage.total * 0.000001;
|
|
432
|
+
}
|
|
433
|
+
// Save file using utility (defaults to "prd.md" if no filename, so we provide the default for combinePRDs)
|
|
434
|
+
const path = (0, file_utils_1.savePRDFile)(content, input.filename || "prd-master.md", input.outputDir);
|
|
435
|
+
input.callbacks?.onProgress?.({
|
|
436
|
+
type: "completed",
|
|
437
|
+
message: `Master PRD saved to ${path}`,
|
|
438
|
+
});
|
|
439
|
+
return {
|
|
440
|
+
path,
|
|
441
|
+
content,
|
|
442
|
+
stats: {
|
|
443
|
+
duration: Date.now() - startTime,
|
|
444
|
+
tokenUsage,
|
|
445
|
+
timeToFirstToken,
|
|
446
|
+
cost,
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Suggest a technology stack based on PRD analysis.
|
|
452
|
+
*/
|
|
453
|
+
async suggestStack(input) {
|
|
454
|
+
const startTime = Date.now();
|
|
455
|
+
input.callbacks?.onProgress?.({
|
|
456
|
+
type: "started",
|
|
457
|
+
message: "Analyzing PRD for stack suggestion...",
|
|
458
|
+
});
|
|
459
|
+
// Validate mutual exclusivity
|
|
460
|
+
if (input.file && input.content) {
|
|
461
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Cannot specify both --file and --content", {
|
|
462
|
+
suggestions: ["Use either --file OR --content, not both."],
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
if (!input.file && !input.content) {
|
|
466
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.INVALID_INPUT, "Must specify either --file or --content", {
|
|
467
|
+
suggestions: [
|
|
468
|
+
"Provide a PRD file with --file or content with --content.",
|
|
469
|
+
],
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
// Get PRD content
|
|
473
|
+
let prdContent;
|
|
474
|
+
if (input.file) {
|
|
475
|
+
(0, file_utils_1.validateFileExists)(input.file, `PRD file not found: ${input.file}`);
|
|
476
|
+
prdContent = (0, fs_1.readFileSync)(input.file, "utf-8");
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
prdContent = input.content;
|
|
480
|
+
}
|
|
481
|
+
// Set working directory
|
|
482
|
+
const workingDir = input.workingDirectory || process.cwd();
|
|
483
|
+
await (0, config_1.setupWorkingDirectory)(workingDir);
|
|
484
|
+
// Validate AI provider if specified
|
|
485
|
+
if (input.aiOptions?.aiProvider &&
|
|
486
|
+
!(0, validation_1.isValidAIProvider)(input.aiOptions.aiProvider)) {
|
|
487
|
+
throw (0, task_o_matic_error_1.createStandardError)(task_o_matic_error_1.TaskOMaticErrorCodes.AI_CONFIGURATION_ERROR, `Invalid AI provider: ${input.aiOptions.aiProvider}`, {
|
|
488
|
+
suggestions: ["Use a valid AI provider, e.g., 'openai', 'anthropic'"],
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
const aiConfig = (0, ai_config_builder_1.buildAIConfig)(input.aiOptions);
|
|
492
|
+
input.callbacks?.onProgress?.({
|
|
493
|
+
type: "progress",
|
|
494
|
+
message: "Calling AI to analyze PRD...",
|
|
495
|
+
});
|
|
496
|
+
// Use utility to wrap streaming options and capture metrics
|
|
497
|
+
const { options: metricsStreamingOptions, getMetrics } = (0, streaming_utils_1.createMetricsStreamingOptions)(input.streamingOptions, startTime);
|
|
498
|
+
const result = await this.aiOperations.suggestStack(prdContent, input.projectName, aiConfig, input.promptOverride, input.messageOverride, metricsStreamingOptions, undefined, // retryConfig
|
|
499
|
+
workingDir, input.enableFilesystemTools);
|
|
500
|
+
// Get metrics after AI operation
|
|
501
|
+
const { tokenUsage, timeToFirstToken } = getMetrics();
|
|
502
|
+
// Calculate cost if needed
|
|
503
|
+
let cost;
|
|
504
|
+
if (tokenUsage && tokenUsage.total > 0) {
|
|
505
|
+
cost = tokenUsage.total * 0.000001; // Placeholder cost calculation
|
|
506
|
+
}
|
|
507
|
+
// Save if requested
|
|
508
|
+
let savedPath;
|
|
509
|
+
if (input.save || input.output) {
|
|
510
|
+
input.callbacks?.onProgress?.({
|
|
511
|
+
type: "progress",
|
|
512
|
+
message: "Saving stack configuration...",
|
|
513
|
+
});
|
|
514
|
+
savedPath = (0, file_utils_1.saveStackFile)(result.config, input.output);
|
|
515
|
+
}
|
|
516
|
+
input.callbacks?.onProgress?.({
|
|
517
|
+
type: "completed",
|
|
518
|
+
message: savedPath
|
|
519
|
+
? `Stack suggestion saved to ${savedPath}`
|
|
520
|
+
: "Stack suggestion complete",
|
|
521
|
+
});
|
|
522
|
+
return {
|
|
523
|
+
success: true,
|
|
524
|
+
stack: result.config,
|
|
525
|
+
reasoning: result.reasoning,
|
|
526
|
+
savedPath,
|
|
527
|
+
stats: {
|
|
528
|
+
duration: Date.now() - startTime,
|
|
529
|
+
tokenUsage,
|
|
530
|
+
timeToFirstToken,
|
|
531
|
+
cost,
|
|
532
|
+
},
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
exports.PRDService = PRDService;
|
|
537
|
+
// Lazy singleton instance - only created when first accessed
|
|
538
|
+
let prdServiceInstance;
|
|
539
|
+
function getPRDService() {
|
|
540
|
+
if (!prdServiceInstance) {
|
|
541
|
+
prdServiceInstance = new PRDService();
|
|
542
|
+
}
|
|
543
|
+
return prdServiceInstance;
|
|
544
|
+
}
|
|
545
|
+
// Backward compatibility: export as const but use getter
|
|
546
|
+
exports.prdService = new Proxy({}, {
|
|
547
|
+
get(target, prop) {
|
|
548
|
+
return getPRDService()[prop];
|
|
549
|
+
},
|
|
550
|
+
});
|