muonroi-cli 1.8.4 → 1.8.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 +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-tee.d.ts +48 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +77 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +11 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +87 -15
- package/dist/packages/agent-harness-core/src/protocol.d.ts +66 -2
- 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 +28 -0
- package/dist/src/agent-harness/mock-model.js +63 -1
- package/dist/src/agent-harness/test-spawn.js +31 -0
- 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 +2 -2
- package/dist/src/cli/keys.js +19 -81
- package/dist/src/council/clarifier.d.ts +28 -2
- package/dist/src/council/clarifier.js +81 -15
- 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 +51 -3
- 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 +1210 -134
- package/dist/src/council/index.d.ts +85 -1
- package/dist/src/council/index.js +634 -196
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +32 -0
- package/dist/src/council/llm.js +231 -38
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +72 -0
- package/dist/src/council/planner.js +23 -0
- package/dist/src/council/preflight.d.ts +7 -0
- package/dist/src/council/preflight.js +14 -2
- package/dist/src/council/prompts.d.ts +30 -3
- package/dist/src/council/prompts.js +234 -64
- 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 +128 -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 +1 -0
- package/dist/src/ee/auth.js +15 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +81 -18
- 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 +45 -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 +13 -1
- package/dist/src/flow/compaction/index.js +70 -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/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 +55 -0
- package/dist/src/gsd/flags.js +83 -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 +251 -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/hooks/index.js +1 -1
- package/dist/src/index.js +44 -11
- 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 +1 -1
- package/dist/src/mcp/ee-tools.js +1 -0
- package/dist/src/mcp/research-onboarding.js +8 -7
- package/dist/src/mcp/runtime.js +34 -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/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 +10 -0
- package/dist/src/orchestrator/compaction.js +27 -7
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +65 -24
- 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/message-processor.js +242 -33
- package/dist/src/orchestrator/orchestrator.d.ts +39 -3
- package/dist/src/orchestrator/orchestrator.js +651 -102
- package/dist/src/orchestrator/preprocessor.js +1 -1
- 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-intercept.d.ts +45 -0
- package/dist/src/orchestrator/safety-intercept.js +55 -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 +24 -3
- package/dist/src/orchestrator/stall-watchdog.js +47 -13
- package/dist/src/orchestrator/stream-runner.js +62 -29
- 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 +22 -0
- package/dist/src/orchestrator/tool-engine.js +620 -56
- 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 +37 -0
- package/dist/src/orchestrator/turn-watchdog.js +55 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +1 -1
- 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.js +16 -11
- 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/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 +33 -2
- package/dist/src/pil/llm-classify.js +123 -131
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +1 -0
- package/dist/src/pil/pipeline.js +34 -2
- 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/backlog-builder.d.ts +14 -1
- package/dist/src/product-loop/backlog-builder.js +30 -6
- 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.js +32 -3
- package/dist/src/product-loop/discovery-schema.js +5 -1
- 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 +333 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +310 -99
- package/dist/src/product-loop/phase-plan.d.ts +5 -0
- package/dist/src/product-loop/phase-plan.js +39 -2
- package/dist/src/product-loop/phase-runner.js +9 -1
- package/dist/src/product-loop/sprint-runner.d.ts +111 -0
- package/dist/src/product-loop/sprint-runner.js +559 -16
- package/dist/src/product-loop/types.d.ts +36 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- 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/openai-oauth.js +1 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.js +4 -1
- package/dist/src/providers/auth/types.d.ts +1 -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/keychain.d.ts +1 -1
- package/dist/src/providers/keychain.js +7 -9
- 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 +27 -2
- package/dist/src/providers/runtime.js +78 -15
- 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 +280 -1
- 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/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 +3 -3
- 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 +284 -13
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/native-tools.js +5 -0
- package/dist/src/tools/registry.d.ts +3 -0
- package/dist/src/tools/registry.js +460 -22
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +118 -3
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- 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/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 +49 -15
- 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 +12 -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/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/containers/modals-layer.d.ts +2 -1
- 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/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/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 +12 -18
- 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/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/install-manager.js +2 -1
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +153 -5
- package/dist/src/utils/settings.js +233 -29
- 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 +1 -1
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +135 -132
- 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
|
@@ -48,6 +48,34 @@ export interface MockModelFixture {
|
|
|
48
48
|
provider?: string;
|
|
49
49
|
/** Reported model id. Default "mock-model". */
|
|
50
50
|
modelId?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Response for PIL's model-first intent classifier (src/pil/llm-classify.ts).
|
|
53
|
+
* Since the no-regex refactor (2026-07-07) PIL classifies EVERY turn by
|
|
54
|
+
* calling the model with a distinctive system prompt ("Reply with ONE line of
|
|
55
|
+
* EIGHT lowercase words…") and parses a comma-separated line. The generic
|
|
56
|
+
* fixture stream ("Hello back!" / arbitrary chunks) does not parse → the turn
|
|
57
|
+
* degrades to intentKind=UNKNOWN, which skips the gsd gate and breaks routing
|
|
58
|
+
* in E2E specs. The mock detects that classify call by its system prompt and
|
|
59
|
+
* returns THIS line instead of consuming the turn fixture — so every spec gets
|
|
60
|
+
* a sane classification for free. Override per-fixture when a spec needs a
|
|
61
|
+
* specific taskType/intent/depth. Format:
|
|
62
|
+
* <taskType>,<style>,<intent>,<deliverable>,<depth>,<scope>,<lang>,<clarity>
|
|
63
|
+
*/
|
|
64
|
+
classify?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Opt in to the PIL-classifier intercept described on `classify`. When true,
|
|
67
|
+
* a `doStream` call carrying the classifier's system prompt is answered with
|
|
68
|
+
* `classify` (or DEFAULT_CLASSIFY_LINE) WITHOUT consuming a turn fixture.
|
|
69
|
+
*
|
|
70
|
+
* This is a convenience for the file-based E2E harness (`loadMockModelFromDir`
|
|
71
|
+
* sets it true by default) whose fixtures supply agent turn-rounds and must
|
|
72
|
+
* not spend a round on the classify call. Direct in-memory callers
|
|
73
|
+
* (`createMockModel`/`installMockModel`, e.g. llm-classify.test.ts) leave it
|
|
74
|
+
* OFF so the fixture stream they configure IS delivered to the classifier —
|
|
75
|
+
* otherwise every classification would collapse to DEFAULT_CLASSIFY_LINE.
|
|
76
|
+
* Setting `classify` implies opting in.
|
|
77
|
+
*/
|
|
78
|
+
autoClassify?: boolean;
|
|
51
79
|
}
|
|
52
80
|
export interface MockModelHandle {
|
|
53
81
|
/** The mock model instance — assign to `globalThis.__muonroiMockModel`. */
|
|
@@ -25,6 +25,40 @@
|
|
|
25
25
|
import { APICallError } from "@ai-sdk/provider";
|
|
26
26
|
import { simulateReadableStream } from "ai";
|
|
27
27
|
import { MockLanguageModelV3 } from "ai/test";
|
|
28
|
+
/**
|
|
29
|
+
* System-prompt substring that uniquely identifies PIL's model-first intent
|
|
30
|
+
* classifier call (see SYSTEM_PROMPT in src/pil/llm-classify.ts). Kept in sync
|
|
31
|
+
* with that constant's opening line.
|
|
32
|
+
*/
|
|
33
|
+
const CLASSIFY_SIGNATURE = "Reply with ONE line of EIGHT lowercase words";
|
|
34
|
+
/**
|
|
35
|
+
* Safe default classification: a non-chitchat coding task of standard depth.
|
|
36
|
+
* `intent=task` keeps the toolset + gsd gate active; `standard` depth avoids
|
|
37
|
+
* forcing heavy-only paths. First word MUST be a valid taskType.
|
|
38
|
+
*/
|
|
39
|
+
const DEFAULT_CLASSIFY_LINE = "generate, balanced, task, code, standard, local, english, clear";
|
|
40
|
+
/** Concatenated text of every `system` message in a doStream call's prompt. */
|
|
41
|
+
function systemPromptText(options) {
|
|
42
|
+
const prompt = options.prompt;
|
|
43
|
+
if (!Array.isArray(prompt))
|
|
44
|
+
return "";
|
|
45
|
+
const parts = [];
|
|
46
|
+
for (const msg of prompt) {
|
|
47
|
+
const m = msg;
|
|
48
|
+
if (m.role !== "system")
|
|
49
|
+
continue;
|
|
50
|
+
if (typeof m.content === "string")
|
|
51
|
+
parts.push(m.content);
|
|
52
|
+
else if (Array.isArray(m.content)) {
|
|
53
|
+
for (const c of m.content) {
|
|
54
|
+
const t = c.text;
|
|
55
|
+
if (typeof t === "string")
|
|
56
|
+
parts.push(t);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return parts.join("\n");
|
|
61
|
+
}
|
|
28
62
|
function isNestedArray(v) {
|
|
29
63
|
return Array.isArray(v) && v.length > 0 && Array.isArray(v[0]);
|
|
30
64
|
}
|
|
@@ -44,10 +78,34 @@ export function createMockModel(fx) {
|
|
|
44
78
|
let genIdx = 0;
|
|
45
79
|
const provider = fx.provider ?? "mock";
|
|
46
80
|
const modelId = fx.modelId ?? "mock-model";
|
|
81
|
+
const classifyLine = fx.classify ?? DEFAULT_CLASSIFY_LINE;
|
|
82
|
+
// Intercept the PIL classifier call ONLY when the fixture opts in (E2E
|
|
83
|
+
// harness fixtures do, via loadMockModelFromDir). Direct in-memory callers
|
|
84
|
+
// (llm-classify.test.ts) leave it off so the stream they configure IS
|
|
85
|
+
// delivered to the classifier — intercepting would override their reply with
|
|
86
|
+
// DEFAULT_CLASSIFY_LINE and make every classification collapse to "generate".
|
|
87
|
+
const interceptClassify = fx.autoClassify === true || fx.classify !== undefined;
|
|
47
88
|
const model = new MockLanguageModelV3({
|
|
48
89
|
provider,
|
|
49
90
|
modelId,
|
|
50
|
-
doStream: async () => {
|
|
91
|
+
doStream: async (options) => {
|
|
92
|
+
// PIL model-first classifier call — answer with the parseable eight-word
|
|
93
|
+
// line and DO NOT advance the turn-fixture cursor, so the classify call
|
|
94
|
+
// (which fires on every turn) never steals the round chunks meant for the
|
|
95
|
+
// agent's actual reply. Without this the generic fixture text fails
|
|
96
|
+
// parseResponse → intentKind=UNKNOWN → gsd gate/routing break in E2E.
|
|
97
|
+
if (interceptClassify && systemPromptText(options).includes(CLASSIFY_SIGNATURE)) {
|
|
98
|
+
if (process.env.MUONROI_DEBUG_MOCK_MODEL === "1") {
|
|
99
|
+
process.stderr.write(`[mock-model] doStream classify → "${classifyLine}"\n`);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
stream: simulateReadableStream({
|
|
103
|
+
chunks: textOnlyStream(classifyLine),
|
|
104
|
+
initialDelayInMs: null,
|
|
105
|
+
chunkDelayInMs: null,
|
|
106
|
+
}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
51
109
|
const chunks = streams[Math.min(callIdx, streams.length - 1)];
|
|
52
110
|
callIdx += 1;
|
|
53
111
|
if (process.env.MUONROI_DEBUG_MOCK_MODEL === "1") {
|
|
@@ -397,6 +455,10 @@ export async function loadMockModelFromDir(dir) {
|
|
|
397
455
|
// to createMockModel, so the AI SDK stream-loop and orchestrator see a
|
|
398
456
|
// consistent Error shape regardless of fixture serialization.
|
|
399
457
|
const normalized = {
|
|
458
|
+
// File-based E2E fixtures supply agent turn-rounds; auto-answer the PIL
|
|
459
|
+
// classifier call so it never consumes a round (a fixture may still set
|
|
460
|
+
// autoClassify:false to opt out, or classify:"…" to force a line).
|
|
461
|
+
autoClassify: true,
|
|
400
462
|
...raw.model,
|
|
401
463
|
stream: isNestedArray(raw.model.stream)
|
|
402
464
|
? raw.model.stream.map(normalizeStreamChunks)
|
|
@@ -19,6 +19,35 @@ import { spawn } from "node:child_process";
|
|
|
19
19
|
import { randomUUID } from "node:crypto";
|
|
20
20
|
import { createServer } from "node:net";
|
|
21
21
|
// ---------------------------------------------------------------------------
|
|
22
|
+
// Internal: teardown-safe stream error guards
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Attach `'error'` listeners to both transport streams so a broken-pipe write
|
|
26
|
+
* (EPIPE / UV_EPIPE -4047 on Windows) or a peer reset (ECONNRESET) during
|
|
27
|
+
* process teardown is logged and swallowed instead of surfacing as an
|
|
28
|
+
* *uncaught* stream error that crashes the whole vitest worker.
|
|
29
|
+
*
|
|
30
|
+
* Root cause of the flake: when the child is killed in `afterAll`, an in-flight
|
|
31
|
+
* `inWrite.write()` (driver sendKey/sendType) or a half-open `outRead` races the
|
|
32
|
+
* child's death. A WritableStream with no `'error'` listener rethrows EPIPE as
|
|
33
|
+
* an unhandled exception — under full-suite load this reliably reproduces on
|
|
34
|
+
* `events.spec.ts` and fails the file even though every assertion passed.
|
|
35
|
+
*
|
|
36
|
+
* Logging (not silent swallow) satisfies the No-Silent-Catch rule — teardown
|
|
37
|
+
* broken-pipe is expected, but a mid-test error still gets a diagnostic line.
|
|
38
|
+
*/
|
|
39
|
+
function attachStreamErrorGuards(inWrite, outRead) {
|
|
40
|
+
const guard = (label) => (err) => {
|
|
41
|
+
// EPIPE / ECONNRESET / ERR_STREAM_DESTROYED are all normal teardown races.
|
|
42
|
+
const code = err?.code ?? "unknown";
|
|
43
|
+
if (code !== "EPIPE" && code !== "ECONNRESET" && code !== "ERR_STREAM_DESTROYED") {
|
|
44
|
+
console.error(`[test-spawn] ${label} stream error (${code}): ${err?.message}`);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
inWrite.on("error", guard("inWrite"));
|
|
48
|
+
outRead.on("error", guard("outRead"));
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
22
51
|
// Internal: Windows named-pipe transport
|
|
23
52
|
// ---------------------------------------------------------------------------
|
|
24
53
|
function makePipeName(role) {
|
|
@@ -143,6 +172,7 @@ async function spawnWindows(args, opts) {
|
|
|
143
172
|
outServer.close();
|
|
144
173
|
};
|
|
145
174
|
proc.once("exit", cleanup);
|
|
175
|
+
attachStreamErrorGuards(inSocket, outSocket);
|
|
146
176
|
return {
|
|
147
177
|
proc,
|
|
148
178
|
inWrite: inSocket, // host writes commands → child reads on MUONROI_HARNESS_IN_PIPE
|
|
@@ -161,6 +191,7 @@ function spawnPosix(args, opts) {
|
|
|
161
191
|
const proc = spawn("bun", ["run", ...args], spawnOptions);
|
|
162
192
|
const outRead = proc.stdio[3];
|
|
163
193
|
const inWrite = proc.stdio[4];
|
|
194
|
+
attachStreamErrorGuards(inWrite, outRead);
|
|
164
195
|
return { proc, inWrite, outRead, cleanup: () => { } };
|
|
165
196
|
}
|
|
166
197
|
// ---------------------------------------------------------------------------
|
|
@@ -9,7 +9,7 @@ import { A, captureKey, divider, enterRawMode, hiddenPrompt, maskKey } from "./t
|
|
|
9
9
|
* until their integration is hardened — the router can still target them
|
|
10
10
|
* programmatically. To re-expose one, add its id here.
|
|
11
11
|
*/
|
|
12
|
-
const VISIBLE_PROVIDERS = ["deepseek", "
|
|
12
|
+
const VISIBLE_PROVIDERS = ["deepseek", "zai", "opencode-go", "xai"];
|
|
13
13
|
const ALL_PROVIDERS = [...VISIBLE_PROVIDERS, "ollama"];
|
|
14
14
|
void KEYCHAIN_PROVIDER_IDS;
|
|
15
15
|
async function loadRows() {
|
|
@@ -35,6 +35,16 @@ export interface CostForensicsSummary {
|
|
|
35
35
|
totalCostUsd: number;
|
|
36
36
|
cacheHitRatio: number;
|
|
37
37
|
peakSingleCallInput: number;
|
|
38
|
+
/**
|
|
39
|
+
* Peak FRESH (uncached) input on any single usage event — `max(input -
|
|
40
|
+
* cacheRead)`. This is the cap-escape discriminator: `task`/`council` rows
|
|
41
|
+
* store `totalUsage` AGGREGATED across a streamText call's internal steps, so
|
|
42
|
+
* a high `peakSingleCallInput` on those sources is usually cached-prefix reuse
|
|
43
|
+
* across steps (high cache hit), NOT a single call that breached the cap. A
|
|
44
|
+
* genuine cold cap-escape sends >cap FRESH tokens in one call, which shows up
|
|
45
|
+
* here regardless of source.
|
|
46
|
+
*/
|
|
47
|
+
peakSingleCallFresh: number;
|
|
38
48
|
events: CostForensicsRow[];
|
|
39
49
|
/** Anti-mù counters for this session (null when none recorded). */
|
|
40
50
|
experience: SessionExperienceCounts | null;
|
|
@@ -83,6 +83,7 @@ export function collectCostForensics(sessionId) {
|
|
|
83
83
|
let totalCacheCreation = 0;
|
|
84
84
|
let totalCostMicros = 0;
|
|
85
85
|
let peakSingleCallInput = 0;
|
|
86
|
+
let peakSingleCallFresh = 0;
|
|
86
87
|
for (const e of events) {
|
|
87
88
|
totalInput += e.inputTokens;
|
|
88
89
|
totalOutput += e.outputTokens;
|
|
@@ -91,6 +92,9 @@ export function collectCostForensics(sessionId) {
|
|
|
91
92
|
totalCostMicros += e.costMicros;
|
|
92
93
|
if (e.inputTokens > peakSingleCallInput)
|
|
93
94
|
peakSingleCallInput = e.inputTokens;
|
|
95
|
+
const fresh = Math.max(0, e.inputTokens - e.cacheReadTokens);
|
|
96
|
+
if (fresh > peakSingleCallFresh)
|
|
97
|
+
peakSingleCallFresh = fresh;
|
|
94
98
|
}
|
|
95
99
|
const cacheable = totalInput;
|
|
96
100
|
const cacheHitRatio = cacheable > 0 ? totalCacheRead / cacheable : 0;
|
|
@@ -106,6 +110,7 @@ export function collectCostForensics(sessionId) {
|
|
|
106
110
|
totalCostUsd: totalCostMicros / 1_000_000,
|
|
107
111
|
cacheHitRatio,
|
|
108
112
|
peakSingleCallInput,
|
|
113
|
+
peakSingleCallFresh,
|
|
109
114
|
events,
|
|
110
115
|
experience: selectSessionExperience(sessionId),
|
|
111
116
|
};
|
|
@@ -159,7 +164,8 @@ export function printCostForensics(summary, opts = {}) {
|
|
|
159
164
|
w(`Total output tokens: ${formatNum(summary.totalOutput)}`);
|
|
160
165
|
w(`Cache read tokens: ${formatNum(summary.totalCacheRead)} (${formatPct(summary.cacheHitRatio)} of input)`);
|
|
161
166
|
w(`Cache create tokens: ${formatNum(summary.totalCacheCreation)}`);
|
|
162
|
-
w(`Peak single call: ${formatNum(summary.peakSingleCallInput)} input`
|
|
167
|
+
w(`Peak single call: ${formatNum(summary.peakSingleCallInput)} input ` +
|
|
168
|
+
`(${formatNum(summary.peakSingleCallFresh)} fresh)`);
|
|
163
169
|
w(`Estimated cost: $${summary.totalCostUsd.toFixed(4)}`);
|
|
164
170
|
// Cache-cadence diagnostic — surface fast-loop prompt-cache latency loss.
|
|
165
171
|
const cadence = computeCacheCadence(summary.events);
|
|
@@ -199,8 +205,17 @@ export function printCostForensics(summary, opts = {}) {
|
|
|
199
205
|
}
|
|
200
206
|
// Acceptance hints — surface anomalies relative to Phase A/B/C targets.
|
|
201
207
|
const anomalies = [];
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
// Phase B breach = a single call that sent >80K FRESH (uncached) tokens.
|
|
209
|
+
// Use FRESH, not raw input: `task`/`council` usage rows store `totalUsage`
|
|
210
|
+
// aggregated across a streamText call's internal steps, so a high raw input
|
|
211
|
+
// there is normally cached-prefix reuse across steps (high cache hit), NOT a
|
|
212
|
+
// cold cap breach. Evidence: session 6f17a13c1591 peaked at 378,613 raw input
|
|
213
|
+
// but only 54,389 fresh (324,224 cache-read) — aggregate reuse, no breach.
|
|
214
|
+
if (summary.peakSingleCallFresh > 80_000) {
|
|
215
|
+
anomalies.push(`peak single-call FRESH input ${formatNum(summary.peakSingleCallFresh)} > 80,000 — sub-agent cap may not have kicked in (Phase B target breach)`);
|
|
216
|
+
}
|
|
217
|
+
else if (summary.peakSingleCallInput > 80_000) {
|
|
218
|
+
anomalies.push(`peak single-call input ${formatNum(summary.peakSingleCallInput)} > 80,000 but only ${formatNum(summary.peakSingleCallFresh)} FRESH — aggregate multi-step reuse (task/council totalUsage), NOT a cap breach`);
|
|
204
219
|
}
|
|
205
220
|
if (summary.events.some((e) => e.messageSeq === null && e.source === "message")) {
|
|
206
221
|
anomalies.push(`some 'message' events have NULL message_seq — Phase A5 message write-ahead bypassed (check persistMessageWriteAhead wiring)`);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Format (JSON):
|
|
8
8
|
* { v:1, kdf:"scrypt", salt:hex, iv:hex, tag:hex, ct:base64 }
|
|
9
9
|
*
|
|
10
|
-
* Plaintext payload (JSON): { providers: { deepseek: "sk-...",
|
|
10
|
+
* Plaintext payload (JSON): { providers: { deepseek: "sk-...", xai: "xai-..." } }
|
|
11
11
|
*
|
|
12
12
|
* Crypto:
|
|
13
13
|
* - scrypt(passphrase, salt, 32) → 256-bit key
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Format (JSON):
|
|
8
8
|
* { v:1, kdf:"scrypt", salt:hex, iv:hex, tag:hex, ct:base64 }
|
|
9
9
|
*
|
|
10
|
-
* Plaintext payload (JSON): { providers: { deepseek: "sk-...",
|
|
10
|
+
* Plaintext payload (JSON): { providers: { deepseek: "sk-...", xai: "xai-..." } }
|
|
11
11
|
*
|
|
12
12
|
* Crypto:
|
|
13
13
|
* - scrypt(passphrase, salt, 32) → 256-bit key
|
package/dist/src/cli/keys.d.ts
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* keys delete <provider> — remove a stored key
|
|
16
16
|
* keys import-bw [providers] — pull from Bitwarden vault, store in keychain
|
|
17
17
|
* keys cleanup-settings — strip plaintext keys from user-settings.json
|
|
18
|
-
* keys login <provider> — OAuth login (openai,
|
|
19
|
-
* keys logout <provider> — OAuth logout (openai,
|
|
18
|
+
* keys login <provider> — OAuth login (openai, xai)
|
|
19
|
+
* keys logout <provider> — OAuth logout (openai, xai)
|
|
20
20
|
*/
|
|
21
21
|
import { type ChatSecretId } from "../chat/chat-keychain.js";
|
|
22
22
|
export interface KeysSetOptions {
|
package/dist/src/cli/keys.js
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* keys delete <provider> — remove a stored key
|
|
16
16
|
* keys import-bw [providers] — pull from Bitwarden vault, store in keychain
|
|
17
17
|
* keys cleanup-settings — strip plaintext keys from user-settings.json
|
|
18
|
-
* keys login <provider> — OAuth login (openai,
|
|
19
|
-
* keys logout <provider> — OAuth logout (openai,
|
|
18
|
+
* keys login <provider> — OAuth login (openai, xai)
|
|
19
|
+
* keys logout <provider> — OAuth logout (openai, xai)
|
|
20
20
|
*/
|
|
21
21
|
import { spawnSync } from "node:child_process";
|
|
22
22
|
import { promises as fs } from "node:fs";
|
|
@@ -43,7 +43,7 @@ const CHAT_SECRET_IDS = ["discord-token", "discord-guild-id", "slack-token", "sl
|
|
|
43
43
|
function isChatSecretId(value) {
|
|
44
44
|
return CHAT_SECRET_IDS.includes(value);
|
|
45
45
|
}
|
|
46
|
-
const
|
|
46
|
+
const getSettingsPath = () => path.join(os.homedir(), ".muonroi-cli", "user-settings.json");
|
|
47
47
|
function maskKey(key) {
|
|
48
48
|
if (key.length <= 10)
|
|
49
49
|
return "***";
|
|
@@ -51,8 +51,6 @@ function maskKey(key) {
|
|
|
51
51
|
}
|
|
52
52
|
function normalizeProvider(p) {
|
|
53
53
|
const lower = p.toLowerCase();
|
|
54
|
-
if (lower === "agy")
|
|
55
|
-
return "google"; // agy is alias for google (OAuth + key)
|
|
56
54
|
if (KEYCHAIN_PROVIDER_IDS.includes(lower)) {
|
|
57
55
|
return lower;
|
|
58
56
|
}
|
|
@@ -115,7 +113,7 @@ async function promptHidden(question) {
|
|
|
115
113
|
export async function runKeysSet(provider, options = {}) {
|
|
116
114
|
const norm = normalizeProvider(provider);
|
|
117
115
|
if (!norm) {
|
|
118
|
-
console.error(`Unknown provider '${provider}'. Valid: ${KEYCHAIN_PROVIDER_IDS.join(", ")}
|
|
116
|
+
console.error(`Unknown provider '${provider}'. Valid: ${KEYCHAIN_PROVIDER_IDS.join(", ")}`);
|
|
119
117
|
process.exit(1);
|
|
120
118
|
}
|
|
121
119
|
const key = (await promptHidden(`Paste ${provider} API key (hidden): `)).trim();
|
|
@@ -199,30 +197,11 @@ export async function runKeysList() {
|
|
|
199
197
|
const oauthIds = await getOAuthProviderIds();
|
|
200
198
|
for (const p of oauthIds) {
|
|
201
199
|
try {
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const agyTokens = await loadAgyTokensWithRefresh();
|
|
208
|
-
if (agyTokens && Date.now() < agyTokens.expiresAt) {
|
|
209
|
-
tokens = agyTokens;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
if (tokens) {
|
|
213
|
-
if (Date.now() < tokens.expiresAt) {
|
|
214
|
-
const cfg = await getOAuthProviderConfig(p);
|
|
215
|
-
const display = cfg?.displayName ?? p;
|
|
216
|
-
oauthRows.push({ provider: p, display, email: tokens.email, expiresAt: tokens.expiresAt });
|
|
217
|
-
}
|
|
218
|
-
else if (p === "google") {
|
|
219
|
-
// auto-clean stale Agy token from our store (imported from old ~/.gemini)
|
|
220
|
-
try {
|
|
221
|
-
const { deleteTokens } = await import("../providers/auth/token-store.js");
|
|
222
|
-
await deleteTokens("google");
|
|
223
|
-
}
|
|
224
|
-
catch { }
|
|
225
|
-
}
|
|
200
|
+
const tokens = await loadTokens(p);
|
|
201
|
+
if (tokens && Date.now() < tokens.expiresAt) {
|
|
202
|
+
const cfg = await getOAuthProviderConfig(p);
|
|
203
|
+
const display = cfg?.displayName ?? p;
|
|
204
|
+
oauthRows.push({ provider: p, display, email: tokens.email, expiresAt: tokens.expiresAt });
|
|
226
205
|
}
|
|
227
206
|
}
|
|
228
207
|
catch {
|
|
@@ -234,7 +213,6 @@ export async function runKeysList() {
|
|
|
234
213
|
console.log("No keys stored in OS keychain.");
|
|
235
214
|
console.log("Run 'muonroi-cli keys set <provider>' or 'muonroi-cli keys import-bw' to add some.");
|
|
236
215
|
console.log("Run 'muonroi-cli keys login openai' to log in with your OpenAI subscription.");
|
|
237
|
-
console.log("Run 'muonroi-cli keys login google' or 'keys login agy' to log in with Agy (Google OAuth).");
|
|
238
216
|
console.log("Run 'muonroi-cli keys login xai' to log in with your SuperGrok / X Premium+ subscription.");
|
|
239
217
|
return;
|
|
240
218
|
}
|
|
@@ -288,35 +266,11 @@ export async function runKeysList() {
|
|
|
288
266
|
export async function runKeysDelete(provider) {
|
|
289
267
|
const norm = normalizeProvider(provider);
|
|
290
268
|
if (!norm) {
|
|
291
|
-
console.error(`Unknown provider '${provider}'. Valid: ${KEYCHAIN_PROVIDER_IDS.join(", ")}
|
|
269
|
+
console.error(`Unknown provider '${provider}'. Valid: ${KEYCHAIN_PROVIDER_IDS.join(", ")}`);
|
|
292
270
|
process.exit(1);
|
|
293
271
|
}
|
|
294
272
|
const ok = await deleteKeyForProvider(norm);
|
|
295
273
|
console.log(ok ? `Deleted ${provider} key from keychain.` : `No ${provider} key was stored.`);
|
|
296
|
-
// If deleting google/agy, also clean the OAuth token (Agy uses the google slot for its OAuth)
|
|
297
|
-
if (norm === "google") {
|
|
298
|
-
try {
|
|
299
|
-
const { loadTokens, deleteTokens } = await import("../providers/auth/token-store.js");
|
|
300
|
-
const { getOAuthProviderConfig } = await import("../providers/auth/registry.js");
|
|
301
|
-
const tokens = await loadTokens("google");
|
|
302
|
-
if (tokens) {
|
|
303
|
-
const cfg = await getOAuthProviderConfig("google");
|
|
304
|
-
if (cfg?.provider) {
|
|
305
|
-
try {
|
|
306
|
-
await cfg.provider.revoke(tokens);
|
|
307
|
-
}
|
|
308
|
-
catch {
|
|
309
|
-
// best effort
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
await deleteTokens("google");
|
|
313
|
-
console.log(`Also cleared Agy/Google OAuth token.`);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
catch {
|
|
317
|
-
// ignore secondary errors
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
274
|
}
|
|
321
275
|
export async function runKeysExport(filePath) {
|
|
322
276
|
const providers = {};
|
|
@@ -679,9 +633,9 @@ export async function runChatImportBw(opts = {}) {
|
|
|
679
633
|
*/
|
|
680
634
|
export async function runKeysLogin(provider) {
|
|
681
635
|
const oauthIds = await getOAuthProviderIds();
|
|
682
|
-
const norm = provider
|
|
636
|
+
const norm = provider;
|
|
683
637
|
if (!oauthIds.includes(norm)) {
|
|
684
|
-
const supported = oauthIds.
|
|
638
|
+
const supported = oauthIds.join(", ");
|
|
685
639
|
console.error(`OAuth login not supported for '${provider}'. Supported: ${supported}`);
|
|
686
640
|
process.exit(1);
|
|
687
641
|
}
|
|
@@ -693,22 +647,6 @@ export async function runKeysLogin(provider) {
|
|
|
693
647
|
process.exit(1);
|
|
694
648
|
}
|
|
695
649
|
const name = cfg.displayName;
|
|
696
|
-
// Special handling for google: prefer importing/reusing token from agy local config
|
|
697
|
-
// (~/.gemini/oauth_creds.json) so existing agy login "just works" without browser.
|
|
698
|
-
if (provider === "google") {
|
|
699
|
-
const { loadAgyTokensWithRefresh } = await import("../providers/auth/gemini-oauth.js");
|
|
700
|
-
const existing = await loadAgyTokensWithRefresh();
|
|
701
|
-
if (existing?.accessToken) {
|
|
702
|
-
console.log(`Found existing agy token for ${existing.email || "(no email)"}.`);
|
|
703
|
-
console.log("Reusing it (refreshed if near expiry). No browser needed.");
|
|
704
|
-
const expiry = new Date(existing.expiresAt).toLocaleString();
|
|
705
|
-
const isExpired = Date.now() > existing.expiresAt;
|
|
706
|
-
console.log(`Token expires: ${expiry}${isExpired ? " (was expired, refresh attempted)" : ""}`);
|
|
707
|
-
console.log("Run 'muonroi-cli keys list' to verify.");
|
|
708
|
-
return;
|
|
709
|
-
}
|
|
710
|
-
// No existing agy token — fall through to normal browser flow (using agy client)
|
|
711
|
-
}
|
|
712
650
|
console.log(`Logging in to ${name} via OAuth...`);
|
|
713
651
|
console.log("A browser window will open. Complete the sign-in to continue.");
|
|
714
652
|
const tokens = await cfg.provider.login({
|
|
@@ -742,9 +680,9 @@ export async function runKeysLogin(provider) {
|
|
|
742
680
|
*/
|
|
743
681
|
export async function runKeysLogout(provider) {
|
|
744
682
|
const oauthIds = await getOAuthProviderIds();
|
|
745
|
-
const norm = provider
|
|
683
|
+
const norm = provider;
|
|
746
684
|
if (!oauthIds.includes(norm)) {
|
|
747
|
-
const supported = oauthIds.
|
|
685
|
+
const supported = oauthIds.join(", ");
|
|
748
686
|
console.error(`OAuth logout not supported for '${provider}'. Supported: ${supported}`);
|
|
749
687
|
process.exit(1);
|
|
750
688
|
}
|
|
@@ -766,7 +704,7 @@ export async function runKeysLogout(provider) {
|
|
|
766
704
|
export async function runKeysCleanupSettings() {
|
|
767
705
|
let raw;
|
|
768
706
|
try {
|
|
769
|
-
raw = await fs.readFile(
|
|
707
|
+
raw = await fs.readFile(getSettingsPath(), "utf8");
|
|
770
708
|
}
|
|
771
709
|
catch (e) {
|
|
772
710
|
if (e.code === "ENOENT") {
|
|
@@ -780,11 +718,11 @@ export async function runKeysCleanupSettings() {
|
|
|
780
718
|
json = JSON.parse(raw);
|
|
781
719
|
}
|
|
782
720
|
catch {
|
|
783
|
-
console.error(`Settings file is not valid JSON: ${
|
|
721
|
+
console.error(`Settings file is not valid JSON: ${getSettingsPath()}`);
|
|
784
722
|
process.exit(1);
|
|
785
723
|
}
|
|
786
724
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
787
|
-
const backup = `${
|
|
725
|
+
const backup = `${getSettingsPath()}.bak.${ts}`;
|
|
788
726
|
await fs.writeFile(backup, raw, "utf8");
|
|
789
727
|
let removed = 0;
|
|
790
728
|
if ("apiKey" in json) {
|
|
@@ -806,9 +744,9 @@ export async function runKeysCleanupSettings() {
|
|
|
806
744
|
delete json.providers;
|
|
807
745
|
}
|
|
808
746
|
}
|
|
809
|
-
await fs.writeFile(
|
|
747
|
+
await fs.writeFile(getSettingsPath(), `${JSON.stringify(json, null, 2)}\n`, "utf8");
|
|
810
748
|
console.log(`Backed up to: ${backup}`);
|
|
811
|
-
console.log(`Removed ${removed} plaintext key field(s) from: ${
|
|
749
|
+
console.log(`Removed ${removed} plaintext key field(s) from: ${getSettingsPath()}`);
|
|
812
750
|
if (removed === 0) {
|
|
813
751
|
console.log("(File was already clean.)");
|
|
814
752
|
}
|
|
@@ -69,6 +69,26 @@ export interface ClarifyOptionsResult {
|
|
|
69
69
|
* so the UI knows to suppress the "(Recommended)" tag.
|
|
70
70
|
*/
|
|
71
71
|
export declare function buildClarifyOptions(suggestions: string[] | undefined, recommended?: string): ClarifyOptionsResult;
|
|
72
|
+
/**
|
|
73
|
+
* Model-designed option object: a choice the user picks between, carrying its
|
|
74
|
+
* own explanation. `recommended:true` marks the pre-selected default. This is
|
|
75
|
+
* the richer shape the clarifier prompt now asks for so every choice shows a
|
|
76
|
+
* per-option "why" (not just the question-level `why`).
|
|
77
|
+
*/
|
|
78
|
+
export interface ClarifyOptionSpec {
|
|
79
|
+
label: string;
|
|
80
|
+
description?: string;
|
|
81
|
+
recommended?: boolean;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build council options from the model's richer `{label, description,
|
|
85
|
+
* recommended}` objects, preserving each choice's explanation as `description`
|
|
86
|
+
* and pointing `defaultIndex` at the option the model flagged `recommended`
|
|
87
|
+
* (falling back to the first when none is flagged). The same "Type something" /
|
|
88
|
+
* "Chat about this" escape-hatches are appended as in `buildClarifyOptions`.
|
|
89
|
+
* Pure + exported for unit testing.
|
|
90
|
+
*/
|
|
91
|
+
export declare function buildClarifyOptionsRich(specs: ClarifyOptionSpec[] | undefined): ClarifyOptionsResult;
|
|
72
92
|
export declare function runClarification(topic: string, leaderModelId: string, conversationContext: string, respondToQuestion: QuestionResponder, llm: CouncilLLM, signal?: AbortSignal, seedQuestions?: GrayAreaQuestion[], maxRounds?: number,
|
|
73
93
|
/**
|
|
74
94
|
* Optional pre-filled answers keyed by seed-question id. When the loop's
|
|
@@ -83,5 +103,11 @@ prefillAnswers?: Map<string, string>,
|
|
|
83
103
|
* a cheaper tier model on the same provider as the leader. Falls back to
|
|
84
104
|
* the leader model if no cheaper model is cataloged. Default false.
|
|
85
105
|
*/
|
|
86
|
-
costAware?: boolean
|
|
87
|
-
|
|
106
|
+
costAware?: boolean,
|
|
107
|
+
/**
|
|
108
|
+
* Healthy panel models to fall back to when the leader's cost-tier spec-synth
|
|
109
|
+
* model is on a failing proxy — keeps the spec's ≥3 observable criteria (and
|
|
110
|
+
* thus a meaningful leader eval) instead of degrading to one generic criterion.
|
|
111
|
+
*/
|
|
112
|
+
fallbackModels?: string[]): AsyncGenerator<StreamChunk, ClarifiedSpec, unknown>;
|
|
113
|
+
export declare function buildSpecFromTopic(topic: string, conversationContext: string): ClarifiedSpec;
|