muonroi-cli 1.8.3 → 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 +21 -21
- package/README.md +133 -122
- 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 +30 -15
- 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 +254 -84
- 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/oauth-callback.js +2 -2
- package/dist/src/mcp/research-onboarding.js +8 -7
- package/dist/src/mcp/runtime.js +34 -2
- package/dist/src/mcp/setup-guide-text.d.ts +1 -1
- package/dist/src/mcp/setup-guide-text.js +77 -76
- 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 +8 -8
- 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 +159 -159
- 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 +26 -0
- package/dist/src/orchestrator/tool-engine.js +669 -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/layer2_5-ponytail.js +8 -8
- 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/done-gate.js +3 -3
- 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 +327 -116
- 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/progress-snapshot.js +4 -4
- 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 +82 -172
- 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/reporter/index.js +1 -1
- 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/bb-ecosystem-apply.js +47 -47
- package/dist/src/scaffold/bb-quality-gate.js +5 -5
- package/dist/src/scaffold/continuation-prompt.d.ts +11 -0
- package/dist/src/scaffold/continuation-prompt.js +86 -60
- package/dist/src/scaffold/init-new.js +453 -453
- 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 +22 -22
- 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/interaction-log.js +5 -5
- package/dist/src/storage/migrations.js +196 -126
- package/dist/src/storage/session-experience-store.js +4 -4
- package/dist/src/storage/sessions.d.ts +28 -10
- package/dist/src/storage/sessions.js +112 -55
- package/dist/src/storage/transcript-view.js +1 -1
- package/dist/src/storage/transcript.d.ts +51 -0
- package/dist/src/storage/transcript.js +383 -112
- package/dist/src/storage/usage.js +14 -14
- package/dist/src/storage/workspaces.js +12 -12
- 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-inspect.js +4 -4
- 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/clipboard-image.js +23 -23
- package/dist/src/utils/install-manager.js +14 -11
- 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/side-question.js +2 -2
- package/dist/src/utils/skills.js +3 -3
- 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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef } from "react";
|
|
3
|
+
import { Dialog } from "../primitives/index.js";
|
|
3
4
|
import { bottomAlignedModalTop } from "../utils/modal.js";
|
|
4
5
|
const TEXTAREA_KEYBINDINGS = [
|
|
5
6
|
{ name: "return", action: "submit" },
|
|
@@ -15,20 +16,20 @@ export function ConnectModal({ t, width, height, selectedIndex, channels, }) {
|
|
|
15
16
|
const panelHeight = Math.min(channels.length + 9, Math.floor(height * 0.5));
|
|
16
17
|
const top = bottomAlignedModalTop(height, panelHeight);
|
|
17
18
|
const overlayBg = "#000000cc";
|
|
18
|
-
return (_jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: Math.min(56, width - 6), height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Connect" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, paddingBottom: 1, children: _jsx("text", { fg: t.textMuted, children: "Choose a channel" }) }), _jsx("scrollbox", { ref: listRef, flexGrow: 1, minHeight: 0, children: channels.map((ch, idx) => (_jsx("box", { id: `connect-${ch.id}`, backgroundColor: idx === selectedIndex ? t.selectedBg : undefined, paddingLeft: 2, paddingRight: 2, children: _jsxs("box", { flexDirection: "row", justifyContent: "space-between", children: [_jsx("text", { fg: idx === selectedIndex ? t.selected : t.text, children: ch.label }), _jsx("text", { fg: t.textMuted, children: ch.description })] }) }, ch.id))) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: _jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "select · " }), _jsx("span", { style: { fg: t.primary }, children: "↑↓ " }), _jsx("span", { style: { fg: t.textMuted }, children: "navigate · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] }) })] }) }));
|
|
19
|
+
return (_jsx(Dialog, { id: "connect-modal", name: "Connect", children: _jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: Math.min(56, width - 6), height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Connect" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, paddingBottom: 1, children: _jsx("text", { fg: t.textMuted, children: "Choose a channel" }) }), _jsx("scrollbox", { ref: listRef, flexGrow: 1, minHeight: 0, children: channels.map((ch, idx) => (_jsx("box", { id: `connect-${ch.id}`, backgroundColor: idx === selectedIndex ? t.selectedBg : undefined, paddingLeft: 2, paddingRight: 2, children: _jsxs("box", { flexDirection: "row", justifyContent: "space-between", children: [_jsx("text", { fg: idx === selectedIndex ? t.selected : t.text, children: ch.label }), _jsx("text", { fg: t.textMuted, children: ch.description })] }) }, ch.id))) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: _jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "select · " }), _jsx("span", { style: { fg: t.primary }, children: "↑↓ " }), _jsx("span", { style: { fg: t.textMuted }, children: "navigate · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] }) })] }) }) }));
|
|
19
20
|
}
|
|
20
21
|
export function TelegramTokenModal({ t, width, height, inputRef, error, onSubmit, }) {
|
|
21
22
|
const overlayBg = "#000000cc";
|
|
22
23
|
const panelWidth = Math.min(68, width - 6);
|
|
23
24
|
const panelHeight = 14;
|
|
24
25
|
const top = bottomAlignedModalTop(height, panelHeight);
|
|
25
|
-
return (_jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Telegram bot token" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.text, children: "From @BotFather: /newbot, then paste the token here. Stored in ~/.muonroi-cli/user-settings.json." }) }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("box", { backgroundColor: t.backgroundElement, paddingLeft: 1, paddingRight: 1, width: "100%", children: _jsx("textarea", { ref: inputRef, focused: true, placeholder: "123456:ABC...", textColor: t.text, backgroundColor: t.backgroundElement, placeholderColor: t.textMuted, minHeight: 1, maxHeight: 3, wrapMode: "word", keyBindings: TEXTAREA_KEYBINDINGS, onSubmit: onSubmit }) }) }), _jsx("box", { flexGrow: 1, minHeight: 0 }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: error ? (_jsx("text", { fg: t.diffRemovedFg, children: error })) : (_jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "save token · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] })) })] }) }));
|
|
26
|
+
return (_jsx(Dialog, { id: "telegram-token-modal", name: "Telegram bot token", children: _jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Telegram bot token" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.text, children: "From @BotFather: /newbot, then paste the token here. Stored in ~/.muonroi-cli/user-settings.json." }) }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("box", { backgroundColor: t.backgroundElement, paddingLeft: 1, paddingRight: 1, width: "100%", children: _jsx("textarea", { ref: inputRef, focused: true, placeholder: "123456:ABC...", textColor: t.text, backgroundColor: t.backgroundElement, placeholderColor: t.textMuted, minHeight: 1, maxHeight: 3, wrapMode: "word", keyBindings: TEXTAREA_KEYBINDINGS, onSubmit: onSubmit }) }) }), _jsx("box", { flexGrow: 1, minHeight: 0 }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: error ? (_jsx("text", { fg: t.diffRemovedFg, children: error })) : (_jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "save token · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] })) })] }) }) }));
|
|
26
27
|
}
|
|
27
28
|
export function TelegramPairModal({ t, width, height, inputRef, error, onSubmit, }) {
|
|
28
29
|
const overlayBg = "#000000cc";
|
|
29
30
|
const panelWidth = Math.min(68, width - 6);
|
|
30
31
|
const panelHeight = 13;
|
|
31
32
|
const top = bottomAlignedModalTop(height, panelHeight);
|
|
32
|
-
return (_jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Pairing code" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.text, children: "DM your bot with /pair, then paste the 6-character code." }) }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("box", { backgroundColor: t.backgroundElement, paddingLeft: 1, paddingRight: 1, width: "100%", children: _jsx("textarea", { ref: inputRef, focused: true, placeholder: "ABC123", textColor: t.text, backgroundColor: t.backgroundElement, placeholderColor: t.textMuted, minHeight: 1, maxHeight: 2, wrapMode: "word", keyBindings: TEXTAREA_KEYBINDINGS, onSubmit: onSubmit }) }) }), _jsx("box", { flexGrow: 1, minHeight: 0 }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: error ? (_jsx("text", { fg: t.diffRemovedFg, children: error })) : (_jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "approve pairing · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] })) })] }) }));
|
|
33
|
+
return (_jsx(Dialog, { id: "telegram-pair-modal", name: "Pairing code", children: _jsx("box", { position: "absolute", left: 0, top: 0, width: width, height: height, alignItems: "center", paddingTop: top, backgroundColor: overlayBg, children: _jsxs("box", { width: panelWidth, height: panelHeight, backgroundColor: t.backgroundPanel, paddingTop: 1, paddingBottom: 1, flexDirection: "column", children: [_jsxs("box", { flexShrink: 0, flexDirection: "row", justifyContent: "space-between", paddingLeft: 2, paddingRight: 2, children: [_jsx("text", { fg: t.primary, children: _jsx("b", { children: "Pairing code" }) }), _jsx("text", { fg: t.textMuted, children: "esc" })] }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.text, children: "DM your bot with /pair, then paste the 6-character code." }) }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("box", { backgroundColor: t.backgroundElement, paddingLeft: 1, paddingRight: 1, width: "100%", children: _jsx("textarea", { ref: inputRef, focused: true, placeholder: "ABC123", textColor: t.text, backgroundColor: t.backgroundElement, placeholderColor: t.textMuted, minHeight: 1, maxHeight: 2, wrapMode: "word", keyBindings: TEXTAREA_KEYBINDINGS, onSubmit: onSubmit }) }) }), _jsx("box", { flexGrow: 1, minHeight: 0 }), _jsx("box", { paddingLeft: 2, paddingRight: 2, paddingTop: 2, paddingBottom: 1, children: error ? (_jsx("text", { fg: t.diffRemovedFg, children: error })) : (_jsxs("text", { children: [_jsx("span", { style: { fg: t.primary }, children: "enter " }), _jsx("span", { style: { fg: t.textMuted }, children: "approve pairing · " }), _jsx("span", { style: { fg: t.primary }, children: "esc " }), _jsx("span", { style: { fg: t.textMuted }, children: "close" })] })) })] }) }) }));
|
|
33
34
|
}
|
|
34
35
|
//# sourceMappingURL=connect-modal.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResumeEntry } from "../../types/index.js";
|
|
2
2
|
import type { Theme } from "../theme.js";
|
|
3
3
|
/**
|
|
4
4
|
* Recent-sessions picker. Opened by `/sessions` or `/session`. Selecting a
|
|
@@ -7,7 +7,7 @@ import type { Theme } from "../theme.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function SessionPickerModal({ t, sessions, focusIndex, width, height, }: {
|
|
9
9
|
t: Theme;
|
|
10
|
-
sessions:
|
|
10
|
+
sessions: ResumeEntry[];
|
|
11
11
|
focusIndex: number;
|
|
12
12
|
width: number;
|
|
13
13
|
height: number;
|
|
@@ -21,11 +21,9 @@ export function SessionPickerModal({ t, sessions, focusIndex, width, height, })
|
|
|
21
21
|
const titleRaw = s.title?.trim() || "(untitled)";
|
|
22
22
|
const titleMax = Math.max(8, panelWidth - 38);
|
|
23
23
|
const title = titleRaw.length > titleMax ? `${titleRaw.slice(0, titleMax - 1)}…` : titleRaw;
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
// same one shown in two formats.
|
|
28
|
-
const idLabel = s.id;
|
|
24
|
+
// Short 8-char id — the tree's root id, enough to disambiguate
|
|
25
|
+
// rows without crowding the model column.
|
|
26
|
+
const idLabel = s.id.slice(0, 8);
|
|
29
27
|
return (_jsx(Semantic, { id: `session-item-${idx}`, role: "listitem", name: `${title} ${idLabel}`, value: s.id, selected: focused || undefined, children: _jsxs("box", { backgroundColor: focused ? t.selectedBg : undefined, paddingLeft: 2, paddingRight: 2, width: "100%", flexDirection: "row", justifyContent: "space-between", children: [_jsx("text", { fg: focused ? t.selected : t.text, children: `${ts} ${title}` }), _jsx("text", { fg: focused ? t.primary : t.textMuted, children: `${s.model} ${idLabel}` })] }) }, s.id));
|
|
30
28
|
})) }), _jsx("box", { flexShrink: 0, paddingLeft: 2, paddingRight: 2, paddingTop: 1, children: _jsx("text", { fg: t.textMuted, children: "↑↓ navigate · enter resume (restarts CLI) · esc cancel" }) })] }) }) }));
|
|
31
29
|
}
|
|
@@ -9,7 +9,7 @@ import type { ProviderId } from "../providers/types.js";
|
|
|
9
9
|
* previously hidden because `configuredProviders` stayed pinned to the splash
|
|
10
10
|
* list (app.tsx never re-applied the async `getConfiguredProviders()` result).
|
|
11
11
|
*
|
|
12
|
-
* Providers with no catalog models (anthropic/ollama
|
|
12
|
+
* Providers with no catalog models (anthropic/ollama in the default
|
|
13
13
|
* catalog) are excluded — they cannot be routed to and would render as dead
|
|
14
14
|
* chips with an empty model list. (xai now ships catalog models, so a
|
|
15
15
|
* configured/OAuth-logged-in xai surfaces here.)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* previously hidden because `configuredProviders` stayed pinned to the splash
|
|
9
9
|
* list (app.tsx never re-applied the async `getConfiguredProviders()` result).
|
|
10
10
|
*
|
|
11
|
-
* Providers with no catalog models (anthropic/ollama
|
|
11
|
+
* Providers with no catalog models (anthropic/ollama in the default
|
|
12
12
|
* catalog) are excluded — they cannot be routed to and would render as dead
|
|
13
13
|
* chips with an empty model list. (xai now ships catalog models, so a
|
|
14
14
|
* configured/OAuth-logged-in xai surfaces here.)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./semantic-primitives.js";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/ui/primitives/semantic-primitives.tsx
|
|
3
|
+
*
|
|
4
|
+
* Role-fixed semantic primitives. Compose these instead of hand-writing
|
|
5
|
+
* `<Semantic role="...">` in feature code. Two things they buy you:
|
|
6
|
+
*
|
|
7
|
+
* 1. The `role` is fixed per component, so it can't be typo'd or drift, and
|
|
8
|
+
* TypeScript enforces the right props per role.
|
|
9
|
+
* 2. Interactive state is passed as plain booleans (`focused`, `selected`,
|
|
10
|
+
* `disabled`, `hidden`) and mirrored to the Semantic node's `true|undefined`
|
|
11
|
+
* flags automatically — no more `focus={cond ? true : undefined}` written
|
|
12
|
+
* by hand at every call site (the #1 source of harness/state drift).
|
|
13
|
+
*
|
|
14
|
+
* Feature authors should reach for these first; a raw `<Semantic>` is only for
|
|
15
|
+
* genuinely bespoke roles not covered here (or a namespaced `x-*` role).
|
|
16
|
+
*
|
|
17
|
+
* These are invisible wrappers (like `<Semantic>` itself): zero OpenTUI element,
|
|
18
|
+
* zero runtime cost when the agent runtime is unset.
|
|
19
|
+
*/
|
|
20
|
+
import type * as React from "react";
|
|
21
|
+
/**
|
|
22
|
+
* Common props shared by every primitive. `focused`/`selected`/`disabled`/
|
|
23
|
+
* `hidden` are plain booleans here (not `true`-literal) and are mirrored to the
|
|
24
|
+
* underlying Semantic flags.
|
|
25
|
+
*/
|
|
26
|
+
export interface BlockProps {
|
|
27
|
+
id: string;
|
|
28
|
+
name?: string;
|
|
29
|
+
value?: string;
|
|
30
|
+
state?: string;
|
|
31
|
+
focused?: boolean;
|
|
32
|
+
selected?: boolean;
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
hidden?: boolean;
|
|
35
|
+
props?: Record<string, unknown>;
|
|
36
|
+
children?: React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
/** A modal dialog. `isModal` defaults to true (pass `isModal={false}` to opt out). */
|
|
39
|
+
export declare function Dialog({ isModal, ...rest }: BlockProps & {
|
|
40
|
+
isModal?: boolean;
|
|
41
|
+
}): React.ReactNode;
|
|
42
|
+
/** A generic grouping region / panel. */
|
|
43
|
+
export declare function Region(props: BlockProps): React.ReactNode;
|
|
44
|
+
/** A titled content panel (IDE-style). */
|
|
45
|
+
export declare function Panel(props: BlockProps): React.ReactNode;
|
|
46
|
+
/** A single-line or multi-line text input. Pass `value` + `focused`. */
|
|
47
|
+
export declare function TextBox(props: BlockProps): React.ReactNode;
|
|
48
|
+
/** A pressable button. Pass `disabled`/`focused` as booleans. */
|
|
49
|
+
export declare function Button(props: BlockProps): React.ReactNode;
|
|
50
|
+
/** A toggle. Reflect checked state via `selected`. */
|
|
51
|
+
export declare function Checkbox(props: BlockProps): React.ReactNode;
|
|
52
|
+
/** A scrollable list container. */
|
|
53
|
+
export declare function ListBox(props: BlockProps): React.ReactNode;
|
|
54
|
+
/** A single list row. Reflect highlight via `selected`. */
|
|
55
|
+
export declare function ListItem(props: BlockProps): React.ReactNode;
|
|
56
|
+
/** A command / context menu. `isModal` defaults to true. */
|
|
57
|
+
export declare function Menu({ isModal, ...rest }: BlockProps & {
|
|
58
|
+
isModal?: boolean;
|
|
59
|
+
}): React.ReactNode;
|
|
60
|
+
/** A single menu entry. */
|
|
61
|
+
export declare function MenuItem(props: BlockProps): React.ReactNode;
|
|
62
|
+
/** A transient notification. */
|
|
63
|
+
export declare function Toast(props: BlockProps): React.ReactNode;
|
|
64
|
+
/** The persistent status bar. */
|
|
65
|
+
export declare function StatusBar(props: BlockProps): React.ReactNode;
|
|
66
|
+
/** A determinate/indeterminate progress indicator. Put `0..1` in `value`. */
|
|
67
|
+
export declare function ProgressBar(props: BlockProps): React.ReactNode;
|
|
68
|
+
/** A scrollback / message log. */
|
|
69
|
+
export declare function Log(props: BlockProps): React.ReactNode;
|
|
70
|
+
/**
|
|
71
|
+
* Escape hatch for a namespaced custom role not covered above. `role` MUST start
|
|
72
|
+
* with `x-` (enforced by the `Role` type). Prefer a named primitive when one fits.
|
|
73
|
+
*/
|
|
74
|
+
export declare function CustomBlock({ role, ...rest }: BlockProps & {
|
|
75
|
+
role: `x-${string}`;
|
|
76
|
+
}): React.ReactNode;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { Semantic } from "@muonroi/agent-harness-opentui";
|
|
3
|
+
/** Coerce a boolean into the Semantic flag shape (`true` present, else absent). */
|
|
4
|
+
function flag(value) {
|
|
5
|
+
return value ? true : undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Internal base. Renders a `<Semantic>` with a fixed `role`, mapping the plain
|
|
9
|
+
* boolean props to the flag shape. `isModal` is passed through for the roles
|
|
10
|
+
* that support it (dialog/menu).
|
|
11
|
+
*/
|
|
12
|
+
function Block({ role, isModal, id, name, value, state, focused, selected, disabled, hidden, props, children, }) {
|
|
13
|
+
return (_jsx(Semantic, { id: id, role: role, name: name, value: value, state: state, focus: flag(focused), selected: flag(selected), disabled: flag(disabled), hidden: flag(hidden), isModal: flag(isModal), props: props, children: children }));
|
|
14
|
+
}
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Role-fixed primitives
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/** A modal dialog. `isModal` defaults to true (pass `isModal={false}` to opt out). */
|
|
19
|
+
export function Dialog({ isModal = true, ...rest }) {
|
|
20
|
+
return _jsx(Block, { role: "dialog", isModal: isModal, ...rest });
|
|
21
|
+
}
|
|
22
|
+
/** A generic grouping region / panel. */
|
|
23
|
+
export function Region(props) {
|
|
24
|
+
return _jsx(Block, { role: "region", ...props });
|
|
25
|
+
}
|
|
26
|
+
/** A titled content panel (IDE-style). */
|
|
27
|
+
export function Panel(props) {
|
|
28
|
+
return _jsx(Block, { role: "panel", ...props });
|
|
29
|
+
}
|
|
30
|
+
/** A single-line or multi-line text input. Pass `value` + `focused`. */
|
|
31
|
+
export function TextBox(props) {
|
|
32
|
+
return _jsx(Block, { role: "textbox", ...props });
|
|
33
|
+
}
|
|
34
|
+
/** A pressable button. Pass `disabled`/`focused` as booleans. */
|
|
35
|
+
export function Button(props) {
|
|
36
|
+
return _jsx(Block, { role: "button", ...props });
|
|
37
|
+
}
|
|
38
|
+
/** A toggle. Reflect checked state via `selected`. */
|
|
39
|
+
export function Checkbox(props) {
|
|
40
|
+
return _jsx(Block, { role: "checkbox", ...props });
|
|
41
|
+
}
|
|
42
|
+
/** A scrollable list container. */
|
|
43
|
+
export function ListBox(props) {
|
|
44
|
+
return _jsx(Block, { role: "listbox", ...props });
|
|
45
|
+
}
|
|
46
|
+
/** A single list row. Reflect highlight via `selected`. */
|
|
47
|
+
export function ListItem(props) {
|
|
48
|
+
return _jsx(Block, { role: "listitem", ...props });
|
|
49
|
+
}
|
|
50
|
+
/** A command / context menu. `isModal` defaults to true. */
|
|
51
|
+
export function Menu({ isModal = true, ...rest }) {
|
|
52
|
+
return _jsx(Block, { role: "menu", isModal: isModal, ...rest });
|
|
53
|
+
}
|
|
54
|
+
/** A single menu entry. */
|
|
55
|
+
export function MenuItem(props) {
|
|
56
|
+
return _jsx(Block, { role: "menuitem", ...props });
|
|
57
|
+
}
|
|
58
|
+
/** A transient notification. */
|
|
59
|
+
export function Toast(props) {
|
|
60
|
+
return _jsx(Block, { role: "toast", ...props });
|
|
61
|
+
}
|
|
62
|
+
/** The persistent status bar. */
|
|
63
|
+
export function StatusBar(props) {
|
|
64
|
+
return _jsx(Block, { role: "statusbar", ...props });
|
|
65
|
+
}
|
|
66
|
+
/** A determinate/indeterminate progress indicator. Put `0..1` in `value`. */
|
|
67
|
+
export function ProgressBar(props) {
|
|
68
|
+
return _jsx(Block, { role: "progressbar", ...props });
|
|
69
|
+
}
|
|
70
|
+
/** A scrollback / message log. */
|
|
71
|
+
export function Log(props) {
|
|
72
|
+
return _jsx(Block, { role: "log", ...props });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Escape hatch for a namespaced custom role not covered above. `role` MUST start
|
|
76
|
+
* with `x-` (enforced by the `Role` type). Prefer a named primitive when one fits.
|
|
77
|
+
*/
|
|
78
|
+
export function CustomBlock({ role, ...rest }) {
|
|
79
|
+
return _jsx(Block, { role: role, ...rest });
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=semantic-primitives.js.map
|
|
@@ -15,11 +15,9 @@ import { FLOW_DIR_NAME } from "../../flow/scaffold.js";
|
|
|
15
15
|
import { registerSlash } from "./registry.js";
|
|
16
16
|
export const handleCompactSlash = async (_args, ctx) => {
|
|
17
17
|
const flowDir = path.join(ctx.cwd, FLOW_DIR_NAME);
|
|
18
|
-
// Check for active run
|
|
18
|
+
// Check for active run (informational only). /compact should work on any
|
|
19
|
+
// session, not only inside a product-loop run, so we no longer block here.
|
|
19
20
|
const runId = await getActiveRunId(flowDir);
|
|
20
|
-
if (!runId) {
|
|
21
|
-
return "No active run. Nothing to compact. Start with /discuss to create a run.";
|
|
22
|
-
}
|
|
23
21
|
// Fire-and-forget: notify EE that surfaced suggestions are going stale due to compact
|
|
24
22
|
const { surfacedIds, timestamp } = getLastSurfacedState();
|
|
25
23
|
if (surfacedIds.length > 0) {
|
|
@@ -31,9 +29,9 @@ export const handleCompactSlash = async (_args, ctx) => {
|
|
|
31
29
|
.catch(() => { });
|
|
32
30
|
}
|
|
33
31
|
// Return signal for orchestrator to perform compaction
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return `__COMPACT__\
|
|
32
|
+
const instructions = _args.length > 0 ? `\nInstructions: ${_args.join(" ")}` : "";
|
|
33
|
+
const runLine = runId ? `Run: ${runId}` : "No active run — compacting chat history only.";
|
|
34
|
+
return `__COMPACT__\n${runLine}${instructions}\nReady for two-pass compaction.`;
|
|
37
35
|
};
|
|
38
36
|
// Self-register on module import
|
|
39
37
|
registerSlash("compact", handleCompactSlash);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { healthDetailed } from "../../ee/health.js";
|
|
11
11
|
import { getDefaultEEClient } from "../../ee/intercept.js";
|
|
12
|
-
import { statusBarStore } from "
|
|
12
|
+
import { statusBarStore } from "../../state/status-bar-store.js";
|
|
13
13
|
import { registerSlash } from "./registry.js";
|
|
14
14
|
export const handleCostSlash = async (_args, _ctx) => {
|
|
15
15
|
const s = statusBarStore.getState();
|
|
@@ -37,10 +37,10 @@ export const handleCouncilInspectSlash = async (args) => {
|
|
|
37
37
|
}
|
|
38
38
|
// Load all system messages for this session — parameterized query prevents SQL injection (T-17-04)
|
|
39
39
|
const rows = db
|
|
40
|
-
.prepare(`SELECT role, message_json, seq, created_at
|
|
41
|
-
FROM messages
|
|
42
|
-
WHERE session_id = ?
|
|
43
|
-
AND role = 'system'
|
|
40
|
+
.prepare(`SELECT role, message_json, seq, created_at
|
|
41
|
+
FROM messages
|
|
42
|
+
WHERE session_id = ?
|
|
43
|
+
AND role = 'system'
|
|
44
44
|
ORDER BY seq ASC`)
|
|
45
45
|
.all(sessionId);
|
|
46
46
|
if (rows.length === 0) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCouncilLanguage, normalizeCouncilLanguage, saveUserSettings } from "../../utils/settings.js";
|
|
1
2
|
import { handleCouncilInspectSlash } from "./council-inspect.js";
|
|
2
3
|
import { registerSlash } from "./registry.js";
|
|
3
4
|
export const handleCouncilSlash = async (args, ctx) => {
|
|
@@ -5,6 +6,22 @@ export const handleCouncilSlash = async (args, ctx) => {
|
|
|
5
6
|
if (args[0] === "inspect") {
|
|
6
7
|
return handleCouncilInspectSlash(args.slice(1), ctx);
|
|
7
8
|
}
|
|
9
|
+
// Feature B — /council lang [value] : read or set the debate language.
|
|
10
|
+
// The chosen language IS the debate language (no translate pass).
|
|
11
|
+
if (args[0] === "lang" || args[0] === "language") {
|
|
12
|
+
const value = args.slice(1).join(" ").trim();
|
|
13
|
+
if (!value) {
|
|
14
|
+
const current = getCouncilLanguage();
|
|
15
|
+
return (`Council debate language: ${current}\n` +
|
|
16
|
+
`- "auto" (default): debate + conclusion follow the language of your prompt.\n` +
|
|
17
|
+
`- "english": force the historical English-only debate.\n` +
|
|
18
|
+
`- <locale> (e.g. "vietnamese", "日本語"): pin the debate to that language.\n` +
|
|
19
|
+
`Set with: /council lang <value>`);
|
|
20
|
+
}
|
|
21
|
+
const normalized = normalizeCouncilLanguage(value);
|
|
22
|
+
saveUserSettings({ councilLanguage: normalized });
|
|
23
|
+
return `Council debate language set to: ${normalized}`;
|
|
24
|
+
}
|
|
8
25
|
let rounds;
|
|
9
26
|
const firstArg = args[0];
|
|
10
27
|
if (firstArg && /^\d+$/.test(firstArg)) {
|
|
@@ -14,7 +31,8 @@ export const handleCouncilSlash = async (args, ctx) => {
|
|
|
14
31
|
const topic = args.join(" ") || ctx.lastPrompt || "";
|
|
15
32
|
if (!topic) {
|
|
16
33
|
return ("/council [rounds] <topic> — multi-model discussion\n" +
|
|
17
|
-
"Default:
|
|
34
|
+
"Default: multi-provider lineup from catalog (implement/verify/research across providers).\n" +
|
|
35
|
+
"Override via roleModels in settings, or councilPreferMultiProvider: false for same-provider.\n" +
|
|
18
36
|
"Example: /council 3 REST vs gRPC for our microservices");
|
|
19
37
|
}
|
|
20
38
|
return `__COUNCIL__\n${rounds ?? ""}\n${topic}`;
|
|
@@ -10,36 +10,8 @@
|
|
|
10
10
|
* /debug off — disable
|
|
11
11
|
* /debug status — show current pipeline state without toggling
|
|
12
12
|
*/
|
|
13
|
+
import { isDebugEnabled, recordTurnTrace } from "../../state/turn-trace.js";
|
|
13
14
|
import type { SlashHandler } from "./registry.js";
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
duration_ms: number;
|
|
17
|
-
input_summary: string;
|
|
18
|
-
output_summary: string;
|
|
19
|
-
tokens_saved?: number;
|
|
20
|
-
}
|
|
21
|
-
export interface TurnTrace {
|
|
22
|
-
turn_id: number;
|
|
23
|
-
timestamp: number;
|
|
24
|
-
raw_prompt: string;
|
|
25
|
-
steps: PipelineStep[];
|
|
26
|
-
model_requested: string;
|
|
27
|
-
model_used: string;
|
|
28
|
-
routed: boolean;
|
|
29
|
-
input_tokens: number;
|
|
30
|
-
output_tokens: number;
|
|
31
|
-
cache_read_tokens: number;
|
|
32
|
-
cost_usd: number;
|
|
33
|
-
estimated_savings: SavingsEstimate;
|
|
34
|
-
}
|
|
35
|
-
export interface SavingsEstimate {
|
|
36
|
-
pil_tokens_saved: number;
|
|
37
|
-
cache_tokens_saved: number;
|
|
38
|
-
router_cost_saved_usd: number;
|
|
39
|
-
total_tokens_saved: number;
|
|
40
|
-
total_cost_saved_usd: number;
|
|
41
|
-
}
|
|
42
|
-
export declare function isDebugEnabled(): boolean;
|
|
43
|
-
export declare function recordTurnTrace(trace: TurnTrace): void;
|
|
44
|
-
export declare function getLastTrace(): TurnTrace | null;
|
|
15
|
+
export type { PipelineStep, SavingsEstimate, TurnTrace } from "../../state/turn-trace.js";
|
|
16
|
+
export { isDebugEnabled, recordTurnTrace };
|
|
45
17
|
export declare const handleDebugSlash: SlashHandler;
|
|
@@ -10,23 +10,10 @@
|
|
|
10
10
|
* /debug off — disable
|
|
11
11
|
* /debug status — show current pipeline state without toggling
|
|
12
12
|
*/
|
|
13
|
-
import { statusBarStore } from "
|
|
13
|
+
import { statusBarStore } from "../../state/status-bar-store.js";
|
|
14
|
+
import { getAllTraces, getLastTrace, isDebugEnabled, recordTurnTrace, setDebugEnabled, } from "../../state/turn-trace.js";
|
|
14
15
|
import { registerSlash } from "./registry.js";
|
|
15
|
-
|
|
16
|
-
const turnTraces = [];
|
|
17
|
-
export function isDebugEnabled() {
|
|
18
|
-
return debugEnabled;
|
|
19
|
-
}
|
|
20
|
-
export function recordTurnTrace(trace) {
|
|
21
|
-
if (!debugEnabled)
|
|
22
|
-
return;
|
|
23
|
-
turnTraces.push(trace);
|
|
24
|
-
if (turnTraces.length > 50)
|
|
25
|
-
turnTraces.shift();
|
|
26
|
-
}
|
|
27
|
-
export function getLastTrace() {
|
|
28
|
-
return turnTraces[turnTraces.length - 1] ?? null;
|
|
29
|
-
}
|
|
16
|
+
export { isDebugEnabled, recordTurnTrace };
|
|
30
17
|
function formatTrace(trace) {
|
|
31
18
|
const lines = [];
|
|
32
19
|
lines.push(`┌─ Turn #${trace.turn_id} ─────────────────────────────────`);
|
|
@@ -62,6 +49,7 @@ function formatTrace(trace) {
|
|
|
62
49
|
}
|
|
63
50
|
function formatSessionSummary() {
|
|
64
51
|
const s = statusBarStore.getState();
|
|
52
|
+
const turnTraces = getAllTraces();
|
|
65
53
|
const totalSavings = turnTraces.reduce((acc, t) => ({
|
|
66
54
|
tokens: acc.tokens + t.estimated_savings.total_tokens_saved,
|
|
67
55
|
cost: acc.cost + t.estimated_savings.total_cost_saved_usd,
|
|
@@ -82,11 +70,11 @@ function formatSessionSummary() {
|
|
|
82
70
|
export const handleDebugSlash = async (args, _ctx) => {
|
|
83
71
|
const cmd = args[0]?.toLowerCase();
|
|
84
72
|
if (cmd === "on") {
|
|
85
|
-
|
|
73
|
+
setDebugEnabled(true);
|
|
86
74
|
return "Pipeline debug tracing: ON\nEach turn will show: PIL → Router → EE hooks → Model → Savings";
|
|
87
75
|
}
|
|
88
76
|
if (cmd === "off") {
|
|
89
|
-
|
|
77
|
+
setDebugEnabled(false);
|
|
90
78
|
return "Pipeline debug tracing: OFF";
|
|
91
79
|
}
|
|
92
80
|
if (cmd === "status") {
|
|
@@ -99,8 +87,9 @@ export const handleDebugSlash = async (args, _ctx) => {
|
|
|
99
87
|
return formatTrace(last);
|
|
100
88
|
}
|
|
101
89
|
// Toggle
|
|
102
|
-
|
|
103
|
-
|
|
90
|
+
const next = !isDebugEnabled();
|
|
91
|
+
setDebugEnabled(next);
|
|
92
|
+
if (next) {
|
|
104
93
|
return "Pipeline debug tracing: ON\nEach turn will show: PIL → Router → EE hooks → Model → Savings\n\nCommands: /debug off | /debug status | /debug last";
|
|
105
94
|
}
|
|
106
95
|
return "Pipeline debug tracing: OFF";
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* /ideal "<idea>" start a new product run (default)
|
|
8
8
|
* /ideal status list active runs
|
|
9
9
|
* /ideal status <runId> detail of one run
|
|
10
|
-
* /ideal resume
|
|
10
|
+
* /ideal resume [runId] resume halted/crashed run (no id = newest incomplete)
|
|
11
11
|
* /ideal abort <runId> hard kill
|
|
12
12
|
* /ideal ship <runId> force user-approval gate (skip if Cond #1-#4 pass)
|
|
13
13
|
*
|
|
@@ -47,7 +47,7 @@ export interface IdealFlags {
|
|
|
47
47
|
/** Mode C only — opt-in: run `gh pr create` after PR is built. Default false. */
|
|
48
48
|
ghPr?: boolean;
|
|
49
49
|
}
|
|
50
|
-
export type IdealSubcommand = "start" | "status" | "resume" | "abort" | "ship" | "help";
|
|
50
|
+
export type IdealSubcommand = "start" | "status" | "resume" | "abort" | "ship" | "review" | "milestones" | "phases" | "help";
|
|
51
51
|
export interface IdealParseResult {
|
|
52
52
|
subcommand: IdealSubcommand;
|
|
53
53
|
idea?: string;
|
|
@@ -60,6 +60,10 @@ export interface IdealParseResult {
|
|
|
60
60
|
* SlashHandler signature (which depends on a SlashContext).
|
|
61
61
|
*/
|
|
62
62
|
export declare function parseIdealArgs(args: string[]): IdealParseResult;
|
|
63
|
+
/** Render `/ideal milestones` — every milestone with its phases + linked runs. */
|
|
64
|
+
export declare function renderMilestones(cwd: string): Promise<string>;
|
|
65
|
+
/** Render `/ideal phases [milestoneId]` — phases under one milestone. */
|
|
66
|
+
export declare function renderPhases(cwd: string, milestoneId?: string): Promise<string>;
|
|
63
67
|
/**
|
|
64
68
|
* Slash handler. Returns a sentinel string parseable by app.tsx, OR a help/error
|
|
65
69
|
* string when no orchestrator dispatch is appropriate.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* /ideal "<idea>" start a new product run (default)
|
|
8
8
|
* /ideal status list active runs
|
|
9
9
|
* /ideal status <runId> detail of one run
|
|
10
|
-
* /ideal resume
|
|
10
|
+
* /ideal resume [runId] resume halted/crashed run (no id = newest incomplete)
|
|
11
11
|
* /ideal abort <runId> hard kill
|
|
12
12
|
* /ideal ship <runId> force user-approval gate (skip if Cond #1-#4 pass)
|
|
13
13
|
*
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
* app.tsx parses and dispatches to orchestrator.runProductLoopV1, mirroring
|
|
26
26
|
* the existing __COUNCIL__ pattern in src/ui/slash/council.ts.
|
|
27
27
|
*/
|
|
28
|
+
import * as path from "node:path";
|
|
28
29
|
import { Command, InvalidArgumentError } from "commander";
|
|
30
|
+
import { getActivePointer, listMilestones, listPhases, migrateLegacyRuns } from "../../flow/hierarchy.js";
|
|
29
31
|
import { registerSlash } from "./registry.js";
|
|
30
32
|
const DEFAULTS = {
|
|
31
33
|
maxCost: 50,
|
|
@@ -38,8 +40,11 @@ const HELP_TEXT = [
|
|
|
38
40
|
"Subcommands:",
|
|
39
41
|
' /ideal "<idea>" Start a new product run',
|
|
40
42
|
" /ideal status [runId] List active runs (or detail one)",
|
|
41
|
-
" /ideal resume
|
|
42
|
-
" /ideal
|
|
43
|
+
" /ideal resume [runId] Resume a run (no id = newest incomplete run)",
|
|
44
|
+
" /ideal review [runId] Render a run's transcript + sprint scores (no id = newest run)",
|
|
45
|
+
" /ideal milestones List milestones (idea/product groups) and their phases",
|
|
46
|
+
" /ideal phases [mId] List phases under a milestone (no id = active milestone)",
|
|
47
|
+
" /ideal abort [runId] Hard-kill a run (no id = newest incomplete run)",
|
|
43
48
|
" /ideal ship <runId> Force user-approval gate (skip Cond #1-#4 if passing)",
|
|
44
49
|
"",
|
|
45
50
|
"Flags (start only):",
|
|
@@ -85,7 +90,18 @@ export function parseIdealArgs(args) {
|
|
|
85
90
|
return { subcommand: "help", flags: { ...DEFAULTS, noCustomerDebate }, warnings };
|
|
86
91
|
}
|
|
87
92
|
// Detect non-start subcommands by first token (subcommand keywords are reserved).
|
|
88
|
-
const RESERVED = new Set([
|
|
93
|
+
const RESERVED = new Set([
|
|
94
|
+
"status",
|
|
95
|
+
"resume",
|
|
96
|
+
"abort",
|
|
97
|
+
"ship",
|
|
98
|
+
"review",
|
|
99
|
+
"milestones",
|
|
100
|
+
"phases",
|
|
101
|
+
"help",
|
|
102
|
+
"--help",
|
|
103
|
+
"-h",
|
|
104
|
+
]);
|
|
89
105
|
const head = args[0];
|
|
90
106
|
if (RESERVED.has(head)) {
|
|
91
107
|
if (head === "help" || head === "--help" || head === "-h") {
|
|
@@ -193,18 +209,92 @@ export function parseIdealArgs(args) {
|
|
|
193
209
|
warnings,
|
|
194
210
|
};
|
|
195
211
|
}
|
|
212
|
+
function flowDirOf(cwd) {
|
|
213
|
+
return path.join(cwd, ".muonroi-flow");
|
|
214
|
+
}
|
|
215
|
+
/** Render `/ideal milestones` — every milestone with its phases + linked runs. */
|
|
216
|
+
export async function renderMilestones(cwd) {
|
|
217
|
+
const flowDir = flowDirOf(cwd);
|
|
218
|
+
// Lazily backfill pre-hierarchy runs so old work is visible. Idempotent.
|
|
219
|
+
await migrateLegacyRuns(flowDir, new Date().toISOString()).catch(() => 0);
|
|
220
|
+
const milestones = await listMilestones(flowDir);
|
|
221
|
+
if (milestones.length === 0) {
|
|
222
|
+
return 'No milestones yet. Start one with `/ideal "<idea>"`.';
|
|
223
|
+
}
|
|
224
|
+
const { milestoneId: activeM, phaseId: activeP } = await getActivePointer(flowDir);
|
|
225
|
+
const lines = ["# Milestones", ""];
|
|
226
|
+
for (const m of milestones) {
|
|
227
|
+
const active = m.id === activeM ? " ← active" : "";
|
|
228
|
+
lines.push(`## ${m.id}: ${m.title} [${m.status}]${active}`);
|
|
229
|
+
if (m.goal)
|
|
230
|
+
lines.push(` goal: ${m.goal}`);
|
|
231
|
+
const phases = await listPhases(flowDir, m.id);
|
|
232
|
+
if (phases.length === 0) {
|
|
233
|
+
lines.push(" (no phases yet)");
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
for (const p of phases) {
|
|
237
|
+
const runs = p.runIds.length > 0 ? ` — runs: ${p.runIds.join(", ")}` : "";
|
|
238
|
+
const pActive = m.id === activeM && p.id === activeP ? " ←" : "";
|
|
239
|
+
lines.push(` - [${p.status === "done" ? "x" : " "}] ${p.id}: ${p.title} [${p.status}]${runs}${pActive}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
lines.push("");
|
|
243
|
+
}
|
|
244
|
+
return lines.join("\n").trimEnd();
|
|
245
|
+
}
|
|
246
|
+
/** Render `/ideal phases [milestoneId]` — phases under one milestone. */
|
|
247
|
+
export async function renderPhases(cwd, milestoneId) {
|
|
248
|
+
const flowDir = flowDirOf(cwd);
|
|
249
|
+
let mId = milestoneId;
|
|
250
|
+
if (!mId) {
|
|
251
|
+
mId = (await getActivePointer(flowDir)).milestoneId ?? undefined;
|
|
252
|
+
}
|
|
253
|
+
if (!mId) {
|
|
254
|
+
return "No active milestone. Run `/ideal milestones` to list, or pass a milestone id.";
|
|
255
|
+
}
|
|
256
|
+
const phases = await listPhases(flowDir, mId);
|
|
257
|
+
if (phases.length === 0) {
|
|
258
|
+
return `No phases under ${mId}.`;
|
|
259
|
+
}
|
|
260
|
+
const { phaseId: activeP } = await getActivePointer(flowDir);
|
|
261
|
+
const lines = [`# Phases of ${mId}`, ""];
|
|
262
|
+
for (const p of phases) {
|
|
263
|
+
const runs = p.runIds.length > 0 ? ` — runs: ${p.runIds.join(", ")}` : "";
|
|
264
|
+
const pActive = p.id === activeP ? " ← active" : "";
|
|
265
|
+
lines.push(`- [${p.status === "done" ? "x" : " "}] ${p.id}: ${p.title} [${p.status}]${runs}${pActive}`);
|
|
266
|
+
if (p.goal)
|
|
267
|
+
lines.push(` goal: ${p.goal}`);
|
|
268
|
+
}
|
|
269
|
+
return lines.join("\n");
|
|
270
|
+
}
|
|
196
271
|
/**
|
|
197
272
|
* Slash handler. Returns a sentinel string parseable by app.tsx, OR a help/error
|
|
198
273
|
* string when no orchestrator dispatch is appropriate.
|
|
199
274
|
*/
|
|
200
|
-
export const handleIdealSlash = async (args) => {
|
|
275
|
+
export const handleIdealSlash = async (args, ctx) => {
|
|
201
276
|
const result = parseIdealArgs(args);
|
|
202
277
|
if (result.subcommand === "help") {
|
|
203
278
|
const warnings = result.warnings.length ? `\n\n${result.warnings.join("\n")}` : "";
|
|
204
279
|
return `${HELP_TEXT}${warnings}`;
|
|
205
280
|
}
|
|
206
|
-
//
|
|
207
|
-
|
|
281
|
+
// Milestones/phases are read-only index views — render inline (no orchestrator
|
|
282
|
+
// dispatch). `runId` carries the optional milestone id for `phases`.
|
|
283
|
+
if (result.subcommand === "milestones") {
|
|
284
|
+
return renderMilestones(ctx.cwd);
|
|
285
|
+
}
|
|
286
|
+
if (result.subcommand === "phases") {
|
|
287
|
+
return renderPhases(ctx.cwd, result.runId);
|
|
288
|
+
}
|
|
289
|
+
// Status/resume/abort without a runId are allowed: status lists all runs,
|
|
290
|
+
// resume + abort auto-detect the newest incomplete run (A/B). ship still
|
|
291
|
+
// requires an explicit runId.
|
|
292
|
+
if (result.subcommand !== "start" &&
|
|
293
|
+
result.subcommand !== "status" &&
|
|
294
|
+
result.subcommand !== "resume" &&
|
|
295
|
+
result.subcommand !== "abort" &&
|
|
296
|
+
result.subcommand !== "review" &&
|
|
297
|
+
!result.runId) {
|
|
208
298
|
return `error: /ideal ${result.subcommand} requires a runId\n\n${HELP_TEXT}`;
|
|
209
299
|
}
|
|
210
300
|
const payload = {
|