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
|
@@ -148,8 +148,8 @@ export async function createLLMBrain(opts) {
|
|
|
148
148
|
const retryOnEmpty = opts.retryOnEmpty !== false;
|
|
149
149
|
// @ai-sdk/openai-compatible's chat schema exposes `strictJsonSchema: false`
|
|
150
150
|
// for providers that don't honour OpenAI's strict JSON schema mode.
|
|
151
|
-
// DeepSeek
|
|
152
|
-
//
|
|
151
|
+
// DeepSeek only supports `response_format: {type: "json_object"}` — it
|
|
152
|
+
// rejects the full
|
|
153
153
|
// schema response_format. Setting strictJsonSchema=false makes AI SDK fall
|
|
154
154
|
// back to lenient json_object mode silently (no "responseFormat not
|
|
155
155
|
// supported" warning) while still steering the model toward JSON output.
|
|
@@ -161,7 +161,7 @@ export async function createLLMBrain(opts) {
|
|
|
161
161
|
const mergedProviderOptions = {
|
|
162
162
|
...(runtime.providerOptions ?? {}),
|
|
163
163
|
};
|
|
164
|
-
if (provider === "deepseek"
|
|
164
|
+
if (provider === "deepseek") {
|
|
165
165
|
mergedProviderOptions[provider] = {
|
|
166
166
|
...(mergedProviderOptions[provider] ?? {}),
|
|
167
167
|
strictJsonSchema: false,
|
|
@@ -21,6 +21,25 @@ export declare const activeRunStore: {
|
|
|
21
21
|
clearActiveRun: () => void;
|
|
22
22
|
subscribe: (fn: Listener) => (() => void);
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Single canonical writer for "which run is the workspace focused on".
|
|
26
|
+
* Writes the durable pointer (`state.md` `Active Run`) AND the in-memory cache
|
|
27
|
+
* atomically, so disk and StatusBar/reporter never drift (F8 follow-up).
|
|
28
|
+
*
|
|
29
|
+
* The disk write is idempotent with `ensureRunScoped`'s earlier write for the
|
|
30
|
+
* same runId — routing the focus moment through here just guarantees they agree.
|
|
31
|
+
*/
|
|
32
|
+
export declare function setWorkspaceFocus(flowDir: string, focus: {
|
|
33
|
+
runId: string;
|
|
34
|
+
productSlug: string;
|
|
35
|
+
reason?: string;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Clear the workspace focus cache when a run ends (shipped / halted).
|
|
39
|
+
* Cache-only by design: the durable `Active Run` pointer is left intact as a
|
|
40
|
+
* historical marker so `/ideal phases` still resolves the last run post-ship.
|
|
41
|
+
*/
|
|
42
|
+
export declare function clearWorkspaceFocus(): void;
|
|
24
43
|
/** Test helper: reset to initial state. */
|
|
25
44
|
export declare function __resetActiveRunStoreForTests(): void;
|
|
26
45
|
export {};
|
|
@@ -37,6 +37,27 @@ function makeActiveRunStore() {
|
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
export const activeRunStore = makeActiveRunStore();
|
|
40
|
+
/**
|
|
41
|
+
* Single canonical writer for "which run is the workspace focused on".
|
|
42
|
+
* Writes the durable pointer (`state.md` `Active Run`) AND the in-memory cache
|
|
43
|
+
* atomically, so disk and StatusBar/reporter never drift (F8 follow-up).
|
|
44
|
+
*
|
|
45
|
+
* The disk write is idempotent with `ensureRunScoped`'s earlier write for the
|
|
46
|
+
* same runId — routing the focus moment through here just guarantees they agree.
|
|
47
|
+
*/
|
|
48
|
+
export async function setWorkspaceFocus(flowDir, focus) {
|
|
49
|
+
const { setActiveRunId } = await import("../flow/run-manager.js");
|
|
50
|
+
await setActiveRunId(flowDir, focus.runId);
|
|
51
|
+
activeRunStore.setActiveRun(focus.runId, flowDir, focus.productSlug);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Clear the workspace focus cache when a run ends (shipped / halted).
|
|
55
|
+
* Cache-only by design: the durable `Active Run` pointer is left intact as a
|
|
56
|
+
* historical marker so `/ideal phases` still resolves the last run post-ship.
|
|
57
|
+
*/
|
|
58
|
+
export function clearWorkspaceFocus() {
|
|
59
|
+
activeRunStore.clearActiveRun();
|
|
60
|
+
}
|
|
40
61
|
/** Test helper: reset to initial state. */
|
|
41
62
|
export function __resetActiveRunStoreForTests() {
|
|
42
63
|
activeRunStore.clearActiveRun();
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* src/
|
|
2
|
+
* src/state/status-bar-store.ts
|
|
3
3
|
*
|
|
4
4
|
* Status bar store: subscribable atom holding model/provider/tier/tokens/USD/degraded.
|
|
5
5
|
* wireStatusBar() connects to routerStore (Plan 03), subscribeThresholds (Plan 04),
|
|
6
6
|
* and subscribeDowngrade (Plan 05).
|
|
7
|
+
*
|
|
8
|
+
* Presentation-agnostic state — lives outside src/ui so the headless core
|
|
9
|
+
* (orchestrator/tool-engine/stream-runner) can read it without importing ui/.
|
|
7
10
|
*/
|
|
8
11
|
export interface SprintProgressSegment {
|
|
9
12
|
/** Active sprint index (1-based). */
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* src/
|
|
2
|
+
* src/state/status-bar-store.ts
|
|
3
3
|
*
|
|
4
4
|
* Status bar store: subscribable atom holding model/provider/tier/tokens/USD/degraded.
|
|
5
5
|
* wireStatusBar() connects to routerStore (Plan 03), subscribeThresholds (Plan 04),
|
|
6
6
|
* and subscribeDowngrade (Plan 05).
|
|
7
|
+
*
|
|
8
|
+
* Presentation-agnostic state — lives outside src/ui so the headless core
|
|
9
|
+
* (orchestrator/tool-engine/stream-runner) can read it without importing ui/.
|
|
7
10
|
*/
|
|
8
|
-
import { getCircuitState } from "
|
|
9
|
-
import { routerStore } from "
|
|
10
|
-
import { subscribeDowngrade } from "
|
|
11
|
-
import { subscribeThresholds } from "
|
|
12
|
-
import { activeRunStore } from "
|
|
11
|
+
import { getCircuitState } from "../ee/client.js";
|
|
12
|
+
import { routerStore } from "../router/store.js";
|
|
13
|
+
import { subscribeDowngrade } from "../usage/downgrade.js";
|
|
14
|
+
import { subscribeThresholds } from "../usage/thresholds.js";
|
|
15
|
+
import { activeRunStore } from "./active-run.js";
|
|
13
16
|
function makeStore() {
|
|
14
17
|
let state = {
|
|
15
18
|
provider: "",
|
|
@@ -141,8 +144,8 @@ export function wireStatusBar() {
|
|
|
141
144
|
}
|
|
142
145
|
try {
|
|
143
146
|
// Lazy import to avoid circular dependency at module load time.
|
|
144
|
-
const { readBacklog } = await import("
|
|
145
|
-
const { readSprintPlan } = await import("
|
|
147
|
+
const { readBacklog } = await import("../product-loop/backlog-store.js");
|
|
148
|
+
const { readSprintPlan } = await import("../product-loop/sprint-store.js");
|
|
146
149
|
const [backlog, sprintPlan] = await Promise.all([
|
|
147
150
|
readBacklog(run.flowDir, run.runId).catch(() => null),
|
|
148
151
|
readSprintPlan(run.flowDir, run.runId).catch(() => null),
|
|
@@ -276,4 +279,4 @@ export function __resetStatusBarStoreForTests() {
|
|
|
276
279
|
});
|
|
277
280
|
wired = false;
|
|
278
281
|
}
|
|
279
|
-
//# sourceMappingURL=store.js.map
|
|
282
|
+
//# sourceMappingURL=status-bar-store.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/state/turn-trace.ts
|
|
3
|
+
*
|
|
4
|
+
* Pipeline debug-trace state — the toggle flag + recorded per-turn traces.
|
|
5
|
+
*
|
|
6
|
+
* Presentation-agnostic: the headless core (tool-engine, message-processor)
|
|
7
|
+
* records traces here without importing src/ui. The /debug slash command
|
|
8
|
+
* (src/ui/slash/debug.ts) owns the human formatting and toggling on top of
|
|
9
|
+
* this state.
|
|
10
|
+
*/
|
|
11
|
+
export interface PipelineStep {
|
|
12
|
+
name: string;
|
|
13
|
+
duration_ms: number;
|
|
14
|
+
input_summary: string;
|
|
15
|
+
output_summary: string;
|
|
16
|
+
tokens_saved?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TurnTrace {
|
|
19
|
+
turn_id: number;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
raw_prompt: string;
|
|
22
|
+
steps: PipelineStep[];
|
|
23
|
+
model_requested: string;
|
|
24
|
+
model_used: string;
|
|
25
|
+
routed: boolean;
|
|
26
|
+
input_tokens: number;
|
|
27
|
+
output_tokens: number;
|
|
28
|
+
cache_read_tokens: number;
|
|
29
|
+
cost_usd: number;
|
|
30
|
+
estimated_savings: SavingsEstimate;
|
|
31
|
+
}
|
|
32
|
+
export interface SavingsEstimate {
|
|
33
|
+
pil_tokens_saved: number;
|
|
34
|
+
cache_tokens_saved: number;
|
|
35
|
+
router_cost_saved_usd: number;
|
|
36
|
+
total_tokens_saved: number;
|
|
37
|
+
total_cost_saved_usd: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function isDebugEnabled(): boolean;
|
|
40
|
+
export declare function setDebugEnabled(value: boolean): void;
|
|
41
|
+
export declare function recordTurnTrace(trace: TurnTrace): void;
|
|
42
|
+
export declare function getLastTrace(): TurnTrace | null;
|
|
43
|
+
export declare function getAllTraces(): readonly TurnTrace[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/state/turn-trace.ts
|
|
3
|
+
*
|
|
4
|
+
* Pipeline debug-trace state — the toggle flag + recorded per-turn traces.
|
|
5
|
+
*
|
|
6
|
+
* Presentation-agnostic: the headless core (tool-engine, message-processor)
|
|
7
|
+
* records traces here without importing src/ui. The /debug slash command
|
|
8
|
+
* (src/ui/slash/debug.ts) owns the human formatting and toggling on top of
|
|
9
|
+
* this state.
|
|
10
|
+
*/
|
|
11
|
+
let debugEnabled = false;
|
|
12
|
+
const turnTraces = [];
|
|
13
|
+
export function isDebugEnabled() {
|
|
14
|
+
return debugEnabled;
|
|
15
|
+
}
|
|
16
|
+
export function setDebugEnabled(value) {
|
|
17
|
+
debugEnabled = value;
|
|
18
|
+
}
|
|
19
|
+
export function recordTurnTrace(trace) {
|
|
20
|
+
if (!debugEnabled)
|
|
21
|
+
return;
|
|
22
|
+
turnTraces.push(trace);
|
|
23
|
+
if (turnTraces.length > 50)
|
|
24
|
+
turnTraces.shift();
|
|
25
|
+
}
|
|
26
|
+
export function getLastTrace() {
|
|
27
|
+
return turnTraces[turnTraces.length - 1] ?? null;
|
|
28
|
+
}
|
|
29
|
+
export function getAllTraces() {
|
|
30
|
+
return turnTraces;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=turn-trace.js.map
|
package/dist/src/storage/db.js
CHANGED
|
@@ -9,7 +9,8 @@ let db = null;
|
|
|
9
9
|
// async would be a much larger refactor.
|
|
10
10
|
const requireSync = createRequire(import.meta.url);
|
|
11
11
|
export function getDatabasePath() {
|
|
12
|
-
const
|
|
12
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? os.homedir();
|
|
13
|
+
const dir = path.join(home, ".muonroi-cli");
|
|
13
14
|
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
14
15
|
return path.join(dir, "muonroi.db");
|
|
15
16
|
}
|
|
@@ -3,7 +3,7 @@ export { loadConfig, type MuonroiConfig } from "./config.js";
|
|
|
3
3
|
export { getDatabasePath } from "./db.js";
|
|
4
4
|
export { type InteractionEventType, logInteraction } from "./interaction-log.js";
|
|
5
5
|
export { SessionStore } from "./sessions.js";
|
|
6
|
-
export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastTodoWriteArgs, getNextMessageSequence, getSessionChain, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, revertLatestCompaction, } from "./transcript.js";
|
|
6
|
+
export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastApprovedPlan, getLastTodoWriteArgs, getNextMessageSequence, getSessionChain, getSessionChainInfos, loadLatestCompaction, loadRawTranscript, loadSessionChainTranscriptState, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistApprovedPlan, persistMessageWriteAhead, persistToolCallWriteAhead, revertLatestCompaction, type SessionChainNode, } from "./transcript.js";
|
|
7
7
|
export { buildEffectiveTranscript, type LoadedTranscriptState, type PersistedCompaction } from "./transcript-view.js";
|
|
8
8
|
export { logUIInteraction, type UIInteractionSubtype } from "./ui-interaction-log.js";
|
|
9
9
|
export { getSessionTotalTokens, listSessionUsage, recordUsageEvent, type TokenUsageLike } from "./usage.js";
|
|
@@ -4,7 +4,7 @@ export { loadConfig } from "./config.js";
|
|
|
4
4
|
export { getDatabasePath } from "./db.js";
|
|
5
5
|
export { logInteraction } from "./interaction-log.js";
|
|
6
6
|
export { SessionStore } from "./sessions.js";
|
|
7
|
-
export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastTodoWriteArgs, getNextMessageSequence, getSessionChain, loadLatestCompaction, loadRawTranscript, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistMessageWriteAhead, persistToolCallWriteAhead, revertLatestCompaction, } from "./transcript.js";
|
|
7
|
+
export { appendCompaction, appendMessages, appendSystemMessage, buildChatEntries, getLastApprovedPlan, getLastTodoWriteArgs, getNextMessageSequence, getSessionChain, getSessionChainInfos, loadLatestCompaction, loadRawTranscript, loadSessionChainTranscriptState, loadTranscript, loadTranscriptState, markMessageCompleted, markMessageErrored, markToolCallErrored, persistApprovedPlan, persistMessageWriteAhead, persistToolCallWriteAhead, revertLatestCompaction, } from "./transcript.js";
|
|
8
8
|
export { buildEffectiveTranscript } from "./transcript-view.js";
|
|
9
9
|
export { logUIInteraction } from "./ui-interaction-log.js";
|
|
10
10
|
export { getSessionTotalTokens, listSessionUsage, recordUsageEvent } from "./usage.js";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Fire-and-forget interaction logging for detailed user-agent event tracking.
|
|
5
5
|
* All calls are fail-open — logging never breaks the main flow.
|
|
6
6
|
*/
|
|
7
|
-
export type InteractionEventType = "user_message" | "agent_response" | "tool_call" | "tool_result" | "compaction" | "routing" | "pil" | "error" | "model_switch" | "council" | "ee_intercept" | "ee_judge" | "ee_injection" | "ui_interaction" | "stream_retry" | "f6_synthesis" | "grounding_flag" | "stall_rescue" | "stream_start" | "text_tool_resteer" | "session_experience";
|
|
7
|
+
export type InteractionEventType = "user_message" | "agent_response" | "tool_call" | "tool_result" | "compaction" | "routing" | "pil" | "error" | "model_switch" | "council" | "ee_intercept" | "ee_judge" | "ee_injection" | "ui_interaction" | "stream_retry" | "f6_synthesis" | "grounding_flag" | "stall_rescue" | "stream_start" | "text_tool_resteer" | "turn_tool_load" | "session_experience";
|
|
8
8
|
export interface EEInjectionRow {
|
|
9
9
|
session_id: string;
|
|
10
10
|
event_subtype: string | null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LATEST_DB_VERSION =
|
|
1
|
+
const LATEST_DB_VERSION = 10;
|
|
2
2
|
export function applyMigrations(db) {
|
|
3
3
|
const version = Number(db.pragma("user_version", { simple: true })) || 0;
|
|
4
4
|
if (version >= LATEST_DB_VERSION)
|
|
@@ -96,9 +96,79 @@ export function applyMigrations(db) {
|
|
|
96
96
|
db.exec("CREATE INDEX IF NOT EXISTS idx_sessions_parent_id ON sessions(parent_session_id)");
|
|
97
97
|
db.pragma("user_version = 8");
|
|
98
98
|
}
|
|
99
|
+
if (version < 9) {
|
|
100
|
+
db.exec(`
|
|
101
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS session_history_fts USING fts5(
|
|
102
|
+
session_id UNINDEXED,
|
|
103
|
+
seq UNINDEXED,
|
|
104
|
+
role UNINDEXED,
|
|
105
|
+
tool_name UNINDEXED,
|
|
106
|
+
content,
|
|
107
|
+
tool_args,
|
|
108
|
+
tool_output
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
CREATE TRIGGER IF NOT EXISTS t_sessions_delete_fts
|
|
112
|
+
AFTER DELETE ON sessions
|
|
113
|
+
BEGIN
|
|
114
|
+
DELETE FROM session_history_fts WHERE session_id = old.id;
|
|
115
|
+
END;
|
|
116
|
+
`);
|
|
117
|
+
db.pragma("user_version = 9");
|
|
118
|
+
}
|
|
119
|
+
if (version < 10) {
|
|
120
|
+
// Thread-aware resume. The resume picker groups sessions by conversation
|
|
121
|
+
// tree; `kind` distinguishes the two kinds of child (both previously only
|
|
122
|
+
// set parent_session_id, indistinguishable) and `root_session_id`
|
|
123
|
+
// denormalizes the tree root so the picker groups without a recursive CTE.
|
|
124
|
+
const cols = db.prepare("PRAGMA table_info(sessions)").all();
|
|
125
|
+
const colNames = new Set(cols.map((c) => c.name));
|
|
126
|
+
if (!colNames.has("kind")) {
|
|
127
|
+
db.exec("ALTER TABLE sessions ADD COLUMN kind TEXT NOT NULL DEFAULT 'conversation'");
|
|
128
|
+
}
|
|
129
|
+
if (!colNames.has("root_session_id")) {
|
|
130
|
+
db.exec("ALTER TABLE sessions ADD COLUMN root_session_id TEXT");
|
|
131
|
+
}
|
|
132
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_sessions_root ON sessions(workspace_id, root_session_id)");
|
|
133
|
+
backfillSessionTrees(db);
|
|
134
|
+
db.pragma("user_version = 10");
|
|
135
|
+
}
|
|
99
136
|
});
|
|
100
137
|
migrate();
|
|
101
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Backfill kind + root_session_id for pre-v10 rows.
|
|
141
|
+
*
|
|
142
|
+
* - Rows with no parent become their own root (kind 'conversation').
|
|
143
|
+
* - Rows WITH a parent are marked 'rotation' — historical data cannot tell
|
|
144
|
+
* rotation apart from sub-agent spawns, and marking them 'rotation' collapses
|
|
145
|
+
* them under their root rather than risking hiding a real conversation.
|
|
146
|
+
* - root_session_id propagates down the parent chain via a bounded fixpoint
|
|
147
|
+
* loop (chains are shallow; the bound also guards against FK cycles).
|
|
148
|
+
*/
|
|
149
|
+
function backfillSessionTrees(db) {
|
|
150
|
+
// Roots: own id, keep default kind 'conversation'.
|
|
151
|
+
db.exec("UPDATE sessions SET root_session_id = id WHERE parent_session_id IS NULL AND root_session_id IS NULL");
|
|
152
|
+
// Children of a real parent → rotation (default kind was 'conversation').
|
|
153
|
+
db.exec("UPDATE sessions SET kind = 'rotation' WHERE parent_session_id IS NOT NULL");
|
|
154
|
+
// Propagate root down the chain until no row changes (bounded to 100 passes).
|
|
155
|
+
for (let i = 0; i < 100; i++) {
|
|
156
|
+
db.exec(`
|
|
157
|
+
UPDATE sessions
|
|
158
|
+
SET root_session_id = (SELECT p.root_session_id FROM sessions p WHERE p.id = sessions.parent_session_id)
|
|
159
|
+
WHERE root_session_id IS NULL
|
|
160
|
+
AND parent_session_id IS NOT NULL
|
|
161
|
+
AND (SELECT p.root_session_id FROM sessions p WHERE p.id = sessions.parent_session_id) IS NOT NULL
|
|
162
|
+
`);
|
|
163
|
+
const remaining = db
|
|
164
|
+
.prepare("SELECT COUNT(*) AS c FROM sessions WHERE root_session_id IS NULL AND parent_session_id IS NOT NULL")
|
|
165
|
+
.get();
|
|
166
|
+
if (!remaining || remaining.c === 0)
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
// Any leftover (orphaned/cyclic parent chains) → treat as its own root.
|
|
170
|
+
db.exec("UPDATE sessions SET root_session_id = id WHERE root_session_id IS NULL");
|
|
171
|
+
}
|
|
102
172
|
function createInitialSchema(db) {
|
|
103
173
|
db.exec(`
|
|
104
174
|
CREATE TABLE IF NOT EXISTS workspaces (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { AgentMode, SessionInfo, SessionStatus, WorkspaceInfo } from "../types/index.js";
|
|
1
|
+
import type { AgentMode, ResumeEntry, SessionInfo, SessionKind, SessionStatus, WorkspaceInfo } from "../types/index.js";
|
|
2
|
+
import { type SQLiteDatabase } from "./db.js";
|
|
2
3
|
export declare class SessionStore {
|
|
3
4
|
private readonly workspace;
|
|
4
5
|
constructor(cwd: string);
|
|
@@ -6,18 +7,22 @@ export declare class SessionStore {
|
|
|
6
7
|
openSession(selector: string | undefined, model: string, mode: AgentMode, cwd: string): SessionInfo;
|
|
7
8
|
createSession(model: string, mode: AgentMode, cwd: string): SessionInfo;
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* CLI launch WITHOUT `--session` opens a fresh empty session, and test /
|
|
14
|
-
* harness runs leave behind title-only stubs — without this filter the picker
|
|
15
|
-
* fills with empty rows that resume to a blank screen, so a user picking one
|
|
16
|
-
* thinks resume is broken.
|
|
10
|
+
* Link a freshly-created session as a child of `parentId`, tagging its `kind`
|
|
11
|
+
* and inheriting the parent's `root_session_id` so the whole tree shares one
|
|
12
|
+
* root. Replaces the ad-hoc `UPDATE sessions SET parent_session_id = ?` the
|
|
13
|
+
* orchestrator previously hand-wrote (which never set kind/root).
|
|
17
14
|
*/
|
|
18
|
-
|
|
15
|
+
linkChild(childId: string, parentId: string, kind: SessionKind): void;
|
|
16
|
+
listRecentSessions(limit?: number): ResumeEntry[];
|
|
19
17
|
getLatestSession(): SessionInfo | null;
|
|
20
18
|
getSessionById(id: string): SessionInfo | null;
|
|
19
|
+
/**
|
|
20
|
+
* Authoritative session kind ("conversation" | "rotation" | "subagent").
|
|
21
|
+
* SessionInfo omits `kind`, so callers that need to know whether a session is
|
|
22
|
+
* a forked child (e.g. the turn_tool_load instrument) read it here. Returns
|
|
23
|
+
* null when the session row is absent.
|
|
24
|
+
*/
|
|
25
|
+
getSessionKind(id: string): SessionKind | null;
|
|
21
26
|
getRequiredSession(id: string): SessionInfo;
|
|
22
27
|
setStatus(id: string, status: SessionStatus): void;
|
|
23
28
|
setTitle(id: string, title: string | null): void;
|
|
@@ -25,4 +30,17 @@ export declare class SessionStore {
|
|
|
25
30
|
setMode(id: string, mode: AgentMode): void;
|
|
26
31
|
touchSession(id: string, cwd: string): void;
|
|
27
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* One row per conversation tree for the `/sessions` resume picker.
|
|
35
|
+
*
|
|
36
|
+
* - Groups by `root_session_id`; sub-agent sessions (`kind='subagent'`) are
|
|
37
|
+
* internal side-conversations and are excluded entirely.
|
|
38
|
+
* - Only trees with at least one persisted message surface (hides empty stub
|
|
39
|
+
* rows every keyless CLI launch creates).
|
|
40
|
+
* - The row's `title`/`created_at` come from the tree ROOT; `resume_id`,
|
|
41
|
+
* `model`, `updated_at`, `status` come from the LATEST leaf (the active tail
|
|
42
|
+
* of a rotation chain), so Enter resumes into the live session, not the
|
|
43
|
+
* compacted root. Ordered by tree activity, newest first.
|
|
44
|
+
*/
|
|
45
|
+
export declare function queryResumeList(db: SQLiteDatabase, workspaceId: string, limit: number): ResumeEntry[];
|
|
28
46
|
export { getSessionDir } from "./session-dir.js";
|
|
@@ -45,9 +45,9 @@ export class SessionStore {
|
|
|
45
45
|
const db = getDatabase();
|
|
46
46
|
db.prepare(`
|
|
47
47
|
INSERT INTO sessions (
|
|
48
|
-
id, workspace_id, title, model, mode, cwd_at_start, cwd_last, status, created_at, updated_at
|
|
48
|
+
id, workspace_id, title, model, mode, cwd_at_start, cwd_last, status, created_at, updated_at, kind, root_session_id
|
|
49
49
|
) VALUES (
|
|
50
|
-
@id, @workspace_id, NULL, @model, @mode, @cwd_at_start, @cwd_last, 'active', @created_at, @updated_at
|
|
50
|
+
@id, @workspace_id, NULL, @model, @mode, @cwd_at_start, @cwd_last, 'active', @created_at, @updated_at, 'conversation', @id
|
|
51
51
|
)
|
|
52
52
|
`).run({
|
|
53
53
|
id,
|
|
@@ -62,27 +62,19 @@ export class SessionStore {
|
|
|
62
62
|
return this.getRequiredSession(id);
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* CLI launch WITHOUT `--session` opens a fresh empty session, and test /
|
|
70
|
-
* harness runs leave behind title-only stubs — without this filter the picker
|
|
71
|
-
* fills with empty rows that resume to a blank screen, so a user picking one
|
|
72
|
-
* thinks resume is broken.
|
|
65
|
+
* Link a freshly-created session as a child of `parentId`, tagging its `kind`
|
|
66
|
+
* and inheriting the parent's `root_session_id` so the whole tree shares one
|
|
67
|
+
* root. Replaces the ad-hoc `UPDATE sessions SET parent_session_id = ?` the
|
|
68
|
+
* orchestrator previously hand-wrote (which never set kind/root).
|
|
73
69
|
*/
|
|
70
|
+
linkChild(childId, parentId, kind) {
|
|
71
|
+
const db = getDatabase();
|
|
72
|
+
const parent = db.prepare("SELECT root_session_id FROM sessions WHERE id = ?").get(parentId);
|
|
73
|
+
const root = parent?.root_session_id ?? parentId;
|
|
74
|
+
db.prepare("UPDATE sessions SET parent_session_id = ?, kind = ?, root_session_id = ?, updated_at = ? WHERE id = ?").run(parentId, kind, root, new Date().toISOString(), childId);
|
|
75
|
+
}
|
|
74
76
|
listRecentSessions(limit = 20) {
|
|
75
|
-
|
|
76
|
-
.prepare(`
|
|
77
|
-
SELECT s.id, s.workspace_id, s.title, s.model, s.mode, s.cwd_at_start, s.cwd_last, s.status, s.created_at, s.updated_at
|
|
78
|
-
FROM sessions s
|
|
79
|
-
WHERE s.workspace_id = ?
|
|
80
|
-
AND EXISTS (SELECT 1 FROM messages m WHERE m.session_id = s.id)
|
|
81
|
-
ORDER BY s.updated_at DESC
|
|
82
|
-
LIMIT ?
|
|
83
|
-
`)
|
|
84
|
-
.all(this.workspace.id, limit);
|
|
85
|
-
return rows.map(toSessionInfo);
|
|
77
|
+
return queryResumeList(getDatabase(), this.workspace.id, limit);
|
|
86
78
|
}
|
|
87
79
|
getLatestSession() {
|
|
88
80
|
const row = getDatabase()
|
|
@@ -106,6 +98,16 @@ export class SessionStore {
|
|
|
106
98
|
.get(id);
|
|
107
99
|
return row ? toSessionInfo(row) : null;
|
|
108
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Authoritative session kind ("conversation" | "rotation" | "subagent").
|
|
103
|
+
* SessionInfo omits `kind`, so callers that need to know whether a session is
|
|
104
|
+
* a forked child (e.g. the turn_tool_load instrument) read it here. Returns
|
|
105
|
+
* null when the session row is absent.
|
|
106
|
+
*/
|
|
107
|
+
getSessionKind(id) {
|
|
108
|
+
const row = getDatabase().prepare("SELECT kind FROM sessions WHERE id = ?").get(id);
|
|
109
|
+
return row?.kind ?? null;
|
|
110
|
+
}
|
|
109
111
|
getRequiredSession(id) {
|
|
110
112
|
const session = this.getSessionById(id);
|
|
111
113
|
if (!session) {
|
|
@@ -180,6 +182,61 @@ function toSessionInfo(row) {
|
|
|
180
182
|
updatedAt: new Date(row.updated_at),
|
|
181
183
|
};
|
|
182
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* One row per conversation tree for the `/sessions` resume picker.
|
|
187
|
+
*
|
|
188
|
+
* - Groups by `root_session_id`; sub-agent sessions (`kind='subagent'`) are
|
|
189
|
+
* internal side-conversations and are excluded entirely.
|
|
190
|
+
* - Only trees with at least one persisted message surface (hides empty stub
|
|
191
|
+
* rows every keyless CLI launch creates).
|
|
192
|
+
* - The row's `title`/`created_at` come from the tree ROOT; `resume_id`,
|
|
193
|
+
* `model`, `updated_at`, `status` come from the LATEST leaf (the active tail
|
|
194
|
+
* of a rotation chain), so Enter resumes into the live session, not the
|
|
195
|
+
* compacted root. Ordered by tree activity, newest first.
|
|
196
|
+
*/
|
|
197
|
+
export function queryResumeList(db, workspaceId, limit) {
|
|
198
|
+
const rows = db
|
|
199
|
+
.prepare(`
|
|
200
|
+
WITH candidates AS (
|
|
201
|
+
SELECT s.id, s.workspace_id, s.title, s.model, s.mode, s.cwd_at_start,
|
|
202
|
+
s.cwd_last, s.status, s.created_at, s.updated_at, s.root_session_id
|
|
203
|
+
FROM sessions s
|
|
204
|
+
WHERE s.workspace_id = ?
|
|
205
|
+
AND s.kind != 'subagent'
|
|
206
|
+
AND EXISTS (SELECT 1 FROM messages m WHERE m.session_id = s.id)
|
|
207
|
+
),
|
|
208
|
+
ranked AS (
|
|
209
|
+
SELECT c.*,
|
|
210
|
+
ROW_NUMBER() OVER (
|
|
211
|
+
PARTITION BY c.root_session_id
|
|
212
|
+
ORDER BY c.updated_at DESC, c.id DESC
|
|
213
|
+
) AS rn
|
|
214
|
+
FROM candidates c
|
|
215
|
+
)
|
|
216
|
+
SELECT
|
|
217
|
+
r.root_session_id AS id,
|
|
218
|
+
r.id AS resume_id,
|
|
219
|
+
COALESCE(root.title, r.title) AS title,
|
|
220
|
+
r.model AS model,
|
|
221
|
+
r.mode AS mode,
|
|
222
|
+
COALESCE(root.cwd_at_start, r.cwd_at_start) AS cwd_at_start,
|
|
223
|
+
r.cwd_last AS cwd_last,
|
|
224
|
+
r.status AS status,
|
|
225
|
+
COALESCE(root.created_at, r.created_at) AS created_at,
|
|
226
|
+
r.updated_at AS updated_at,
|
|
227
|
+
r.workspace_id AS workspace_id
|
|
228
|
+
FROM ranked r
|
|
229
|
+
LEFT JOIN sessions root ON root.id = r.root_session_id
|
|
230
|
+
WHERE r.rn = 1
|
|
231
|
+
ORDER BY r.updated_at DESC
|
|
232
|
+
LIMIT ?
|
|
233
|
+
`)
|
|
234
|
+
.all(workspaceId, limit);
|
|
235
|
+
return rows.map(toResumeEntry);
|
|
236
|
+
}
|
|
237
|
+
function toResumeEntry(row) {
|
|
238
|
+
return { ...toSessionInfo(row), resumeId: row.resume_id };
|
|
239
|
+
}
|
|
183
240
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
184
241
|
// B-3: Re-export getSessionDir from the isolated session-dir module.
|
|
185
242
|
//
|
|
@@ -10,7 +10,7 @@ export function buildEffectiveTranscript(messages, seqs, timestamps, compaction)
|
|
|
10
10
|
}
|
|
11
11
|
const firstKeptIndex = seqs.findIndex((seq) => seq >= compaction.firstKeptSeq);
|
|
12
12
|
let keptIndex = firstKeptIndex >= 0 ? firstKeptIndex : messages.length;
|
|
13
|
-
// Anti-mù / Resilience: if firstKeptSeq landed on a `tool` message (e.g. due to seq array
|
|
13
|
+
// Anti-mù / Resilience: if firstKeptSeq landed on a `tool` message (e.g. due to seq array
|
|
14
14
|
// misalignment or forced cut), we MUST step back to include its preceding `assistant` message.
|
|
15
15
|
// Otherwise Vercel AI SDK throws: "Messages with role 'tool' must be a response to a preceding message with 'tool_calls'"
|
|
16
16
|
if (keptIndex > 0 && messages[keptIndex]?.role === "tool") {
|
|
@@ -5,6 +5,45 @@ export declare function loadLatestCompaction(sessionId: string): PersistedCompac
|
|
|
5
5
|
export declare function loadRawTranscript(sessionId: string): ModelMessage[];
|
|
6
6
|
export declare function loadTranscriptState(sessionId: string): LoadedTranscriptState;
|
|
7
7
|
export declare function loadTranscript(sessionId: string): ModelMessage[];
|
|
8
|
+
/**
|
|
9
|
+
* Resume a session together with every session in its conversation tree.
|
|
10
|
+
*
|
|
11
|
+
* When a session has spawned child sessions (silent rotations, sub-agents,
|
|
12
|
+
* sub-sessions), resuming only the parent loses the work that happened in the
|
|
13
|
+
* children. This loader walks up to the root and then down through all
|
|
14
|
+
* descendants, applies each session's own compaction, merges the messages
|
|
15
|
+
* chronologically, and returns them as one flat transcript for the model.
|
|
16
|
+
*
|
|
17
|
+
* Sequence numbers from sessions other than the one being resumed are replaced
|
|
18
|
+
* with `null` so that usage attribution and compaction still belong to the
|
|
19
|
+
* resumed session.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadSessionChainTranscriptState(sessionId: string): LoadedTranscriptState;
|
|
22
|
+
/**
|
|
23
|
+
* One node of the session tree that a single resumed TUI hosts: the root
|
|
24
|
+
* conversation plus every rotation / sub-agent descendant. Powers the rail's
|
|
25
|
+
* "Sessions" block so the multi-session structure is visible after resume
|
|
26
|
+
* (the message content is already merged by loadSessionChainTranscriptState;
|
|
27
|
+
* this exposes WHICH sessions produced it).
|
|
28
|
+
*/
|
|
29
|
+
export interface SessionChainNode {
|
|
30
|
+
id: string;
|
|
31
|
+
kind: "conversation" | "rotation" | "subagent" | null;
|
|
32
|
+
model: string | null;
|
|
33
|
+
status: string | null;
|
|
34
|
+
messageCount: number;
|
|
35
|
+
parentId: string | null;
|
|
36
|
+
/** Tree depth: 0 = root, 1 = direct child, … (for indented rendering). */
|
|
37
|
+
depth: number;
|
|
38
|
+
/** True for the node whose id was passed to resume (the "current" session). */
|
|
39
|
+
isCurrent: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Enumerate the full session chain (root + all descendants) with per-session
|
|
43
|
+
* metadata, ordered root-first then by creation time. Read-only; safe to call
|
|
44
|
+
* on every render. Returns a single-node array for a session with no children.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getSessionChainInfos(sessionId: string): SessionChainNode[];
|
|
8
47
|
export declare function getNextMessageSequence(sessionId: string): number;
|
|
9
48
|
export declare function appendMessages(sessionId: string, messages: ModelMessage[]): number[];
|
|
10
49
|
export declare function appendSystemMessage(sessionId: string, content: string): number | null;
|
|
@@ -108,3 +147,15 @@ export declare function revertLatestCompaction(sessionId: string): void;
|
|
|
108
147
|
export declare function getSessionChain(sessionId: string): string[];
|
|
109
148
|
export declare function buildChatEntries(sessionId: string): ChatEntry[];
|
|
110
149
|
export declare function getLastTodoWriteArgs(sessionId: string): string | null;
|
|
150
|
+
/**
|
|
151
|
+
* Persist the approved plan text for a session so that "tiếp tục"/"continue"
|
|
152
|
+
* turns (which are classified as chitchat/general by PIL Pass 0) can re-inject
|
|
153
|
+
* the APPROVED PLAN section into the system prompt instead of forgetting context.
|
|
154
|
+
*
|
|
155
|
+
* Stored as a synthetic tool_call row (tool_name='__approved_plan') so we reuse
|
|
156
|
+
* the existing schema and getLast* query pattern without a new table/migration.
|
|
157
|
+
* The planText is stored verbatim in args_json.
|
|
158
|
+
*/
|
|
159
|
+
export declare function persistApprovedPlan(sessionId: string, planText: string): void;
|
|
160
|
+
/** Load the most recent persisted approved plan for this session (or parent chain). */
|
|
161
|
+
export declare function getLastApprovedPlan(sessionId: string): string | null;
|