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
|
@@ -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
|
* Quality Handlers — WebSocket message router for quality scanning
|
|
@@ -14,15 +13,16 @@
|
|
|
14
13
|
import { join, resolve } from 'node:path';
|
|
15
14
|
import { validatePathWithinWorkingDir } from '../pathUtils.js';
|
|
16
15
|
import type { HandlerContext } from './handler-context.js';
|
|
16
|
+
import { estimateCodebaseSize, estimateScanMs } from './quality-eta.js';
|
|
17
|
+
import { operationRegistry } from './quality-operations.js';
|
|
17
18
|
import { QualityPersistence } from './quality-persistence.js';
|
|
18
19
|
import { handleCodeReview } from './quality-review-agent.js';
|
|
19
|
-
import { detectTools, installTools, runQualityScan } from './quality-service.js';
|
|
20
|
+
import { detectTools, installTools, QualityScanAbortedError, runQualityScan } from './quality-service.js';
|
|
20
21
|
import type { WebSocketMessage, WSContext } from './types.js';
|
|
21
22
|
|
|
22
23
|
// ── Shared state ──────────────────────────────────────────────
|
|
23
24
|
|
|
24
25
|
const persistenceCache = new Map<string, QualityPersistence>();
|
|
25
|
-
const activeReviews = new Set<string>();
|
|
26
26
|
|
|
27
27
|
function getPersistence(workingDir: string): QualityPersistence {
|
|
28
28
|
let persistence = persistenceCache.get(workingDir);
|
|
@@ -87,10 +87,32 @@ export function handleQualityMessage(
|
|
|
87
87
|
if (error) { sendPathError(msg.data?.path || '.', error); return; }
|
|
88
88
|
const reportPath = msg.data?.path || '.';
|
|
89
89
|
const persistence = getPersistence(workingDir);
|
|
90
|
+
let controller: AbortController;
|
|
91
|
+
try {
|
|
92
|
+
controller = operationRegistry.start(workingDir, reportPath, 'reviewing');
|
|
93
|
+
} catch {
|
|
94
|
+
// Look up what's actually running so the user sees the right message
|
|
95
|
+
// — clicking "Run checks" during an in-flight AI review used to surface
|
|
96
|
+
// "A scan is already running" because the error was hardcoded to the
|
|
97
|
+
// *new* op kind rather than the existing one.
|
|
98
|
+
const runningKind = operationRegistry.getKind(workingDir, reportPath);
|
|
99
|
+
const error = runningKind === 'scanning'
|
|
100
|
+
? 'A scan is already running for this directory.'
|
|
101
|
+
: 'An AI review is already running for this directory.';
|
|
102
|
+
ctx.send(ws, { type: 'qualityError', data: { path: reportPath, error } });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
90
105
|
persistence.setActiveOperation(reportPath, 'reviewing');
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
// The review agent is responsible for emitting the first progress
|
|
107
|
+
// message with an ETA; the handler just wires up the controller +
|
|
108
|
+
// persistence cleanup.
|
|
109
|
+
handleCodeReview(ctx, ws, reportPath, dirPath, workingDir, getPersistence, controller.signal)
|
|
110
|
+
.finally(() => {
|
|
111
|
+
operationRegistry.finish(workingDir, reportPath);
|
|
112
|
+
persistence.clearActiveOperation(reportPath);
|
|
113
|
+
});
|
|
93
114
|
},
|
|
115
|
+
qualityCancel: () => handleCancel(ctx, msg, workingDir),
|
|
94
116
|
qualityLoadState: () => handleLoadState(ctx, ws, workingDir),
|
|
95
117
|
qualityClearPending: () => {
|
|
96
118
|
const persistence = getPersistence(workingDir);
|
|
@@ -138,6 +160,27 @@ async function handleLoadState(
|
|
|
138
160
|
persistence.clearPendingResults();
|
|
139
161
|
}
|
|
140
162
|
|
|
163
|
+
// Reconcile orphaned active operations: anything persisted to disk that
|
|
164
|
+
// has no live `AbortController` in the registry was interrupted by a CLI
|
|
165
|
+
// restart or crash. Surface as an error so the UI clears the spinner and
|
|
166
|
+
// remove from disk so the same op doesn't keep haunting future reconnects.
|
|
167
|
+
const orphans = state.activeOperations.filter(
|
|
168
|
+
(op) => !operationRegistry.has(workingDir, op.path),
|
|
169
|
+
);
|
|
170
|
+
if (orphans.length > 0) {
|
|
171
|
+
for (const op of orphans) {
|
|
172
|
+
persistence.clearActiveOperation(op.path);
|
|
173
|
+
ctx.send(ws, {
|
|
174
|
+
type: 'qualityError',
|
|
175
|
+
data: { path: op.path, error: 'Operation interrupted — please run again.' },
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
// Reload so the response reflects the cleared ops.
|
|
179
|
+
const refreshed = persistence.loadState();
|
|
180
|
+
ctx.send(ws, { type: 'qualityStateLoaded', data: refreshed });
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
141
184
|
ctx.send(ws, { type: 'qualityStateLoaded', data: state });
|
|
142
185
|
} catch (error) {
|
|
143
186
|
ctx.send(ws, {
|
|
@@ -147,6 +190,30 @@ async function handleLoadState(
|
|
|
147
190
|
}
|
|
148
191
|
}
|
|
149
192
|
|
|
193
|
+
function handleCancel(
|
|
194
|
+
ctx: HandlerContext,
|
|
195
|
+
msg: WebSocketMessage,
|
|
196
|
+
workingDir: string,
|
|
197
|
+
): void {
|
|
198
|
+
const reportPath = msg.data?.path || '.';
|
|
199
|
+
const persistence = getPersistence(workingDir);
|
|
200
|
+
const wasRunning = operationRegistry.cancel(workingDir, reportPath);
|
|
201
|
+
// Always clear persistence — cancel for an orphan should still leave the
|
|
202
|
+
// disk clean so future reconnects don't re-emit the orphan reconciliation
|
|
203
|
+
// error.
|
|
204
|
+
persistence.clearActiveOperation(reportPath);
|
|
205
|
+
// Broadcast so every paired device sees the operation end (multi-device
|
|
206
|
+
// sync). If nothing was running we still emit so a stale spinner on a
|
|
207
|
+
// second device gets cleared by the `qualityError` handler.
|
|
208
|
+
ctx.broadcastToAll({
|
|
209
|
+
type: 'qualityError',
|
|
210
|
+
data: {
|
|
211
|
+
path: reportPath,
|
|
212
|
+
error: wasRunning ? 'Cancelled by user' : 'Operation already finished',
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
150
217
|
async function handleSaveDirectories(
|
|
151
218
|
ctx: HandlerContext,
|
|
152
219
|
ws: WSContext,
|
|
@@ -231,18 +298,90 @@ async function handleScan(
|
|
|
231
298
|
const reportPath = msg.data?.path || '.';
|
|
232
299
|
const persistence = getPersistence(workingDir);
|
|
233
300
|
|
|
301
|
+
let controller: AbortController;
|
|
302
|
+
try {
|
|
303
|
+
controller = operationRegistry.start(workingDir, reportPath, 'scanning');
|
|
304
|
+
} catch {
|
|
305
|
+
// Same reasoning as the qualityCodeReview handler above — surface the
|
|
306
|
+
// *running* op kind, not the requested one.
|
|
307
|
+
const runningKind = operationRegistry.getKind(workingDir, reportPath);
|
|
308
|
+
const error = runningKind === 'reviewing'
|
|
309
|
+
? 'An AI review is already running for this directory.'
|
|
310
|
+
: 'A scan is already running for this directory.';
|
|
311
|
+
ctx.send(ws, { type: 'qualityError', data: { path: reportPath, error } });
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const scanStartedAt = Date.now();
|
|
316
|
+
// Pre-compute a size + ETA so the very first progress event carries an
|
|
317
|
+
// estimate. We deliberately do this *before* `setActiveOperation` so a
|
|
318
|
+
// freshly-clicked scan shows numbers immediately rather than after a
|
|
319
|
+
// file-collection round-trip.
|
|
320
|
+
let etaMs: number | undefined;
|
|
321
|
+
try {
|
|
322
|
+
const size = await estimateCodebaseSize(dirPath);
|
|
323
|
+
etaMs = estimateScanMs(size, persistence.loadHistory(), reportPath);
|
|
324
|
+
} catch {
|
|
325
|
+
// Falling back to no ETA is fine — the UI will simply hide the remaining-time chip.
|
|
326
|
+
}
|
|
327
|
+
|
|
234
328
|
try {
|
|
235
329
|
persistence.setActiveOperation(reportPath, 'scanning');
|
|
236
330
|
|
|
331
|
+
// Emit a "Detecting tools" frame *before* the long detect call so the
|
|
332
|
+
// user sees motion immediately on click — `detectTools` spawns one
|
|
333
|
+
// child process per ecosystem tool and can sit silent for several
|
|
334
|
+
// seconds on a cold cache.
|
|
335
|
+
ctx.send(ws, {
|
|
336
|
+
type: 'qualityScanProgress',
|
|
337
|
+
data: {
|
|
338
|
+
path: reportPath,
|
|
339
|
+
progress: { step: 'Detecting tools', current: 0, total: 8, etaMs, startedAt: scanStartedAt },
|
|
340
|
+
},
|
|
341
|
+
});
|
|
237
342
|
const { tools: detectedTools } = await detectTools(dirPath);
|
|
238
343
|
const installedToolNames = detectedTools.filter((t) => t.installed).map((t) => t.name);
|
|
239
344
|
|
|
240
|
-
|
|
345
|
+
// Heartbeat — keeps the progress UI showing elapsed time during long
|
|
346
|
+
// sub-steps (lint/format/build) where `runQualityScan` doesn't get a
|
|
347
|
+
// chance to call the progress callback again.
|
|
348
|
+
let lastProgress: { step: string; current: number; total: number } = {
|
|
349
|
+
step: 'Detecting tools',
|
|
350
|
+
current: 0,
|
|
351
|
+
total: 8,
|
|
352
|
+
};
|
|
353
|
+
const heartbeat = setInterval(() => {
|
|
354
|
+
const elapsedSec = Math.round((Date.now() - scanStartedAt) / 1000);
|
|
241
355
|
ctx.send(ws, {
|
|
242
356
|
type: 'qualityScanProgress',
|
|
243
|
-
data: {
|
|
357
|
+
data: {
|
|
358
|
+
path: reportPath,
|
|
359
|
+
progress: { ...lastProgress, etaMs, startedAt: scanStartedAt, detail: `${elapsedSec}s elapsed` },
|
|
360
|
+
},
|
|
244
361
|
});
|
|
245
|
-
},
|
|
362
|
+
}, 5_000);
|
|
363
|
+
|
|
364
|
+
let results: Awaited<ReturnType<typeof runQualityScan>>;
|
|
365
|
+
try {
|
|
366
|
+
results = await runQualityScan(dirPath, (progress) => {
|
|
367
|
+
lastProgress = progress;
|
|
368
|
+
ctx.send(ws, {
|
|
369
|
+
type: 'qualityScanProgress',
|
|
370
|
+
data: {
|
|
371
|
+
path: reportPath,
|
|
372
|
+
progress: { ...progress, etaMs, startedAt: scanStartedAt },
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
}, installedToolNames, controller.signal);
|
|
376
|
+
} finally {
|
|
377
|
+
clearInterval(heartbeat);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Annotate the report with the wall-clock duration so subsequent scans
|
|
381
|
+
// of this directory have real history to base their ETA on. Same pattern
|
|
382
|
+
// applies for the AI review duration written by the review agent.
|
|
383
|
+
const scanDurationMs = Date.now() - scanStartedAt;
|
|
384
|
+
results.scanDurationMs = scanDurationMs;
|
|
246
385
|
|
|
247
386
|
// Persist before sending — results survive if WebSocket drops
|
|
248
387
|
try {
|
|
@@ -267,11 +406,17 @@ async function handleScan(
|
|
|
267
406
|
});
|
|
268
407
|
}
|
|
269
408
|
} catch (error) {
|
|
409
|
+
if (error instanceof QualityScanAbortedError) {
|
|
410
|
+
// Cancellation already broadcast a `qualityError` from `handleCancel`.
|
|
411
|
+
// Don't send a second error message.
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
270
414
|
ctx.send(ws, {
|
|
271
415
|
type: 'qualityError',
|
|
272
416
|
data: { path: reportPath, error: error instanceof Error ? error.message : String(error) },
|
|
273
417
|
});
|
|
274
418
|
} finally {
|
|
419
|
+
operationRegistry.finish(workingDir, reportPath);
|
|
275
420
|
persistence.clearActiveOperation(reportPath);
|
|
276
421
|
}
|
|
277
422
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Quality Operation Registry — in-process tracking of in-flight scans and
|
|
5
|
+
* code reviews so they can be cancelled (or detected as orphaned) without
|
|
6
|
+
* depending on durable state.
|
|
7
|
+
*
|
|
8
|
+
* Persistence (`.mstro/quality/active-ops.json`) survives a CLI restart but
|
|
9
|
+
* has no live `AbortController` to cancel; this registry holds the controllers
|
|
10
|
+
* for the current process. The two layers are deliberately decoupled — when a
|
|
11
|
+
* persisted op exists with no registry entry, callers know the op is orphaned.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type OperationKind = 'scanning' | 'reviewing';
|
|
15
|
+
|
|
16
|
+
interface RegisteredOperation {
|
|
17
|
+
controller: AbortController;
|
|
18
|
+
kind: OperationKind;
|
|
19
|
+
startedAt: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class OperationRegistry {
|
|
23
|
+
private readonly ops = new Map<string, RegisteredOperation>();
|
|
24
|
+
|
|
25
|
+
private key(workingDir: string, path: string): string {
|
|
26
|
+
return `${workingDir}::${path}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Reserve an operation slot and return its `AbortController`. Throws when
|
|
31
|
+
* the same `(workingDir, path)` pair is already in flight — callers should
|
|
32
|
+
* surface this to the user as "already running" rather than silently
|
|
33
|
+
* starting a second worker.
|
|
34
|
+
*/
|
|
35
|
+
start(workingDir: string, path: string, kind: OperationKind): AbortController {
|
|
36
|
+
const k = this.key(workingDir, path);
|
|
37
|
+
if (this.ops.has(k)) {
|
|
38
|
+
throw new Error(`Operation already in flight: ${kind} ${path}`);
|
|
39
|
+
}
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
this.ops.set(k, { controller, kind, startedAt: Date.now() });
|
|
42
|
+
return controller;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Cancel an in-flight operation. Returns `true` when an op was found and
|
|
47
|
+
* aborted, `false` when nothing was registered (the caller should still
|
|
48
|
+
* clear persistence — the op is either already finished or was orphaned).
|
|
49
|
+
*/
|
|
50
|
+
cancel(workingDir: string, path: string): boolean {
|
|
51
|
+
const k = this.key(workingDir, path);
|
|
52
|
+
const op = this.ops.get(k);
|
|
53
|
+
if (!op) return false;
|
|
54
|
+
op.controller.abort();
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
finish(workingDir: string, path: string): void {
|
|
59
|
+
this.ops.delete(this.key(workingDir, path));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
has(workingDir: string, path: string): boolean {
|
|
63
|
+
return this.ops.has(this.key(workingDir, path));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Kind of the live operation, or null when nothing is registered. */
|
|
67
|
+
getKind(workingDir: string, path: string): OperationKind | null {
|
|
68
|
+
return this.ops.get(this.key(workingDir, path))?.kind ?? null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const operationRegistry = new OperationRegistry();
|
|
@@ -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
|
* Quality Persistence — Persists quality config, reports, and history
|
|
@@ -13,6 +12,7 @@
|
|
|
13
12
|
|
|
14
13
|
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
15
14
|
import { join } from 'node:path';
|
|
15
|
+
import { gradeFromScore } from './quality-grading.js';
|
|
16
16
|
import type { QualityResults } from './quality-service.js';
|
|
17
17
|
|
|
18
18
|
// ============================================================================
|
|
@@ -46,7 +46,21 @@ export interface QualityHistoryEntry {
|
|
|
46
46
|
grade: string;
|
|
47
47
|
issueDensity?: number;
|
|
48
48
|
categoryScores?: HistoryCategoryScore[];
|
|
49
|
+
dimensionScores?: {
|
|
50
|
+
security: { score: number; grade: string };
|
|
51
|
+
reliability: { score: number; grade: string };
|
|
52
|
+
maintainability: { score: number; grade: string };
|
|
53
|
+
};
|
|
49
54
|
directories: HistoryDirectoryEntry[];
|
|
55
|
+
/**
|
|
56
|
+
* Wall-clock duration of the CLI scan that produced this entry, in
|
|
57
|
+
* milliseconds. Older entries persisted before the ETA rollout will not
|
|
58
|
+
* include this field, in which case the ETA estimator falls back to the
|
|
59
|
+
* heuristic until enough samples accumulate.
|
|
60
|
+
*/
|
|
61
|
+
scanDurationMs?: number;
|
|
62
|
+
/** Wall-clock duration of the AI review pass, when one ran for this entry. */
|
|
63
|
+
reviewDurationMs?: number;
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
interface QualityHistory {
|
|
@@ -232,6 +246,7 @@ export class QualityPersistence {
|
|
|
232
246
|
: undefined;
|
|
233
247
|
|
|
234
248
|
const issueDensity = results.scoreBreakdown?.issueDensity;
|
|
249
|
+
const dimensionScores = extractDimensionScores(results);
|
|
235
250
|
|
|
236
251
|
if (lastEntry && now.getTime() - lastTime < mergeWindow) {
|
|
237
252
|
const existing = lastEntry.directories.findIndex((d) => d.path === dirPath);
|
|
@@ -242,10 +257,21 @@ export class QualityPersistence {
|
|
|
242
257
|
}
|
|
243
258
|
const totalScore = lastEntry.directories.reduce((sum, d) => sum + d.score, 0);
|
|
244
259
|
lastEntry.overall = Math.round(totalScore / lastEntry.directories.length);
|
|
245
|
-
|
|
260
|
+
// Preserve N/A when every directory is N/A; otherwise map averaged score
|
|
261
|
+
// back to a letter. `gradeFromScore` returns A-F only, so this is the
|
|
262
|
+
// only place the N/A signal could be lost during multi-directory merges.
|
|
263
|
+
const allNA = lastEntry.directories.every((d) => d.grade === 'N/A');
|
|
264
|
+
lastEntry.grade = allNA ? 'N/A' : gradeFromScore(lastEntry.overall);
|
|
246
265
|
lastEntry.timestamp = now.toISOString();
|
|
247
266
|
if (categoryScores) lastEntry.categoryScores = categoryScores;
|
|
248
267
|
if (issueDensity !== undefined) lastEntry.issueDensity = issueDensity;
|
|
268
|
+
if (dimensionScores) lastEntry.dimensionScores = dimensionScores;
|
|
269
|
+
// Carry through whichever duration is present on this report. We
|
|
270
|
+
// overwrite — the latest scan/review is the most accurate sample for
|
|
271
|
+
// this directory. (Multi-dir merges within the 60s window write each
|
|
272
|
+
// dir's duration in turn; the final entry reflects the last write.)
|
|
273
|
+
if (typeof results.scanDurationMs === 'number') lastEntry.scanDurationMs = results.scanDurationMs;
|
|
274
|
+
if (typeof results.reviewDurationMs === 'number') lastEntry.reviewDurationMs = results.reviewDurationMs;
|
|
249
275
|
} else {
|
|
250
276
|
history.push({
|
|
251
277
|
timestamp: now.toISOString(),
|
|
@@ -253,7 +279,10 @@ export class QualityPersistence {
|
|
|
253
279
|
grade: results.grade,
|
|
254
280
|
issueDensity,
|
|
255
281
|
categoryScores,
|
|
282
|
+
dimensionScores,
|
|
256
283
|
directories: [dirEntry],
|
|
284
|
+
scanDurationMs: results.scanDurationMs,
|
|
285
|
+
reviewDurationMs: results.reviewDurationMs,
|
|
257
286
|
});
|
|
258
287
|
}
|
|
259
288
|
|
|
@@ -361,10 +390,20 @@ export class QualityPersistence {
|
|
|
361
390
|
}
|
|
362
391
|
}
|
|
363
392
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return
|
|
393
|
+
// Snapshot per-dimension scores when the new rating fields are present.
|
|
394
|
+
// Older `QualityResults` objects (e.g., loaded from pre-redesign reports)
|
|
395
|
+
// omit `dimensions`, in which case we return undefined so old history rows
|
|
396
|
+
// continue to round-trip without synthesized data.
|
|
397
|
+
function extractDimensionScores(results: QualityResults): QualityHistoryEntry['dimensionScores'] | undefined {
|
|
398
|
+
if (!results.dimensions) return undefined;
|
|
399
|
+
const byName = new Map(results.dimensions.map((d) => [d.name, d]));
|
|
400
|
+
const sec = byName.get('security');
|
|
401
|
+
const rel = byName.get('reliability');
|
|
402
|
+
const maint = byName.get('maintainability');
|
|
403
|
+
if (!sec || !rel || !maint) return undefined;
|
|
404
|
+
return {
|
|
405
|
+
security: { score: sec.score, grade: sec.grade },
|
|
406
|
+
reliability: { score: rel.score, grade: rel.grade },
|
|
407
|
+
maintainability: { score: maint.score, grade: maint.grade },
|
|
408
|
+
};
|
|
370
409
|
}
|