mstro-app 0.5.0 → 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +129 -190
- package/PRIVACY.md +11 -11
- package/README.md +75 -28
- package/bin/commands/config.js +1 -2
- package/bin/mstro.js +55 -5
- package/bin/postinstall.js +0 -1
- package/dist/server/cli/eta-estimator.d.ts +55 -0
- package/dist/server/cli/eta-estimator.d.ts.map +1 -0
- package/dist/server/cli/eta-estimator.js +222 -0
- package/dist/server/cli/eta-estimator.js.map +1 -0
- package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker-process.js +0 -1
- package/dist/server/cli/headless/claude-invoker-process.js.map +1 -1
- package/dist/server/cli/headless/claude-invoker-stall.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker-stall.js +0 -1
- package/dist/server/cli/headless/claude-invoker-stall.js.map +1 -1
- package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker-stream.js +0 -1
- package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -1
- package/dist/server/cli/headless/claude-invoker-tools.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker-tools.js +0 -1
- package/dist/server/cli/headless/claude-invoker-tools.js.map +1 -1
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker.js +0 -1
- package/dist/server/cli/headless/claude-invoker.js.map +1 -1
- package/dist/server/cli/headless/haiku-assessments.d.ts.map +1 -1
- package/dist/server/cli/headless/haiku-assessments.js +0 -1
- package/dist/server/cli/headless/haiku-assessments.js.map +1 -1
- package/dist/server/cli/headless/headless-logger.d.ts.map +1 -1
- package/dist/server/cli/headless/headless-logger.js +0 -1
- package/dist/server/cli/headless/headless-logger.js.map +1 -1
- package/dist/server/cli/headless/index.d.ts.map +1 -1
- package/dist/server/cli/headless/index.js +0 -1
- package/dist/server/cli/headless/index.js.map +1 -1
- package/dist/server/cli/headless/native-timeout-detector.d.ts.map +1 -1
- package/dist/server/cli/headless/native-timeout-detector.js +0 -1
- package/dist/server/cli/headless/native-timeout-detector.js.map +1 -1
- package/dist/server/cli/headless/output-utils.d.ts.map +1 -1
- package/dist/server/cli/headless/output-utils.js +0 -1
- package/dist/server/cli/headless/output-utils.js.map +1 -1
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -1
- package/dist/server/cli/headless/prompt-utils.js +0 -1
- package/dist/server/cli/headless/prompt-utils.js.map +1 -1
- package/dist/server/cli/headless/resilient-runner.d.ts.map +1 -1
- package/dist/server/cli/headless/resilient-runner.js +0 -1
- package/dist/server/cli/headless/resilient-runner.js.map +1 -1
- package/dist/server/cli/headless/retry-strategies.d.ts.map +1 -1
- package/dist/server/cli/headless/retry-strategies.js +0 -1
- package/dist/server/cli/headless/retry-strategies.js.map +1 -1
- package/dist/server/cli/headless/runner.d.ts.map +1 -1
- package/dist/server/cli/headless/runner.js +0 -1
- package/dist/server/cli/headless/runner.js.map +1 -1
- package/dist/server/cli/headless/stall-assessor.d.ts +50 -0
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +64 -10
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.d.ts +21 -0
- package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.js +19 -13
- package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/cli/headless/types.js +0 -1
- package/dist/server/cli/headless/types.js.map +1 -1
- package/dist/server/cli/improvisation-attachments.d.ts.map +1 -1
- package/dist/server/cli/improvisation-attachments.js +0 -1
- package/dist/server/cli/improvisation-attachments.js.map +1 -1
- package/dist/server/cli/improvisation-history-store.d.ts.map +1 -1
- package/dist/server/cli/improvisation-history-store.js +5 -2
- package/dist/server/cli/improvisation-history-store.js.map +1 -1
- package/dist/server/cli/improvisation-movements.d.ts.map +1 -1
- package/dist/server/cli/improvisation-movements.js +0 -1
- package/dist/server/cli/improvisation-movements.js.map +1 -1
- package/dist/server/cli/improvisation-output-queue.d.ts +5 -1
- package/dist/server/cli/improvisation-output-queue.d.ts.map +1 -1
- package/dist/server/cli/improvisation-output-queue.js +30 -8
- package/dist/server/cli/improvisation-output-queue.js.map +1 -1
- package/dist/server/cli/improvisation-retry.d.ts.map +1 -1
- package/dist/server/cli/improvisation-retry.js +0 -1
- package/dist/server/cli/improvisation-retry.js.map +1 -1
- package/dist/server/cli/improvisation-session-manager.d.ts +29 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +50 -2
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/cli/improvisation-types.d.ts +2 -0
- package/dist/server/cli/improvisation-types.d.ts.map +1 -1
- package/dist/server/cli/improvisation-types.js +0 -1
- package/dist/server/cli/improvisation-types.js.map +1 -1
- package/dist/server/cli/retry/retry-best-result.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-best-result.js +0 -1
- package/dist/server/cli/retry/retry-best-result.js.map +1 -1
- package/dist/server/cli/retry/retry-context-loss.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-context-loss.js +0 -1
- package/dist/server/cli/retry/retry-context-loss.js.map +1 -1
- package/dist/server/cli/retry/retry-premature-completion.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-premature-completion.js +1 -2
- package/dist/server/cli/retry/retry-premature-completion.js.map +1 -1
- package/dist/server/cli/retry/retry-recovery-strategies.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-recovery-strategies.js +0 -1
- package/dist/server/cli/retry/retry-recovery-strategies.js.map +1 -1
- package/dist/server/cli/retry/retry-resume-strategy.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-resume-strategy.js +0 -1
- package/dist/server/cli/retry/retry-resume-strategy.js.map +1 -1
- package/dist/server/cli/retry/retry-runner-factory.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-runner-factory.js +0 -1
- package/dist/server/cli/retry/retry-runner-factory.js.map +1 -1
- package/dist/server/cli/retry/retry-tool-results.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-tool-results.js +0 -1
- package/dist/server/cli/retry/retry-tool-results.js.map +1 -1
- package/dist/server/cli/retry/retry-types.d.ts.map +1 -1
- package/dist/server/cli/retry/retry-types.js +0 -1
- package/dist/server/cli/retry/retry-types.js.map +1 -1
- package/dist/server/engines/EngineEvent.d.ts +126 -0
- package/dist/server/engines/EngineEvent.d.ts.map +1 -0
- package/dist/server/engines/EngineEvent.js +11 -0
- package/dist/server/engines/EngineEvent.js.map +1 -0
- package/dist/server/engines/claude/ClaudeCodeEngine.d.ts +47 -0
- package/dist/server/engines/claude/ClaudeCodeEngine.d.ts.map +1 -0
- package/dist/server/engines/claude/ClaudeCodeEngine.js +338 -0
- package/dist/server/engines/claude/ClaudeCodeEngine.js.map +1 -0
- package/dist/server/engines/factory.d.ts +21 -0
- package/dist/server/engines/factory.d.ts.map +1 -0
- package/dist/server/engines/factory.js +152 -0
- package/dist/server/engines/factory.js.map +1 -0
- package/dist/server/engines/opencode/OpenCodeEngine.d.ts +148 -0
- package/dist/server/engines/opencode/OpenCodeEngine.d.ts.map +1 -0
- package/dist/server/engines/opencode/OpenCodeEngine.js +630 -0
- package/dist/server/engines/opencode/OpenCodeEngine.js.map +1 -0
- package/dist/server/engines/opencode/OpenCodeServerManager.d.ts +172 -0
- package/dist/server/engines/opencode/OpenCodeServerManager.d.ts.map +1 -0
- package/dist/server/engines/opencode/OpenCodeServerManager.js +390 -0
- package/dist/server/engines/opencode/OpenCodeServerManager.js.map +1 -0
- package/dist/server/engines/opencode/model-catalog.d.ts +94 -0
- package/dist/server/engines/opencode/model-catalog.d.ts.map +1 -0
- package/dist/server/engines/opencode/model-catalog.js +141 -0
- package/dist/server/engines/opencode/model-catalog.js.map +1 -0
- package/dist/server/engines/types.d.ts +146 -0
- package/dist/server/engines/types.d.ts.map +1 -0
- package/dist/server/engines/types.js +4 -0
- package/dist/server/engines/types.js.map +1 -0
- package/dist/server/index.js +1 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-cli.js +0 -1
- package/dist/server/mcp/bouncer-cli.js.map +1 -1
- package/dist/server/mcp/bouncer-haiku.d.ts +17 -4
- package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-haiku.js +8 -125
- package/dist/server/mcp/bouncer-haiku.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts +45 -0
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +69 -6
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/classifier/BouncerClassifier.d.ts +34 -0
- package/dist/server/mcp/classifier/BouncerClassifier.d.ts.map +1 -0
- package/dist/server/mcp/classifier/BouncerClassifier.js +4 -0
- package/dist/server/mcp/classifier/BouncerClassifier.js.map +1 -0
- package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts +17 -0
- package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts.map +1 -0
- package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +142 -0
- package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js.map +1 -0
- package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts +68 -0
- package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts.map +1 -0
- package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js +182 -0
- package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js.map +1 -0
- package/dist/server/mcp/classifier/factory.d.ts +70 -0
- package/dist/server/mcp/classifier/factory.d.ts.map +1 -0
- package/dist/server/mcp/classifier/factory.js +155 -0
- package/dist/server/mcp/classifier/factory.js.map +1 -0
- package/dist/server/mcp/security-analysis.d.ts.map +1 -1
- package/dist/server/mcp/security-analysis.js +0 -1
- package/dist/server/mcp/security-analysis.js.map +1 -1
- package/dist/server/mcp/security-audit.d.ts.map +1 -1
- package/dist/server/mcp/security-audit.js +0 -1
- package/dist/server/mcp/security-audit.js.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +0 -1
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/mcp/server.js +0 -1
- package/dist/server/mcp/server.js.map +1 -1
- package/dist/server/routes/files.d.ts.map +1 -1
- package/dist/server/routes/files.js +0 -1
- package/dist/server/routes/files.js.map +1 -1
- package/dist/server/routes/improvise.d.ts.map +1 -1
- package/dist/server/routes/improvise.js +0 -1
- package/dist/server/routes/improvise.js.map +1 -1
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +0 -1
- package/dist/server/routes/index.js.map +1 -1
- package/dist/server/routes/instances.d.ts.map +1 -1
- package/dist/server/routes/instances.js +0 -1
- package/dist/server/routes/instances.js.map +1 -1
- package/dist/server/routes/notifications.d.ts.map +1 -1
- package/dist/server/routes/notifications.js +0 -1
- package/dist/server/routes/notifications.js.map +1 -1
- package/dist/server/server-setup.d.ts.map +1 -1
- package/dist/server/server-setup.js +0 -1
- package/dist/server/server-setup.js.map +1 -1
- package/dist/server/services/analytics.d.ts.map +1 -1
- package/dist/server/services/analytics.js +0 -1
- package/dist/server/services/analytics.js.map +1 -1
- package/dist/server/services/auth.d.ts.map +1 -1
- package/dist/server/services/auth.js +0 -1
- package/dist/server/services/auth.js.map +1 -1
- package/dist/server/services/client-id.d.ts.map +1 -1
- package/dist/server/services/client-id.js +0 -1
- package/dist/server/services/client-id.js.map +1 -1
- package/dist/server/services/file-explorer-ops.d.ts.map +1 -1
- package/dist/server/services/file-explorer-ops.js +0 -1
- package/dist/server/services/file-explorer-ops.js.map +1 -1
- package/dist/server/services/files.d.ts.map +1 -1
- package/dist/server/services/files.js +0 -1
- package/dist/server/services/files.js.map +1 -1
- package/dist/server/services/instances.d.ts.map +1 -1
- package/dist/server/services/instances.js +0 -1
- package/dist/server/services/instances.js.map +1 -1
- package/dist/server/services/pathUtils.d.ts.map +1 -1
- package/dist/server/services/pathUtils.js +0 -1
- package/dist/server/services/pathUtils.js.map +1 -1
- package/dist/server/services/plan/agent-loader.d.ts.map +1 -1
- package/dist/server/services/plan/agent-loader.js +0 -1
- package/dist/server/services/plan/agent-loader.js.map +1 -1
- package/dist/server/services/plan/agent-resolver.d.ts +26 -0
- package/dist/server/services/plan/agent-resolver.d.ts.map +1 -0
- package/dist/server/services/plan/agent-resolver.js +102 -0
- package/dist/server/services/plan/agent-resolver.js.map +1 -0
- package/dist/server/services/plan/board-config.d.ts.map +1 -1
- package/dist/server/services/plan/board-config.js +0 -1
- package/dist/server/services/plan/board-config.js.map +1 -1
- package/dist/server/services/plan/composer.d.ts.map +1 -1
- package/dist/server/services/plan/composer.js +59 -12
- package/dist/server/services/plan/composer.js.map +1 -1
- package/dist/server/services/plan/config-installer.d.ts.map +1 -1
- package/dist/server/services/plan/config-installer.js +0 -1
- package/dist/server/services/plan/config-installer.js.map +1 -1
- package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -1
- package/dist/server/services/plan/dependency-resolver.js +0 -1
- package/dist/server/services/plan/dependency-resolver.js.map +1 -1
- package/dist/server/services/plan/executor.d.ts.map +1 -1
- package/dist/server/services/plan/executor.js +48 -4
- package/dist/server/services/plan/executor.js.map +1 -1
- package/dist/server/services/plan/front-matter.d.ts.map +1 -1
- package/dist/server/services/plan/front-matter.js +0 -1
- package/dist/server/services/plan/front-matter.js.map +1 -1
- package/dist/server/services/plan/issue-classification.d.ts.map +1 -1
- package/dist/server/services/plan/issue-classification.js +0 -1
- package/dist/server/services/plan/issue-classification.js.map +1 -1
- package/dist/server/services/plan/issue-loader.d.ts.map +1 -1
- package/dist/server/services/plan/issue-loader.js +0 -1
- package/dist/server/services/plan/issue-loader.js.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.js +33 -2
- package/dist/server/services/plan/issue-prompt-builder.js.map +1 -1
- package/dist/server/services/plan/issue-retry.d.ts +3 -1
- package/dist/server/services/plan/issue-retry.d.ts.map +1 -1
- package/dist/server/services/plan/issue-retry.js +2 -1
- package/dist/server/services/plan/issue-retry.js.map +1 -1
- package/dist/server/services/plan/issue-writer.d.ts.map +1 -1
- package/dist/server/services/plan/issue-writer.js +0 -1
- package/dist/server/services/plan/issue-writer.js.map +1 -1
- package/dist/server/services/plan/output-manager.d.ts.map +1 -1
- package/dist/server/services/plan/output-manager.js +0 -1
- package/dist/server/services/plan/output-manager.js.map +1 -1
- package/dist/server/services/plan/parser-core.d.ts.map +1 -1
- package/dist/server/services/plan/parser-core.js +1 -1
- package/dist/server/services/plan/parser-core.js.map +1 -1
- package/dist/server/services/plan/parser-migration.d.ts.map +1 -1
- package/dist/server/services/plan/parser-migration.js +0 -1
- package/dist/server/services/plan/parser-migration.js.map +1 -1
- package/dist/server/services/plan/parser.d.ts.map +1 -1
- package/dist/server/services/plan/parser.js +0 -1
- package/dist/server/services/plan/parser.js.map +1 -1
- package/dist/server/services/plan/progress-log.d.ts.map +1 -1
- package/dist/server/services/plan/progress-log.js +0 -1
- package/dist/server/services/plan/progress-log.js.map +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/prompt-builder.js +0 -1
- package/dist/server/services/plan/prompt-builder.js.map +1 -1
- package/dist/server/services/plan/readiness-planner.d.ts.map +1 -1
- package/dist/server/services/plan/readiness-planner.js +0 -1
- package/dist/server/services/plan/readiness-planner.js.map +1 -1
- package/dist/server/services/plan/review-gate.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.js +0 -1
- package/dist/server/services/plan/review-gate.js.map +1 -1
- package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
- package/dist/server/services/plan/state-reconciler.js +0 -1
- package/dist/server/services/plan/state-reconciler.js.map +1 -1
- package/dist/server/services/plan/types.d.ts +1 -0
- package/dist/server/services/plan/types.d.ts.map +1 -1
- package/dist/server/services/plan/types.js +0 -1
- package/dist/server/services/plan/types.js.map +1 -1
- package/dist/server/services/plan/watcher.d.ts.map +1 -1
- package/dist/server/services/plan/watcher.js +0 -1
- package/dist/server/services/plan/watcher.js.map +1 -1
- package/dist/server/services/platform-credentials.d.ts.map +1 -1
- package/dist/server/services/platform-credentials.js +0 -1
- package/dist/server/services/platform-credentials.js.map +1 -1
- package/dist/server/services/platform-token-lifecycle.d.ts +70 -0
- package/dist/server/services/platform-token-lifecycle.d.ts.map +1 -0
- package/dist/server/services/platform-token-lifecycle.js +156 -0
- package/dist/server/services/platform-token-lifecycle.js.map +1 -0
- package/dist/server/services/platform.d.ts +21 -56
- package/dist/server/services/platform.d.ts.map +1 -1
- package/dist/server/services/platform.js +98 -142
- package/dist/server/services/platform.js.map +1 -1
- package/dist/server/services/sentry.d.ts.map +1 -1
- package/dist/server/services/sentry.js +0 -1
- package/dist/server/services/sentry.js.map +1 -1
- package/dist/server/services/settings.d.ts +76 -2
- package/dist/server/services/settings.d.ts.map +1 -1
- package/dist/server/services/settings.js +127 -5
- package/dist/server/services/settings.js.map +1 -1
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-manager.js +0 -1
- package/dist/server/services/terminal/pty-manager.js.map +1 -1
- package/dist/server/services/terminal/pty-utils.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-utils.js +0 -1
- package/dist/server/services/terminal/pty-utils.js.map +1 -1
- package/dist/server/services/websocket/autocomplete.d.ts.map +1 -1
- package/dist/server/services/websocket/autocomplete.js +0 -1
- package/dist/server/services/websocket/autocomplete.js.map +1 -1
- package/dist/server/services/websocket/file-definition-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/file-definition-handlers.js +0 -1
- package/dist/server/services/websocket/file-definition-handlers.js.map +1 -1
- package/dist/server/services/websocket/file-download-handler.d.ts.map +1 -1
- package/dist/server/services/websocket/file-download-handler.js +0 -1
- package/dist/server/services/websocket/file-download-handler.js.map +1 -1
- package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/file-explorer-handlers.js +0 -1
- package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
- package/dist/server/services/websocket/file-search-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/file-search-handlers.js +0 -1
- package/dist/server/services/websocket/file-search-handlers.js.map +1 -1
- package/dist/server/services/websocket/file-upload-handler.d.ts +2 -3
- package/dist/server/services/websocket/file-upload-handler.d.ts.map +1 -1
- package/dist/server/services/websocket/file-upload-handler.js +4 -7
- package/dist/server/services/websocket/file-upload-handler.js.map +1 -1
- package/dist/server/services/websocket/file-utils.d.ts.map +1 -1
- package/dist/server/services/websocket/file-utils.js +0 -1
- package/dist/server/services/websocket/file-utils.js.map +1 -1
- package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-branch-handlers.js +19 -7
- package/dist/server/services/websocket/git-branch-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-diff-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-diff-handlers.js +0 -1
- package/dist/server/services/websocket/git-diff-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-handlers.js +58 -6
- package/dist/server/services/websocket/git-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-head-watcher.d.ts.map +1 -1
- package/dist/server/services/websocket/git-head-watcher.js +0 -1
- package/dist/server/services/websocket/git-head-watcher.js.map +1 -1
- package/dist/server/services/websocket/git-log-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-log-handlers.js +0 -1
- package/dist/server/services/websocket/git-log-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-pr-handlers.js +0 -1
- package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-tag-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-tag-handlers.js +0 -1
- package/dist/server/services/websocket/git-tag-handlers.js.map +1 -1
- package/dist/server/services/websocket/git-utils.d.ts +18 -3
- package/dist/server/services/websocket/git-utils.d.ts.map +1 -1
- package/dist/server/services/websocket/git-utils.js +58 -8
- package/dist/server/services/websocket/git-utils.js.map +1 -1
- package/dist/server/services/websocket/git-worktree-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/git-worktree-handlers.js +230 -14
- package/dist/server/services/websocket/git-worktree-handlers.js.map +1 -1
- package/dist/server/services/websocket/handler-context.d.ts.map +1 -1
- package/dist/server/services/websocket/handler-context.js +0 -1
- package/dist/server/services/websocket/handler-context.js.map +1 -1
- package/dist/server/services/websocket/handler.d.ts +17 -1
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +57 -6
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/index.d.ts.map +1 -1
- package/dist/server/services/websocket/index.js +0 -1
- package/dist/server/services/websocket/index.js.map +1 -1
- package/dist/server/services/websocket/msg-id-tracker.d.ts.map +1 -1
- package/dist/server/services/websocket/msg-id-tracker.js +0 -1
- package/dist/server/services/websocket/msg-id-tracker.js.map +1 -1
- package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-board-handlers.js +0 -1
- package/dist/server/services/websocket/plan-board-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-execution-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-execution-handlers.js +6 -2
- package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-handlers.js +0 -1
- package/dist/server/services/websocket/plan-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-helpers.js +0 -1
- package/dist/server/services/websocket/plan-helpers.js.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.js +0 -1
- package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.js +0 -1
- package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -1
- package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-complexity.js +78 -27
- package/dist/server/services/websocket/quality-complexity.js.map +1 -1
- package/dist/server/services/websocket/quality-eta.d.ts +47 -0
- package/dist/server/services/websocket/quality-eta.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-eta.js +110 -0
- package/dist/server/services/websocket/quality-eta.js.map +1 -0
- package/dist/server/services/websocket/quality-grading.d.ts +69 -0
- package/dist/server/services/websocket/quality-grading.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-grading.js +650 -0
- package/dist/server/services/websocket/quality-grading.js.map +1 -0
- package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-handlers.js +145 -8
- package/dist/server/services/websocket/quality-handlers.js.map +1 -1
- package/dist/server/services/websocket/quality-linting.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-linting.js +0 -1
- package/dist/server/services/websocket/quality-linting.js.map +1 -1
- package/dist/server/services/websocket/quality-operations.d.ts +34 -0
- package/dist/server/services/websocket/quality-operations.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-operations.js +47 -0
- package/dist/server/services/websocket/quality-operations.js.map +1 -0
- package/dist/server/services/websocket/quality-persistence.d.ts +23 -0
- package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-persistence.js +38 -12
- package/dist/server/services/websocket/quality-persistence.js.map +1 -1
- package/dist/server/services/websocket/quality-review-agent.d.ts +1 -1
- package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-review-agent.js +105 -57
- package/dist/server/services/websocket/quality-review-agent.js.map +1 -1
- package/dist/server/services/websocket/quality-service.d.ts +12 -2
- package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-service.js +387 -72
- package/dist/server/services/websocket/quality-service.js.map +1 -1
- package/dist/server/services/websocket/quality-tools.d.ts +22 -1
- package/dist/server/services/websocket/quality-tools.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-tools.js +55 -3
- package/dist/server/services/websocket/quality-tools.js.map +1 -1
- package/dist/server/services/websocket/quality-types.d.ts +52 -3
- package/dist/server/services/websocket/quality-types.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-types.js +1 -2
- package/dist/server/services/websocket/quality-types.js.map +1 -1
- package/dist/server/services/websocket/session-handlers.d.ts +3 -1
- package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/session-handlers.js +57 -10
- package/dist/server/services/websocket/session-handlers.js.map +1 -1
- package/dist/server/services/websocket/session-history.d.ts.map +1 -1
- package/dist/server/services/websocket/session-history.js +3 -1
- package/dist/server/services/websocket/session-history.js.map +1 -1
- package/dist/server/services/websocket/session-initialization.d.ts.map +1 -1
- package/dist/server/services/websocket/session-initialization.js +158 -43
- package/dist/server/services/websocket/session-initialization.js.map +1 -1
- package/dist/server/services/websocket/session-registry.d.ts +25 -0
- package/dist/server/services/websocket/session-registry.d.ts.map +1 -1
- package/dist/server/services/websocket/session-registry.js +19 -1
- package/dist/server/services/websocket/session-registry.js.map +1 -1
- package/dist/server/services/websocket/settings-handlers.d.ts +1 -1
- package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/settings-handlers.js +35 -5
- package/dist/server/services/websocket/settings-handlers.js.map +1 -1
- package/dist/server/services/websocket/skill-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/skill-handlers.js +0 -1
- package/dist/server/services/websocket/skill-handlers.js.map +1 -1
- package/dist/server/services/websocket/skill-watcher.d.ts.map +1 -1
- package/dist/server/services/websocket/skill-watcher.js +0 -1
- package/dist/server/services/websocket/skill-watcher.js.map +1 -1
- package/dist/server/services/websocket/tab-broadcast.d.ts +7 -2
- package/dist/server/services/websocket/tab-broadcast.d.ts.map +1 -1
- package/dist/server/services/websocket/tab-broadcast.js +10 -3
- package/dist/server/services/websocket/tab-broadcast.js.map +1 -1
- package/dist/server/services/websocket/tab-event-buffer.d.ts +97 -8
- package/dist/server/services/websocket/tab-event-buffer.d.ts.map +1 -1
- package/dist/server/services/websocket/tab-event-buffer.js +138 -13
- package/dist/server/services/websocket/tab-event-buffer.js.map +1 -1
- package/dist/server/services/websocket/tab-event-replay.d.ts +29 -13
- package/dist/server/services/websocket/tab-event-replay.d.ts.map +1 -1
- package/dist/server/services/websocket/tab-event-replay.js +55 -3
- package/dist/server/services/websocket/tab-event-replay.js.map +1 -1
- package/dist/server/services/websocket/tab-handlers.d.ts +9 -1
- package/dist/server/services/websocket/tab-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/tab-handlers.js +47 -3
- package/dist/server/services/websocket/tab-handlers.js.map +1 -1
- package/dist/server/services/websocket/terminal-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/terminal-handlers.js +39 -4
- package/dist/server/services/websocket/terminal-handlers.js.map +1 -1
- package/dist/server/services/websocket/types.d.ts +30 -7
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/dist/server/services/websocket/types.js +12 -7
- package/dist/server/services/websocket/types.js.map +1 -1
- package/dist/server/utils/agent-manager.d.ts.map +1 -1
- package/dist/server/utils/agent-manager.js +0 -1
- package/dist/server/utils/agent-manager.js.map +1 -1
- package/dist/server/utils/paths.d.ts.map +1 -1
- package/dist/server/utils/paths.js +0 -1
- package/dist/server/utils/paths.js.map +1 -1
- package/dist/server/utils/port-manager.d.ts.map +1 -1
- package/dist/server/utils/port-manager.js +0 -1
- package/dist/server/utils/port-manager.js.map +1 -1
- package/dist/server/utils/port.d.ts.map +1 -1
- package/dist/server/utils/port.js +0 -1
- package/dist/server/utils/port.js.map +1 -1
- package/package.json +6 -4
- package/server/cli/eta-estimator.ts +249 -0
- package/server/cli/headless/claude-invoker-process.ts +0 -1
- package/server/cli/headless/claude-invoker-stall.ts +0 -1
- package/server/cli/headless/claude-invoker-stream.ts +0 -1
- package/server/cli/headless/claude-invoker-tools.ts +0 -1
- package/server/cli/headless/claude-invoker.ts +0 -1
- package/server/cli/headless/haiku-assessments.ts +0 -1
- package/server/cli/headless/headless-logger.ts +0 -1
- package/server/cli/headless/index.ts +0 -1
- package/server/cli/headless/native-timeout-detector.ts +0 -1
- package/server/cli/headless/output-utils.ts +0 -1
- package/server/cli/headless/prompt-utils.ts +0 -1
- package/server/cli/headless/resilient-runner.ts +0 -1
- package/server/cli/headless/retry-strategies.ts +0 -1
- package/server/cli/headless/runner.ts +0 -1
- package/server/cli/headless/stall-assessor.ts +93 -1
- package/server/cli/headless/tool-watchdog.ts +21 -1
- package/server/cli/headless/types.ts +0 -1
- package/server/cli/improvisation-attachments.ts +0 -1
- package/server/cli/improvisation-history-store.ts +4 -2
- package/server/cli/improvisation-movements.ts +0 -1
- package/server/cli/improvisation-output-queue.ts +29 -8
- package/server/cli/improvisation-retry.ts +0 -1
- package/server/cli/improvisation-session-manager.ts +54 -2
- package/server/cli/improvisation-types.ts +2 -1
- package/server/cli/retry/retry-best-result.ts +0 -1
- package/server/cli/retry/retry-context-loss.ts +0 -1
- package/server/cli/retry/retry-premature-completion.ts +1 -2
- package/server/cli/retry/retry-recovery-strategies.ts +0 -1
- package/server/cli/retry/retry-resume-strategy.ts +0 -1
- package/server/cli/retry/retry-runner-factory.ts +0 -1
- package/server/cli/retry/retry-tool-results.ts +0 -1
- package/server/cli/retry/retry-types.ts +0 -1
- package/server/engines/EngineEvent.ts +156 -0
- package/server/engines/claude/ClaudeCodeEngine.ts +404 -0
- package/server/engines/factory.ts +176 -0
- package/server/engines/opencode/OpenCodeEngine.ts +786 -0
- package/server/engines/opencode/OpenCodeServerManager.ts +577 -0
- package/server/engines/opencode/model-catalog.ts +217 -0
- package/server/engines/types.ts +173 -0
- package/server/index.ts +1 -2
- package/server/mcp/bouncer-cli.ts +0 -1
- package/server/mcp/bouncer-haiku.ts +21 -146
- package/server/mcp/bouncer-integration.ts +107 -6
- package/server/mcp/classifier/BouncerClassifier.ts +40 -0
- package/server/mcp/classifier/ClaudeBouncerClassifier.ts +189 -0
- package/server/mcp/classifier/OpenCodeBouncerClassifier.ts +305 -0
- package/server/mcp/classifier/factory.ts +195 -0
- package/server/mcp/security-analysis.ts +0 -1
- package/server/mcp/security-audit.ts +0 -1
- package/server/mcp/security-patterns.ts +0 -1
- package/server/mcp/server.ts +0 -1
- package/server/routes/files.ts +0 -1
- package/server/routes/improvise.ts +0 -1
- package/server/routes/index.ts +0 -1
- package/server/routes/instances.ts +0 -1
- package/server/routes/notifications.ts +0 -1
- package/server/server-setup.ts +0 -1
- package/server/services/analytics.ts +0 -1
- package/server/services/auth.ts +0 -1
- package/server/services/client-id.ts +0 -1
- package/server/services/file-explorer-ops.ts +0 -1
- package/server/services/files.ts +0 -1
- package/server/services/instances.ts +0 -1
- package/server/services/pathUtils.ts +0 -1
- package/server/services/plan/agent-loader.ts +0 -1
- package/server/services/plan/agent-resolver.ts +115 -0
- package/server/services/plan/agents/code-review.md +43 -11
- package/server/services/plan/board-config.ts +0 -1
- package/server/services/plan/composer.ts +63 -12
- package/server/services/plan/config-installer.ts +0 -1
- package/server/services/plan/dependency-resolver.ts +0 -1
- package/server/services/plan/executor.ts +48 -4
- package/server/services/plan/front-matter.ts +0 -1
- package/server/services/plan/issue-classification.ts +0 -1
- package/server/services/plan/issue-loader.ts +0 -1
- package/server/services/plan/issue-prompt-builder.ts +39 -2
- package/server/services/plan/issue-retry.ts +5 -2
- package/server/services/plan/issue-writer.ts +0 -1
- package/server/services/plan/output-manager.ts +0 -1
- package/server/services/plan/parser-core.ts +1 -1
- package/server/services/plan/parser-migration.ts +0 -1
- package/server/services/plan/parser.ts +0 -1
- package/server/services/plan/progress-log.ts +0 -1
- package/server/services/plan/prompt-builder.ts +0 -1
- package/server/services/plan/readiness-planner.ts +0 -1
- package/server/services/plan/review-gate.ts +0 -1
- package/server/services/plan/state-reconciler.ts +0 -1
- package/server/services/plan/types.ts +4 -1
- package/server/services/plan/watcher.ts +0 -1
- package/server/services/platform-credentials.ts +0 -1
- package/server/services/platform-token-lifecycle.ts +171 -0
- package/server/services/platform.ts +106 -148
- package/server/services/sentry.ts +0 -1
- package/server/services/settings.ts +161 -5
- package/server/services/terminal/pty-manager.ts +0 -1
- package/server/services/terminal/pty-utils.ts +0 -1
- package/server/services/websocket/autocomplete.ts +0 -1
- package/server/services/websocket/file-definition-handlers.ts +0 -1
- package/server/services/websocket/file-download-handler.ts +0 -1
- package/server/services/websocket/file-explorer-handlers.ts +0 -1
- package/server/services/websocket/file-search-handlers.ts +0 -1
- package/server/services/websocket/file-upload-handler.ts +6 -5
- package/server/services/websocket/file-utils.ts +0 -1
- package/server/services/websocket/git-branch-handlers.ts +20 -7
- package/server/services/websocket/git-diff-handlers.ts +0 -1
- package/server/services/websocket/git-handlers.ts +66 -10
- package/server/services/websocket/git-head-watcher.ts +0 -1
- package/server/services/websocket/git-log-handlers.ts +0 -1
- package/server/services/websocket/git-pr-handlers.ts +0 -1
- package/server/services/websocket/git-tag-handlers.ts +0 -1
- package/server/services/websocket/git-utils.ts +69 -9
- package/server/services/websocket/git-worktree-handlers.ts +260 -17
- package/server/services/websocket/handler-context.ts +0 -1
- package/server/services/websocket/handler.ts +62 -6
- package/server/services/websocket/index.ts +0 -1
- package/server/services/websocket/msg-id-tracker.ts +0 -1
- package/server/services/websocket/plan-board-handlers.ts +0 -1
- package/server/services/websocket/plan-execution-handlers.ts +6 -2
- package/server/services/websocket/plan-handlers.ts +0 -1
- package/server/services/websocket/plan-helpers.ts +0 -1
- package/server/services/websocket/plan-issue-handlers.ts +0 -1
- package/server/services/websocket/plan-sprint-handlers.ts +0 -1
- package/server/services/websocket/quality-complexity.ts +80 -27
- package/server/services/websocket/quality-eta.ts +155 -0
- package/server/services/websocket/quality-grading.ts +834 -0
- package/server/services/websocket/quality-handlers.ts +153 -8
- package/server/services/websocket/quality-linting.ts +0 -1
- package/server/services/websocket/quality-operations.ts +72 -0
- package/server/services/websocket/quality-persistence.ts +47 -8
- package/server/services/websocket/quality-review-agent.ts +154 -65
- package/server/services/websocket/quality-service.ts +415 -68
- package/server/services/websocket/quality-tools.ts +62 -3
- package/server/services/websocket/quality-types.ts +61 -4
- package/server/services/websocket/session-handlers.ts +64 -11
- package/server/services/websocket/session-history.ts +3 -1
- package/server/services/websocket/session-initialization.ts +189 -47
- package/server/services/websocket/session-registry.ts +37 -1
- package/server/services/websocket/settings-handlers.ts +41 -5
- package/server/services/websocket/skill-handlers.ts +0 -1
- package/server/services/websocket/skill-watcher.ts +0 -1
- package/server/services/websocket/tab-broadcast.ts +10 -3
- package/server/services/websocket/tab-event-buffer.ts +143 -12
- package/server/services/websocket/tab-event-replay.ts +70 -4
- package/server/services/websocket/tab-handlers.ts +53 -6
- package/server/services/websocket/terminal-handlers.ts +39 -3
- package/server/services/websocket/types.ts +39 -8
- package/server/utils/agent-manager.ts +0 -1
- package/server/utils/paths.ts +0 -1
- package/server/utils/port-manager.ts +0 -1
- package/server/utils/port.ts +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bouncer classifier factory.
|
|
6
|
+
*
|
|
7
|
+
* Two entry points:
|
|
8
|
+
*
|
|
9
|
+
* - `getClassifier()` — production path. Reads
|
|
10
|
+
* `settings.bouncerClassifier: { engine, model }` and returns the
|
|
11
|
+
* matching `BouncerClassifier` instance. If the persisted config is
|
|
12
|
+
* missing, malformed, or names a non-eligible model, it logs a clear
|
|
13
|
+
* warning and falls back to `ClaudeBouncerClassifier` + Haiku — the
|
|
14
|
+
* Bouncer must always have a classifier to call, so "no config" and
|
|
15
|
+
* "bad config" both collapse to the known-safe default rather than
|
|
16
|
+
* throwing.
|
|
17
|
+
*
|
|
18
|
+
* - `createBouncerClassifier(options?)` — direct-construction helper used
|
|
19
|
+
* by the engineSwap feature-flag gate (see `engine-swap-flag.test.ts`).
|
|
20
|
+
* Accepts an explicit `engineId` and is deliberately feature-flag-aware:
|
|
21
|
+
* when `engineSwap` is disabled, the flag short-circuits to Claude.
|
|
22
|
+
*
|
|
23
|
+
* New callers should prefer `getClassifier()` so the user-selected model
|
|
24
|
+
* takes effect without plumbing. The bouncer-integration layer constructs
|
|
25
|
+
* its default classifier lazily so env var changes and settings edits
|
|
26
|
+
* propagate on the next classification call.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { OpenCodeServerManager } from '../../engines/opencode/OpenCodeServerManager.js';
|
|
30
|
+
import type { EngineId } from '../../engines/types.js';
|
|
31
|
+
import {
|
|
32
|
+
BOUNCER_ELIGIBLE_MODELS,
|
|
33
|
+
type BouncerClassifierConfig,
|
|
34
|
+
DEFAULT_BOUNCER_CLASSIFIER,
|
|
35
|
+
getBouncerClassifier,
|
|
36
|
+
isEngineSwapEnabled,
|
|
37
|
+
} from '../../services/settings.js';
|
|
38
|
+
import type { BouncerClassifier } from './BouncerClassifier.js';
|
|
39
|
+
import { ClaudeBouncerClassifier } from './ClaudeBouncerClassifier.js';
|
|
40
|
+
import { OpenCodeBouncerClassifier } from './OpenCodeBouncerClassifier.js';
|
|
41
|
+
|
|
42
|
+
/** Options accepted by every classifier implementation. */
|
|
43
|
+
export interface ClassifierFactoryOptions {
|
|
44
|
+
/**
|
|
45
|
+
* Which engine backs the classifier. With `engineSwap` off this is
|
|
46
|
+
* ignored and `'claude-code'` is used; with the flag on, non-Claude
|
|
47
|
+
* engines throw until their implementations land (Epic 4).
|
|
48
|
+
*/
|
|
49
|
+
engineId?: EngineId;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Construct the Layer-2 Bouncer classifier by engine id (no settings
|
|
54
|
+
* lookup). Exists for the `engineSwap` feature-flag gate, which asserts
|
|
55
|
+
* that the factory is flag-aware in both on/off states. New production
|
|
56
|
+
* callers should route through {@link getClassifier} instead.
|
|
57
|
+
*/
|
|
58
|
+
export function createBouncerClassifier(
|
|
59
|
+
options: ClassifierFactoryOptions = {},
|
|
60
|
+
): BouncerClassifier {
|
|
61
|
+
if (!isEngineSwapEnabled()) {
|
|
62
|
+
return new ClaudeBouncerClassifier();
|
|
63
|
+
}
|
|
64
|
+
const engineId = options.engineId ?? 'claude-code';
|
|
65
|
+
switch (engineId) {
|
|
66
|
+
case 'claude-code':
|
|
67
|
+
return new ClaudeBouncerClassifier();
|
|
68
|
+
case 'opencode':
|
|
69
|
+
// Wired through `getClassifier()` (settings path). Direct engine-id
|
|
70
|
+
// construction stays intentionally narrow — callers that want the
|
|
71
|
+
// OpenCode classifier should pick it via the Settings UI so the
|
|
72
|
+
// shared `OpenCodeServerManager` is available.
|
|
73
|
+
throw new Error(
|
|
74
|
+
'OpenCode bouncer classifier is not implemented yet (Epic 4). ' +
|
|
75
|
+
'Keep engineSwap off until the OpenCode classifier ships.',
|
|
76
|
+
);
|
|
77
|
+
default: {
|
|
78
|
+
const exhaustive: never = engineId;
|
|
79
|
+
throw new Error(`Unknown classifier engine id: ${String(exhaustive)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Process-lifetime singleton for the `opencode serve` subprocess used by
|
|
86
|
+
* the classifier. Deliberately separate from the engines-side manager so
|
|
87
|
+
* tests can inject a mock client without touching the engine factory.
|
|
88
|
+
* Lazy: never created until an OpenCode classifier is first requested.
|
|
89
|
+
*/
|
|
90
|
+
let sharedOpenCodeManager: OpenCodeServerManager | null = null;
|
|
91
|
+
let openCodeManagerFactory: () => OpenCodeServerManager = () =>
|
|
92
|
+
new OpenCodeServerManager({ registerProcessHandlers: true });
|
|
93
|
+
|
|
94
|
+
function getSharedOpenCodeServerManager(): OpenCodeServerManager {
|
|
95
|
+
if (!sharedOpenCodeManager) {
|
|
96
|
+
sharedOpenCodeManager = openCodeManagerFactory();
|
|
97
|
+
}
|
|
98
|
+
return sharedOpenCodeManager;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Override the OpenCode manager used by the classifier factory. Test-only;
|
|
103
|
+
* production code never calls this. Pass `null` to reset to the default.
|
|
104
|
+
*/
|
|
105
|
+
export function __setOpenCodeManagerFactoryForTests(
|
|
106
|
+
factory: (() => OpenCodeServerManager) | null,
|
|
107
|
+
): void {
|
|
108
|
+
sharedOpenCodeManager = null;
|
|
109
|
+
openCodeManagerFactory = factory
|
|
110
|
+
?? (() => new OpenCodeServerManager({ registerProcessHandlers: true }));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Log a fallback reason in a single place so grep + log analysis surface
|
|
115
|
+
* every path where we silently dropped back to Claude+Haiku. Goes to
|
|
116
|
+
* stderr (matching the rest of the Bouncer logs) so it shows up in the
|
|
117
|
+
* CLI's `--trace` output and in audit transcripts.
|
|
118
|
+
*/
|
|
119
|
+
function logFallback(reason: string): void {
|
|
120
|
+
console.warn(
|
|
121
|
+
`[Bouncer] Classifier config invalid, falling back to Claude+Haiku: ${reason}`,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Construct a `BouncerClassifier` for the provided config. Throws on bad
|
|
127
|
+
* config — callers that need fallback semantics should use
|
|
128
|
+
* {@link getClassifier} instead.
|
|
129
|
+
*/
|
|
130
|
+
export function createClassifierForConfig(
|
|
131
|
+
config: BouncerClassifierConfig,
|
|
132
|
+
): BouncerClassifier {
|
|
133
|
+
const eligible = BOUNCER_ELIGIBLE_MODELS[config.engine];
|
|
134
|
+
if (!eligible || !eligible.includes(config.model)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`Model '${config.model}' is not bouncer-eligible for engine '${config.engine}'`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
switch (config.engine) {
|
|
140
|
+
case 'claude-code':
|
|
141
|
+
// The Claude classifier currently hardcodes `--model haiku` in the
|
|
142
|
+
// subprocess call. Passing `sonnet` still returns Haiku until a
|
|
143
|
+
// later issue threads the model through — the eligibility check
|
|
144
|
+
// guards correctness; the subprocess args are a follow-up.
|
|
145
|
+
return new ClaudeBouncerClassifier();
|
|
146
|
+
case 'opencode':
|
|
147
|
+
return new OpenCodeBouncerClassifier({
|
|
148
|
+
manager: getSharedOpenCodeServerManager(),
|
|
149
|
+
model: config.model,
|
|
150
|
+
});
|
|
151
|
+
default: {
|
|
152
|
+
const exhaustive: never = config.engine;
|
|
153
|
+
throw new Error(`Unknown classifier engine id: ${String(exhaustive)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Production classifier accessor. Reads the user's current Bouncer
|
|
160
|
+
* classifier choice from persistent settings and returns a fresh
|
|
161
|
+
* `BouncerClassifier` instance. Invalid or missing config logs a clear
|
|
162
|
+
* warning and falls back to the default Claude+Haiku classifier — the
|
|
163
|
+
* Bouncer is a required security layer, so "no classifier available" is
|
|
164
|
+
* never an acceptable outcome.
|
|
165
|
+
*
|
|
166
|
+
* Called on every `reviewOperation()` path (indirectly via the
|
|
167
|
+
* integration layer's lazy default); cheap because classifier
|
|
168
|
+
* construction is synchronous and does not spawn subprocesses until the
|
|
169
|
+
* first `classify()` call.
|
|
170
|
+
*/
|
|
171
|
+
export function getClassifier(): BouncerClassifier {
|
|
172
|
+
let config: BouncerClassifierConfig;
|
|
173
|
+
try {
|
|
174
|
+
config = getBouncerClassifier();
|
|
175
|
+
} catch (err) {
|
|
176
|
+
logFallback(err instanceof Error ? err.message : String(err));
|
|
177
|
+
return new ClaudeBouncerClassifier();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
return createClassifierForConfig(config);
|
|
182
|
+
} catch (err) {
|
|
183
|
+
logFallback(err instanceof Error ? err.message : String(err));
|
|
184
|
+
// Last-resort fallback — if even the default config can't build the
|
|
185
|
+
// classifier (e.g. OpenCode catalogue edit broke the model list), we
|
|
186
|
+
// still return Claude+Haiku so the Bouncer keeps functioning.
|
|
187
|
+
if (
|
|
188
|
+
config.engine === DEFAULT_BOUNCER_CLASSIFIER.engine &&
|
|
189
|
+
config.model === DEFAULT_BOUNCER_CLASSIFIER.model
|
|
190
|
+
) {
|
|
191
|
+
return new ClaudeBouncerClassifier();
|
|
192
|
+
}
|
|
193
|
+
return new ClaudeBouncerClassifier();
|
|
194
|
+
}
|
|
195
|
+
}
|
package/server/mcp/server.ts
CHANGED
package/server/routes/files.ts
CHANGED
package/server/routes/index.ts
CHANGED
package/server/server-setup.ts
CHANGED
package/server/services/auth.ts
CHANGED
package/server/services/files.ts
CHANGED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Resolver — Maps issue.agents hints to subagents installed on the user's system.
|
|
5
|
+
*
|
|
6
|
+
* Issue front matter may specify `agents` as either canonical Claude Code subagent
|
|
7
|
+
* names (e.g. `backend-architect`) or general role pointers (e.g. `backend engineer`).
|
|
8
|
+
* This module bridges the two: it consults AgentManager (project / global / bundled
|
|
9
|
+
* `.claude/agents/`) and resolves each hint to a concrete agent name when possible,
|
|
10
|
+
* falling back to the original hint when no match is found so the executor can still
|
|
11
|
+
* surface the user's intent in the prompt.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { type AgentInfo, agentManager } from '../../utils/agent-manager.js';
|
|
15
|
+
|
|
16
|
+
export interface ResolvedAgent {
|
|
17
|
+
/** The original hint as written in the issue front matter. */
|
|
18
|
+
hint: string;
|
|
19
|
+
/** The resolved canonical agent name, or null if no installed agent matched. */
|
|
20
|
+
resolvedName: string | null;
|
|
21
|
+
/** The matching agent info, or null if no installed agent matched. */
|
|
22
|
+
info: AgentInfo | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const NON_WORD = /[^a-z0-9]+/g;
|
|
26
|
+
|
|
27
|
+
function normalize(input: string): string {
|
|
28
|
+
return input.toLowerCase().replace(NON_WORD, ' ').trim();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function tokenize(input: string): string[] {
|
|
32
|
+
return normalize(input).split(' ').filter(Boolean);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Discover every available agent across project / global / bundled directories.
|
|
37
|
+
* Project entries shadow global, which shadows bundled (deduped by canonical name).
|
|
38
|
+
*/
|
|
39
|
+
function listAvailableAgents(workingDir: string): AgentInfo[] {
|
|
40
|
+
const seen = new Map<string, AgentInfo>();
|
|
41
|
+
const layers = [
|
|
42
|
+
agentManager.listProjectAgents(workingDir),
|
|
43
|
+
agentManager.listGlobalAgents(),
|
|
44
|
+
agentManager.listBundledAgents(),
|
|
45
|
+
];
|
|
46
|
+
for (const layer of layers) {
|
|
47
|
+
for (const agent of layer) {
|
|
48
|
+
if (!seen.has(agent.name)) seen.set(agent.name, agent);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return Array.from(seen.values());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Score how well an agent matches a hint. Returns 0 when there is no token overlap.
|
|
56
|
+
* Higher is better. Exact normalized matches return Infinity.
|
|
57
|
+
*/
|
|
58
|
+
function matchScore(hint: string, agent: AgentInfo): number {
|
|
59
|
+
const normalizedHint = normalize(hint);
|
|
60
|
+
const normalizedName = normalize(agent.name);
|
|
61
|
+
if (normalizedHint === normalizedName) return Number.POSITIVE_INFINITY;
|
|
62
|
+
|
|
63
|
+
const hintTokens = tokenize(hint);
|
|
64
|
+
if (hintTokens.length === 0) return 0;
|
|
65
|
+
|
|
66
|
+
const haystack = `${normalizedName} ${normalize(agent.description ?? '')}`;
|
|
67
|
+
let matched = 0;
|
|
68
|
+
for (const token of hintTokens) {
|
|
69
|
+
if (token.length < 2) continue;
|
|
70
|
+
if (haystack.includes(token)) matched++;
|
|
71
|
+
}
|
|
72
|
+
if (matched === 0) return 0;
|
|
73
|
+
|
|
74
|
+
// Reward agents whose name (not just description) contains hint tokens.
|
|
75
|
+
const nameMatches = hintTokens.filter(t => t.length >= 2 && normalizedName.includes(t)).length;
|
|
76
|
+
return matched + nameMatches * 0.5;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resolve a single hint against the catalog of available agents.
|
|
81
|
+
* Returns the highest-scoring agent, or null when no agent has any token overlap.
|
|
82
|
+
*/
|
|
83
|
+
function resolveHint(hint: string, available: AgentInfo[]): AgentInfo | null {
|
|
84
|
+
let bestScore = 0;
|
|
85
|
+
let best: AgentInfo | null = null;
|
|
86
|
+
for (const agent of available) {
|
|
87
|
+
const score = matchScore(hint, agent);
|
|
88
|
+
if (score > bestScore) {
|
|
89
|
+
bestScore = score;
|
|
90
|
+
best = agent;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return best;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Resolve every hint in `agents` against the user's installed Claude Code subagents.
|
|
98
|
+
* Hints with no match are preserved (resolvedName: null) so the executor can still
|
|
99
|
+
* mention them in the prompt with a graceful fallback note.
|
|
100
|
+
*/
|
|
101
|
+
export function resolveAgentHints(agents: string[], workingDir: string): ResolvedAgent[] {
|
|
102
|
+
if (!agents || agents.length === 0) return [];
|
|
103
|
+
const available = listAvailableAgents(workingDir);
|
|
104
|
+
return agents
|
|
105
|
+
.map(raw => raw.trim())
|
|
106
|
+
.filter(Boolean)
|
|
107
|
+
.map(hint => {
|
|
108
|
+
const info = resolveHint(hint, available);
|
|
109
|
+
return {
|
|
110
|
+
hint,
|
|
111
|
+
resolvedName: info?.name ?? null,
|
|
112
|
+
info,
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
}
|
|
@@ -74,14 +74,49 @@ For each finding, use this reasoning process:
|
|
|
74
74
|
|
|
75
75
|
## Scoring Guidelines
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
- **A (90-100)**: Excellent — clean architecture, minimal issues, well-tested, follows best practices
|
|
79
|
-
- **B (80-89)**: Good — solid code with minor issues, mostly well-structured
|
|
80
|
-
- **C (70-79)**: Adequate — functional but has notable quality issues that should be addressed
|
|
81
|
-
- **D (60-69)**: Below average — significant issues in architecture, testing, or code quality
|
|
82
|
-
- **F (0-59)**: Poor — serious problems: security vulnerabilities, broken architecture, major bugs, or unmaintainable code
|
|
77
|
+
The overall grade is computed deterministically from your findings, not from a number you supply. **Severity and category on each finding are what drive the grade — pick them carefully.** When in doubt, downgrade.
|
|
83
78
|
|
|
84
|
-
|
|
79
|
+
### Severity Ladder — calibrate by likelihood × user impact, not just by topic
|
|
80
|
+
|
|
81
|
+
Severity should answer two questions:
|
|
82
|
+
1. **How likely is this to actually trigger?** (Common path vs. edge case vs. theoretical)
|
|
83
|
+
2. **What happens when it triggers?** (User-visible breakage / data loss vs. internal-only / cosmetic)
|
|
84
|
+
|
|
85
|
+
Use this ladder. Worked examples follow each level.
|
|
86
|
+
|
|
87
|
+
- **`critical`** — Reserved for "this is broken in production today on common code paths." Active data corruption, RCE, auth bypass for normal users, unrecoverable crash on the happy path. If the on-call would page at 3 AM for it, it's critical.
|
|
88
|
+
- ✅ SQL injection on a public form. Hard-coded production credentials in a deployed file. A `null`-deref on the homepage render path.
|
|
89
|
+
- ❌ "Could become a problem if traffic 100×". "Edge case where two clients race within 50ms." A theoretical bug in error-handling code that has never run.
|
|
90
|
+
|
|
91
|
+
- **`high`** — A real bug or vulnerability that **definitely affects normal users on common code paths** with **user-visible consequences** (broken UI, wrong data shown, action silently fails). Or an exploitable security issue that requires only realistic conditions.
|
|
92
|
+
- ✅ Wrong state shown after a successful save (UI/UX bug). XSS via reflected URL parameter on a logged-in dashboard. Wrong calculation in a money-handling code path. Memory leak that grows on every page-view.
|
|
93
|
+
- ❌ Race condition on degraded shutdown paths. Edge-case exploit gated behind admin auth on a feature that hasn't shipped. A theoretical SSRF on an internal endpoint with no user reach. Defense-in-depth gaps (rate limit absent, header missing) — those are `low`.
|
|
94
|
+
|
|
95
|
+
- **`medium`** — Real issue but affects an edge case OR has limited user impact OR requires unusual conditions to trigger. Worth fixing eventually; not blocking.
|
|
96
|
+
- ✅ Missing error handling on a rarely-failing dependency. Logic bug in an admin-only page. A bug only reachable when two specific feature flags are both on. Performance issue that adds 50 ms but isn't user-perceptible.
|
|
97
|
+
- ❌ "Best practice" preferences with no user impact. Theoretical bugs in unreachable code.
|
|
98
|
+
|
|
99
|
+
- **`low`** — Improbable, theoretical, or cosmetic. Defense-in-depth missing, style/preference, "could be cleaner." Many of these are fine to leave for years.
|
|
100
|
+
- ✅ Missing rate limit on a low-traffic admin endpoint. SQL injection-shaped pattern that ends up safely parameterized. A `console.log` left in code. A nullable field that's only null in a code path that never executes.
|
|
101
|
+
|
|
102
|
+
### Likelihood-weighted severity rules
|
|
103
|
+
|
|
104
|
+
Apply these as veto rules **after** you've chosen a severity from topic alone:
|
|
105
|
+
|
|
106
|
+
- If the bug only fires on a path that **realistically never executes in production**, downgrade by at least one step (high→medium, medium→low). A bug that requires "the network connection drops between line 42 and 43 of the shutdown handler" is `low` even if its consequences would be severe.
|
|
107
|
+
- If the issue has **no user-visible effect** (no UI/UX impact, no incorrect data shown, no security boundary crossed), it caps at `medium`. UI/UX wiring bugs and broken interactive flows skew higher; pure-internal architecture / observability gaps skew lower.
|
|
108
|
+
- If the issue is a **defense-in-depth gap** (rate limits, hardening headers, additional validation on already-validated input), cap at `low` unless you can articulate the realistic exploit chain that survives the existing defenses.
|
|
109
|
+
- If exploitability requires **conditions that only matter at high traffic / wide user attack surface**, downgrade for early-stage projects: this is `low` or `medium`, not `high`. (Make this explicit in the description so the reader knows the call.)
|
|
110
|
+
|
|
111
|
+
### Three dimension grades the engine derives
|
|
112
|
+
|
|
113
|
+
- **Security** (category: `security`) — strictest. A = 0 findings, B = only low, C = ≥1 medium, F = ≥1 high, F- = ≥1 critical.
|
|
114
|
+
- **Reliability** (categories: `bugs`, `logic`, `performance`) — density-based grade per KLOC with severity escape: critical → F, any high → caps at C. Multiple medium findings escalate gradually rather than auto-failing.
|
|
115
|
+
- **Maintainability** (categories: `architecture`, `oop`, `maintainability`) — density-based with severity escape: critical → F, any high → C.
|
|
116
|
+
|
|
117
|
+
Overall grade = the worst of the three. A single critical security finding caps the entire codebase at F-.
|
|
118
|
+
|
|
119
|
+
You may still emit `score`, `grade`, and `scoreRationale` for reference — they are persisted but ignored when computing the displayed grade. Focus your effort on accurate severity classification, not on guessing the overall number.
|
|
85
120
|
|
|
86
121
|
## Output
|
|
87
122
|
|
|
@@ -89,13 +124,10 @@ After your analysis, output EXACTLY one JSON code block with your findings. No o
|
|
|
89
124
|
|
|
90
125
|
```json
|
|
91
126
|
{
|
|
92
|
-
"score": 72,
|
|
93
|
-
"grade": "C",
|
|
94
|
-
"scoreRationale": "Brief explanation of why this score was given, referencing key issues",
|
|
95
127
|
"findings": [
|
|
96
128
|
{
|
|
97
129
|
"severity": "critical|high|medium|low",
|
|
98
|
-
"category": "architecture|oop|security|bugs|performance|logic",
|
|
130
|
+
"category": "architecture|oop|security|bugs|performance|logic|maintainability",
|
|
99
131
|
"file": "relative/path/to/file.ts",
|
|
100
132
|
"line": 42,
|
|
101
133
|
"title": "Short title describing the issue",
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
-
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Plan Composer — Handles natural language prompts for PPS creation/editing.
|
|
@@ -11,6 +10,7 @@
|
|
|
11
10
|
|
|
12
11
|
import { existsSync, readFileSync } from 'node:fs';
|
|
13
12
|
import { join } from 'node:path';
|
|
13
|
+
import { getEtaProfileCached } from '../../cli/eta-estimator.js';
|
|
14
14
|
import type { ToolUseEvent } from '../../cli/headless/index.js';
|
|
15
15
|
import { ResilientRunner } from '../../cli/headless/resilient-runner.js';
|
|
16
16
|
import { cleanupAttachments, preparePromptAndAttachments } from '../../cli/improvisation-attachments.js';
|
|
@@ -29,6 +29,21 @@ const PROMPT_TOOL_MESSAGES: Record<string, string> = {
|
|
|
29
29
|
Bash: 'Running commands...',
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the ETA quantile profile used by the planning indicator. Reads
|
|
34
|
+
* .mstro/history (chat improv movements) since planning-prompt durations
|
|
35
|
+
* cluster in the same range. Failures degrade silently to undefined — the
|
|
36
|
+
* indicator falls back to elapsed-only display.
|
|
37
|
+
*/
|
|
38
|
+
async function resolvePromptEtaProfile(workingDir: string): Promise<NonNullable<Awaited<ReturnType<typeof getEtaProfileCached>>> | undefined> {
|
|
39
|
+
try {
|
|
40
|
+
const profile = await getEtaProfileCached(join(workingDir, '.mstro', 'history'));
|
|
41
|
+
return profile ?? undefined;
|
|
42
|
+
} catch {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
32
47
|
function getPromptToolCompleteMessage(event: ToolUseEvent): string | null {
|
|
33
48
|
const input = event.completeInput;
|
|
34
49
|
if (!input) return null;
|
|
@@ -230,6 +245,7 @@ blocks: [] # Use backlog-relative paths: backlog/IS-NNN.md
|
|
|
230
245
|
review_gate: auto
|
|
231
246
|
output_type: auto # code = modify source files, document = produce written artifact, auto = infer
|
|
232
247
|
output_file: null
|
|
248
|
+
agents: [] # Agent hints — see "agents field rules" below
|
|
233
249
|
---
|
|
234
250
|
|
|
235
251
|
# IS-NNN: Title
|
|
@@ -269,6 +285,21 @@ Implementation guidance.
|
|
|
269
285
|
- When output_type is \`document\`, "Files to Modify" entries are treated as references, not files to edit. The AI produces a document artifact and is reviewed on document quality.
|
|
270
286
|
- When output_type is \`code\`, "Files to Modify" lists actual source files the AI must edit. The review gate verifies source files were changed.
|
|
271
287
|
|
|
288
|
+
## agents field rules
|
|
289
|
+
|
|
290
|
+
The \`agents\` field is a list of agent hints for the executing Claude Code session. The executor uses Claude Code's Task tool to delegate work to matching subagents in the user's \`.claude/agents/\` directory (project / global / bundled), with a fallback to the general-purpose agent when no match is found.
|
|
291
|
+
|
|
292
|
+
- ALWAYS populate \`agents\` with the most relevant 1–4 agents for the work the issue describes. Empty arrays mean "no hints" — only use \`[]\` when no agent type plausibly applies (rare).
|
|
293
|
+
- Entries can be specific agent file names (e.g. \`backend-architect\`, \`frontend-developer\`, \`code-reviewer\`, \`security-auditor\`) OR general role pointers the user's system can match (e.g. \`backend engineer\`, \`product designer\`, \`marketing\`). Prefer specific names — they resolve more reliably.
|
|
294
|
+
- Match agents to the actual work, not the issue's surface topic. A "fix login button" issue is frontend work (\`frontend-developer\`); a "design login flow" issue is product/design (\`product-designer\`, \`ux-writer\`).
|
|
295
|
+
- Common pairings:
|
|
296
|
+
- Code implementation: pick from \`frontend-developer\`, \`backend-architect\`, \`typescript-pro\`, \`python-pro\`, \`golang-pro\`, etc., based on stack
|
|
297
|
+
- UI/design work: \`ui-designer\`, \`product-designer\`, \`design-system-architect\`, \`ux-writer\`
|
|
298
|
+
- Data/DB: \`database-architect\`, \`database-optimizer\`, \`data-engineer\`, \`sql-pro\`
|
|
299
|
+
- Quality: pair an implementation agent with \`code-reviewer\`, \`test-automator\`, or \`security-auditor\` for sensitive issues
|
|
300
|
+
- Product/strategy: \`product-manager\`, \`product-marketing\`, \`business-analyst\`
|
|
301
|
+
- YAML format: inline \`agents: [backend-architect, code-reviewer]\` or block list with \`-\` items both work.
|
|
302
|
+
|
|
272
303
|
## Epic creation rules
|
|
273
304
|
|
|
274
305
|
- Create an EP-*.md file in ${cc.backlogPath} with type: epic and a children: [] field in front matter
|
|
@@ -288,11 +319,27 @@ User request: ${userPrompt}`;
|
|
|
288
319
|
prepareAttachmentPrompt(ctx, enrichedPrompt, attachments, workingDir, cc.effectiveBoardId);
|
|
289
320
|
|
|
290
321
|
const streamBoardId = cc.effectiveBoardId ?? null;
|
|
322
|
+
const etaProfile = await resolvePromptEtaProfile(workingDir);
|
|
323
|
+
|
|
324
|
+
// Tracks whether `planPromptResponse` has been broadcast. The web side
|
|
325
|
+
// treats this event as the authoritative completion signal — without it,
|
|
326
|
+
// the composer todo list stays stuck on a spinner. The finally block
|
|
327
|
+
// guarantees a completion broadcast even if the runner throws or exits
|
|
328
|
+
// through an unexpected path.
|
|
329
|
+
let responseSent = false;
|
|
330
|
+
const sendResponse = (response: string, success: boolean, error: string | null) => {
|
|
331
|
+
if (responseSent) return;
|
|
332
|
+
responseSent = true;
|
|
333
|
+
ctx.broadcastToAll({
|
|
334
|
+
type: 'planPromptResponse',
|
|
335
|
+
data: { response, success, error, boardId: streamBoardId },
|
|
336
|
+
});
|
|
337
|
+
};
|
|
291
338
|
|
|
292
339
|
try {
|
|
293
340
|
ctx.broadcastToAll({
|
|
294
341
|
type: 'planPromptProgress',
|
|
295
|
-
data: { message: 'Starting project planning...', boardId: streamBoardId },
|
|
342
|
+
data: { message: 'Starting project planning...', boardId: streamBoardId, etaProfile },
|
|
296
343
|
});
|
|
297
344
|
|
|
298
345
|
const runner = new ResilientRunner({
|
|
@@ -340,15 +387,11 @@ User request: ${userPrompt}`;
|
|
|
340
387
|
data: { message: 'Finalizing project plan...', boardId: streamBoardId },
|
|
341
388
|
});
|
|
342
389
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
error: result.error || null,
|
|
349
|
-
boardId: streamBoardId,
|
|
350
|
-
},
|
|
351
|
-
});
|
|
390
|
+
sendResponse(
|
|
391
|
+
result.completed ? 'Prompt executed successfully.' : (result.error || 'Unknown error'),
|
|
392
|
+
result.completed,
|
|
393
|
+
result.error || null,
|
|
394
|
+
);
|
|
352
395
|
|
|
353
396
|
// Re-parse and broadcast updated state
|
|
354
397
|
const updatedState = parsePlanDirectory(workingDir);
|
|
@@ -356,11 +399,19 @@ User request: ${userPrompt}`;
|
|
|
356
399
|
ctx.broadcastToAll({ type: 'planStateUpdated', data: updatedState });
|
|
357
400
|
}
|
|
358
401
|
} catch (error) {
|
|
402
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
359
403
|
ctx.broadcastToAll({
|
|
360
404
|
type: 'planError',
|
|
361
|
-
data: { error:
|
|
405
|
+
data: { error: errorMsg, boardId: streamBoardId },
|
|
362
406
|
});
|
|
407
|
+
// Send a completion signal too — `planError` clears streaming on the web
|
|
408
|
+
// but doesn't set the response banner. Without this, the user sees a
|
|
409
|
+
// half-finished UI (no spinner, no message).
|
|
410
|
+
sendResponse(errorMsg, false, errorMsg);
|
|
363
411
|
} finally {
|
|
364
412
|
cleanupAttachments(workingDir, attachmentSessionId);
|
|
413
|
+
// Defense in depth: guarantee a completion broadcast for any control
|
|
414
|
+
// flow not covered above (process abort, unexpected throw types, etc.).
|
|
415
|
+
sendResponse('Prompt execution ended unexpectedly.', false, 'No completion signal');
|
|
365
416
|
}
|
|
366
417
|
}
|