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
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/research.ts
|
|
3
|
+
*
|
|
4
|
+
* Native research tools for the inner agent.
|
|
5
|
+
*
|
|
6
|
+
* These replace the previous external MCP servers (fetch, tavily, and eventually
|
|
7
|
+
* context7 / muonroi-docs) so that web/docs lookup and search are:
|
|
8
|
+
* - Always available without spawn / warmup / "Connection closed"
|
|
9
|
+
* - Subject to the same permission, capping, redaction and cost rules as other builtins
|
|
10
|
+
* - Fast and reliable on first turn
|
|
11
|
+
*
|
|
12
|
+
* memory and playwright were removed from defaults (see auto-setup.ts).
|
|
13
|
+
* Full browser automation (playwright) can still be added manually if needed.
|
|
14
|
+
*/
|
|
15
|
+
import { dynamicTool, jsonSchema } from "ai";
|
|
16
|
+
import TurndownService from "turndown";
|
|
17
|
+
import { getMcpKey } from "../mcp/mcp-keychain.js";
|
|
18
|
+
const turndown = new TurndownService({
|
|
19
|
+
headingStyle: "atx",
|
|
20
|
+
codeBlockStyle: "fenced",
|
|
21
|
+
bulletListMarker: "-",
|
|
22
|
+
});
|
|
23
|
+
// Basic cleanup for HTML before turndown (remove scripts, styles, etc.)
|
|
24
|
+
function sanitizeForMarkdown(html) {
|
|
25
|
+
return html
|
|
26
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
27
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
28
|
+
.replace(/<noscript[\s\S]*?<\/noscript>/gi, "")
|
|
29
|
+
.replace(/<!--[\s\S]*?-->/g, "");
|
|
30
|
+
}
|
|
31
|
+
function extractTitle(html) {
|
|
32
|
+
const m = html.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
33
|
+
return m ? m[1].trim() : undefined;
|
|
34
|
+
}
|
|
35
|
+
export async function fetchUrl(url, opts = {}) {
|
|
36
|
+
const { format = "markdown", maxChars = 12000 } = opts;
|
|
37
|
+
const controller = new AbortController();
|
|
38
|
+
const timeout = setTimeout(() => controller.abort(), 15000);
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(url, {
|
|
41
|
+
signal: controller.signal,
|
|
42
|
+
headers: {
|
|
43
|
+
"User-Agent": "muonroi-cli/1.0 (+https://github.com/muonroi/muonroi-cli)",
|
|
44
|
+
Accept: "text/html,application/xhtml+xml,application/json,text/plain,*/*",
|
|
45
|
+
},
|
|
46
|
+
redirect: "follow",
|
|
47
|
+
});
|
|
48
|
+
if (!res.ok) {
|
|
49
|
+
return `ERROR fetch_failed: HTTP ${res.status} ${res.statusText} for ${url}`;
|
|
50
|
+
}
|
|
51
|
+
const contentType = res.headers.get("content-type") || "";
|
|
52
|
+
let body = await res.text();
|
|
53
|
+
if (format === "html") {
|
|
54
|
+
return body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
|
|
55
|
+
}
|
|
56
|
+
if (contentType.includes("application/json")) {
|
|
57
|
+
try {
|
|
58
|
+
const obj = JSON.parse(body);
|
|
59
|
+
body = JSON.stringify(obj, null, 2);
|
|
60
|
+
}
|
|
61
|
+
catch { }
|
|
62
|
+
return body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
|
|
63
|
+
}
|
|
64
|
+
// Treat as HTML or plain text
|
|
65
|
+
const isHtml = /<\/?[a-z][\s\S]*>/i.test(body) || contentType.includes("html");
|
|
66
|
+
if (format === "text") {
|
|
67
|
+
// Very lightweight text extraction
|
|
68
|
+
const text = isHtml
|
|
69
|
+
? body
|
|
70
|
+
.replace(/<[^>]+>/g, " ")
|
|
71
|
+
.replace(/\s+/g, " ")
|
|
72
|
+
.trim()
|
|
73
|
+
: body;
|
|
74
|
+
return text.length > maxChars ? text.slice(0, maxChars) + "\n... [truncated]" : text;
|
|
75
|
+
}
|
|
76
|
+
// markdown (default)
|
|
77
|
+
if (isHtml) {
|
|
78
|
+
const cleaned = sanitizeForMarkdown(body);
|
|
79
|
+
const title = extractTitle(body);
|
|
80
|
+
let md = turndown.turndown(cleaned);
|
|
81
|
+
if (title && !md.startsWith("# ")) {
|
|
82
|
+
md = `# ${title}\n\n${md}`;
|
|
83
|
+
}
|
|
84
|
+
if (md.length > maxChars) {
|
|
85
|
+
md = md.slice(0, maxChars) + "\n\n... [truncated — use more specific URL or smaller scope]";
|
|
86
|
+
}
|
|
87
|
+
// Add source
|
|
88
|
+
return `${md}\n\n_Source: ${url}_`;
|
|
89
|
+
}
|
|
90
|
+
// Plain text → code block or just return
|
|
91
|
+
const out = body.length > maxChars ? body.slice(0, maxChars) + "\n... [truncated]" : body;
|
|
92
|
+
return `\`\`\`\n${out}\n\`\`\`\n\n_Source: ${url}_`;
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (err?.name === "AbortError") {
|
|
96
|
+
return `ERROR fetch_timeout: timed out after 15s fetching ${url}`;
|
|
97
|
+
}
|
|
98
|
+
return `ERROR fetch_error: ${err instanceof Error ? err.message : String(err)}`;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
clearTimeout(timeout);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export async function webSearch(query, opts = {}) {
|
|
105
|
+
const maxResults = Math.max(1, Math.min(opts.maxResults ?? 8, 20));
|
|
106
|
+
let key = opts.apiKey;
|
|
107
|
+
if (!key) {
|
|
108
|
+
key = (await getMcpKey("tavily")) || process.env.TAVILY_API_KEY || "";
|
|
109
|
+
}
|
|
110
|
+
if (!key || key.length < 10) {
|
|
111
|
+
return ("ERROR no_tavily_key: Tavily API key is required for web_search. " +
|
|
112
|
+
"Run `muonroi-cli mcp setup-research` or set TAVILY_API_KEY. " +
|
|
113
|
+
"You can also use `fetch_url` for direct URLs.");
|
|
114
|
+
}
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
const timeout = setTimeout(() => controller.abort(), 12000);
|
|
117
|
+
try {
|
|
118
|
+
const res = await fetch("https://api.tavily.com/search", {
|
|
119
|
+
method: "POST",
|
|
120
|
+
signal: controller.signal,
|
|
121
|
+
headers: {
|
|
122
|
+
"Content-Type": "application/json",
|
|
123
|
+
},
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
api_key: key,
|
|
126
|
+
query,
|
|
127
|
+
max_results: maxResults,
|
|
128
|
+
include_answer: true,
|
|
129
|
+
include_raw_content: false,
|
|
130
|
+
search_depth: "basic",
|
|
131
|
+
}),
|
|
132
|
+
});
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
const text = await res.text().catch(() => "");
|
|
135
|
+
return `ERROR tavily_http_${res.status}: ${text.slice(0, 300)}`;
|
|
136
|
+
}
|
|
137
|
+
const data = await res.json();
|
|
138
|
+
const lines = [];
|
|
139
|
+
if (data.answer) {
|
|
140
|
+
lines.push("**Answer summary:**");
|
|
141
|
+
lines.push(data.answer);
|
|
142
|
+
lines.push("");
|
|
143
|
+
}
|
|
144
|
+
const results = Array.isArray(data.results) ? data.results : [];
|
|
145
|
+
if (results.length === 0) {
|
|
146
|
+
return "No web results found.";
|
|
147
|
+
}
|
|
148
|
+
lines.push(`**Web results** (top ${Math.min(results.length, maxResults)}):\n`);
|
|
149
|
+
for (const r of results.slice(0, maxResults)) {
|
|
150
|
+
const title = r.title || r.url;
|
|
151
|
+
const url = r.url;
|
|
152
|
+
const content = (r.content || r.raw_content || "").trim().slice(0, 600);
|
|
153
|
+
lines.push(`- **${title}**`);
|
|
154
|
+
lines.push(` ${url}`);
|
|
155
|
+
if (content)
|
|
156
|
+
lines.push(` ${content.replace(/\s+/g, " ")}`);
|
|
157
|
+
lines.push("");
|
|
158
|
+
}
|
|
159
|
+
if (data.query) {
|
|
160
|
+
lines.push(`_Query: ${data.query}_`);
|
|
161
|
+
}
|
|
162
|
+
return lines.join("\n");
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
if (err?.name === "AbortError") {
|
|
166
|
+
return "ERROR web_search_timeout: Tavily request timed out.";
|
|
167
|
+
}
|
|
168
|
+
return `ERROR web_search_failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
clearTimeout(timeout);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/** Register the native research tools into the provided ToolSet. */
|
|
175
|
+
export function registerNativeResearchTools(tools) {
|
|
176
|
+
tools.fetch_url = dynamicTool({
|
|
177
|
+
description: "Fetch a URL and return clean, readable content as markdown (default), plain text, or raw HTML. " +
|
|
178
|
+
"Ideal for documentation, articles, GitHub, blog posts, raw files, and any public web page. " +
|
|
179
|
+
"Use this for most 'read this URL' needs instead of external MCP fetch.",
|
|
180
|
+
inputSchema: jsonSchema({
|
|
181
|
+
type: "object",
|
|
182
|
+
properties: {
|
|
183
|
+
url: { type: "string", description: "The full http(s) URL to fetch" },
|
|
184
|
+
format: {
|
|
185
|
+
type: "string",
|
|
186
|
+
enum: ["markdown", "text", "html"],
|
|
187
|
+
description: "Output format. Default: markdown (best for agents)",
|
|
188
|
+
},
|
|
189
|
+
maxChars: {
|
|
190
|
+
type: "number",
|
|
191
|
+
description: "Maximum characters to return (500-30000). Default ~12000.",
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
required: ["url"],
|
|
195
|
+
additionalProperties: false,
|
|
196
|
+
}),
|
|
197
|
+
execute: async (input) => {
|
|
198
|
+
const url = String(input?.url || "").trim();
|
|
199
|
+
if (!url || !/^https?:\/\//i.test(url)) {
|
|
200
|
+
return "ERROR invalid_url: fetch_url requires a full http(s):// URL";
|
|
201
|
+
}
|
|
202
|
+
const format = (["markdown", "text", "html"].includes(input?.format) ? input.format : "markdown");
|
|
203
|
+
const maxChars = typeof input?.maxChars === "number" ? input.maxChars : undefined;
|
|
204
|
+
return fetchUrl(url, { format, maxChars });
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
tools.web_search = dynamicTool({
|
|
208
|
+
description: "Search the live web using Tavily (LLM-optimized search with summaries). " +
|
|
209
|
+
"Returns titles, URLs, and content snippets. Requires a Tavily API key (free tier available). " +
|
|
210
|
+
"Use together with fetch_url when you need deeper content from specific results.",
|
|
211
|
+
inputSchema: jsonSchema({
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
query: { type: "string", description: "Search query (natural language is fine)" },
|
|
215
|
+
maxResults: {
|
|
216
|
+
type: "number",
|
|
217
|
+
description: "How many results to return (1-20). Default 8.",
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
required: ["query"],
|
|
221
|
+
additionalProperties: false,
|
|
222
|
+
}),
|
|
223
|
+
execute: async (input) => {
|
|
224
|
+
const query = String(input?.query || "").trim();
|
|
225
|
+
if (!query)
|
|
226
|
+
return "ERROR invalid_query: web_search requires a non-empty query";
|
|
227
|
+
const maxResults = typeof input?.maxResults === "number" ? input.maxResults : undefined;
|
|
228
|
+
return webSearch(query, { maxResults });
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
return tools;
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=research.js.map
|
|
@@ -34,6 +34,8 @@ export interface TaskRequest {
|
|
|
34
34
|
description: string;
|
|
35
35
|
prompt: string;
|
|
36
36
|
maxToolRounds?: number;
|
|
37
|
+
/** When set, bypasses parent-tier cap and uses this model for the sub-agent. */
|
|
38
|
+
modelId?: string;
|
|
37
39
|
}
|
|
38
40
|
export interface TaskRun {
|
|
39
41
|
agent: string;
|
|
@@ -246,7 +248,7 @@ export interface CouncilQuestionData {
|
|
|
246
248
|
options?: CouncilQuestionOption[];
|
|
247
249
|
defaultIndex?: number;
|
|
248
250
|
}
|
|
249
|
-
export type CouncilStatusPhase = "clarify" | "plan_debate" | "research" | "opening" | "exchange" | "evaluate" | "synthesis" | "summary";
|
|
251
|
+
export type CouncilStatusPhase = "clarify" | "panel_select" | "plan_debate" | "research" | "opening" | "exchange" | "evaluate" | "synthesis" | "summary";
|
|
250
252
|
export type CouncilStatusState = "start" | "tick" | "done" | "error";
|
|
251
253
|
export interface CouncilStatusData {
|
|
252
254
|
statusId: string;
|
|
@@ -256,12 +258,14 @@ export interface CouncilStatusData {
|
|
|
256
258
|
detail?: string;
|
|
257
259
|
role?: string;
|
|
258
260
|
elapsedMs?: number;
|
|
261
|
+
/** Client-side first-seen stamp (upsertStatus), back-dated by the emitted elapsedMs. Drives live-ticking elapsed. */
|
|
262
|
+
startedAt?: number;
|
|
259
263
|
tokensIn?: number;
|
|
260
264
|
tokensOut?: number;
|
|
261
265
|
errorMessage?: string;
|
|
262
266
|
}
|
|
263
267
|
/** High-level lifecycle event for a council phase. Drives the phase timeline UI. */
|
|
264
|
-
export type CouncilPhaseKind = "clarification" | "clarification_round" | "preflight" | "debate_plan" | "research" | "opening" | "round" | "evaluation" | "mid_research" | "summary" | "synthesis" | "action_plan"
|
|
268
|
+
export type CouncilPhaseKind = "clarification" | "clarification_round" | "preflight" | "debate_plan" | "research" | "opening" | "round" | "evaluation" | "mid_research" | "grounding_verify" | "summary" | "synthesis" | "action_plan"
|
|
265
269
|
/**
|
|
266
270
|
* Sprint stage emitted by sprint-runner — one of planning/implementation/
|
|
267
271
|
* verification/judgment. label distinguishes the stage. Used so the user
|
|
@@ -333,6 +337,84 @@ export interface CouncilInfoCard {
|
|
|
333
337
|
title: string;
|
|
334
338
|
sections: CouncilInfoCardSection[];
|
|
335
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Incremental council metadata for the context rail (P3). Emitted as one or more
|
|
342
|
+
* `council_meta` chunks — the leader/panel/researchMode/costAware fields come
|
|
343
|
+
* from the council entrypoint, the round budget/ceiling from inside runDebate
|
|
344
|
+
* (locals invisible to the entrypoint). The UI upsert-merges each patch into a
|
|
345
|
+
* single `councilMeta` object, so any subset of fields may be present.
|
|
346
|
+
*/
|
|
347
|
+
/**
|
|
348
|
+
* One debate round's lifecycle record for the round-grouped transcript (P5/P6).
|
|
349
|
+
* Emitted as `council_round` chunks: a `running` record at round start, then a
|
|
350
|
+
* `done` record (guaranteed on every loop exit) carrying the outcome. The UI
|
|
351
|
+
* upsert-merges by `round` (running → done overwrite).
|
|
352
|
+
*/
|
|
353
|
+
export interface CouncilRoundRecord {
|
|
354
|
+
round: number;
|
|
355
|
+
state: "running" | "done";
|
|
356
|
+
/** This round's focus, carried from the prior round's `nextRoundFocus`. */
|
|
357
|
+
topic?: string;
|
|
358
|
+
/** Role labels of the participants active this round. */
|
|
359
|
+
participants: string[];
|
|
360
|
+
/** Number of debate pairs exchanged this round. */
|
|
361
|
+
pairCount: number;
|
|
362
|
+
/** True when this round is beyond the leader's original planned budget. */
|
|
363
|
+
emergent: boolean;
|
|
364
|
+
/** Leader-evaluated criteria met / total (absent until the round is done). */
|
|
365
|
+
criteriaMet?: number;
|
|
366
|
+
criteriaTotal?: number;
|
|
367
|
+
/** Leader's one-sentence decision reason. */
|
|
368
|
+
leaderReason?: string;
|
|
369
|
+
/** What the leader / engine decided at the end of this round. */
|
|
370
|
+
leaderDecision?: "continue" | "stop" | "extend" | "aborted" | "circuit-break" | "eval-unavailable";
|
|
371
|
+
/** Topic the leader set for the NEXT round (drives the overview). */
|
|
372
|
+
nextRoundFocus?: string;
|
|
373
|
+
/**
|
|
374
|
+
* B5 — the leader's pre-round DIRECTIVE for this round (goal + criteria still
|
|
375
|
+
* unmet going in). Captured on the round record so it survives into the
|
|
376
|
+
* post-debate conclusion card, not only the ephemeral live directive bubble —
|
|
377
|
+
* otherwise a user who looks away during the debate never sees the leader
|
|
378
|
+
* conduct the round. Present only when the conductor is on + criteria pinned.
|
|
379
|
+
*/
|
|
380
|
+
directive?: string;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Incremental council metadata for the context rail (P3). Emitted as one or more
|
|
384
|
+
* `council_meta` chunks — the leader/panel/researchMode/costAware fields come
|
|
385
|
+
* from the council entrypoint, the round budget/ceiling from inside runDebate
|
|
386
|
+
* (locals invisible to the entrypoint). The UI upsert-merges each patch into a
|
|
387
|
+
* single `councilMeta` object, so any subset of fields may be present.
|
|
388
|
+
*/
|
|
389
|
+
export interface CouncilMetaPatch {
|
|
390
|
+
/** The debate topic / question under discussion (shown at the top of the rail). */
|
|
391
|
+
topic?: string;
|
|
392
|
+
/** Leader model id driving the debate. */
|
|
393
|
+
leader?: string;
|
|
394
|
+
/** Panel member role labels. */
|
|
395
|
+
panel?: string[];
|
|
396
|
+
/** Planned round budget resolved for this debate. */
|
|
397
|
+
roundBudget?: number;
|
|
398
|
+
/** Hard ceiling rounds may extend to (emergent rounds). */
|
|
399
|
+
roundCeiling?: number;
|
|
400
|
+
/** Research mode enabled for this debate. */
|
|
401
|
+
researchMode?: boolean;
|
|
402
|
+
/** Cost-aware budgeting active. */
|
|
403
|
+
costAware?: boolean;
|
|
404
|
+
/**
|
|
405
|
+
* The pinned outcome criteria the debate is graded against (the user-owned
|
|
406
|
+
* `ClarifiedSpec.successCriteria`). Emitted once after clarify so the rail can
|
|
407
|
+
* show the OUTCOME the debate is chasing — fixes "criteria met là gì tôi không
|
|
408
|
+
* biết". Stable for the whole debate.
|
|
409
|
+
*/
|
|
410
|
+
successCriteria?: string[];
|
|
411
|
+
/**
|
|
412
|
+
* Per-criterion met status, index-aligned to `successCriteria`. Upsert-merged
|
|
413
|
+
* and refreshed after each round's leader evaluation so the rail shows live
|
|
414
|
+
* ✓/○ against the pinned criteria. Length matches `successCriteria`.
|
|
415
|
+
*/
|
|
416
|
+
criteriaMet?: boolean[];
|
|
417
|
+
}
|
|
336
418
|
export interface CouncilMessage {
|
|
337
419
|
kind: CouncilMessageKind;
|
|
338
420
|
speaker: {
|
|
@@ -343,6 +425,7 @@ export interface CouncilMessage {
|
|
|
343
425
|
role: string;
|
|
344
426
|
};
|
|
345
427
|
round?: number;
|
|
428
|
+
phase?: "directive" | "verdict";
|
|
346
429
|
text: string;
|
|
347
430
|
toolCalls?: {
|
|
348
431
|
name: string;
|
|
@@ -352,7 +435,7 @@ export interface CouncilMessage {
|
|
|
352
435
|
runId?: string;
|
|
353
436
|
}
|
|
354
437
|
export interface StreamChunk {
|
|
355
|
-
type: "content" | "tool_calls" | "tool_result" | "tool_approval_request" | "council_question" | "council_preflight" | "council_status" | "council_phase" | "council_message" | "council_info_card" | "done" | "error" | "reasoning" | "structured_response" | "product_status_card" | "experience_warning" | "experience_injected" | "push_notification" | "halt" | "task_list_update";
|
|
438
|
+
type: "content" | "tool_calls" | "tool_result" | "tool_approval_request" | "council_question" | "council_preflight" | "council_status" | "council_phase" | "council_message" | "council_info_card" | "council_meta" | "council_round" | "done" | "error" | "reasoning" | "structured_response" | "product_status_card" | "experience_warning" | "experience_injected" | "push_notification" | "halt" | "toast" | "task_list_update";
|
|
356
439
|
content?: string;
|
|
357
440
|
toolCalls?: ToolCall[];
|
|
358
441
|
toolCall?: ToolCall;
|
|
@@ -367,12 +450,21 @@ export interface StreamChunk {
|
|
|
367
450
|
councilPhase?: CouncilPhaseEvent;
|
|
368
451
|
councilMessage?: CouncilMessage;
|
|
369
452
|
councilInfoCard?: CouncilInfoCard;
|
|
453
|
+
councilMeta?: CouncilMetaPatch;
|
|
454
|
+
councilRound?: CouncilRoundRecord;
|
|
370
455
|
productStatusCard?: import("../product-loop/types.js").ProductStatusCardData;
|
|
371
456
|
/** Populated when type === "halt". Contains structured recovery options. */
|
|
372
457
|
haltChunk?: import("../product-loop/types.js").HaltChunk;
|
|
373
458
|
experienceWarning?: ExperienceWarningData;
|
|
374
459
|
experienceInjected?: ExperienceInjectedData;
|
|
375
460
|
taskListSnapshot?: TaskListSnapshot;
|
|
461
|
+
/**
|
|
462
|
+
* Populated when type === "toast". A transient, ephemeral notice (e.g.
|
|
463
|
+
* "initializing sub-session…") that the UI shows briefly then auto-dismisses
|
|
464
|
+
* — it is NOT appended to the persisted assistant message. `content` holds
|
|
465
|
+
* the text; `toastLevel` selects the style (defaults to "info").
|
|
466
|
+
*/
|
|
467
|
+
toastLevel?: "info" | "warn" | "error";
|
|
376
468
|
}
|
|
377
469
|
export type TaskListItemStatus = "pending" | "in_progress" | "completed";
|
|
378
470
|
export interface TaskListItem {
|
|
@@ -413,13 +505,28 @@ export interface ModelInfo {
|
|
|
413
505
|
multiAgent?: boolean;
|
|
414
506
|
supportsClientTools?: boolean;
|
|
415
507
|
supportsMaxOutputTokens?: boolean;
|
|
508
|
+
/**
|
|
509
|
+
* When set, the provider rejects any temperature other than this exact value
|
|
510
|
+
* (e.g. Moonshot/Kimi: "only 1 is allowed for this model"). Callers must send
|
|
511
|
+
* this value verbatim rather than their preferred temperature — see
|
|
512
|
+
* `resolveTemperature` in src/providers/capabilities.ts.
|
|
513
|
+
*/
|
|
514
|
+
fixedTemperature?: number;
|
|
416
515
|
defaultReasoningEffort?: ReasoningEffort;
|
|
417
516
|
supportsReasoningEffort?: boolean;
|
|
418
517
|
thinkingType?: "enabled" | "adaptive";
|
|
419
518
|
supportsVision?: boolean;
|
|
519
|
+
/** When false, excluded from getModelByTier / automatic compaction routing. Default: routable. */
|
|
520
|
+
tierRouting?: boolean;
|
|
521
|
+
/** Extra tiers this model may satisfy in getModelByTier (primary tier remains `tier`). */
|
|
522
|
+
routingTiers?: ModelTier[];
|
|
523
|
+
roles?: string[];
|
|
524
|
+
/** Part E — model has native online web research (its own web_search/browsing). */
|
|
525
|
+
nativeWebResearch?: boolean;
|
|
420
526
|
}
|
|
421
527
|
export type AgentMode = "agent" | "plan" | "ask";
|
|
422
528
|
export type SessionStatus = "active" | "completed" | "archived" | "abandoned";
|
|
529
|
+
export type SessionKind = "conversation" | "rotation" | "subagent";
|
|
423
530
|
export type UsageSource = "message" | "title" | "task" | "delegation" | "council" | "other";
|
|
424
531
|
export interface WorkspaceInfo {
|
|
425
532
|
id: string;
|
|
@@ -441,6 +548,14 @@ export interface SessionInfo {
|
|
|
441
548
|
createdAt: Date;
|
|
442
549
|
updatedAt: Date;
|
|
443
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* One row in the `/sessions` resume picker: a whole conversation tree collapsed
|
|
553
|
+
* to a single entry. `id`/`title`/`createdAt` describe the tree root; `resumeId`
|
|
554
|
+
* is the latest leaf to relaunch; `model`/`updatedAt`/`status` describe that leaf.
|
|
555
|
+
*/
|
|
556
|
+
export interface ResumeEntry extends SessionInfo {
|
|
557
|
+
resumeId: string;
|
|
558
|
+
}
|
|
444
559
|
export interface UsageEvent {
|
|
445
560
|
id: number;
|
|
446
561
|
sessionId: string;
|
package/dist/src/ui/app.js
CHANGED
|
Binary file
|
|
@@ -49,7 +49,7 @@ export function ProductStatusCard({ data, theme: t }) {
|
|
|
49
49
|
const costSpark = data.costHistory?.length
|
|
50
50
|
? sparkline(data.costHistory.map((h) => (data.costCap > 0 ? h.cumulativeUsd / data.costCap : 0)))
|
|
51
51
|
: "";
|
|
52
|
-
return (_jsx(Semantic, { id: "ideal-status", role: "region", name: "Ideal status", children: _jsxs("box", { flexDirection: "column", paddingLeft: 2, paddingTop: 0, flexShrink: 0, children: [_jsx("box", { children: _jsx("text", { fg: t.accent, children: `▶ Product Loop · ${data.currentStage}` }) }), _jsx(Semantic, { id: `ideal-phase-sprint`, role: "listitem", name: "Sprint", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Sprint: " }), _jsx("text", { fg: t.text, children: `${data.sprintN}/${data.totalSprints} ` }), _jsx("text", { fg: t.accent, children: bar(sprintPct) }), _jsx("text", { fg: t.textDim, children: ` ${sprintPct.toFixed(0)}%` })] }) }), _jsx(Semantic, { id: `ideal-phase-cost`, role: "listitem", name: "Cost", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Cost: " }), _jsx("text", { fg: t.text, children: `$${data.costSpent.toFixed(2)}/$${data.costCap.toFixed(2)} ` }), _jsx("text", { fg: costColor, children: bar(costPct) }), _jsx("text", { fg: t.textDim, children: ` ${costPct.toFixed(0)}%` })] }) }), costSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Burn: " }), _jsx("text", { fg: costColor, children: costSpark }), _jsx("text", { fg: t.textDim, children: `
|
|
52
|
+
return (_jsx(Semantic, { id: "ideal-status", role: "region", name: "Ideal status", children: _jsxs("box", { flexDirection: "column", paddingLeft: 2, paddingTop: 0, flexShrink: 0, children: [_jsx("box", { children: _jsx("text", { fg: t.accent, children: `▶ Product Loop · ${data.currentStage}` }) }), _jsx(Semantic, { id: `ideal-phase-sprint`, role: "listitem", name: "Sprint", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Sprint: " }), _jsx("text", { fg: t.text, children: `${data.sprintN}/${data.totalSprints} ` }), _jsx("text", { fg: t.accent, children: bar(sprintPct) }), _jsx("text", { fg: t.textDim, children: ` ${sprintPct.toFixed(0)}%` })] }) }), _jsx(Semantic, { id: `ideal-phase-cost`, role: "listitem", name: "Cost", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Cost: " }), _jsx("text", { fg: t.text, children: `$${data.costSpent.toFixed(2)}/$${data.costCap.toFixed(2)} ` }), _jsx("text", { fg: costColor, children: bar(costPct) }), _jsx("text", { fg: t.textDim, children: ` ${costPct.toFixed(0)}%` })] }) }), costSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Burn: " }), _jsx("text", { fg: costColor, children: costSpark }), _jsx("text", { fg: t.textDim, children: ` spend per sprint` })] })), _jsx(Semantic, { id: `ideal-phase-criteria`, role: "listitem", name: "Criteria", children: _jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Criteria: " }), _jsx("text", { fg: t.planOptionCheck, children: `✓ ${data.criteriaMet}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.accent, children: `◐ ${data.criteriaPartial}` }), _jsx("text", { fg: t.text, children: " " }), _jsx("text", { fg: t.diffRemovedFg, children: `✗ ${data.criteriaUnmet}` }), _jsx("text", { fg: t.textDim, children: ` (of ${totalCriteria})` })] }) }), criteriaSpark && (_jsxs("box", { children: [_jsx("text", { fg: t.textMuted, children: "Trend: " }), _jsx("text", { fg: t.planOptionCheck, children: criteriaSpark }), _jsx("text", { fg: t.textDim, children: ` criteria met per sprint` })] }))] }) }));
|
|
53
53
|
}
|
|
54
54
|
export default ProductStatusCard;
|
|
55
55
|
//# sourceMappingURL=product-status-card.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-time guard for council message bodies.
|
|
3
|
+
*
|
|
4
|
+
* Root cause it defends against (live-diagnosed 2026-07-08, run mrbj8v6w81a3):
|
|
5
|
+
* a single round-1 debate turn whose body contained a very long whitespace-free
|
|
6
|
+
* run (an import graph / path list / blob a Flash-tier model dumped over a
|
|
7
|
+
* 1286-file repo). `CouncilMessageBubble` hands the raw body to a single
|
|
8
|
+
* OpenTUI `<text>` node with NO length or line-length bound. OpenTUI's word-wrap
|
|
9
|
+
* on such a mega-line pegs the main thread at 100% CPU — and because render and
|
|
10
|
+
* the product-loop share one JS thread, the entire `/ideal` run hard-freezes
|
|
11
|
+
* (render + input + debate logic all starve). Every muonroi-owned text function
|
|
12
|
+
* on the path (`truncateCodeBlocks`, `renderMarkdown`, `parseInline`,
|
|
13
|
+
* `tokenize`) was benchmarked fast on 80–130KB adversarial input, so the block
|
|
14
|
+
* lives in the terminal's layout of an unbounded body.
|
|
15
|
+
*
|
|
16
|
+
* This function bounds BOTH failure axes before the body reaches `<text>`:
|
|
17
|
+
* 1. total length — cap at `maxChars`, append a muted pointer to /export.
|
|
18
|
+
* 2. line length — hard-break any whitespace-free run longer than the
|
|
19
|
+
* terminal width so the wrapper always has a break opportunity (turns a
|
|
20
|
+
* pathological O(n²) single-line wrap into linear per-segment wrapping).
|
|
21
|
+
*
|
|
22
|
+
* Pure + side-effect free — safe to unit-test without a terminal.
|
|
23
|
+
*/
|
|
24
|
+
/** Default ceiling on a rendered bubble body. Well above any real prose turn
|
|
25
|
+
* (~2–4KB) but far below the 100KB+ blobs that trigger the layout hang. */
|
|
26
|
+
export declare const MAX_BUBBLE_BODY_CHARS = 12000;
|
|
27
|
+
export declare function capBubbleBody(text: string, terminalCols: number, maxChars?: number): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render-time guard for council message bodies.
|
|
3
|
+
*
|
|
4
|
+
* Root cause it defends against (live-diagnosed 2026-07-08, run mrbj8v6w81a3):
|
|
5
|
+
* a single round-1 debate turn whose body contained a very long whitespace-free
|
|
6
|
+
* run (an import graph / path list / blob a Flash-tier model dumped over a
|
|
7
|
+
* 1286-file repo). `CouncilMessageBubble` hands the raw body to a single
|
|
8
|
+
* OpenTUI `<text>` node with NO length or line-length bound. OpenTUI's word-wrap
|
|
9
|
+
* on such a mega-line pegs the main thread at 100% CPU — and because render and
|
|
10
|
+
* the product-loop share one JS thread, the entire `/ideal` run hard-freezes
|
|
11
|
+
* (render + input + debate logic all starve). Every muonroi-owned text function
|
|
12
|
+
* on the path (`truncateCodeBlocks`, `renderMarkdown`, `parseInline`,
|
|
13
|
+
* `tokenize`) was benchmarked fast on 80–130KB adversarial input, so the block
|
|
14
|
+
* lives in the terminal's layout of an unbounded body.
|
|
15
|
+
*
|
|
16
|
+
* This function bounds BOTH failure axes before the body reaches `<text>`:
|
|
17
|
+
* 1. total length — cap at `maxChars`, append a muted pointer to /export.
|
|
18
|
+
* 2. line length — hard-break any whitespace-free run longer than the
|
|
19
|
+
* terminal width so the wrapper always has a break opportunity (turns a
|
|
20
|
+
* pathological O(n²) single-line wrap into linear per-segment wrapping).
|
|
21
|
+
*
|
|
22
|
+
* Pure + side-effect free — safe to unit-test without a terminal.
|
|
23
|
+
*/
|
|
24
|
+
/** Default ceiling on a rendered bubble body. Well above any real prose turn
|
|
25
|
+
* (~2–4KB) but far below the 100KB+ blobs that trigger the layout hang. */
|
|
26
|
+
export const MAX_BUBBLE_BODY_CHARS = 12_000;
|
|
27
|
+
/** Lower bound on the wrap column, so a bogus `terminalCols` (0/undefined on a
|
|
28
|
+
* detached harness) never produces a degenerate 1-char break cadence. */
|
|
29
|
+
const MIN_WRAP_COLS = 20;
|
|
30
|
+
export function capBubbleBody(text, terminalCols, maxChars = MAX_BUBBLE_BODY_CHARS) {
|
|
31
|
+
// 1) Total-length cap first — bounds the work the hard-wrap below has to do.
|
|
32
|
+
let body = text;
|
|
33
|
+
let truncated = false;
|
|
34
|
+
if (body.length > maxChars) {
|
|
35
|
+
body = body.slice(0, maxChars);
|
|
36
|
+
truncated = true;
|
|
37
|
+
}
|
|
38
|
+
// 2) Hard-break whitespace-free runs longer than the wrap column. The lookahead
|
|
39
|
+
// `(?=\S)` avoids inserting a break right before an existing whitespace/EOL,
|
|
40
|
+
// so normal prose (which breaks on spaces) is left untouched. Linear: each
|
|
41
|
+
// char is visited once by the non-overlapping global match.
|
|
42
|
+
const cols = Math.max(MIN_WRAP_COLS, Number.isFinite(terminalCols) && terminalCols > 0 ? terminalCols : 80);
|
|
43
|
+
const runBreaker = new RegExp(`(\\S{${cols}})(?=\\S)`, "g");
|
|
44
|
+
body = body.replace(runBreaker, "$1\n");
|
|
45
|
+
if (truncated) {
|
|
46
|
+
body += "\n… truncated — see /export for the full turn";
|
|
47
|
+
}
|
|
48
|
+
return body;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=bubble-body-guard.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/** A single label/value row shown in the rail's metadata block. */
|
|
3
|
+
export interface ContextRailRow {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ContextRailProps {
|
|
8
|
+
/** Fixed column width of the rail (app.tsx decides based on terminal size). */
|
|
9
|
+
width: number;
|
|
10
|
+
/** Metadata rows (session id, mode, leader, panel, budget, …). */
|
|
11
|
+
rows: ContextRailRow[];
|
|
12
|
+
/**
|
|
13
|
+
* Rich content rendered below the metadata rows — info cards (Clarified Spec,
|
|
14
|
+
* Discussion Brief, Debate Plan), phase timeline, product-status. Wired by
|
|
15
|
+
* later phases; absent in the skeleton.
|
|
16
|
+
*/
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Right-hand context rail (MUONROI_CONTEXT_RAIL). Moves metadata-heavy chrome
|
|
21
|
+
* (session/leader/panel/budget + info cards) out of the scrolling transcript so
|
|
22
|
+
* the live debate stays on screen. Always renders the GLOBAL view — it never
|
|
23
|
+
* re-scopes to a selected round (that hides the overview and recreates the
|
|
24
|
+
* "empty rounds" problem). app.tsx gates visibility on width ≥ 100 and Ctrl+B.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ContextRail({ width, rows, children }: ContextRailProps): ReactNode;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { Semantic } from "@muonroi/agent-harness-opentui";
|
|
3
|
+
import { dark } from "../theme.js";
|
|
4
|
+
/**
|
|
5
|
+
* Right-hand context rail (MUONROI_CONTEXT_RAIL). Moves metadata-heavy chrome
|
|
6
|
+
* (session/leader/panel/budget + info cards) out of the scrolling transcript so
|
|
7
|
+
* the live debate stays on screen. Always renders the GLOBAL view — it never
|
|
8
|
+
* re-scopes to a selected round (that hides the overview and recreates the
|
|
9
|
+
* "empty rounds" problem). app.tsx gates visibility on width ≥ 100 and Ctrl+B.
|
|
10
|
+
*/
|
|
11
|
+
export function ContextRail({ width, rows, children }) {
|
|
12
|
+
return (_jsx(Semantic, { id: "context-rail", role: "region", name: "Context",
|
|
13
|
+
// labels/values exposed for harness assertions (rail rows are plain <text>,
|
|
14
|
+
// not semantic nodes, so they don't otherwise show in the snapshot tree).
|
|
15
|
+
props: {
|
|
16
|
+
rowCount: rows.length,
|
|
17
|
+
labels: rows.map((r) => r.label).join(","),
|
|
18
|
+
values: rows.map((r) => r.value).join(" | "),
|
|
19
|
+
}, children: _jsxs("box", { flexShrink: 0, width: width, flexDirection: "column", border: ["left"], borderColor: dark.councilLeaderBorder, paddingLeft: 2, paddingRight: 1, gap: 1, children: [_jsx("text", { fg: dark.textMuted, attributes: 1, children: "Context" }), rows.length > 0 && (_jsx("box", { flexDirection: "column", flexShrink: 0, children: rows.map((r, idx) => (
|
|
20
|
+
// Index key: list-style rows (e.g. per-criterion outcome lines) may
|
|
21
|
+
// share an empty or duplicate label, which would collide on a
|
|
22
|
+
// label-keyed map. An empty label renders value-only (no "· : ").
|
|
23
|
+
//
|
|
24
|
+
// Label + value MUST live in one <text> node (via an inline <span>),
|
|
25
|
+
// not two sibling <text> in a flex-row: when a long value wraps, the
|
|
26
|
+
// terminal trims the trailing separator of the preceding text node,
|
|
27
|
+
// so "Topic: rest…" rendered as "Topicrest…" and "Progress: Round…"
|
|
28
|
+
// lost its space. A single text flow keeps the "Label: " prefix.
|
|
29
|
+
_jsx("box", { flexDirection: "column", children: _jsxs("text", { children: [r.label ? _jsx("span", { style: { fg: dark.textMuted }, children: `${r.label}: ` }) : null, r.value] }) }, idx))) })), children ? (
|
|
30
|
+
// biome-ignore lint/suspicious/noExplicitAny: OpenTUI stickyStart typing
|
|
31
|
+
_jsx("scrollbox", { flexGrow: 1, stickyScroll: false, stickyStart: "top", children: children })) : null] }) }));
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=context-rail.js.map
|