muonroi-cli 1.8.4 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -5
- package/dist/packages/agent-harness-core/src/driver.d.ts +27 -1
- package/dist/packages/agent-harness-core/src/driver.js +46 -0
- package/dist/packages/agent-harness-core/src/event-filter.js +11 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
- package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
- package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
- package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
- package/dist/packages/agent-harness-core/src/protocol.js +15 -0
- package/dist/packages/agent-harness-core/src/visual-quality.d.ts +58 -0
- package/dist/packages/agent-harness-core/src/visual-quality.js +141 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.d.ts +6 -0
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +14 -1
- package/dist/packages/agent-harness-opentui/src/input-bridge.d.ts +2 -10
- package/dist/packages/agent-harness-opentui/src/input-bridge.js +103 -16
- package/dist/packages/agent-harness-opentui/src/install.d.ts +8 -0
- package/dist/packages/agent-harness-opentui/src/install.js +10 -0
- package/dist/packages/agent-harness-opentui/src/semantic.js +12 -10
- package/dist/packages/agent-harness-opentui/src/visual-capture.d.ts +56 -0
- package/dist/packages/agent-harness-opentui/src/visual-capture.js +103 -0
- package/dist/src/agent-harness/mock-model.d.ts +38 -0
- package/dist/src/agent-harness/mock-model.js +69 -3
- package/dist/src/agent-harness/test-spawn.js +31 -0
- package/dist/src/chat/chat-keychain.d.ts +7 -12
- package/dist/src/chat/chat-keychain.js +19 -86
- package/dist/src/cli/config/screen-providers.js +1 -1
- package/dist/src/cli/cost-forensics.d.ts +10 -0
- package/dist/src/cli/cost-forensics.js +18 -3
- package/dist/src/cli/keys-bundle.d.ts +1 -1
- package/dist/src/cli/keys-bundle.js +1 -1
- package/dist/src/cli/keys.d.ts +10 -47
- package/dist/src/cli/keys.js +31 -399
- package/dist/src/council/clarifier.d.ts +31 -3
- package/dist/src/council/clarifier.js +220 -32
- package/dist/src/council/context.js +49 -15
- package/dist/src/council/debate-checkpoint.d.ts +129 -0
- package/dist/src/council/debate-checkpoint.js +176 -0
- package/dist/src/council/debate-planner.js +54 -5
- package/dist/src/council/debate-summary.d.ts +25 -0
- package/dist/src/council/debate-summary.js +85 -0
- package/dist/src/council/debate.d.ts +169 -2
- package/dist/src/council/debate.js +1265 -135
- package/dist/src/council/index.d.ts +108 -1
- package/dist/src/council/index.js +670 -197
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +94 -0
- package/dist/src/council/llm.js +348 -55
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +82 -0
- package/dist/src/council/planner.js +40 -0
- package/dist/src/council/preflight.d.ts +17 -0
- package/dist/src/council/preflight.js +50 -2
- package/dist/src/council/prompts.d.ts +39 -4
- package/dist/src/council/prompts.js +256 -69
- package/dist/src/council/stance-recall.d.ts +42 -0
- package/dist/src/council/stance-recall.js +57 -0
- package/dist/src/council/strip-think.d.ts +17 -0
- package/dist/src/council/strip-think.js +33 -0
- package/dist/src/council/types.d.ts +138 -0
- package/dist/src/ee/artifact-cache.d.ts +16 -0
- package/dist/src/ee/artifact-cache.js +32 -0
- package/dist/src/ee/auth.d.ts +20 -0
- package/dist/src/ee/auth.js +54 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +109 -21
- package/dist/src/ee/ee-onboarding.js +6 -26
- package/dist/src/ee/export-transcripts.d.ts +1 -0
- package/dist/src/ee/export-transcripts.js +8 -10
- package/dist/src/ee/extract-session.js +29 -0
- package/dist/src/ee/extract-style.d.ts +58 -0
- package/dist/src/ee/extract-style.js +270 -0
- package/dist/src/ee/recall-ledger.d.ts +9 -0
- package/dist/src/ee/recall-ledger.js +3 -0
- package/dist/src/ee/scope.d.ts +1 -0
- package/dist/src/ee/scope.js +26 -1
- package/dist/src/ee/search.d.ts +7 -0
- package/dist/src/ee/search.js +24 -0
- package/dist/src/ee/transcript-emit.js +2 -0
- package/dist/src/ee/types.d.ts +22 -0
- package/dist/src/ee/who-am-i-brain.d.ts +35 -0
- package/dist/src/ee/who-am-i-brain.js +220 -0
- package/dist/src/ee/who-am-i.d.ts +10 -3
- package/dist/src/ee/who-am-i.js +12 -0
- package/dist/src/ee/workflow-event.d.ts +48 -0
- package/dist/src/ee/workflow-event.js +81 -0
- package/dist/src/flow/compaction/compress.d.ts +3 -3
- package/dist/src/flow/compaction/compress.js +58 -8
- package/dist/src/flow/compaction/extract.d.ts +4 -7
- package/dist/src/flow/compaction/extract.js +50 -10
- package/dist/src/flow/compaction/index.d.ts +14 -1
- package/dist/src/flow/compaction/index.js +96 -3
- package/dist/src/flow/compaction/input-guard.d.ts +24 -0
- package/dist/src/flow/compaction/input-guard.js +43 -0
- package/dist/src/flow/compaction/progress.d.ts +35 -0
- package/dist/src/flow/compaction/progress.js +35 -0
- package/dist/src/flow/fold-planning.d.ts +36 -0
- package/dist/src/flow/fold-planning.js +83 -0
- package/dist/src/flow/hierarchy.d.ts +146 -0
- package/dist/src/flow/hierarchy.js +427 -0
- package/dist/src/flow/index.d.ts +1 -0
- package/dist/src/flow/index.js +2 -0
- package/dist/src/flow/run-artifacts.d.ts +102 -0
- package/dist/src/flow/run-artifacts.js +208 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/gsd/assessment-schema.d.ts +44 -0
- package/dist/src/gsd/assessment-schema.js +134 -0
- package/dist/src/gsd/capability-registry.d.ts +45 -0
- package/dist/src/gsd/capability-registry.js +337 -0
- package/dist/src/gsd/complexity-assessor.d.ts +39 -0
- package/dist/src/gsd/complexity-assessor.js +152 -0
- package/dist/src/gsd/config-bridge.d.ts +7 -0
- package/dist/src/gsd/config-bridge.js +114 -0
- package/dist/src/gsd/config-loader.d.ts +27 -0
- package/dist/src/gsd/config-loader.js +50 -0
- package/dist/src/gsd/council-context.d.ts +44 -0
- package/dist/src/gsd/council-context.js +114 -0
- package/dist/src/gsd/ee-closure.d.ts +28 -0
- package/dist/src/gsd/ee-closure.js +49 -0
- package/dist/src/gsd/flags.d.ts +66 -0
- package/dist/src/gsd/flags.js +102 -0
- package/dist/src/gsd/gsd-dispatch.d.ts +58 -0
- package/dist/src/gsd/gsd-dispatch.js +131 -0
- package/dist/src/gsd/gsd-runtime.d.ts +22 -0
- package/dist/src/gsd/gsd-runtime.js +37 -0
- package/dist/src/gsd/host-adapter.d.ts +11 -0
- package/dist/src/gsd/host-adapter.js +29 -0
- package/dist/src/gsd/index.d.ts +24 -1
- package/dist/src/gsd/index.js +27 -0
- package/dist/src/gsd/loop-host-contract.d.ts +21 -0
- package/dist/src/gsd/loop-host-contract.js +39 -0
- package/dist/src/gsd/loop-host.d.ts +69 -0
- package/dist/src/gsd/loop-host.js +245 -0
- package/dist/src/gsd/loop-resolver.d.ts +36 -0
- package/dist/src/gsd/loop-resolver.js +79 -0
- package/dist/src/gsd/model-tier.d.ts +13 -0
- package/dist/src/gsd/model-tier.js +45 -0
- package/dist/src/gsd/mutation-gate.d.ts +16 -0
- package/dist/src/gsd/mutation-gate.js +41 -0
- package/dist/src/gsd/native-roadmap.d.ts +89 -0
- package/dist/src/gsd/native-roadmap.js +343 -0
- package/dist/src/gsd/native-state.d.ts +47 -0
- package/dist/src/gsd/native-state.js +220 -0
- package/dist/src/gsd/paths.d.ts +23 -0
- package/dist/src/gsd/paths.js +66 -0
- package/dist/src/gsd/phase-dag.d.ts +12 -0
- package/dist/src/gsd/phase-dag.js +94 -0
- package/dist/src/gsd/phase-sync.d.ts +42 -0
- package/dist/src/gsd/phase-sync.js +321 -0
- package/dist/src/gsd/pil-gate-context.d.ts +13 -0
- package/dist/src/gsd/pil-gate-context.js +64 -0
- package/dist/src/gsd/pil-gate-critic.d.ts +19 -0
- package/dist/src/gsd/pil-gate-critic.js +74 -0
- package/dist/src/gsd/plan-council-prompts.d.ts +25 -0
- package/dist/src/gsd/plan-council-prompts.js +79 -0
- package/dist/src/gsd/plan-council.d.ts +44 -0
- package/dist/src/gsd/plan-council.js +283 -0
- package/dist/src/gsd/plan-gate-vocabulary.d.ts +40 -0
- package/dist/src/gsd/plan-gate-vocabulary.js +64 -0
- package/dist/src/gsd/product-workspace.d.ts +13 -0
- package/dist/src/gsd/product-workspace.js +124 -0
- package/dist/src/gsd/ship-bridge.d.ts +25 -0
- package/dist/src/gsd/ship-bridge.js +65 -0
- package/dist/src/gsd/state-document.d.ts +40 -0
- package/dist/src/gsd/state-document.js +163 -0
- package/dist/src/gsd/verdict-schema.d.ts +39 -0
- package/dist/src/gsd/verdict-schema.js +144 -0
- package/dist/src/gsd/verify-context.d.ts +22 -0
- package/dist/src/gsd/verify-context.js +27 -0
- package/dist/src/gsd/verify-council-prompts.d.ts +19 -0
- package/dist/src/gsd/verify-council-prompts.js +85 -0
- package/dist/src/gsd/verify-council.d.ts +25 -0
- package/dist/src/gsd/verify-council.js +119 -0
- package/dist/src/gsd/verify-gate-vocabulary.d.ts +25 -0
- package/dist/src/gsd/verify-gate-vocabulary.js +46 -0
- package/dist/src/gsd/workflow-engine.d.ts +60 -0
- package/dist/src/gsd/workflow-engine.js +207 -0
- package/dist/src/gsd/workflow-tools.d.ts +13 -0
- package/dist/src/gsd/workflow-tools.js +277 -0
- package/dist/src/headless/council-answers.js +4 -0
- package/dist/src/hooks/index.js +1 -1
- package/dist/src/index.js +172 -270
- package/dist/src/lsp/builtins.js +3 -1
- package/dist/src/lsp/manager.d.ts +5 -1
- package/dist/src/lsp/manager.js +249 -3
- package/dist/src/lsp/npm-cache.d.ts +11 -1
- package/dist/src/lsp/npm-cache.js +17 -1
- package/dist/src/lsp/runtime.d.ts +6 -1
- package/dist/src/lsp/runtime.js +17 -1
- package/dist/src/lsp/types.d.ts +83 -1
- package/dist/src/lsp/types.js +10 -0
- package/dist/src/maintain/pr-builder.js +23 -13
- package/dist/src/mcp/auto-setup.js +57 -32
- package/dist/src/mcp/client-pool.js +44 -16
- package/dist/src/mcp/lsp-tools.d.ts +5 -1
- package/dist/src/mcp/lsp-tools.js +93 -2
- package/dist/src/mcp/mcp-keychain.d.ts +3 -5
- package/dist/src/mcp/mcp-keychain.js +9 -49
- package/dist/src/mcp/research-onboarding.js +8 -7
- package/dist/src/mcp/runtime.js +34 -2
- package/dist/src/mcp/setup-guide-text.d.ts +1 -1
- package/dist/src/mcp/setup-guide-text.js +22 -2
- package/dist/src/mcp/tools-server.d.ts +10 -0
- package/dist/src/mcp/tools-server.js +10 -2
- package/dist/src/models/catalog-client.d.ts +87 -0
- package/dist/src/models/catalog-client.js +105 -38
- package/dist/src/models/catalog.json +528 -265
- package/dist/src/models/registry.d.ts +22 -7
- package/dist/src/models/registry.js +73 -10
- package/dist/src/ops/doctor.js +1 -1
- package/dist/src/orchestrator/ask-user.d.ts +61 -0
- package/dist/src/orchestrator/ask-user.js +65 -0
- package/dist/src/orchestrator/auto-commit.js +1 -1
- package/dist/src/orchestrator/batch-turn-runner.js +2 -2
- package/dist/src/orchestrator/cache-prefix.d.ts +67 -0
- package/dist/src/orchestrator/cache-prefix.js +83 -0
- package/dist/src/orchestrator/compact-request.d.ts +32 -0
- package/dist/src/orchestrator/compact-request.js +41 -0
- package/dist/src/orchestrator/compaction.d.ts +12 -3
- package/dist/src/orchestrator/compaction.js +35 -15
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +74 -32
- package/dist/src/orchestrator/council-request.d.ts +49 -0
- package/dist/src/orchestrator/council-request.js +62 -0
- package/dist/src/orchestrator/cross-turn-dedup.d.ts +6 -0
- package/dist/src/orchestrator/cross-turn-dedup.js +22 -1
- package/dist/src/orchestrator/error-utils.d.ts +29 -0
- package/dist/src/orchestrator/error-utils.js +132 -24
- package/dist/src/orchestrator/grounding-check.js +39 -1
- package/dist/src/orchestrator/interactive-pause.d.ts +26 -0
- package/dist/src/orchestrator/interactive-pause.js +36 -0
- package/dist/src/orchestrator/message-processor.d.ts +4 -0
- package/dist/src/orchestrator/message-processor.js +268 -41
- package/dist/src/orchestrator/orchestrator.d.ts +64 -3
- package/dist/src/orchestrator/orchestrator.js +823 -120
- package/dist/src/orchestrator/preprocessor.js +3 -3
- package/dist/src/orchestrator/proactive-compact-detector.d.ts +26 -0
- package/dist/src/orchestrator/proactive-compact-detector.js +36 -0
- package/dist/src/orchestrator/prompts.js +17 -17
- package/dist/src/orchestrator/reactive-delegation.d.ts +39 -0
- package/dist/src/orchestrator/reactive-delegation.js +59 -0
- package/dist/src/orchestrator/retry-classifier.d.ts +2 -1
- package/dist/src/orchestrator/retry-classifier.js +46 -2
- package/dist/src/orchestrator/safety-askcard.d.ts +1 -1
- package/dist/src/orchestrator/safety-askcard.js +5 -2
- package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
- package/dist/src/orchestrator/safety-intercept.js +62 -0
- package/dist/src/orchestrator/scope-reminder.js +1 -1
- package/dist/src/orchestrator/session-experience.d.ts +2 -1
- package/dist/src/orchestrator/session-experience.js +2 -1
- package/dist/src/orchestrator/should-run-gate.d.ts +5 -0
- package/dist/src/orchestrator/should-run-gate.js +18 -0
- package/dist/src/orchestrator/stall-watchdog.d.ts +31 -3
- package/dist/src/orchestrator/stall-watchdog.js +65 -10
- package/dist/src/orchestrator/stream-runner.d.ts +13 -3
- package/dist/src/orchestrator/stream-runner.js +115 -49
- package/dist/src/orchestrator/sub-agent-cap.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-cap.js +16 -1
- package/dist/src/orchestrator/sub-agent-model-tier.d.ts +13 -1
- package/dist/src/orchestrator/sub-agent-model-tier.js +16 -2
- package/dist/src/orchestrator/subagent-compactor.d.ts +53 -1
- package/dist/src/orchestrator/subagent-compactor.js +126 -15
- package/dist/src/orchestrator/tool-engine.d.ts +41 -0
- package/dist/src/orchestrator/tool-engine.js +846 -66
- package/dist/src/orchestrator/tool-limit-auto-recover.d.ts +22 -0
- package/dist/src/orchestrator/tool-limit-auto-recover.js +30 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +19 -0
- package/dist/src/orchestrator/turn-watchdog.d.ts +44 -0
- package/dist/src/orchestrator/turn-watchdog.js +84 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +6 -4
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +5 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/discovery-types.d.ts +1 -0
- package/dist/src/pil/discovery.d.ts +1 -1
- package/dist/src/pil/discovery.js +18 -13
- package/dist/src/pil/layer1-intent.d.ts +18 -6
- package/dist/src/pil/layer1-intent.js +66 -757
- package/dist/src/pil/layer15-context-scan.js +15 -1
- package/dist/src/pil/layer1_5-complexity-size.d.ts +7 -0
- package/dist/src/pil/layer1_5-complexity-size.js +31 -5
- package/dist/src/pil/layer3-ee-injection.js +23 -8
- package/dist/src/pil/layer4-gsd.js +69 -16
- package/dist/src/pil/layer5-context.js +7 -3
- package/dist/src/pil/layer6-output.d.ts +23 -0
- package/dist/src/pil/layer6-output.js +5 -1
- package/dist/src/pil/llm-classify.d.ts +111 -5
- package/dist/src/pil/llm-classify.js +421 -189
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +8 -0
- package/dist/src/pil/pipeline.js +36 -2
- package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
- package/dist/src/pil/repo-grounding-probe.js +136 -0
- package/dist/src/pil/repo-structure-hints.d.ts +7 -0
- package/dist/src/pil/repo-structure-hints.js +45 -0
- package/dist/src/pil/response-tools.js +5 -3
- package/dist/src/pil/schema.d.ts +1 -0
- package/dist/src/pil/schema.js +2 -0
- package/dist/src/pil/types.d.ts +18 -0
- package/dist/src/playbook/directives.d.ts +4 -0
- package/dist/src/playbook/directives.js +17 -5
- package/dist/src/product-loop/artifact-io.js +4 -0
- package/dist/src/product-loop/backlog-builder.d.ts +14 -1
- package/dist/src/product-loop/backlog-builder.js +30 -6
- package/dist/src/product-loop/criteria-seed.d.ts +51 -0
- package/dist/src/product-loop/criteria-seed.js +200 -0
- package/dist/src/product-loop/discovery-context-format.js +3 -1
- package/dist/src/product-loop/discovery-ecosystem.js +4 -1
- package/dist/src/product-loop/discovery-interview.d.ts +9 -0
- package/dist/src/product-loop/discovery-interview.js +60 -12
- package/dist/src/product-loop/discovery-recommender.js +2 -1
- package/dist/src/product-loop/discovery-schema.js +19 -2
- package/dist/src/product-loop/discovery-triage.d.ts +23 -0
- package/dist/src/product-loop/discovery-triage.js +109 -0
- package/dist/src/product-loop/gather.js +150 -2
- package/dist/src/product-loop/ideal-trace.d.ts +7 -0
- package/dist/src/product-loop/ideal-trace.js +64 -0
- package/dist/src/product-loop/index.d.ts +13 -1
- package/dist/src/product-loop/index.js +340 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +330 -106
- package/dist/src/product-loop/phase-plan.d.ts +21 -0
- package/dist/src/product-loop/phase-plan.js +81 -6
- package/dist/src/product-loop/phase-rituals.d.ts +3 -0
- package/dist/src/product-loop/phase-rituals.js +8 -3
- package/dist/src/product-loop/phase-runner.js +39 -12
- package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
- package/dist/src/product-loop/plan-adherence-review.js +144 -0
- package/dist/src/product-loop/sprint-runner.d.ts +173 -0
- package/dist/src/product-loop/sprint-runner.js +863 -19
- package/dist/src/product-loop/types.d.ts +61 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- package/dist/src/providers/anthropic.d.ts +9 -8
- package/dist/src/providers/anthropic.js +13 -47
- package/dist/src/providers/auth/browser-flow.d.ts +1 -1
- package/dist/src/providers/auth/browser-flow.js +1 -1
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -0
- package/dist/src/providers/auth/grok-oauth.js +30 -5
- package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
- package/dist/src/providers/auth/openai-oauth.js +15 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.d.ts +9 -9
- package/dist/src/providers/auth/token-store.js +8 -67
- package/dist/src/providers/auth/types.d.ts +9 -1
- package/dist/src/providers/auth/types.js +1 -1
- package/dist/src/providers/capabilities.d.ts +24 -5
- package/dist/src/providers/capabilities.js +42 -24
- package/dist/src/providers/endpoints.d.ts +2 -2
- package/dist/src/providers/endpoints.js +11 -10
- package/dist/src/providers/env-store.d.ts +17 -0
- package/dist/src/providers/env-store.js +228 -0
- package/dist/src/providers/keychain.d.ts +22 -18
- package/dist/src/providers/keychain.js +127 -140
- package/dist/src/providers/mcp-vision-bridge.js +56 -146
- package/dist/src/providers/openai-compatible.js +8 -1
- package/dist/src/providers/pricing.d.ts +2 -2
- package/dist/src/providers/pricing.js +3 -13
- package/dist/src/providers/runtime.d.ts +43 -3
- package/dist/src/providers/runtime.js +88 -14
- package/dist/src/providers/strategies/base.strategy.d.ts +16 -0
- package/dist/src/providers/strategies/base.strategy.js +24 -1
- package/dist/src/providers/strategies/{siliconflow.strategy.d.ts → opencode-go.strategy.d.ts} +3 -3
- package/dist/src/providers/strategies/opencode-go.strategy.js +83 -0
- package/dist/src/providers/strategies/registry.js +4 -4
- package/dist/src/providers/strategies/thinking-mode.d.ts +109 -0
- package/dist/src/providers/strategies/thinking-mode.js +288 -1
- package/dist/src/providers/strategies/xai.strategy.js +27 -0
- package/dist/src/providers/strategies/zai.strategy.d.ts +14 -0
- package/dist/src/providers/strategies/zai.strategy.js +44 -0
- package/dist/src/providers/types.d.ts +5 -6
- package/dist/src/providers/types.js +2 -2
- package/dist/src/providers/vision-backend.d.ts +47 -0
- package/dist/src/providers/vision-backend.js +258 -0
- package/dist/src/providers/vision-proxy.d.ts +22 -9
- package/dist/src/providers/vision-proxy.js +63 -132
- package/dist/src/providers/warm.d.ts +65 -0
- package/dist/src/providers/warm.js +145 -0
- package/dist/src/providers/wire-debug.js +95 -0
- package/dist/src/router/decide.d.ts +13 -0
- package/dist/src/router/decide.js +138 -36
- package/dist/src/router/peak-hour.d.ts +38 -0
- package/dist/src/router/peak-hour.js +107 -0
- package/dist/src/router/step-router.js +3 -2
- package/dist/src/router/warm.js +4 -5
- package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
- package/dist/src/scaffold/continuation-prompt.js +26 -0
- package/dist/src/scaffold/point-to-existing.d.ts +21 -0
- package/dist/src/scaffold/point-to-existing.js +25 -0
- package/dist/src/self-qa/agentic-loop.js +6 -5
- package/dist/src/{ui/state → state}/active-run.d.ts +19 -0
- package/dist/src/{ui/state → state}/active-run.js +21 -0
- package/dist/src/{ui/status-bar/store.d.ts → state/status-bar-store.d.ts} +4 -1
- package/dist/src/{ui/status-bar/store.js → state/status-bar-store.js} +12 -9
- package/dist/src/state/turn-trace.d.ts +43 -0
- package/dist/src/state/turn-trace.js +32 -0
- package/dist/src/storage/db.js +2 -1
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/interaction-log.d.ts +1 -1
- package/dist/src/storage/migrations.js +71 -1
- package/dist/src/storage/sessions.d.ts +28 -10
- package/dist/src/storage/sessions.js +78 -21
- package/dist/src/storage/transcript-view.js +1 -1
- package/dist/src/storage/transcript.d.ts +51 -0
- package/dist/src/storage/transcript.js +340 -15
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/git-safety.d.ts +19 -0
- package/dist/src/tools/git-safety.js +168 -0
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +81 -1
- package/dist/src/tools/registry.d.ts +20 -0
- package/dist/src/tools/registry.js +576 -23
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +147 -4
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
- package/dist/src/ui/components/agent-rail-activities.js +47 -0
- package/dist/src/ui/components/bubble-body-guard.d.ts +27 -0
- package/dist/src/ui/components/bubble-body-guard.js +50 -0
- package/dist/src/ui/components/compact-progress-card.d.ts +24 -0
- package/dist/src/ui/components/compact-progress-card.js +42 -0
- package/dist/src/ui/components/context-rail.d.ts +26 -0
- package/dist/src/ui/components/context-rail.js +33 -0
- package/dist/src/ui/components/council-conclusion-card.d.ts +73 -0
- package/dist/src/ui/components/council-conclusion-card.js +420 -0
- package/dist/src/ui/components/council-debate-pill.d.ts +36 -0
- package/dist/src/ui/components/council-debate-pill.js +34 -0
- package/dist/src/ui/components/council-info-card.js +2 -2
- package/dist/src/ui/components/council-leader-bubble.d.ts +10 -3
- package/dist/src/ui/components/council-leader-bubble.js +21 -11
- package/dist/src/ui/components/council-message-bubble.d.ts +15 -2
- package/dist/src/ui/components/council-message-bubble.js +16 -15
- package/dist/src/ui/components/council-phase-timeline.d.ts +9 -1
- package/dist/src/ui/components/council-phase-timeline.js +66 -17
- package/dist/src/ui/components/council-placeholder-bubble.d.ts +16 -9
- package/dist/src/ui/components/council-placeholder-bubble.js +32 -29
- package/dist/src/ui/components/council-question-card.js +13 -12
- package/dist/src/ui/components/council-rail-rounds.d.ts +26 -0
- package/dist/src/ui/components/council-rail-rounds.js +57 -0
- package/dist/src/ui/components/council-round-group.d.ts +38 -0
- package/dist/src/ui/components/council-round-group.js +88 -0
- package/dist/src/ui/components/council-status-list.d.ts +3 -1
- package/dist/src/ui/components/council-status-list.js +36 -24
- package/dist/src/ui/components/council-synthesis-banner.d.ts +7 -2
- package/dist/src/ui/components/council-synthesis-banner.js +20 -5
- package/dist/src/ui/components/halt-recovery-card.js +9 -5
- package/dist/src/ui/components/jump-to-latest-pill.d.ts +11 -0
- package/dist/src/ui/components/jump-to-latest-pill.js +14 -0
- package/dist/src/ui/components/message-view.d.ts +15 -0
- package/dist/src/ui/components/message-view.js +50 -1
- package/dist/src/ui/components/prompt-box.js +18 -16
- package/dist/src/ui/components/session-tree-card.d.ts +14 -0
- package/dist/src/ui/components/session-tree-card.js +46 -0
- package/dist/src/ui/components/slash-inline-menu.d.ts +12 -0
- package/dist/src/ui/components/slash-inline-menu.js +26 -5
- package/dist/src/ui/components/task-list-panel.d.ts +14 -1
- package/dist/src/ui/components/task-list-panel.js +22 -2
- package/dist/src/ui/components/tool-group.d.ts +15 -3
- package/dist/src/ui/components/tool-group.js +69 -11
- package/dist/src/ui/containers/modals-layer.d.ts +4 -2
- package/dist/src/ui/containers/modals-layer.js +2 -2
- package/dist/src/ui/council-harness-event.d.ts +57 -0
- package/dist/src/ui/council-harness-event.js +46 -0
- package/dist/src/ui/heartbeat-debug.d.ts +29 -0
- package/dist/src/ui/heartbeat-debug.js +45 -0
- package/dist/src/ui/hooks/use-session-picker.d.ts +3 -3
- package/dist/src/ui/mcp-modal.js +2 -4
- package/dist/src/ui/modals/api-key-modal.js +1 -1
- package/dist/src/ui/modals/connect-modal.js +4 -3
- package/dist/src/ui/modals/model-picker-modal.d.ts +8 -18
- package/dist/src/ui/modals/model-picker-modal.js +8 -10
- package/dist/src/ui/modals/session-picker-modal.d.ts +2 -2
- package/dist/src/ui/modals/session-picker-modal.js +3 -5
- package/dist/src/ui/picker-providers.d.ts +1 -1
- package/dist/src/ui/picker-providers.js +1 -1
- package/dist/src/ui/primitives/index.d.ts +1 -0
- package/dist/src/ui/primitives/index.js +2 -0
- package/dist/src/ui/primitives/semantic-primitives.d.ts +76 -0
- package/dist/src/ui/primitives/semantic-primitives.js +81 -0
- package/dist/src/ui/slash/compact.js +5 -7
- package/dist/src/ui/slash/cost.js +1 -1
- package/dist/src/ui/slash/council.js +19 -1
- package/dist/src/ui/slash/debug.d.ts +3 -31
- package/dist/src/ui/slash/debug.js +9 -20
- package/dist/src/ui/slash/ee.js +81 -0
- package/dist/src/ui/slash/ideal.d.ts +6 -2
- package/dist/src/ui/slash/ideal.js +97 -7
- package/dist/src/ui/slash/menu-items.d.ts +7 -0
- package/dist/src/ui/slash/menu-items.js +23 -20
- package/dist/src/ui/slash/registry.d.ts +2 -0
- package/dist/src/ui/slash/registry.js +4 -0
- package/dist/src/ui/status-bar/cache-hit.d.ts +6 -0
- package/dist/src/ui/status-bar/cache-hit.js +9 -0
- package/dist/src/ui/status-bar/index.d.ts +1 -1
- package/dist/src/ui/status-bar/index.js +7 -3
- package/dist/src/ui/status-bar/usd-meter.d.ts +5 -4
- package/dist/src/ui/status-bar/usd-meter.js +6 -4
- package/dist/src/ui/theme.d.ts +1 -0
- package/dist/src/ui/theme.js +2 -0
- package/dist/src/ui/types.d.ts +7 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/agent-activities.d.ts +39 -0
- package/dist/src/ui/utils/agent-activities.js +96 -0
- package/dist/src/ui/utils/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
- package/dist/src/ui/utils/group-tool-entries.js +111 -0
- package/dist/src/ui/utils/tool-summary.d.ts +21 -0
- package/dist/src/ui/utils/tool-summary.js +91 -0
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/event-loop-monitor.d.ts +85 -0
- package/dist/src/utils/event-loop-monitor.js +107 -0
- package/dist/src/utils/install-manager.js +2 -1
- package/dist/src/utils/llm-deadline.d.ts +14 -0
- package/dist/src/utils/llm-deadline.js +19 -0
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/loop-profiler.d.ts +102 -0
- package/dist/src/utils/loop-profiler.js +202 -0
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +180 -5
- package/dist/src/utils/settings.js +271 -31
- package/dist/src/utils/side-question.d.ts +1 -2
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/visible-retry.d.ts +11 -0
- package/dist/src/utils/visible-retry.js +10 -1
- package/dist/src/verify/entrypoint.d.ts +1 -1
- package/dist/src/verify/entrypoint.js +52 -17
- package/dist/src/verify/orchestrator.d.ts +1 -1
- package/dist/src/verify/orchestrator.js +20 -3
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +134 -132
- package/dist/src/cli/bw-vault.d.ts +0 -55
- package/dist/src/cli/bw-vault.js +0 -133
- package/dist/src/mcp/ee-tools.d.ts +0 -46
- package/dist/src/mcp/ee-tools.js +0 -193
- package/dist/src/providers/auth/gcloud.d.ts +0 -28
- package/dist/src/providers/auth/gcloud.js +0 -102
- package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
- package/dist/src/providers/auth/gemini-oauth.js +0 -472
- package/dist/src/providers/gemini.d.ts +0 -11
- package/dist/src/providers/gemini.js +0 -45
- package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
- package/dist/src/providers/siliconflow-sse-repair.js +0 -177
- package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
- package/dist/src/providers/strategies/google.strategy.js +0 -174
- package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
- package/dist/src/ui/containers/chat-feed.d.ts +0 -40
- package/dist/src/ui/containers/chat-feed.js +0 -66
package/dist/src/index.js
CHANGED
|
@@ -24,8 +24,7 @@ import { createAbortContext } from "./orchestrator/abort.js";
|
|
|
24
24
|
import { completeDelegation, failDelegation, loadDelegation } from "./orchestrator/delegations.js";
|
|
25
25
|
import { Agent } from "./orchestrator/orchestrator.js";
|
|
26
26
|
import { createPendingCallsLog } from "./orchestrator/pending-calls.js";
|
|
27
|
-
import {
|
|
28
|
-
import { listStoredProviders, loadKeyForProvider, setKeyForProvider } from "./providers/keychain.js";
|
|
27
|
+
import { loadKeyForProvider, setKeyForProvider } from "./providers/keychain.js";
|
|
29
28
|
import { detectProviderForModel } from "./providers/runtime.js";
|
|
30
29
|
import { loadConfig } from "./storage/config.js";
|
|
31
30
|
import { loadUsage } from "./storage/usage-cap.js";
|
|
@@ -35,7 +34,7 @@ import { runScriptManagedUninstall } from "./utils/install-manager.js";
|
|
|
35
34
|
import { getApiKey, getBaseURL, getCurrentModel, saveUserSettings } from "./utils/settings.js";
|
|
36
35
|
import { runUpdate } from "./utils/update-checker.js";
|
|
37
36
|
import { buildVerifyPrompt, getVerifyCliError } from "./verify/entrypoint.js";
|
|
38
|
-
// Hydrate chat secrets
|
|
37
|
+
// Hydrate chat secrets (no-op now: secrets live in the environment/env-store)
|
|
39
38
|
await hydrateChatEnvFromKeychain();
|
|
40
39
|
const exitCleanlyOnSigterm = () => {
|
|
41
40
|
process.exit(0);
|
|
@@ -61,6 +60,78 @@ export function appendCrashLog(label, msg) {
|
|
|
61
60
|
/* crash.log is best-effort diagnostics; the logger itself must never throw */
|
|
62
61
|
}
|
|
63
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Arm the event-loop freeze diagnostics for this TUI session.
|
|
65
|
+
*
|
|
66
|
+
* Every existing hang guard in this codebase (provider stall watchdog, turn
|
|
67
|
+
* watchdog) is driven by a timer, so all of them are blind to a blocked event
|
|
68
|
+
* loop — a timer cannot fire while the JS thread is stuck. Measured live
|
|
69
|
+
* 2026-07-16 (session 90c3ff533826): the TUI froze 304.5s, input replayed on
|
|
70
|
+
* recovery, and the 120s stall watchdog only rescued the turn 6.7s AFTER the
|
|
71
|
+
* loop came back. This closes that blind spot: the monitor reports the block
|
|
72
|
+
* once the loop frees up, and — when armed — the CPU profiler supplies the
|
|
73
|
+
* stack captured DURING it.
|
|
74
|
+
*
|
|
75
|
+
* Best-effort: never let diagnostics break the CLI.
|
|
76
|
+
*/
|
|
77
|
+
async function startFreezeDiagnostics() {
|
|
78
|
+
try {
|
|
79
|
+
const { getLoopBlockThresholdMs, isLoopProfileEnabled } = await import("./utils/settings.js");
|
|
80
|
+
const { startEventLoopMonitor } = await import("./utils/event-loop-monitor.js");
|
|
81
|
+
const { logger } = await import("./utils/logger.js");
|
|
82
|
+
const thresholdMs = getLoopBlockThresholdMs();
|
|
83
|
+
if (thresholdMs <= 0)
|
|
84
|
+
return;
|
|
85
|
+
const profiler = isLoopProfileEnabled()
|
|
86
|
+
? await (await import("./utils/loop-profiler.js")).createLoopProfiler()
|
|
87
|
+
: null;
|
|
88
|
+
if (profiler) {
|
|
89
|
+
// Bound segment size. Loop-driven ON PURPOSE: it cannot rotate during a
|
|
90
|
+
// block, so the segment covering a freeze survives to be captured.
|
|
91
|
+
const rotateTimer = setInterval(() => profiler.rotate(), 30_000);
|
|
92
|
+
rotateTimer.unref?.();
|
|
93
|
+
}
|
|
94
|
+
logger.info("cli", `[freeze] diagnostics armed (threshold ${thresholdMs}ms)`, {
|
|
95
|
+
thresholdMs,
|
|
96
|
+
profiler: profiler ? "on" : "off",
|
|
97
|
+
});
|
|
98
|
+
startEventLoopMonitor({
|
|
99
|
+
thresholdMs,
|
|
100
|
+
onBlock: (block) => {
|
|
101
|
+
logger.warn("cli", `[freeze] event loop blocked for ${block.blockedMs}ms — UI was frozen and no timer could fire`, {
|
|
102
|
+
blockedMs: block.blockedMs,
|
|
103
|
+
breadcrumb: block.breadcrumb,
|
|
104
|
+
detectedAt: block.detectedAt,
|
|
105
|
+
profiler: profiler ? "armed" : "off (set MUONROI_LOOP_PROFILE=1 for the culprit stack)",
|
|
106
|
+
});
|
|
107
|
+
if (!profiler)
|
|
108
|
+
return;
|
|
109
|
+
void profiler
|
|
110
|
+
.capture(block.breadcrumb ?? "unknown")
|
|
111
|
+
.then((res) => {
|
|
112
|
+
if (res) {
|
|
113
|
+
// The leaf is usually a native primitive (`now`, a regex step) —
|
|
114
|
+
// true but useless as a headline. Lead with the first frame that
|
|
115
|
+
// has a file:line, i.e. OUR code.
|
|
116
|
+
const suspect = res.hotStack.find((f) => !f.endsWith("(native)")) ?? res.hotStack[0];
|
|
117
|
+
logger.warn("cli", `[freeze] blocked in: ${suspect ?? "(unattributed)"}`, {
|
|
118
|
+
hotStack: res.hotStack,
|
|
119
|
+
file: res.file,
|
|
120
|
+
blockedMs: block.blockedMs,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
.catch((err) => {
|
|
125
|
+
logger.error("cli", `[freeze] profile capture failed: ${err?.message}`, { error: err });
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// Diagnostics must never take the CLI down with them.
|
|
132
|
+
appendCrashLog("FREEZE_DIAG", err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
64
135
|
process.on("uncaughtException", (err) => {
|
|
65
136
|
appendCrashLog("UNCAUGHT", err.stack || err.message);
|
|
66
137
|
console.error("Fatal:", err.message);
|
|
@@ -111,7 +182,7 @@ setRenderSink((lineOrChunk) => {
|
|
|
111
182
|
// Provider console URLs are sourced from providers/capabilities.ts via ProviderCapabilities.consoleSignupURL().
|
|
112
183
|
/**
|
|
113
184
|
* Try to find an API key for the model the CLI is about to run with.
|
|
114
|
-
* Resolution: env (
|
|
185
|
+
* Resolution: per-provider env var (env-store), else OAuth sentinel.
|
|
115
186
|
* Returns null if nothing usable is configured anywhere.
|
|
116
187
|
*/
|
|
117
188
|
async function resolveKeyForModel(modelId) {
|
|
@@ -154,188 +225,7 @@ async function hasOAuthForModel(modelId) {
|
|
|
154
225
|
return false;
|
|
155
226
|
}
|
|
156
227
|
}
|
|
157
|
-
|
|
158
|
-
* First-run wizard. If the keychain already has keys, prints a hint
|
|
159
|
-
* (model probably doesn't match any stored provider). Otherwise prompts
|
|
160
|
-
* for provider + key and persists to the OS keychain.
|
|
161
|
-
*/
|
|
162
|
-
/**
|
|
163
|
-
* Supported splash providers — mirrors SPLASH_PROVIDERS in ui/app.tsx.
|
|
164
|
-
* The wizard only surfaces these; other providers still work programmatically.
|
|
165
|
-
*/
|
|
166
|
-
const WIZARD_PROVIDERS = ["deepseek", "siliconflow"];
|
|
167
|
-
async function firstRunWizard(currentModel) {
|
|
168
|
-
let rl;
|
|
169
|
-
try {
|
|
170
|
-
rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
171
|
-
const ask = (q) => new Promise((resolve) => rl.question(q, (answer) => resolve(answer)));
|
|
172
|
-
process.stderr.write("\nWelcome to muonroi-cli!\n\n");
|
|
173
|
-
const stored = await listStoredProviders();
|
|
174
|
-
if (stored.length > 0) {
|
|
175
|
-
process.stderr.write(`Keys already in keychain for: ${stored.join(", ")}\n`);
|
|
176
|
-
if (currentModel) {
|
|
177
|
-
const provider = detectProviderForModel(currentModel);
|
|
178
|
-
process.stderr.write(`Current model '${currentModel}' uses provider '${provider}', which has no stored key.\n`);
|
|
179
|
-
}
|
|
180
|
-
process.stderr.write("\nOptions:\n" +
|
|
181
|
-
" 1. Run with a model that matches a stored provider:\n" +
|
|
182
|
-
" muonroi-cli --model <model-id>\n" +
|
|
183
|
-
" 2. Open /providers inside the TUI to add another key.\n" +
|
|
184
|
-
" 3. muonroi-cli keys set <provider>\n\n");
|
|
185
|
-
rl.close();
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
process.stderr.write("Pick how you want to add credentials:\n\n");
|
|
189
|
-
process.stderr.write(" 1. Paste an API key (most common)\n");
|
|
190
|
-
process.stderr.write(" 2. Import an encrypted bundle file (from another device)\n");
|
|
191
|
-
process.stderr.write(" 3. Sync from a Bitwarden vault\n");
|
|
192
|
-
process.stderr.write(" 4. Skip — set up later via /providers inside the TUI\n\n");
|
|
193
|
-
const actionChoice = (await ask("Choice [1-4, default 1]: ")).trim() || "1";
|
|
194
|
-
if (actionChoice === "4") {
|
|
195
|
-
process.stderr.write("\nSkipped. Open /providers inside the TUI to add a key any time.\n");
|
|
196
|
-
rl.close();
|
|
197
|
-
return null;
|
|
198
|
-
}
|
|
199
|
-
if (actionChoice === "2") {
|
|
200
|
-
const file = (await ask("Path to bundle file: ")).trim();
|
|
201
|
-
if (!file) {
|
|
202
|
-
process.stderr.write("No file provided. Aborted.\n");
|
|
203
|
-
rl.close();
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
const passphrase = await ask("Bundle passphrase: ");
|
|
207
|
-
try {
|
|
208
|
-
const { readFileSync: readFile } = await import("node:fs");
|
|
209
|
-
const { decryptBundle } = await import("./cli/keys-bundle.js");
|
|
210
|
-
const raw = readFile(file, "utf8");
|
|
211
|
-
const bundle = JSON.parse(raw);
|
|
212
|
-
const payload = decryptBundle(bundle, passphrase);
|
|
213
|
-
let imported = 0;
|
|
214
|
-
for (const [prov, key] of Object.entries(payload.providers)) {
|
|
215
|
-
if (!WIZARD_PROVIDERS.includes(prov))
|
|
216
|
-
continue;
|
|
217
|
-
if (typeof key !== "string" || key.length < 20)
|
|
218
|
-
continue;
|
|
219
|
-
const ok = await setKeyForProvider(prov, key);
|
|
220
|
-
if (ok) {
|
|
221
|
-
imported++;
|
|
222
|
-
process.stderr.write(` ✓ ${prov} → keychain\n`);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
process.stderr.write(`\nImported ${imported} key(s). Launch the TUI to start.\n`);
|
|
226
|
-
rl.close();
|
|
227
|
-
// Return any imported key just so caller treats setup as done.
|
|
228
|
-
return imported > 0 ? "imported" : null;
|
|
229
|
-
}
|
|
230
|
-
catch (err) {
|
|
231
|
-
process.stderr.write(`\nImport failed: ${err.message}\n`);
|
|
232
|
-
rl.close();
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (actionChoice === "3") {
|
|
237
|
-
const password = await ask("Bitwarden master password: ");
|
|
238
|
-
try {
|
|
239
|
-
const { unlockWithPassword, listSecureNotesByPrefix } = await import("./cli/bw-vault.js");
|
|
240
|
-
const unlock = await unlockWithPassword(password);
|
|
241
|
-
if (!unlock.ok || !unlock.session) {
|
|
242
|
-
process.stderr.write(`\nBitwarden unlock failed: ${unlock.error ?? "unknown error"}\n`);
|
|
243
|
-
rl.close();
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
const list = await listSecureNotesByPrefix(unlock.session, "muonroi-cli/");
|
|
247
|
-
if (!list.ok) {
|
|
248
|
-
process.stderr.write(`\nBitwarden list failed: ${list.error}\n`);
|
|
249
|
-
rl.close();
|
|
250
|
-
return null;
|
|
251
|
-
}
|
|
252
|
-
let imported = 0;
|
|
253
|
-
for (const item of list.items) {
|
|
254
|
-
const prov = item.name.slice("muonroi-cli/".length);
|
|
255
|
-
if (!WIZARD_PROVIDERS.includes(prov))
|
|
256
|
-
continue;
|
|
257
|
-
if (item.notes.length < 20)
|
|
258
|
-
continue;
|
|
259
|
-
const ok = await setKeyForProvider(prov, item.notes);
|
|
260
|
-
if (ok) {
|
|
261
|
-
imported++;
|
|
262
|
-
process.stderr.write(` ✓ ${prov} → keychain\n`);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
process.stderr.write(`\nImported ${imported} key(s) from Bitwarden. Launch the TUI to start.\n`);
|
|
266
|
-
rl.close();
|
|
267
|
-
return imported > 0 ? "imported" : null;
|
|
268
|
-
}
|
|
269
|
-
catch (err) {
|
|
270
|
-
process.stderr.write(`\nBitwarden sync failed: ${err.message}\n`);
|
|
271
|
-
rl.close();
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
// Default path: paste an API key for one of WIZARD_PROVIDERS.
|
|
276
|
-
process.stderr.write("\nSupported providers:\n\n");
|
|
277
|
-
WIZARD_PROVIDERS.forEach((p, i) => {
|
|
278
|
-
process.stderr.write(` ${i + 1}. ${p.padEnd(12)} ${getProviderCapabilities(p).consoleSignupURL()}\n`);
|
|
279
|
-
});
|
|
280
|
-
process.stderr.write("\n");
|
|
281
|
-
const choice = (await ask(`Provider [1-${WIZARD_PROVIDERS.length}, default 1]: `)).trim();
|
|
282
|
-
const idx = choice ? Number.parseInt(choice, 10) - 1 : 0;
|
|
283
|
-
if (!Number.isFinite(idx) || idx < 0 || idx >= WIZARD_PROVIDERS.length) {
|
|
284
|
-
process.stderr.write("Invalid choice — aborted.\n");
|
|
285
|
-
rl.close();
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
const provider = WIZARD_PROVIDERS[idx];
|
|
289
|
-
if (!provider) {
|
|
290
|
-
process.stderr.write("Invalid choice — aborted.\n");
|
|
291
|
-
rl.close();
|
|
292
|
-
return null;
|
|
293
|
-
}
|
|
294
|
-
process.stderr.write(`\nGet a key here: ${getProviderCapabilities(provider).consoleSignupURL()}\n`);
|
|
295
|
-
const raw = await ask(`Paste your ${provider} API key: `);
|
|
296
|
-
const trimmed = raw.trim();
|
|
297
|
-
if (!trimmed) {
|
|
298
|
-
process.stderr.write("No key provided. Aborted.\n");
|
|
299
|
-
rl.close();
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
if (trimmed.length < 20) {
|
|
303
|
-
process.stderr.write("Key looks too short (< 20 chars). Aborted.\n");
|
|
304
|
-
rl.close();
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
try {
|
|
308
|
-
const ok = await setKeyForProvider(provider, trimmed);
|
|
309
|
-
if (ok) {
|
|
310
|
-
process.stderr.write(`\nStored ${provider} key in OS keychain.\n`);
|
|
311
|
-
process.stderr.write("Tip: run 'muonroi-cli keys export ~/keys.json' to back up + move to other devices.\n");
|
|
312
|
-
if (currentModel) {
|
|
313
|
-
const currentProvider = detectProviderForModel(currentModel);
|
|
314
|
-
if (currentProvider !== provider) {
|
|
315
|
-
process.stderr.write(`\nNote: defaultModel '${currentModel}' is on '${currentProvider}'. ` +
|
|
316
|
-
`Edit ~/.muonroi-cli/user-settings.json or rerun with --model to use ${provider}.\n`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
else {
|
|
321
|
-
process.stderr.write("\nOS keychain unavailable (keytar or secret service backend).\n" +
|
|
322
|
-
"Linux: sudo dnf install libsecret (Fedora) or sudo apt-get install libsecret-1-0 (Ubuntu).\n" +
|
|
323
|
-
"Key will be used for this session only. For persistence across runs:\n" +
|
|
324
|
-
` export ${provider.toUpperCase()}_API_KEY=...\n`);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
catch (err) {
|
|
328
|
-
process.stderr.write(`\nWarning: failed to store key in keychain: ${err.message}\n`);
|
|
329
|
-
}
|
|
330
|
-
rl.close();
|
|
331
|
-
return trimmed;
|
|
332
|
-
}
|
|
333
|
-
catch {
|
|
334
|
-
rl?.close();
|
|
335
|
-
return null;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi, session, initialMessage, permissionMode = "safe", injectHalt = false) {
|
|
228
|
+
async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi, session, initialMessage, permissionMode = "safe", injectHalt = false, injectHaltSprint = false) {
|
|
339
229
|
// ── Plan 00-07 boot order ──────────────────────────────────────────────────
|
|
340
230
|
// 1. redactor.installGlobalPatches() — already at top of file (line 6).
|
|
341
231
|
// 2. loadConfig + loadUsage (validates storage paths, logs usage cap state).
|
|
@@ -401,6 +291,14 @@ async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi,
|
|
|
401
291
|
const { warmMcpClients } = await import("./mcp/client-pool.js");
|
|
402
292
|
const { loadMcpServers } = await import("./utils/settings.js");
|
|
403
293
|
await warmMcpClients(loadMcpServers(), !session);
|
|
294
|
+
// Register a factory for every credentialed provider, not just the session's.
|
|
295
|
+
// A model resolved for another provider (compaction, classify, a sub-agent,
|
|
296
|
+
// a mode-specific model) can then be routed to ITS OWN endpoint instead of
|
|
297
|
+
// being POSTed to the session provider's — the 404 in session 0c6728ba1a25
|
|
298
|
+
// (`gpt-5.4` → api.x.ai) existed only because the openai factory this
|
|
299
|
+
// redirect needs had never been built. Best-effort: never blocks boot.
|
|
300
|
+
const { warmProviderFactories } = await import("./providers/warm.js");
|
|
301
|
+
await warmProviderFactories();
|
|
404
302
|
const agent = new Agent(apiKey, baseURL, model, maxToolRounds, {
|
|
405
303
|
session,
|
|
406
304
|
batchApi,
|
|
@@ -416,6 +314,14 @@ async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi,
|
|
|
416
314
|
const { relaunchWithSession } = await import("./ui/utils/relaunch.js");
|
|
417
315
|
const renderer = await createCliRenderer({
|
|
418
316
|
exitOnCtrlC: false,
|
|
317
|
+
// OpenTUI defaults openConsoleOnError:true — its process-level
|
|
318
|
+
// unhandledRejection/uncaughtException handler then calls console.show(),
|
|
319
|
+
// which focuses the debug console overlay and captures ALL keypresses.
|
|
320
|
+
// The overlay's keybindings have no hide/close action, so a stray rejection
|
|
321
|
+
// (e.g. a provider dropping a streaming socket) traps the user in a console
|
|
322
|
+
// they cannot dismiss. We surface errors in-band instead — keep it off.
|
|
323
|
+
// Toggle it deliberately with F12 (wired below).
|
|
324
|
+
openConsoleOnError: false,
|
|
419
325
|
// We manage SIGINT ourselves (orchestrator abort → agent cleanup → renderer destroy).
|
|
420
326
|
// Prevent OpenTUI from registering its own SIGINT/SIGTERM handler which would
|
|
421
327
|
// call renderer.destroy() prematurely and race with our orderly shutdown.
|
|
@@ -426,10 +332,33 @@ async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi,
|
|
|
426
332
|
alternateKeys: true,
|
|
427
333
|
},
|
|
428
334
|
});
|
|
335
|
+
// Agent-mode: hand the renderer to the harness so it can snapshot the ACTUAL
|
|
336
|
+
// rendered cell grid (colors + attributes) via VisualFrame, not just the
|
|
337
|
+
// semantic tree. No-op outside agent-mode (runtime undefined).
|
|
338
|
+
{
|
|
339
|
+
const agentRt = globalThis.__muonroiAgentRuntime;
|
|
340
|
+
agentRt?.attachRenderer?.(renderer);
|
|
341
|
+
}
|
|
429
342
|
// The TUI now owns the terminal — route fatal-handler behaviour away from
|
|
430
343
|
// process.exit(1) (see the unhandledRejection handler above). Cleared in
|
|
431
344
|
// restoreTerminalSync() the moment we begin tearing the terminal back down.
|
|
432
345
|
setTuiActive(true);
|
|
346
|
+
// Armed only once the TUI owns the terminal: this hunts a freeze of the
|
|
347
|
+
// interactive session, and the logger only routes to debug.log (instead of
|
|
348
|
+
// stdout, which would corrupt the framebuffer) once the TUI is active.
|
|
349
|
+
await startFreezeDiagnostics();
|
|
350
|
+
// Deliberate debug-console toggle. With openConsoleOnError:false the overlay
|
|
351
|
+
// never auto-pops, so F12 is the ONLY way in — and, crucially, back out:
|
|
352
|
+
// console.toggle() hides it when it is visible+focused, so it can never trap.
|
|
353
|
+
try {
|
|
354
|
+
renderer.keyInput?.on("keypress", (key) => {
|
|
355
|
+
if (key?.name === "f12")
|
|
356
|
+
renderer.console.toggle();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
/* keyInput/console are best-effort dev affordances — never block boot */
|
|
361
|
+
}
|
|
433
362
|
/**
|
|
434
363
|
* Restore terminal to main-screen mode before the process exits.
|
|
435
364
|
*
|
|
@@ -616,6 +545,7 @@ async function startInteractive(apiKey, baseURL, model, maxToolRounds, batchApi,
|
|
|
616
545
|
maxToolRounds,
|
|
617
546
|
version: packageJson.version,
|
|
618
547
|
injectHalt,
|
|
548
|
+
injectHaltSprint,
|
|
619
549
|
},
|
|
620
550
|
initialMessage,
|
|
621
551
|
onExit,
|
|
@@ -733,7 +663,7 @@ async function runBackgroundDelegation(jobPath, options) {
|
|
|
733
663
|
const model = explicitModel ? normalizeModelId(explicitModel) : undefined;
|
|
734
664
|
// Resolve API key: explicit flag > legacy env/settings.apiKey > per-provider keychain
|
|
735
665
|
// (matches the foreground flow — delegations were previously broken when the user
|
|
736
|
-
// only had a per-provider key in the
|
|
666
|
+
// only had a per-provider key in the environment, e.g. deepseek.)
|
|
737
667
|
let apiKey = stringOption(options.apiKey) || getApiKey();
|
|
738
668
|
if (!apiKey) {
|
|
739
669
|
const modelForResolve = model ?? delegation.model ?? getCurrentModel("agent");
|
|
@@ -802,8 +732,8 @@ function resolveConfig(options) {
|
|
|
802
732
|
// flag or MUONROI_MAX_TOOL_ROUNDS env.
|
|
803
733
|
const maxToolRounds = parseInt(stringOption(options.maxToolRounds) || "100", 10) || 100;
|
|
804
734
|
if (typeof options.apiKey === "string" && process.env.MUONROI_TEST_NO_PERSIST !== "1") {
|
|
805
|
-
// Persist to
|
|
806
|
-
// Fire-and-forget:
|
|
735
|
+
// Persist to the env-store (per-provider) instead of plaintext settings.json.
|
|
736
|
+
// Fire-and-forget: env-store write is sync; the key is also set in process.env so it
|
|
807
737
|
// works for this run via `apiKey` above and the user can re-supply it next invocation.
|
|
808
738
|
void persistApiKeyToKeychain(options.apiKey, stringOption(options.model)).catch(() => { });
|
|
809
739
|
}
|
|
@@ -852,6 +782,7 @@ program
|
|
|
852
782
|
.option("--agent-fake-clock", "Use deterministic frame-counter clock")
|
|
853
783
|
.option("--mock-llm <dir>", "Use fixture-based mock LLM from <dir> instead of real provider (E2E testing)")
|
|
854
784
|
.option("--inject-halt", "TEST SEAM: render a synthetic halt recovery card after boot (harness E2E only)")
|
|
785
|
+
.option("--inject-halt-sprint", "TEST SEAM: render a synthetic sprint-failed recovery card after boot (harness E2E only)")
|
|
855
786
|
.action(async (message, options) => {
|
|
856
787
|
// Agent-mode: start the sidechannel runtime BEFORE any TUI or model work.
|
|
857
788
|
// The runtime is exposed on globalThis so the renderer wiring (Task 1.6c)
|
|
@@ -978,50 +909,51 @@ program
|
|
|
978
909
|
}
|
|
979
910
|
changeDirectoryOrExit(options.directory);
|
|
980
911
|
// Boot model registry BEFORE any key resolution path runs —
|
|
981
|
-
// detectProviderForModel consults the catalog's alias map to route
|
|
982
|
-
//
|
|
983
|
-
//
|
|
984
|
-
//
|
|
985
|
-
// main interactive/headless path below.
|
|
912
|
+
// detectProviderForModel consults the catalog's alias map to route model
|
|
913
|
+
// ids to the correct provider. With an empty registry it falls back to a
|
|
914
|
+
// prefix match and the CLI may load the wrong provider's key. Affects both
|
|
915
|
+
// runBackgroundDelegation and the main interactive/headless path below.
|
|
986
916
|
let catalogLoadFailed = false;
|
|
987
917
|
await loadCatalog().catch(() => {
|
|
988
918
|
catalogLoadFailed = true;
|
|
989
919
|
});
|
|
920
|
+
// Load the env-store (~/.muonroi-cli/.env) into process.env and migrate any
|
|
921
|
+
// legacy keychain/settings keys BEFORE any key resolution. Best-effort.
|
|
922
|
+
try {
|
|
923
|
+
const { loadEnvFileIntoProcess } = await import("./providers/env-store.js");
|
|
924
|
+
loadEnvFileIntoProcess();
|
|
925
|
+
const { migrateLegacyKeysToEnv } = await import("./providers/keychain.js");
|
|
926
|
+
await migrateLegacyKeysToEnv();
|
|
927
|
+
}
|
|
928
|
+
catch (err) {
|
|
929
|
+
console.error(`[muonroi-cli] env-store init failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
930
|
+
}
|
|
990
931
|
if (options.backgroundTaskFile) {
|
|
991
932
|
await runBackgroundDelegation(options.backgroundTaskFile, options);
|
|
992
933
|
return;
|
|
993
934
|
}
|
|
994
935
|
const config = resolveConfig(options);
|
|
995
|
-
//
|
|
996
|
-
//
|
|
997
|
-
|
|
936
|
+
// One auth mode per provider (OAuth XOR API key): if the resolved model's
|
|
937
|
+
// provider has an OAuth token, OAuth wins OUTRIGHT — a stored API key
|
|
938
|
+
// (env/flag/settings) is ignored, never blended. Only when there is no
|
|
939
|
+
// OAuth token do we fall back to the provider's env API key. The "oauth"
|
|
940
|
+
// sentinel satisfies downstream gating (which only checks for a truthy
|
|
941
|
+
// apiKey); the runtime injects Bearer headers.
|
|
942
|
+
{
|
|
998
943
|
const modelForResolve = config.model ?? getCurrentModel("agent");
|
|
999
|
-
|
|
1000
|
-
if (keychainKey) {
|
|
1001
|
-
config.apiKey = keychainKey;
|
|
1002
|
-
}
|
|
1003
|
-
else if (await hasOAuthForModel(modelForResolve)) {
|
|
1004
|
-
// OAuth-authenticated provider — runtime will inject Bearer headers.
|
|
1005
|
-
// Set placeholder so downstream gating code (which only checks for
|
|
1006
|
-
// a truthy apiKey) is satisfied.
|
|
944
|
+
if (await hasOAuthForModel(modelForResolve)) {
|
|
1007
945
|
config.apiKey = "oauth";
|
|
1008
946
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
const modelForWizard = config.model ?? getCurrentModel("agent");
|
|
1014
|
-
const wizardKey = await firstRunWizard(modelForWizard);
|
|
1015
|
-
if (wizardKey) {
|
|
1016
|
-
// Key is already persisted to the OS keychain by the wizard. We DO NOT
|
|
1017
|
-
// write it back to settings.json (avoids resurrecting plaintext that
|
|
1018
|
-
// 'keys cleanup-settings' just removed).
|
|
1019
|
-
config.apiKey = wizardKey;
|
|
1020
|
-
}
|
|
1021
|
-
else {
|
|
1022
|
-
process.exit(1);
|
|
947
|
+
else if (!config.apiKey) {
|
|
948
|
+
const envKey = await resolveKeyForModel(modelForResolve);
|
|
949
|
+
if (envKey)
|
|
950
|
+
config.apiKey = envKey;
|
|
1023
951
|
}
|
|
1024
952
|
}
|
|
953
|
+
// First run with no credentials does NOT block: boot straight into the TUI.
|
|
954
|
+
// The in-chat provider picker (/providers) handles auth on demand.
|
|
955
|
+
// Headless (`--prompt`/`--verify`) with no key still fails via requireApiKey.
|
|
956
|
+
const isInteractive = !options.prompt && !options.verify && process.stdin.isTTY;
|
|
1025
957
|
// Bootstrap EE auth (loads serverBaseUrl + token from ~/.experience/config.json)
|
|
1026
958
|
const { loadEEAuthToken, getCachedServerBaseUrl } = await import("./ee/auth.js");
|
|
1027
959
|
await loadEEAuthToken().catch(() => { });
|
|
@@ -1049,10 +981,15 @@ program
|
|
|
1049
981
|
// so each request doesn't re-probe.
|
|
1050
982
|
const { detectEEClientMode, describeMode } = await import("./ee/client-mode.js");
|
|
1051
983
|
detectEEClientMode()
|
|
1052
|
-
.then((info) => {
|
|
984
|
+
.then(async (info) => {
|
|
1053
985
|
if (process.env.MUONROI_EE_DEBUG === "1") {
|
|
1054
986
|
console.error(`[muonroi-cli] ${describeMode(info)}`);
|
|
1055
987
|
}
|
|
988
|
+
// WhoAmI thin-client fallback: once the mode is cached, derive the working-style
|
|
989
|
+
// profile from the behavioral brain and prime the sync cache so the PIL picks it
|
|
990
|
+
// up from the next turn. Fire-and-forget, fail-open — never blocks boot.
|
|
991
|
+
const { warmWhoAmIFromBrain } = await import("./ee/bridge.js");
|
|
992
|
+
await warmWhoAmIFromBrain();
|
|
1056
993
|
})
|
|
1057
994
|
.catch(() => { });
|
|
1058
995
|
// Patch zod-to-json-schema for Zod v4 compat (fixes tool calls for DeepSeek etc.)
|
|
@@ -1130,7 +1067,7 @@ program
|
|
|
1130
1067
|
return;
|
|
1131
1068
|
}
|
|
1132
1069
|
const initialMessage = message.length > 0 ? message.join(" ") : undefined;
|
|
1133
|
-
await startInteractive(config.apiKey, config.baseURL, config.model, config.maxToolRounds, options.batchApi === true, options.session, initialMessage, options.permission, options.injectHalt === true);
|
|
1070
|
+
await startInteractive(config.apiKey, config.baseURL, config.model, config.maxToolRounds, options.batchApi === true, options.session, initialMessage, options.permission, options.injectHalt === true, options.injectHaltSprint === true);
|
|
1134
1071
|
});
|
|
1135
1072
|
program
|
|
1136
1073
|
.command("models")
|
|
@@ -1220,41 +1157,31 @@ program
|
|
|
1220
1157
|
});
|
|
1221
1158
|
const keys = program
|
|
1222
1159
|
.command("keys")
|
|
1223
|
-
.description("Manage provider API keys
|
|
1160
|
+
.description("Manage provider API keys as environment variables (set, list, delete)");
|
|
1224
1161
|
keys
|
|
1225
1162
|
.command("set <provider>")
|
|
1226
|
-
.description("Prompt for a provider API key and store it
|
|
1227
|
-
.
|
|
1228
|
-
.option("--prefix <prefix>", "Bitwarden item name prefix when --bw is set (default: 'muonroi-cli/')", "muonroi-cli/")
|
|
1229
|
-
.action(async (provider, opts) => {
|
|
1163
|
+
.description("Prompt for a provider API key and store it as an environment variable")
|
|
1164
|
+
.action(async (provider) => {
|
|
1230
1165
|
const { runKeysSet } = await import("./cli/keys.js");
|
|
1231
|
-
await runKeysSet(provider
|
|
1166
|
+
await runKeysSet(provider);
|
|
1232
1167
|
});
|
|
1233
1168
|
keys
|
|
1234
1169
|
.command("list")
|
|
1235
|
-
.description("Show provider keys currently
|
|
1170
|
+
.description("Show provider keys currently set in the environment (masked)")
|
|
1236
1171
|
.action(async () => {
|
|
1237
1172
|
const { runKeysList } = await import("./cli/keys.js");
|
|
1238
1173
|
await runKeysList();
|
|
1239
1174
|
});
|
|
1240
1175
|
keys
|
|
1241
1176
|
.command("delete <provider>")
|
|
1242
|
-
.description("Delete a stored provider key from the
|
|
1177
|
+
.description("Delete a stored provider key from the environment")
|
|
1243
1178
|
.action(async (provider) => {
|
|
1244
1179
|
const { runKeysDelete } = await import("./cli/keys.js");
|
|
1245
1180
|
await runKeysDelete(provider);
|
|
1246
1181
|
});
|
|
1247
|
-
keys
|
|
1248
|
-
.command("import-bw [providers...]")
|
|
1249
|
-
.description("Import keys from a Bitwarden vault into the OS keychain (requires bw CLI + BW_SESSION)")
|
|
1250
|
-
.option("--prefix <prefix>", "Vault item name prefix (default: 'muonroi-cli/')", "muonroi-cli/")
|
|
1251
|
-
.action(async (providers, opts) => {
|
|
1252
|
-
const { runKeysImportBw } = await import("./cli/keys.js");
|
|
1253
|
-
await runKeysImportBw({ providers, itemPrefix: opts.prefix });
|
|
1254
|
-
});
|
|
1255
1182
|
keys
|
|
1256
1183
|
.command("login <provider>")
|
|
1257
|
-
.description("Log in to a provider via OAuth subscription (supported: openai,
|
|
1184
|
+
.description("Log in to a provider via OAuth subscription (supported: openai, xai).")
|
|
1258
1185
|
.action(async (provider) => {
|
|
1259
1186
|
const { runKeysLogin } = await import("./cli/keys.js");
|
|
1260
1187
|
await runKeysLogin(provider);
|
|
@@ -1268,28 +1195,21 @@ keys
|
|
|
1268
1195
|
});
|
|
1269
1196
|
keys
|
|
1270
1197
|
.command("export <file>")
|
|
1271
|
-
.description("Export all
|
|
1198
|
+
.description("Export all provider keys to an encrypted portable bundle (move between devices)")
|
|
1272
1199
|
.action(async (file) => {
|
|
1273
1200
|
const { runKeysExport } = await import("./cli/keys.js");
|
|
1274
1201
|
await runKeysExport(file);
|
|
1275
1202
|
});
|
|
1276
1203
|
keys
|
|
1277
1204
|
.command("import <file>")
|
|
1278
|
-
.description("Import an encrypted bundle
|
|
1205
|
+
.description("Import an encrypted bundle of provider keys (created by 'keys export')")
|
|
1279
1206
|
.action(async (file) => {
|
|
1280
1207
|
const { runKeysImport } = await import("./cli/keys.js");
|
|
1281
1208
|
await runKeysImport(file);
|
|
1282
1209
|
});
|
|
1283
|
-
keys
|
|
1284
|
-
.command("cleanup-settings")
|
|
1285
|
-
.description("Strip plaintext API keys out of ~/.muonroi-cli/user-settings.json after migrating to keychain")
|
|
1286
|
-
.action(async () => {
|
|
1287
|
-
const { runKeysCleanupSettings } = await import("./cli/keys.js");
|
|
1288
|
-
await runKeysCleanupSettings();
|
|
1289
|
-
});
|
|
1290
1210
|
keys
|
|
1291
1211
|
.command("set-chat <id>")
|
|
1292
|
-
.description("Set a chat-service secret (discord-token, discord-guild-id, slack-token, slack-team-id) in the
|
|
1212
|
+
.description("Set a chat-service secret (discord-token, discord-guild-id, slack-token, slack-team-id) in the environment")
|
|
1293
1213
|
.action(async (id) => {
|
|
1294
1214
|
const { runChatKeySet } = await import("./cli/keys.js");
|
|
1295
1215
|
if (!["discord-token", "discord-guild-id", "slack-token", "slack-team-id"].includes(id)) {
|
|
@@ -1309,14 +1229,6 @@ keys
|
|
|
1309
1229
|
}
|
|
1310
1230
|
await runChatKeySet(id, value);
|
|
1311
1231
|
});
|
|
1312
|
-
keys
|
|
1313
|
-
.command("import-bw-chat [ids...]")
|
|
1314
|
-
.option("--prefix <prefix>", "BW item name prefix", "muonroi-cli/chat-")
|
|
1315
|
-
.description("Import chat-service secrets from Bitwarden vault into OS keychain")
|
|
1316
|
-
.action(async (ids, opts) => {
|
|
1317
|
-
const { runChatImportBw } = await import("./cli/keys.js");
|
|
1318
|
-
await runChatImportBw({ ids: ids.length > 0 ? ids : undefined, itemPrefix: opts.prefix });
|
|
1319
|
-
});
|
|
1320
1232
|
const usage = program.command("usage").description("Inspect cost ledger and find spend bloat");
|
|
1321
1233
|
usage
|
|
1322
1234
|
.command("report")
|
|
@@ -1391,7 +1303,7 @@ usage
|
|
|
1391
1303
|
const mcp = program.command("mcp").description("Manage MCP server configuration");
|
|
1392
1304
|
mcp
|
|
1393
1305
|
.command("setup-research")
|
|
1394
|
-
.description("Configure web research
|
|
1306
|
+
.description("Configure web research (native fetch_url + web_search; optional MCPs for context7/muonroi-docs)")
|
|
1395
1307
|
.action(async () => {
|
|
1396
1308
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1397
1309
|
const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a)));
|
|
@@ -1410,20 +1322,10 @@ mcp
|
|
|
1410
1322
|
});
|
|
1411
1323
|
mcp
|
|
1412
1324
|
.command("set <id>")
|
|
1413
|
-
.description("Prompt for an MCP API key (e.g. tavily) and store it
|
|
1414
|
-
.
|
|
1415
|
-
.option("--prefix <prefix>", "Bitwarden item name prefix when --bw is set (default: 'muonroi-cli/')", "muonroi-cli/")
|
|
1416
|
-
.action(async (id, opts) => {
|
|
1325
|
+
.description("Prompt for an MCP API key (e.g. tavily) and store it as an environment variable")
|
|
1326
|
+
.action(async (id) => {
|
|
1417
1327
|
const { runMcpKeysSet } = await import("./cli/keys.js");
|
|
1418
|
-
await runMcpKeysSet(id
|
|
1419
|
-
});
|
|
1420
|
-
mcp
|
|
1421
|
-
.command("import-bw [keys...]")
|
|
1422
|
-
.description("Import MCP secrets (e.g. tavily) from a Bitwarden vault into the OS keychain (requires bw CLI + BW_SESSION)")
|
|
1423
|
-
.option("--prefix <prefix>", "Vault item name prefix (default: 'muonroi-cli/')", "muonroi-cli/")
|
|
1424
|
-
.action(async (keys, opts) => {
|
|
1425
|
-
const { runMcpImportBw } = await import("./cli/keys.js");
|
|
1426
|
-
await runMcpImportBw({ keys, itemPrefix: opts.prefix });
|
|
1328
|
+
await runMcpKeysSet(id);
|
|
1427
1329
|
});
|
|
1428
1330
|
program
|
|
1429
1331
|
.command("mcp-driver")
|
package/dist/src/lsp/builtins.js
CHANGED
|
@@ -342,7 +342,9 @@ async function resolveNodeServerLaunch(root, binary, packageName, baseArgs, auto
|
|
|
342
342
|
}
|
|
343
343
|
if (!autoInstall)
|
|
344
344
|
return null;
|
|
345
|
-
|
|
345
|
+
// Pass `binary` explicitly: a package can ship several bins and the one named
|
|
346
|
+
// after the package is not always the language server (see lspNpmWhich).
|
|
347
|
+
const cached = await lspNpmWhich(packageName, binary);
|
|
346
348
|
if (cached) {
|
|
347
349
|
return { command: cached, args: baseArgs };
|
|
348
350
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type RuntimeLspServerDefinition } from "./builtins.js";
|
|
2
2
|
import { type LspClientSession } from "./client.js";
|
|
3
|
-
import type { LspDiagnosticFile, LspQueryInput, LspToolResponse, NormalizedLspSettings } from "./types.js";
|
|
3
|
+
import type { ImpactOfChangeResult, LspDiagnosticFile, LspQueryInput, LspQueryResult, LspToolResponse, MutationPreviewResult, NormalizedLspSettings, PolicyAction } from "./types.js";
|
|
4
4
|
interface WorkspaceLspManagerOptions {
|
|
5
5
|
createClient?: (input: {
|
|
6
6
|
serverId: string;
|
|
@@ -13,6 +13,10 @@ export interface WorkspaceLspManager {
|
|
|
13
13
|
touchFile(filePath: string, waitForDiagnostics?: boolean): Promise<LspDiagnosticFile[]>;
|
|
14
14
|
syncFile(filePath: string, content: string, save?: boolean, waitForDiagnostics?: boolean, diagnosticsTimeoutMs?: number): Promise<LspDiagnosticFile[]>;
|
|
15
15
|
query(input: LspQueryInput): Promise<LspToolResponse>;
|
|
16
|
+
waitForDiagnostics(filePath: string, timeout: number): Promise<LspQueryResult>;
|
|
17
|
+
impactOfChange(filePath: string, query?: string, timeout?: number): Promise<ImpactOfChangeResult>;
|
|
18
|
+
lspMutationPreview(filePath: string, change: string): Promise<MutationPreviewResult>;
|
|
19
|
+
lspBeforeGrep(filePath: string, query?: string): Promise<PolicyAction>;
|
|
16
20
|
close(): Promise<void>;
|
|
17
21
|
}
|
|
18
22
|
export declare function createWorkspaceLspManager(cwd: string, settings: NormalizedLspSettings, options?: WorkspaceLspManagerOptions): WorkspaceLspManager;
|