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
package/LICENSE
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Copyright (c) 2026 muonroi
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { type Predicate } from "./predicate.js";
|
|
2
|
-
import type { LiveEvent, LiveFrame, UINode } from "./protocol.js";
|
|
2
|
+
import type { LiveEvent, LiveFrame, UINode, VisualFrame } from "./protocol.js";
|
|
3
|
+
import { type VisualQualityReport } from "./visual-quality.js";
|
|
4
|
+
/** A single decoded cell from the rendered grid (returned by `visual_cell`). */
|
|
5
|
+
export type VisualCell = {
|
|
6
|
+
char: string;
|
|
7
|
+
fg: string;
|
|
8
|
+
bg: string;
|
|
9
|
+
attrs: number;
|
|
10
|
+
};
|
|
3
11
|
type WaitConditionIdle = {
|
|
4
12
|
idle: true;
|
|
5
13
|
};
|
|
@@ -31,6 +39,9 @@ type DriverDeps = {
|
|
|
31
39
|
type Ingested = {
|
|
32
40
|
kind: "frame";
|
|
33
41
|
frame: LiveFrame;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "visual";
|
|
44
|
+
frame: VisualFrame;
|
|
34
45
|
} | {
|
|
35
46
|
kind: "idle";
|
|
36
47
|
} | {
|
|
@@ -69,6 +80,21 @@ export type Driver = {
|
|
|
69
80
|
*/
|
|
70
81
|
events: (filter?: EventFilter) => AsyncIterable<LiveEvent>;
|
|
71
82
|
render_text: () => string;
|
|
83
|
+
/** Latest VisualFrame — the ACTUAL rendered cell grid (colors + attributes),
|
|
84
|
+
* or null if the TUI has not emitted one (renderer not attached). */
|
|
85
|
+
snapshot_visual: () => VisualFrame | null;
|
|
86
|
+
/** Render the visual grid as plain text (what a human reads on screen) —
|
|
87
|
+
* faithful to the rendered characters, unlike render_text (semantic tree). */
|
|
88
|
+
render_visual: () => string;
|
|
89
|
+
/** Decode the cell at (row, col) — char + fg/bg hex + attribute bits — from
|
|
90
|
+
* the latest VisualFrame, accounting for wide (2-col) glyphs. Null if out of
|
|
91
|
+
* range or no visual frame yet. */
|
|
92
|
+
visual_cell: (row: number, col: number) => VisualCell | null;
|
|
93
|
+
/** Programmatic visual-quality heuristics over the latest VisualFrame:
|
|
94
|
+
* near-empty-row ratio, blank-row runs, whitespace density, and mojibake —
|
|
95
|
+
* the exact "messy render" signals the semantic tree is blind to. Null if no
|
|
96
|
+
* visual frame yet. */
|
|
97
|
+
visual_quality: () => VisualQualityReport | null;
|
|
72
98
|
_ingest: (m: Ingested) => void;
|
|
73
99
|
/** Called when the TUI exits. Cleanly terminates all active `events()` iterables. */
|
|
74
100
|
_closeAllSubscribers: () => void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { evaluatePredicate, predicateSchema } from "./predicate.js";
|
|
2
2
|
import { matchSelector } from "./selector.js";
|
|
3
|
+
import { computeVisualQuality } from "./visual-quality.js";
|
|
3
4
|
// ---------------------------------------------------------------------------
|
|
4
5
|
// Constants
|
|
5
6
|
// ---------------------------------------------------------------------------
|
|
@@ -12,6 +13,7 @@ const PER_SUBSCRIBER_QUEUE_CAP = 256;
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
export function createDriver(deps) {
|
|
14
15
|
let latestFrame = null;
|
|
16
|
+
let latestVisualFrame = null;
|
|
15
17
|
let lastIdleAt = -1;
|
|
16
18
|
const eventBuffer = [];
|
|
17
19
|
const waiters = new Set();
|
|
@@ -276,10 +278,54 @@ export function createDriver(deps) {
|
|
|
276
278
|
return "(no frame)";
|
|
277
279
|
return latestFrame.nodes.map((n) => renderNode(n, 0)).join("\n");
|
|
278
280
|
},
|
|
281
|
+
snapshot_visual() {
|
|
282
|
+
return latestVisualFrame;
|
|
283
|
+
},
|
|
284
|
+
render_visual() {
|
|
285
|
+
if (!latestVisualFrame)
|
|
286
|
+
return "(no visual frame)";
|
|
287
|
+
return latestVisualFrame.lines
|
|
288
|
+
.map((ln) => ln.spans
|
|
289
|
+
.map((s) => s.text)
|
|
290
|
+
.join("")
|
|
291
|
+
.replace(/\s+$/, ""))
|
|
292
|
+
.join("\n");
|
|
293
|
+
},
|
|
294
|
+
visual_cell(row, col) {
|
|
295
|
+
const frame = latestVisualFrame;
|
|
296
|
+
if (!frame)
|
|
297
|
+
return null;
|
|
298
|
+
const line = frame.lines[row];
|
|
299
|
+
if (!line)
|
|
300
|
+
return null;
|
|
301
|
+
// Walk spans accumulating display columns; a wide glyph spans 2 columns
|
|
302
|
+
// but its span.width already reflects that, so index within the run by
|
|
303
|
+
// string position while tracking the column cursor.
|
|
304
|
+
let colCursor = 0;
|
|
305
|
+
for (const span of line.spans) {
|
|
306
|
+
const chars = [...span.text];
|
|
307
|
+
for (const ch of chars) {
|
|
308
|
+
// A char occupies span.width / chars.length columns on average; for
|
|
309
|
+
// the common width===text-length case this is 1. Round to stay integral.
|
|
310
|
+
const chCols = Math.max(1, Math.round(span.width / Math.max(1, chars.length)));
|
|
311
|
+
if (col >= colCursor && col < colCursor + chCols) {
|
|
312
|
+
return { char: ch, fg: span.fg, bg: span.bg, attrs: span.attrs };
|
|
313
|
+
}
|
|
314
|
+
colCursor += chCols;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
},
|
|
319
|
+
visual_quality() {
|
|
320
|
+
return latestVisualFrame ? computeVisualQuality(latestVisualFrame) : null;
|
|
321
|
+
},
|
|
279
322
|
_ingest(m) {
|
|
280
323
|
if (m.kind === "frame") {
|
|
281
324
|
latestFrame = m.frame;
|
|
282
325
|
}
|
|
326
|
+
else if (m.kind === "visual") {
|
|
327
|
+
latestVisualFrame = m.frame;
|
|
328
|
+
}
|
|
283
329
|
else if (m.kind === "idle") {
|
|
284
330
|
lastIdleAt = Date.now();
|
|
285
331
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* event-tee.ts — optional JSONL sink for harness LiveEvents.
|
|
3
|
+
*
|
|
4
|
+
* Why: the MCP wake mechanism that re-invokes an external agent is a background
|
|
5
|
+
* task (e.g. a milestone watcher), which is a SEPARATE process from the MCP
|
|
6
|
+
* server. That watcher can only read files — it cannot reach the in-process
|
|
7
|
+
* driver that holds the real UI. So a generic, reusable milestone watcher needs
|
|
8
|
+
* the harness to persist events to a file it can tail.
|
|
9
|
+
*
|
|
10
|
+
* The DB only records debate-END rows (synthesis/debate_complete), so a
|
|
11
|
+
* DB-poll watcher is blind to mid-flight modal pauses (askcard-open) that never
|
|
12
|
+
* write a DB row. Teeing every LiveEvent to a JSONL file closes that gap for
|
|
13
|
+
* ANY event kind.
|
|
14
|
+
*
|
|
15
|
+
* Ephemeral events (toast, disconnect, retry, ee-*) flash and vanish before an
|
|
16
|
+
* agent can wake + render, so for those kinds — and ONLY those — we attach a
|
|
17
|
+
* plain-text visual snapshot captured at emit time, so the watcher's wake
|
|
18
|
+
* payload carries the exact frame. Persistent states (askcard, post-debate
|
|
19
|
+
* card) stay put, so the agent renders them fresh on demand; embedding a stale
|
|
20
|
+
* snapshot for those would be worse, not better.
|
|
21
|
+
*
|
|
22
|
+
* Gated entirely behind MUONROI_HARNESS_EVENT_LOG — unset means zero behavior
|
|
23
|
+
* change (clean checkouts are byte-identical to before this file existed).
|
|
24
|
+
*/
|
|
25
|
+
import type { LiveEvent } from "./protocol.js";
|
|
26
|
+
/**
|
|
27
|
+
* Event kinds that flash and disappear before an agent can wake + render.
|
|
28
|
+
* Only these carry an at-emit visual snapshot in the teed line.
|
|
29
|
+
*/
|
|
30
|
+
export declare const EPHEMERAL_KINDS: ReadonlySet<string>;
|
|
31
|
+
/** One teed JSONL record. */
|
|
32
|
+
export interface TeedEventLine {
|
|
33
|
+
ts: number;
|
|
34
|
+
kind: string;
|
|
35
|
+
event: LiveEvent;
|
|
36
|
+
/** Present only for EPHEMERAL_KINDS — plain-text visual frame at emit time. */
|
|
37
|
+
visualText?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build an event-tee sink. Returns null when MUONROI_HARNESS_EVENT_LOG is unset
|
|
41
|
+
* or blank (no-op path — caller skips it entirely).
|
|
42
|
+
*
|
|
43
|
+
* @param getVisualText - lazily renders the current visual frame to plain text
|
|
44
|
+
* (driver.render_visual). Called ONLY for ephemeral kinds, so persistent
|
|
45
|
+
* events pay nothing.
|
|
46
|
+
* @param envValue - value of MUONROI_HARNESS_EVENT_LOG (injectable for tests).
|
|
47
|
+
*/
|
|
48
|
+
export declare function createEventTee(getVisualText: () => string | null, envValue?: string): ((event: LiveEvent) => void) | null;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* event-tee.ts — optional JSONL sink for harness LiveEvents.
|
|
3
|
+
*
|
|
4
|
+
* Why: the MCP wake mechanism that re-invokes an external agent is a background
|
|
5
|
+
* task (e.g. a milestone watcher), which is a SEPARATE process from the MCP
|
|
6
|
+
* server. That watcher can only read files — it cannot reach the in-process
|
|
7
|
+
* driver that holds the real UI. So a generic, reusable milestone watcher needs
|
|
8
|
+
* the harness to persist events to a file it can tail.
|
|
9
|
+
*
|
|
10
|
+
* The DB only records debate-END rows (synthesis/debate_complete), so a
|
|
11
|
+
* DB-poll watcher is blind to mid-flight modal pauses (askcard-open) that never
|
|
12
|
+
* write a DB row. Teeing every LiveEvent to a JSONL file closes that gap for
|
|
13
|
+
* ANY event kind.
|
|
14
|
+
*
|
|
15
|
+
* Ephemeral events (toast, disconnect, retry, ee-*) flash and vanish before an
|
|
16
|
+
* agent can wake + render, so for those kinds — and ONLY those — we attach a
|
|
17
|
+
* plain-text visual snapshot captured at emit time, so the watcher's wake
|
|
18
|
+
* payload carries the exact frame. Persistent states (askcard, post-debate
|
|
19
|
+
* card) stay put, so the agent renders them fresh on demand; embedding a stale
|
|
20
|
+
* snapshot for those would be worse, not better.
|
|
21
|
+
*
|
|
22
|
+
* Gated entirely behind MUONROI_HARNESS_EVENT_LOG — unset means zero behavior
|
|
23
|
+
* change (clean checkouts are byte-identical to before this file existed).
|
|
24
|
+
*/
|
|
25
|
+
import { appendFileSync } from "node:fs";
|
|
26
|
+
/**
|
|
27
|
+
* Event kinds that flash and disappear before an agent can wake + render.
|
|
28
|
+
* Only these carry an at-emit visual snapshot in the teed line.
|
|
29
|
+
*/
|
|
30
|
+
export const EPHEMERAL_KINDS = new Set([
|
|
31
|
+
"toast",
|
|
32
|
+
"disconnect",
|
|
33
|
+
"stream-retry",
|
|
34
|
+
"ee-timeout",
|
|
35
|
+
"ee-error",
|
|
36
|
+
"grounding-flag",
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Build an event-tee sink. Returns null when MUONROI_HARNESS_EVENT_LOG is unset
|
|
40
|
+
* or blank (no-op path — caller skips it entirely).
|
|
41
|
+
*
|
|
42
|
+
* @param getVisualText - lazily renders the current visual frame to plain text
|
|
43
|
+
* (driver.render_visual). Called ONLY for ephemeral kinds, so persistent
|
|
44
|
+
* events pay nothing.
|
|
45
|
+
* @param envValue - value of MUONROI_HARNESS_EVENT_LOG (injectable for tests).
|
|
46
|
+
*/
|
|
47
|
+
export function createEventTee(getVisualText, envValue) {
|
|
48
|
+
const path = (envValue ?? "").trim();
|
|
49
|
+
if (!path)
|
|
50
|
+
return null;
|
|
51
|
+
return (event) => {
|
|
52
|
+
// The idle sentinel arrives as { t: "idle" } — never here. Guard anyway so
|
|
53
|
+
// a malformed event can't crash the ingest loop.
|
|
54
|
+
const kind = event.kind;
|
|
55
|
+
if (typeof kind !== "string")
|
|
56
|
+
return;
|
|
57
|
+
const line = { ts: Date.now(), kind, event };
|
|
58
|
+
if (EPHEMERAL_KINDS.has(kind)) {
|
|
59
|
+
try {
|
|
60
|
+
const visual = getVisualText();
|
|
61
|
+
if (visual)
|
|
62
|
+
line.visualText = visual;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
// A visual-render failure must not drop the event record itself.
|
|
66
|
+
console.error(`[event-tee] visual snapshot failed for kind=${kind}: ${err?.message}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
appendFileSync(path, `${JSON.stringify(line)}\n`);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
console.error(`[event-tee] append failed (path=${path}, kind=${kind}): ${err?.message}`);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=event-tee.js.map
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
15
|
import { type Driver } from "./driver.js";
|
|
16
|
+
import type { LiveEvent } from "./protocol.js";
|
|
16
17
|
/**
|
|
17
18
|
* The result returned by a HarnessSpawn implementation.
|
|
18
19
|
* Both the POSIX fd-3/4 and Windows named-pipe transports satisfy this shape.
|
|
@@ -95,6 +96,16 @@ export declare function registerAsyncTools(server: McpServer, getDriver: () => D
|
|
|
95
96
|
export declare function createMcpHarnessServer({ spawn }: {
|
|
96
97
|
spawn: HarnessSpawn;
|
|
97
98
|
}): McpServer;
|
|
99
|
+
/**
|
|
100
|
+
* Build the onLine sidechannel handler: parse each JSON line, ingest frames /
|
|
101
|
+
* visuals / idle / events into the driver, and tee events to the optional JSONL
|
|
102
|
+
* sink. Extracted (and exported) so the frame/event/tee wiring is unit-testable
|
|
103
|
+
* without a live TUI or an MCP protocol handshake.
|
|
104
|
+
*
|
|
105
|
+
* @param driver the driver to ingest into (only _ingest is used).
|
|
106
|
+
* @param eventTee optional sink from createEventTee (null → no tee).
|
|
107
|
+
*/
|
|
108
|
+
export declare function makeLineHandler(driver: Pick<Driver, "_ingest">, eventTee: ((event: LiveEvent) => void) | null): (line: string) => void;
|
|
98
109
|
/**
|
|
99
110
|
* Run the MCP harness driver over stdio with the OpenTUI spawn implementation
|
|
100
111
|
* injected by the consumer.
|
|
@@ -18,6 +18,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
18
18
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
import { createDriver } from "./driver.js";
|
|
21
|
+
import { createEventTee } from "./event-tee.js";
|
|
21
22
|
import { PROTOCOL_VERSION } from "./protocol.js";
|
|
22
23
|
const ARG_ALLOW = /^(--agent-[a-z-]+(=.*)?|--mock-llm(=.+)?|--profile=[a-zA-Z0-9_-]+)$/;
|
|
23
24
|
const ENV_KEY_RE = /^[A-Z_][A-Z0-9_]{0,63}$/;
|
|
@@ -133,7 +134,20 @@ export function validateMockLlmPath(value) {
|
|
|
133
134
|
const sep = process.platform === "win32" ? "\\" : "/";
|
|
134
135
|
return real === root || real.startsWith(root + sep);
|
|
135
136
|
}
|
|
136
|
-
const FEATURES = [
|
|
137
|
+
const FEATURES = [
|
|
138
|
+
"capabilities",
|
|
139
|
+
"snapshot",
|
|
140
|
+
"press",
|
|
141
|
+
"type",
|
|
142
|
+
"wait_for",
|
|
143
|
+
"query",
|
|
144
|
+
"expect",
|
|
145
|
+
"render_text",
|
|
146
|
+
"render_visual",
|
|
147
|
+
"snapshot_visual",
|
|
148
|
+
"cell",
|
|
149
|
+
"visual_quality",
|
|
150
|
+
];
|
|
137
151
|
export function buildCapabilitiesPayload() {
|
|
138
152
|
return {
|
|
139
153
|
protocol: PROTOCOL_VERSION,
|
|
@@ -203,6 +217,42 @@ export function registerReadTools(server, getDriver) {
|
|
|
203
217
|
return noDriver();
|
|
204
218
|
return { content: [{ type: "text", text: d.render_text() }] };
|
|
205
219
|
});
|
|
220
|
+
server.registerTool("tui.render_visual", {
|
|
221
|
+
description: "Render the ACTUAL rendered cell grid as plain text — the characters a human reads on screen. Unlike tui.render_text (semantic tree), this reflects the real render. Requires agent-mode with the renderer attached.",
|
|
222
|
+
inputSchema: {},
|
|
223
|
+
}, async () => {
|
|
224
|
+
const d = getDriver();
|
|
225
|
+
if (!d)
|
|
226
|
+
return noDriver();
|
|
227
|
+
return { content: [{ type: "text", text: d.render_visual() }] };
|
|
228
|
+
});
|
|
229
|
+
server.registerTool("tui.snapshot_visual", {
|
|
230
|
+
description: "Return the latest VisualFrame — the real rendered cell grid with per-cell char + fg/bg hex + attribute bits. null until the renderer emits one.",
|
|
231
|
+
inputSchema: {},
|
|
232
|
+
}, async () => {
|
|
233
|
+
const d = getDriver();
|
|
234
|
+
if (!d)
|
|
235
|
+
return noDriver();
|
|
236
|
+
return { content: [{ type: "text", text: JSON.stringify(d.snapshot_visual()) }] };
|
|
237
|
+
});
|
|
238
|
+
server.registerTool("tui.cell", {
|
|
239
|
+
description: "Decode the rendered cell at (row, col): char + fg/bg hex + attribute bits, from the latest VisualFrame. Use to assert the colors/formatting a human actually sees.",
|
|
240
|
+
inputSchema: { row: z.number().int().min(0), col: z.number().int().min(0) },
|
|
241
|
+
}, async ({ row, col }) => {
|
|
242
|
+
const d = getDriver();
|
|
243
|
+
if (!d)
|
|
244
|
+
return noDriver();
|
|
245
|
+
return { content: [{ type: "text", text: JSON.stringify(d.visual_cell(row, col)) }] };
|
|
246
|
+
});
|
|
247
|
+
server.registerTool("tui.visual_quality", {
|
|
248
|
+
description: "Heuristic visual-quality report over the rendered grid: near-empty-row ratio, blank-row runs, whitespace density, mojibake, a 0-100 score and issues[]. Catches 'messy render' the semantic tree cannot see.",
|
|
249
|
+
inputSchema: {},
|
|
250
|
+
}, async () => {
|
|
251
|
+
const d = getDriver();
|
|
252
|
+
if (!d)
|
|
253
|
+
return noDriver();
|
|
254
|
+
return { content: [{ type: "text", text: JSON.stringify(d.visual_quality()) }] };
|
|
255
|
+
});
|
|
206
256
|
}
|
|
207
257
|
export function registerActionTools(server, getDriver) {
|
|
208
258
|
const noDriver = () => ({
|
|
@@ -459,22 +509,13 @@ export function createMcpHarnessServer({ spawn }) {
|
|
|
459
509
|
sendKey: (k) => sendLine(JSON.stringify({ op: "press", key: k })),
|
|
460
510
|
sendType: (t) => sendLine(JSON.stringify({ op: "type", text: t })),
|
|
461
511
|
});
|
|
512
|
+
// Optional JSONL event sink for external milestone watchers (null unless
|
|
513
|
+
// MUONROI_HARNESS_EVENT_LOG is set). Ephemeral kinds carry an at-emit
|
|
514
|
+
// visual snapshot so flash events aren't lost before an agent wakes.
|
|
515
|
+
const eventTee = createEventTee(() => driver.render_visual(), process.env["MUONROI_HARNESS_EVENT_LOG"]);
|
|
462
516
|
// onLine already delivers complete newline-stripped lines — no extra
|
|
463
517
|
// splitting required.
|
|
464
|
-
const unsub = onLine((
|
|
465
|
-
try {
|
|
466
|
-
const msg = JSON.parse(line);
|
|
467
|
-
if (msg.mode === "live")
|
|
468
|
-
driver._ingest({ kind: "frame", frame: msg });
|
|
469
|
-
else if (msg.t === "idle")
|
|
470
|
-
driver._ingest({ kind: "idle" });
|
|
471
|
-
else if (msg.t === "event")
|
|
472
|
-
driver._ingest({ kind: "event", event: msg });
|
|
473
|
-
}
|
|
474
|
-
catch {
|
|
475
|
-
// ignore malformed lines
|
|
476
|
-
}
|
|
477
|
-
});
|
|
518
|
+
const unsub = onLine(makeLineHandler(driver, eventTee));
|
|
478
519
|
spawnResult.exited.then(() => {
|
|
479
520
|
unsub();
|
|
480
521
|
if (currentPid === proc.pid) {
|
|
@@ -491,6 +532,37 @@ export function createMcpHarnessServer({ spawn }) {
|
|
|
491
532
|
registerAsyncTools(server, () => currentDriver, { onStop });
|
|
492
533
|
return server;
|
|
493
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Build the onLine sidechannel handler: parse each JSON line, ingest frames /
|
|
537
|
+
* visuals / idle / events into the driver, and tee events to the optional JSONL
|
|
538
|
+
* sink. Extracted (and exported) so the frame/event/tee wiring is unit-testable
|
|
539
|
+
* without a live TUI or an MCP protocol handshake.
|
|
540
|
+
*
|
|
541
|
+
* @param driver the driver to ingest into (only _ingest is used).
|
|
542
|
+
* @param eventTee optional sink from createEventTee (null → no tee).
|
|
543
|
+
*/
|
|
544
|
+
export function makeLineHandler(driver, eventTee) {
|
|
545
|
+
return (line) => {
|
|
546
|
+
try {
|
|
547
|
+
const msg = JSON.parse(line);
|
|
548
|
+
if (msg.mode === "live")
|
|
549
|
+
driver._ingest({ kind: "frame", frame: msg });
|
|
550
|
+
else if (msg.mode === "visual")
|
|
551
|
+
driver._ingest({ kind: "visual", frame: msg });
|
|
552
|
+
else if (msg.t === "idle")
|
|
553
|
+
driver._ingest({ kind: "idle" });
|
|
554
|
+
else if (msg.t === "event") {
|
|
555
|
+
const event = msg;
|
|
556
|
+
driver._ingest({ kind: "event", event });
|
|
557
|
+
// Tee AFTER ingest so render_visual reflects the frame at this event.
|
|
558
|
+
eventTee?.(event);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
// ignore malformed lines
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
494
566
|
/**
|
|
495
567
|
* Run the MCP harness driver over stdio with the OpenTUI spawn implementation
|
|
496
568
|
* injected by the consumer.
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export declare const PROTOCOL_VERSION: "0.4.0";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Known accessibility-style roles for semantic blocks. Closed vocabulary —
|
|
4
|
+
* `Role` (below) additionally admits namespaced `x-*` custom roles so new UI
|
|
5
|
+
* surfaces can be introduced without a protocol version bump (additive-only).
|
|
6
|
+
*/
|
|
7
|
+
export type KnownRole = "dialog" | "textbox" | "listbox" | "listitem" | "button" | "checkbox" | "radio" | "radiogroup" | "tab" | "tablist" | "tree" | "treeitem" | "table" | "row" | "cell" | "progressbar" | "spinner" | "log" | "statusbar" | "menu" | "menuitem" | "toast" | "tooltip" | "region" | "editor" | "diff" | "gutter" | "panel";
|
|
8
|
+
/**
|
|
9
|
+
* A semantic role. Either a well-known {@link KnownRole} or a namespaced
|
|
10
|
+
* `x-<custom>` role. The `x-` prefix keeps custom roles greppable and prevents
|
|
11
|
+
* silent collisions with future well-known roles — additive versioning via the
|
|
12
|
+
* `tui.capabilities` handshake rather than a breaking protocol bump.
|
|
13
|
+
*/
|
|
14
|
+
export type Role = KnownRole | `x-${string}`;
|
|
3
15
|
export type UINode = {
|
|
4
16
|
id: string;
|
|
5
17
|
role: Role;
|
|
@@ -23,6 +35,58 @@ export type LiveFrame = {
|
|
|
23
35
|
modals?: string[];
|
|
24
36
|
nodes: UINode[];
|
|
25
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Text-attribute bit flags in {@link VisualSpan.attrs}. Mirrors the low byte of
|
|
40
|
+
* OpenTUI's `TextAttributes` (`ATTRIBUTE_BASE_MASK = 255`), so a consumer can
|
|
41
|
+
* decode `attrs & VisualAttr.BOLD` etc. without importing the renderer.
|
|
42
|
+
*/
|
|
43
|
+
export declare const VisualAttr: {
|
|
44
|
+
readonly BOLD: 1;
|
|
45
|
+
readonly DIM: 2;
|
|
46
|
+
readonly ITALIC: 4;
|
|
47
|
+
readonly UNDERLINE: 8;
|
|
48
|
+
readonly BLINK: 16;
|
|
49
|
+
readonly INVERSE: 32;
|
|
50
|
+
readonly HIDDEN: 64;
|
|
51
|
+
readonly STRIKETHROUGH: 128;
|
|
52
|
+
};
|
|
53
|
+
/** One coalesced run of identically-styled cells on a visual line. */
|
|
54
|
+
export type VisualSpan = {
|
|
55
|
+
/** The run's text (wide-char continuation cells omitted; `width` reflects columns). */
|
|
56
|
+
text: string;
|
|
57
|
+
/** Foreground color as "#rrggbb" (or "#rrggbbaa" when alpha < 255). */
|
|
58
|
+
fg: string;
|
|
59
|
+
/** Background color as "#rrggbb" (or "#rrggbbaa"). */
|
|
60
|
+
bg: string;
|
|
61
|
+
/** Text-attribute bitmask — decode with {@link VisualAttr}. */
|
|
62
|
+
attrs: number;
|
|
63
|
+
/** Display columns this run occupies (accounts for wide CJK/emoji). */
|
|
64
|
+
width: number;
|
|
65
|
+
};
|
|
66
|
+
/** One row of the rendered grid, as style-coalesced spans. */
|
|
67
|
+
export type VisualLine = {
|
|
68
|
+
spans: VisualSpan[];
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Ground-truth snapshot of the ACTUAL rendered terminal cell grid — the real
|
|
72
|
+
* characters, colors, and attributes OpenTUI painted, read directly from
|
|
73
|
+
* `CliRenderer.currentRenderBuffer.getSpanLines()`. Unlike {@link LiveFrame}
|
|
74
|
+
* (semantic structure), this is what a human SEES on screen. No OCR — the cell
|
|
75
|
+
* buffer is authoritative. Emitted on the same sidechannel as LiveFrame,
|
|
76
|
+
* deduped by content hash, and (to bound `getSpanLines` allocation) only
|
|
77
|
+
* captured when a semantic frame also changes.
|
|
78
|
+
*/
|
|
79
|
+
export type VisualFrame = {
|
|
80
|
+
mode: "visual";
|
|
81
|
+
version: typeof PROTOCOL_VERSION;
|
|
82
|
+
seq: number;
|
|
83
|
+
ts: number;
|
|
84
|
+
cols: number;
|
|
85
|
+
rows: number;
|
|
86
|
+
/** Cursor [col, row], or null when hidden/unknown. */
|
|
87
|
+
cursor: [number, number] | null;
|
|
88
|
+
lines: VisualLine[];
|
|
89
|
+
};
|
|
26
90
|
export type LiveEvent = {
|
|
27
91
|
t: "event";
|
|
28
92
|
kind: "stream.delta";
|
|
@@ -226,4 +290,4 @@ export type DesignSpec = {
|
|
|
226
290
|
notes?: string;
|
|
227
291
|
}>;
|
|
228
292
|
};
|
|
229
|
-
export type HarnessMessage = LiveFrame | LiveEvent;
|
|
293
|
+
export type HarnessMessage = LiveFrame | VisualFrame | LiveEvent;
|
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
export const PROTOCOL_VERSION = "0.4.0";
|
|
2
|
+
/**
|
|
3
|
+
* Text-attribute bit flags in {@link VisualSpan.attrs}. Mirrors the low byte of
|
|
4
|
+
* OpenTUI's `TextAttributes` (`ATTRIBUTE_BASE_MASK = 255`), so a consumer can
|
|
5
|
+
* decode `attrs & VisualAttr.BOLD` etc. without importing the renderer.
|
|
6
|
+
*/
|
|
7
|
+
export const VisualAttr = {
|
|
8
|
+
BOLD: 1,
|
|
9
|
+
DIM: 2,
|
|
10
|
+
ITALIC: 4,
|
|
11
|
+
UNDERLINE: 8,
|
|
12
|
+
BLINK: 16,
|
|
13
|
+
INVERSE: 32,
|
|
14
|
+
HIDDEN: 64,
|
|
15
|
+
STRIKETHROUGH: 128,
|
|
16
|
+
};
|
|
2
17
|
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* visual-quality.ts — programmatic visual-quality heuristics over a VisualFrame.
|
|
3
|
+
*
|
|
4
|
+
* P1 of Harness TUI v2. Given the ground-truth rendered cell grid, compute cheap
|
|
5
|
+
* ground-truth signals a human would call "messy" — WITHOUT a vision model:
|
|
6
|
+
* - blank / near-blank row ratios (the council "↳" + "· Skip" garbage)
|
|
7
|
+
* - long runs of consecutive blank rows (dead space)
|
|
8
|
+
* - whitespace density
|
|
9
|
+
* - mojibake (U+FFFD replacement chars + misdecoded-UTF8 clusters like `💡`)
|
|
10
|
+
*
|
|
11
|
+
* These are the exact defects the semantic tree (LiveFrame) is blind to — the
|
|
12
|
+
* 2217600e1f27 export had 12 near-empty rows + mojibake that no existing
|
|
13
|
+
* self-verify check could see. A composite `score` + `issues[]` lets self-QA
|
|
14
|
+
* fail a render regression automatically.
|
|
15
|
+
*
|
|
16
|
+
* Thresholds are conservative defaults; tune per surface. This is a heuristic,
|
|
17
|
+
* not a proof — a low score flags "look closer", it does not assert a bug.
|
|
18
|
+
*/
|
|
19
|
+
import type { VisualFrame } from "./protocol.js";
|
|
20
|
+
export interface VisualQualityThresholds {
|
|
21
|
+
/** Rows with <= this many non-space chars count as "near-empty". */
|
|
22
|
+
nearEmptyMaxChars: number;
|
|
23
|
+
/** Flag when the near-empty-row ratio exceeds this. */
|
|
24
|
+
nearEmptyRowPct: number;
|
|
25
|
+
/** Flag when consecutive blank rows exceed this run length. */
|
|
26
|
+
maxConsecutiveBlankRows: number;
|
|
27
|
+
/** Flag when any mojibake is detected at/above this count. */
|
|
28
|
+
mojibakeCount: number;
|
|
29
|
+
/** Flag when whitespace density exceeds this fraction. */
|
|
30
|
+
whitespacePct: number;
|
|
31
|
+
}
|
|
32
|
+
export declare const DEFAULT_VISUAL_QUALITY_THRESHOLDS: VisualQualityThresholds;
|
|
33
|
+
export interface VisualQualityReport {
|
|
34
|
+
rows: number;
|
|
35
|
+
cols: number;
|
|
36
|
+
/** Non-space characters across the whole grid. */
|
|
37
|
+
contentChars: number;
|
|
38
|
+
/** Rows that are entirely whitespace. */
|
|
39
|
+
blankRows: number;
|
|
40
|
+
/** Rows with 1..nearEmptyMaxChars non-space chars (skeleton noise). */
|
|
41
|
+
nearEmptyRows: number;
|
|
42
|
+
nearEmptyRowPct: number;
|
|
43
|
+
/** Longest run of consecutive fully-blank rows. */
|
|
44
|
+
maxConsecutiveBlankRows: number;
|
|
45
|
+
whitespacePct: number;
|
|
46
|
+
/** Count of mojibake signals (U+FFFD + misdecoded-UTF8 clusters). */
|
|
47
|
+
mojibakeCount: number;
|
|
48
|
+
/** Sample of offending text fragments (for diagnostics). */
|
|
49
|
+
mojibakeSamples: string[];
|
|
50
|
+
/** 0-100 composite; lower = messier. */
|
|
51
|
+
score: number;
|
|
52
|
+
/** Human-readable problems that tripped a threshold. */
|
|
53
|
+
issues: string[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Compute visual-quality signals for a rendered frame. Pure + deterministic.
|
|
57
|
+
*/
|
|
58
|
+
export declare function computeVisualQuality(frame: VisualFrame, thresholds?: VisualQualityThresholds): VisualQualityReport;
|