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,83 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
import type { ExecutorConfig, ExternalExecutor } from "../../types";
|
|
4
|
+
import { logger } from "../logger";
|
|
5
|
+
|
|
6
|
+
export class KiloExecutor implements ExternalExecutor {
|
|
7
|
+
name = "kilo";
|
|
8
|
+
private config?: ExecutorConfig;
|
|
9
|
+
|
|
10
|
+
constructor(config?: ExecutorConfig) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
supportsSessionResumption(): boolean {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async execute(
|
|
19
|
+
message: string,
|
|
20
|
+
dry: boolean = false,
|
|
21
|
+
config?: ExecutorConfig
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
// Merge constructor config with execution config (execution takes precedence)
|
|
24
|
+
const finalConfig = { ...this.config, ...config };
|
|
25
|
+
|
|
26
|
+
// Build arguments array
|
|
27
|
+
const args: string[] = [];
|
|
28
|
+
|
|
29
|
+
// Add model if specified
|
|
30
|
+
if (finalConfig.model) {
|
|
31
|
+
args.push("-mo", finalConfig.model);
|
|
32
|
+
logger.progress(`🤖 Using model: ${finalConfig.model}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Add session resumption if specified
|
|
36
|
+
if (finalConfig.continueLastSession) {
|
|
37
|
+
args.push("-c");
|
|
38
|
+
logger.progress("🔄 Continuing last session");
|
|
39
|
+
} else if (finalConfig.sessionId) {
|
|
40
|
+
args.push("-s", finalConfig.sessionId);
|
|
41
|
+
logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Run in autonomous mode (non-interactive) for automation
|
|
45
|
+
args.push("--auto");
|
|
46
|
+
|
|
47
|
+
// Enable auto-approval of all tool permissions
|
|
48
|
+
args.push("--yolo");
|
|
49
|
+
|
|
50
|
+
// Add prompt as positional argument
|
|
51
|
+
args.push(message);
|
|
52
|
+
|
|
53
|
+
if (dry) {
|
|
54
|
+
logger.progress(`🔧 Using executor: ${this.name}`);
|
|
55
|
+
logger.progress(`kilocode ${args.join(" ")}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Launch kilocode and wait for it to complete
|
|
60
|
+
const child = spawn("kilocode", args, {
|
|
61
|
+
stdio: "inherit", // Give tool full terminal control
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Wait for completion (blocking)
|
|
65
|
+
await new Promise<void>((resolve, reject) => {
|
|
66
|
+
child.on("close", (code: number) => {
|
|
67
|
+
if (code === 0) {
|
|
68
|
+
logger.success("✅ Kilo Code execution completed successfully");
|
|
69
|
+
resolve();
|
|
70
|
+
} else {
|
|
71
|
+
const error = new Error(`Kilo Code exited with code ${code}`);
|
|
72
|
+
logger.error(`❌ ${error.message}`);
|
|
73
|
+
reject(error);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
child.on("error", (error: Error) => {
|
|
78
|
+
logger.error(`❌ Failed to launch Kilo Code: ${error.message}`);
|
|
79
|
+
reject(error);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
import type { ExecutorConfig, ExternalExecutor } from "../../types";
|
|
4
|
+
import { logger } from "../logger";
|
|
5
|
+
|
|
6
|
+
export class OpencodeExecutor implements ExternalExecutor {
|
|
7
|
+
name = "opencode";
|
|
8
|
+
private config?: ExecutorConfig;
|
|
9
|
+
|
|
10
|
+
constructor(config?: ExecutorConfig) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
supportsSessionResumption(): boolean {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async execute(
|
|
19
|
+
message: string,
|
|
20
|
+
dry: boolean = false,
|
|
21
|
+
config?: ExecutorConfig
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
// Merge constructor config with execution config (execution takes precedence)
|
|
24
|
+
const finalConfig = { ...this.config, ...config };
|
|
25
|
+
|
|
26
|
+
// Build arguments array
|
|
27
|
+
const args: string[] = [];
|
|
28
|
+
|
|
29
|
+
// Add model if specified
|
|
30
|
+
if (finalConfig.model) {
|
|
31
|
+
args.push("-m", finalConfig.model);
|
|
32
|
+
logger.progress(`🤖 Using model: ${finalConfig.model}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Add session resumption if specified
|
|
36
|
+
if (finalConfig.continueLastSession) {
|
|
37
|
+
args.push("-c");
|
|
38
|
+
logger.progress("🔄 Continuing last session");
|
|
39
|
+
} else if (finalConfig.sessionId) {
|
|
40
|
+
args.push("-s", finalConfig.sessionId);
|
|
41
|
+
logger.progress(`🔄 Resuming session: ${finalConfig.sessionId}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Use 'run' subcommand with message as positional argument
|
|
45
|
+
args.push("run", message);
|
|
46
|
+
|
|
47
|
+
if (dry) {
|
|
48
|
+
logger.progress(`🔧 Using executor: ${this.name}`);
|
|
49
|
+
// Quote arguments that contain spaces for display
|
|
50
|
+
const quotedArgs = args.map((arg) =>
|
|
51
|
+
arg.includes(" ") ? `"${arg.replace(/"/g, '\\"')}"` : arg
|
|
52
|
+
);
|
|
53
|
+
logger.progress(`opencode ${quotedArgs.join(" ")}`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Launch opencode and wait for it to complete
|
|
58
|
+
const child = spawn("opencode", args, {
|
|
59
|
+
stdio: "inherit", // Give tool full terminal control
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Wait for completion (blocking)
|
|
63
|
+
await new Promise<void>((resolve, reject) => {
|
|
64
|
+
child.on("close", (code: number) => {
|
|
65
|
+
if (code === 0) {
|
|
66
|
+
logger.success("✅ Opencode execution completed successfully");
|
|
67
|
+
resolve();
|
|
68
|
+
} else {
|
|
69
|
+
const error = new Error(`Opencode exited with code ${code}`);
|
|
70
|
+
logger.error(`❌ ${error.message}`);
|
|
71
|
+
reject(error);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
child.on("error", (error: Error) => {
|
|
76
|
+
logger.error(`❌ Failed to launch opencode: ${error.message}`);
|
|
77
|
+
reject(error);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { logger } from "./logger";
|
|
4
|
+
import { getAIOperations } from "../utils/ai-service-factory";
|
|
5
|
+
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Git state captured before and after execution
|
|
10
|
+
*/
|
|
11
|
+
export interface GitState {
|
|
12
|
+
beforeHead: string;
|
|
13
|
+
afterHead: string;
|
|
14
|
+
hasUncommittedChanges: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Commit information extracted from git state
|
|
19
|
+
*/
|
|
20
|
+
export interface CommitInfo {
|
|
21
|
+
message: string;
|
|
22
|
+
files: string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Check if new commits were made since a given HEAD
|
|
27
|
+
* Used to detect if the AI agent already committed during execution
|
|
28
|
+
*/
|
|
29
|
+
export async function hasNewCommitsSince(
|
|
30
|
+
beforeHead: string,
|
|
31
|
+
execFn: (
|
|
32
|
+
command: string
|
|
33
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
34
|
+
): Promise<boolean> {
|
|
35
|
+
if (!beforeHead) return false;
|
|
36
|
+
try {
|
|
37
|
+
const { stdout } = await execFn("git rev-parse HEAD");
|
|
38
|
+
return stdout.trim() !== beforeHead;
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Capture git state (HEAD commit and uncommitted changes)
|
|
46
|
+
*/
|
|
47
|
+
export async function captureGitState(
|
|
48
|
+
execFn: (
|
|
49
|
+
command: string
|
|
50
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
51
|
+
): Promise<Partial<GitState>> {
|
|
52
|
+
try {
|
|
53
|
+
const { stdout: headStdout } = await execFn("git rev-parse HEAD");
|
|
54
|
+
const { stdout: statusStdout } = await execFn("git status --porcelain");
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
beforeHead: headStdout.trim(),
|
|
58
|
+
afterHead: headStdout.trim(),
|
|
59
|
+
hasUncommittedChanges: statusStdout.trim().length > 0,
|
|
60
|
+
};
|
|
61
|
+
} catch (e) {
|
|
62
|
+
// Git might not be initialized or no commits yet
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Extract commit message and file list from git state
|
|
69
|
+
* This function analyzes the actual git state to generate appropriate commit info
|
|
70
|
+
*/
|
|
71
|
+
export async function extractCommitInfo(
|
|
72
|
+
taskId: string,
|
|
73
|
+
taskTitle: string,
|
|
74
|
+
executionMessage: string,
|
|
75
|
+
gitState: GitState,
|
|
76
|
+
execFn: (
|
|
77
|
+
command: string
|
|
78
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync,
|
|
79
|
+
aiOps: any = getAIOperations()
|
|
80
|
+
): Promise<CommitInfo> {
|
|
81
|
+
try {
|
|
82
|
+
// Case 1: Executor created a commit
|
|
83
|
+
if (gitState.beforeHead !== gitState.afterHead) {
|
|
84
|
+
logger.info("📝 Executor created a commit, extracting info...");
|
|
85
|
+
const { stdout } = await execFn(
|
|
86
|
+
`git show --stat --format="%s%n%b" ${gitState.afterHead}`
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const lines = stdout.trim().split("\n");
|
|
90
|
+
const message = lines[0].trim();
|
|
91
|
+
// Parse files from stat output (e.g. " src/file.ts | 10 +")
|
|
92
|
+
const files = lines
|
|
93
|
+
.slice(1)
|
|
94
|
+
.filter((line) => line.includes("|"))
|
|
95
|
+
.map((line) => line.split("|")[0].trim());
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
message,
|
|
99
|
+
files,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Case 2: Executor left uncommitted changes
|
|
104
|
+
if (gitState.hasUncommittedChanges) {
|
|
105
|
+
logger.info(
|
|
106
|
+
"📝 Uncommitted changes detected, generating commit message..."
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Get the diff to send to AI
|
|
110
|
+
const { stdout: diff } = await execFn("git diff HEAD");
|
|
111
|
+
|
|
112
|
+
// Get list of changed files
|
|
113
|
+
const { stdout: status } = await execFn("git status --porcelain");
|
|
114
|
+
const files = status
|
|
115
|
+
.split("\n")
|
|
116
|
+
.filter((line) => line.length > 0)
|
|
117
|
+
.map((line) => line.substring(3).trim())
|
|
118
|
+
.filter((file) => file.length > 0);
|
|
119
|
+
|
|
120
|
+
// Use AI to generate commit message based on the diff
|
|
121
|
+
const prompt = `Based on the following git diff, generate a concise git commit message.
|
|
122
|
+
|
|
123
|
+
Task: ${taskTitle}
|
|
124
|
+
|
|
125
|
+
Git Diff:
|
|
126
|
+
${diff.substring(0, 10000)} // Limit diff size
|
|
127
|
+
|
|
128
|
+
Please respond in JSON format:
|
|
129
|
+
{
|
|
130
|
+
"message": "concise commit message following conventional commits format"
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
The commit message should:
|
|
134
|
+
- Follow conventional commits format (feat:, fix:, refactor:, etc.)
|
|
135
|
+
- Be concise and descriptive
|
|
136
|
+
- Focus on what changed
|
|
137
|
+
`;
|
|
138
|
+
|
|
139
|
+
const response = await aiOps.streamText(
|
|
140
|
+
prompt,
|
|
141
|
+
undefined,
|
|
142
|
+
"You are a helpful assistant that generates git commit messages."
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// Try to parse JSON from response
|
|
146
|
+
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
147
|
+
let message = `feat: complete task ${taskTitle}`;
|
|
148
|
+
|
|
149
|
+
if (jsonMatch) {
|
|
150
|
+
try {
|
|
151
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
152
|
+
if (parsed.message) {
|
|
153
|
+
message = parsed.message;
|
|
154
|
+
}
|
|
155
|
+
} catch (e) {
|
|
156
|
+
// Ignore parse error
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
message,
|
|
162
|
+
files,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Case 3: No changes detected
|
|
167
|
+
return {
|
|
168
|
+
message: `feat: complete task ${taskTitle}`,
|
|
169
|
+
files: [],
|
|
170
|
+
};
|
|
171
|
+
} catch (error) {
|
|
172
|
+
logger.warn(
|
|
173
|
+
`⚠️ Failed to extract commit info: ${
|
|
174
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
175
|
+
}`
|
|
176
|
+
);
|
|
177
|
+
// Fallback commit info
|
|
178
|
+
return {
|
|
179
|
+
message: `feat: complete task ${taskTitle}`,
|
|
180
|
+
files: [],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Auto-commit changes using the provided commit info
|
|
187
|
+
*/
|
|
188
|
+
export async function autoCommit(
|
|
189
|
+
commitInfo: CommitInfo,
|
|
190
|
+
execFn: (
|
|
191
|
+
command: string
|
|
192
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
193
|
+
): Promise<void> {
|
|
194
|
+
try {
|
|
195
|
+
const { message, files } = commitInfo;
|
|
196
|
+
|
|
197
|
+
if (files.length > 0) {
|
|
198
|
+
// Stage specific files
|
|
199
|
+
const gitAdd = `git add ${files.join(" ")}`;
|
|
200
|
+
logger.info(`📦 Staging files: ${gitAdd}`);
|
|
201
|
+
await execFn(gitAdd);
|
|
202
|
+
} else {
|
|
203
|
+
// Stage all changes
|
|
204
|
+
logger.info("📦 Staging all changes");
|
|
205
|
+
await execFn("git add .");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Commit
|
|
209
|
+
const gitCommit = `git commit -m "${message}"`;
|
|
210
|
+
logger.info(`💾 Committing: ${message}`);
|
|
211
|
+
await execFn(gitCommit);
|
|
212
|
+
|
|
213
|
+
logger.success("✅ Changes committed successfully\n");
|
|
214
|
+
} catch (error) {
|
|
215
|
+
logger.warn(
|
|
216
|
+
`⚠️ Auto-commit failed: ${
|
|
217
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
218
|
+
}\n`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Commit a specific file with a custom message
|
|
225
|
+
*/
|
|
226
|
+
export async function commitFile(
|
|
227
|
+
filePath: string,
|
|
228
|
+
message: string,
|
|
229
|
+
execFn: (
|
|
230
|
+
command: string
|
|
231
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
232
|
+
): Promise<void> {
|
|
233
|
+
try {
|
|
234
|
+
logger.info(`📦 Staging file: ${filePath}`);
|
|
235
|
+
await execFn(`git add ${filePath}`);
|
|
236
|
+
await execFn(`git commit -m "${message}"`);
|
|
237
|
+
logger.success("✅ File committed successfully");
|
|
238
|
+
} catch (e) {
|
|
239
|
+
logger.warn(
|
|
240
|
+
`⚠️ Failed to commit file: ${
|
|
241
|
+
e instanceof Error ? e.message : "Unknown error"
|
|
242
|
+
}`
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ============================================================================
|
|
248
|
+
// Benchmarking Git Utilities
|
|
249
|
+
// ============================================================================
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Check if the working directory is clean
|
|
253
|
+
*/
|
|
254
|
+
export async function isClean(
|
|
255
|
+
execFn: (
|
|
256
|
+
command: string
|
|
257
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
258
|
+
): Promise<boolean> {
|
|
259
|
+
try {
|
|
260
|
+
const { stdout } = await execFn("git status --porcelain");
|
|
261
|
+
return stdout.trim().length === 0;
|
|
262
|
+
} catch (error) {
|
|
263
|
+
logger.warn("Could not check git status");
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get the current branch name
|
|
270
|
+
*/
|
|
271
|
+
export async function getCurrentBranch(
|
|
272
|
+
execFn: (
|
|
273
|
+
command: string
|
|
274
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
275
|
+
): Promise<string> {
|
|
276
|
+
try {
|
|
277
|
+
const { stdout } = await execFn("git rev-parse --abbrev-ref HEAD");
|
|
278
|
+
return stdout.trim();
|
|
279
|
+
} catch (error) {
|
|
280
|
+
throw new Error("Failed to get current branch");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Create a new branch for benchmarking
|
|
286
|
+
*/
|
|
287
|
+
export async function createBenchmarkBranch(
|
|
288
|
+
name: string,
|
|
289
|
+
baseBranch: string = "HEAD",
|
|
290
|
+
execFn: (
|
|
291
|
+
command: string
|
|
292
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
293
|
+
): Promise<void> {
|
|
294
|
+
try {
|
|
295
|
+
logger.info(`🌿 Creating benchmark branch: ${name} from ${baseBranch}`);
|
|
296
|
+
await execFn(`git checkout -b ${name} ${baseBranch}`);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
throw new Error(`Failed to create benchmark branch ${name}: ${error}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Checkout an existing branch
|
|
304
|
+
*/
|
|
305
|
+
export async function checkoutBranch(
|
|
306
|
+
name: string,
|
|
307
|
+
execFn: (
|
|
308
|
+
command: string
|
|
309
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
310
|
+
): Promise<void> {
|
|
311
|
+
try {
|
|
312
|
+
logger.info(`🌿 Checking out branch: ${name}`);
|
|
313
|
+
await execFn(`git checkout ${name}`);
|
|
314
|
+
} catch (error) {
|
|
315
|
+
throw new Error(`Failed to checkout branch ${name}: ${error}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Delete a benchmark branch (force delete)
|
|
321
|
+
*/
|
|
322
|
+
export async function cleanupBenchmarkBranch(
|
|
323
|
+
name: string,
|
|
324
|
+
execFn: (
|
|
325
|
+
command: string
|
|
326
|
+
) => Promise<{ stdout: string; stderr: string }> = execAsync
|
|
327
|
+
): Promise<void> {
|
|
328
|
+
try {
|
|
329
|
+
logger.info(`🗑️ Deleting benchmark branch: ${name}`);
|
|
330
|
+
await execFn(`git branch -D ${name}`);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
logger.warn(`Failed to delete branch ${name}: ${error}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
package/src/lib/hooks.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Task } from "../types";
|
|
2
|
+
|
|
3
|
+
// Define all possible event types
|
|
4
|
+
export type TaskEventType =
|
|
5
|
+
| "task:created"
|
|
6
|
+
| "task:updated"
|
|
7
|
+
| "task:deleted"
|
|
8
|
+
| "task:status-changed"
|
|
9
|
+
| "task:progress"
|
|
10
|
+
| "execution:start"
|
|
11
|
+
| "execution:end"
|
|
12
|
+
| "execution:error"
|
|
13
|
+
| "log:info"
|
|
14
|
+
| "log:warn"
|
|
15
|
+
| "log:error"
|
|
16
|
+
| "log:success"
|
|
17
|
+
| "log:progress";
|
|
18
|
+
|
|
19
|
+
// Log event payload
|
|
20
|
+
export interface LogEventPayload {
|
|
21
|
+
message: string;
|
|
22
|
+
context?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Define payload types for each event
|
|
26
|
+
export interface TaskEventPayloads {
|
|
27
|
+
"task:created": { task: Task };
|
|
28
|
+
"task:updated": { task: Task; changes: Partial<Task> };
|
|
29
|
+
"task:deleted": { taskId: string };
|
|
30
|
+
"task:status-changed": { task: Task; oldStatus: string; newStatus: string };
|
|
31
|
+
"task:progress": { taskId?: string; message: string; type?: string };
|
|
32
|
+
"execution:start": { taskId: string; tool: string };
|
|
33
|
+
"execution:end": { taskId: string; success: boolean };
|
|
34
|
+
"execution:error": { taskId: string; error: Error };
|
|
35
|
+
"log:info": LogEventPayload;
|
|
36
|
+
"log:warn": LogEventPayload;
|
|
37
|
+
"log:error": LogEventPayload;
|
|
38
|
+
"log:success": LogEventPayload;
|
|
39
|
+
"log:progress": LogEventPayload;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Type for the event handler function
|
|
43
|
+
export type TaskEventHandler<T extends TaskEventType> = (
|
|
44
|
+
payload: TaskEventPayloads[T]
|
|
45
|
+
) => Promise<void> | void;
|
|
46
|
+
|
|
47
|
+
class HookRegistry {
|
|
48
|
+
private static instance: HookRegistry;
|
|
49
|
+
private listeners: Map<TaskEventType, Set<TaskEventHandler<any>>>;
|
|
50
|
+
|
|
51
|
+
private constructor() {
|
|
52
|
+
this.listeners = new Map();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public static getInstance(): HookRegistry {
|
|
56
|
+
if (!HookRegistry.instance) {
|
|
57
|
+
HookRegistry.instance = new HookRegistry();
|
|
58
|
+
}
|
|
59
|
+
return HookRegistry.instance;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Register a handler for a specific event type
|
|
64
|
+
*/
|
|
65
|
+
public on<T extends TaskEventType>(
|
|
66
|
+
type: T,
|
|
67
|
+
handler: TaskEventHandler<T>
|
|
68
|
+
): void {
|
|
69
|
+
if (!this.listeners.has(type)) {
|
|
70
|
+
this.listeners.set(type, new Set());
|
|
71
|
+
}
|
|
72
|
+
this.listeners.get(type)!.add(handler);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Remove a handler
|
|
77
|
+
*/
|
|
78
|
+
public off<T extends TaskEventType>(
|
|
79
|
+
type: T,
|
|
80
|
+
handler: TaskEventHandler<T>
|
|
81
|
+
): void {
|
|
82
|
+
const handlers = this.listeners.get(type);
|
|
83
|
+
if (handlers) {
|
|
84
|
+
handlers.delete(handler);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Emit an event to all registered handlers
|
|
90
|
+
* We don't await handlers to prevent blocking the main flow,
|
|
91
|
+
* but we catch errors to prevent crashes.
|
|
92
|
+
*/
|
|
93
|
+
public async emit<T extends TaskEventType>(
|
|
94
|
+
type: T,
|
|
95
|
+
payload: TaskEventPayloads[T]
|
|
96
|
+
): Promise<void> {
|
|
97
|
+
const handlers = this.listeners.get(type);
|
|
98
|
+
if (!handlers || handlers.size === 0) return;
|
|
99
|
+
|
|
100
|
+
const promises = Array.from(handlers).map(async (handler) => {
|
|
101
|
+
try {
|
|
102
|
+
await handler(payload);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
// NOTE: Using console.error here intentionally - this is the hooks system
|
|
105
|
+
// that the logger depends on, so we can't use logger here (circular dependency)
|
|
106
|
+
console.error(`Error in hook handler for event ${type}:`, error);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await Promise.all(promises);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Clear all listeners (useful for testing)
|
|
115
|
+
*/
|
|
116
|
+
public clear(): void {
|
|
117
|
+
this.listeners.clear();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const hooks = HookRegistry.getInstance();
|