muonroi-cli 1.8.4 → 1.9.0
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-filter.js +11 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +7 -0
- package/dist/packages/agent-harness-core/src/event-tee.d.ts +64 -0
- package/dist/packages/agent-harness-core/src/event-tee.js +104 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +25 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +169 -21
- package/dist/packages/agent-harness-core/src/predicate.d.ts +1 -1
- package/dist/packages/agent-harness-core/src/protocol.d.ts +90 -4
- 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 +38 -0
- package/dist/src/agent-harness/mock-model.js +69 -3
- package/dist/src/agent-harness/test-spawn.js +31 -0
- package/dist/src/chat/chat-keychain.d.ts +7 -12
- package/dist/src/chat/chat-keychain.js +19 -86
- 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 +10 -47
- package/dist/src/cli/keys.js +31 -399
- package/dist/src/council/clarifier.d.ts +31 -3
- package/dist/src/council/clarifier.js +220 -32
- 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 +54 -5
- 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 +1265 -135
- package/dist/src/council/index.d.ts +108 -1
- package/dist/src/council/index.js +670 -197
- package/dist/src/council/leader.d.ts +26 -0
- package/dist/src/council/leader.js +150 -9
- package/dist/src/council/llm.d.ts +94 -0
- package/dist/src/council/llm.js +348 -55
- package/dist/src/council/panel-select.d.ts +30 -0
- package/dist/src/council/panel-select.js +82 -0
- package/dist/src/council/planner.js +40 -0
- package/dist/src/council/preflight.d.ts +17 -0
- package/dist/src/council/preflight.js +50 -2
- package/dist/src/council/prompts.d.ts +39 -4
- package/dist/src/council/prompts.js +256 -69
- 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 +138 -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 +20 -0
- package/dist/src/ee/auth.js +54 -2
- package/dist/src/ee/bridge.d.ts +10 -0
- package/dist/src/ee/bridge.js +58 -0
- package/dist/src/ee/client.js +109 -21
- package/dist/src/ee/ee-onboarding.js +6 -26
- 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 +58 -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 +14 -1
- package/dist/src/flow/compaction/index.js +96 -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/compaction/progress.d.ts +35 -0
- package/dist/src/flow/compaction/progress.js +35 -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 +66 -0
- package/dist/src/gsd/flags.js +102 -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 +283 -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/headless/council-answers.js +4 -0
- package/dist/src/hooks/index.js +1 -1
- package/dist/src/index.js +172 -270
- package/dist/src/lsp/builtins.js +3 -1
- package/dist/src/lsp/manager.d.ts +5 -1
- package/dist/src/lsp/manager.js +249 -3
- package/dist/src/lsp/npm-cache.d.ts +11 -1
- package/dist/src/lsp/npm-cache.js +17 -1
- package/dist/src/lsp/runtime.d.ts +6 -1
- package/dist/src/lsp/runtime.js +17 -1
- package/dist/src/lsp/types.d.ts +83 -1
- package/dist/src/lsp/types.js +10 -0
- 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 +44 -16
- package/dist/src/mcp/lsp-tools.d.ts +5 -1
- package/dist/src/mcp/lsp-tools.js +93 -2
- package/dist/src/mcp/mcp-keychain.d.ts +3 -5
- package/dist/src/mcp/mcp-keychain.js +9 -49
- 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 +22 -2
- package/dist/src/mcp/tools-server.d.ts +10 -0
- package/dist/src/mcp/tools-server.js +10 -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/ask-user.d.ts +61 -0
- package/dist/src/orchestrator/ask-user.js +65 -0
- 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 +12 -3
- package/dist/src/orchestrator/compaction.js +35 -15
- package/dist/src/orchestrator/council-manager.d.ts +12 -3
- package/dist/src/orchestrator/council-manager.js +74 -32
- package/dist/src/orchestrator/council-request.d.ts +49 -0
- package/dist/src/orchestrator/council-request.js +62 -0
- 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/interactive-pause.d.ts +26 -0
- package/dist/src/orchestrator/interactive-pause.js +36 -0
- package/dist/src/orchestrator/message-processor.d.ts +4 -0
- package/dist/src/orchestrator/message-processor.js +268 -41
- package/dist/src/orchestrator/orchestrator.d.ts +64 -3
- package/dist/src/orchestrator/orchestrator.js +823 -120
- package/dist/src/orchestrator/preprocessor.js +3 -3
- 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-askcard.d.ts +1 -1
- package/dist/src/orchestrator/safety-askcard.js +5 -2
- package/dist/src/orchestrator/safety-intercept.d.ts +50 -0
- package/dist/src/orchestrator/safety-intercept.js +62 -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 +31 -3
- package/dist/src/orchestrator/stall-watchdog.js +65 -10
- package/dist/src/orchestrator/stream-runner.d.ts +13 -3
- package/dist/src/orchestrator/stream-runner.js +115 -49
- 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 +41 -0
- package/dist/src/orchestrator/tool-engine.js +846 -66
- 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 +44 -0
- package/dist/src/orchestrator/turn-watchdog.js +84 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +6 -4
- 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.d.ts +1 -1
- package/dist/src/pil/discovery.js +18 -13
- 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/layer1_5-complexity-size.d.ts +7 -0
- package/dist/src/pil/layer1_5-complexity-size.js +31 -5
- 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 +111 -5
- package/dist/src/pil/llm-classify.js +421 -189
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +8 -0
- package/dist/src/pil/pipeline.js +36 -2
- package/dist/src/pil/repo-grounding-probe.d.ts +15 -0
- package/dist/src/pil/repo-grounding-probe.js +136 -0
- package/dist/src/pil/repo-structure-hints.d.ts +7 -0
- package/dist/src/pil/repo-structure-hints.js +45 -0
- 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/artifact-io.js +4 -0
- 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/criteria-seed.d.ts +51 -0
- package/dist/src/product-loop/criteria-seed.js +200 -0
- 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.d.ts +9 -0
- package/dist/src/product-loop/discovery-interview.js +60 -12
- package/dist/src/product-loop/discovery-recommender.js +2 -1
- package/dist/src/product-loop/discovery-schema.js +19 -2
- package/dist/src/product-loop/discovery-triage.d.ts +23 -0
- package/dist/src/product-loop/discovery-triage.js +109 -0
- package/dist/src/product-loop/gather.js +150 -2
- 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 +340 -52
- package/dist/src/product-loop/loop-driver.d.ts +7 -0
- package/dist/src/product-loop/loop-driver.js +330 -106
- package/dist/src/product-loop/phase-plan.d.ts +21 -0
- package/dist/src/product-loop/phase-plan.js +81 -6
- package/dist/src/product-loop/phase-rituals.d.ts +3 -0
- package/dist/src/product-loop/phase-rituals.js +8 -3
- package/dist/src/product-loop/phase-runner.js +39 -12
- package/dist/src/product-loop/plan-adherence-review.d.ts +26 -0
- package/dist/src/product-loop/plan-adherence-review.js +144 -0
- package/dist/src/product-loop/sprint-runner.d.ts +173 -0
- package/dist/src/product-loop/sprint-runner.js +863 -19
- package/dist/src/product-loop/types.d.ts +61 -5
- package/dist/src/providers/adapter.d.ts +1 -1
- package/dist/src/providers/adapter.js +3 -4
- package/dist/src/providers/anthropic.d.ts +9 -8
- package/dist/src/providers/anthropic.js +13 -47
- 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/grok-oauth.d.ts +1 -0
- package/dist/src/providers/auth/grok-oauth.js +30 -5
- package/dist/src/providers/auth/openai-oauth.d.ts +1 -0
- package/dist/src/providers/auth/openai-oauth.js +15 -1
- package/dist/src/providers/auth/registry.js +0 -34
- package/dist/src/providers/auth/token-store.d.ts +9 -9
- package/dist/src/providers/auth/token-store.js +8 -67
- package/dist/src/providers/auth/types.d.ts +9 -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/env-store.d.ts +17 -0
- package/dist/src/providers/env-store.js +228 -0
- package/dist/src/providers/keychain.d.ts +22 -18
- package/dist/src/providers/keychain.js +127 -140
- 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 +43 -3
- package/dist/src/providers/runtime.js +88 -14
- 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 +288 -1
- package/dist/src/providers/strategies/xai.strategy.js +27 -0
- 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/warm.d.ts +65 -0
- package/dist/src/providers/warm.js +145 -0
- 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 +6 -5
- 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 +340 -15
- package/dist/src/tools/file.d.ts +15 -0
- package/dist/src/tools/file.js +32 -0
- package/dist/src/tools/git-safety.d.ts +19 -0
- package/dist/src/tools/git-safety.js +168 -0
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +81 -1
- package/dist/src/tools/registry.d.ts +20 -0
- package/dist/src/tools/registry.js +576 -23
- package/dist/src/tools/research.d.ts +29 -0
- package/dist/src/tools/research.js +233 -0
- package/dist/src/types/index.d.ts +147 -4
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/cards/product-status-card.js +1 -1
- package/dist/src/ui/components/agent-rail-activities.d.ts +26 -0
- package/dist/src/ui/components/agent-rail-activities.js +47 -0
- 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/compact-progress-card.d.ts +24 -0
- package/dist/src/ui/components/compact-progress-card.js +42 -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 +66 -17
- 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 +13 -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/message-view.d.ts +15 -0
- package/dist/src/ui/components/message-view.js +50 -1
- 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/components/tool-group.d.ts +15 -3
- package/dist/src/ui/components/tool-group.js +69 -11
- package/dist/src/ui/containers/modals-layer.d.ts +4 -2
- package/dist/src/ui/containers/modals-layer.js +2 -2
- package/dist/src/ui/council-harness-event.d.ts +57 -0
- package/dist/src/ui/council-harness-event.js +46 -0
- package/dist/src/ui/heartbeat-debug.d.ts +29 -0
- package/dist/src/ui/heartbeat-debug.js +45 -0
- 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/model-picker-modal.d.ts +8 -18
- package/dist/src/ui/modals/model-picker-modal.js +8 -10
- 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/ee.js +81 -0
- 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 +23 -20
- 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/agent-activities.d.ts +39 -0
- package/dist/src/ui/utils/agent-activities.js +96 -0
- package/dist/src/ui/utils/format.d.ts +14 -0
- package/dist/src/ui/utils/format.js +23 -3
- package/dist/src/ui/utils/group-tool-entries.d.ts +26 -0
- package/dist/src/ui/utils/group-tool-entries.js +111 -0
- package/dist/src/ui/utils/tool-summary.d.ts +21 -0
- package/dist/src/ui/utils/tool-summary.js +91 -0
- package/dist/src/usage/downgrade.js +2 -2
- package/dist/src/usage/product-ledger.js +2 -2
- package/dist/src/utils/event-loop-monitor.d.ts +85 -0
- package/dist/src/utils/event-loop-monitor.js +107 -0
- package/dist/src/utils/install-manager.js +2 -1
- package/dist/src/utils/llm-deadline.d.ts +14 -0
- package/dist/src/utils/llm-deadline.js +19 -0
- package/dist/src/utils/logger.js +2 -2
- package/dist/src/utils/loop-profiler.d.ts +102 -0
- package/dist/src/utils/loop-profiler.js +202 -0
- package/dist/src/utils/permission-mode.js +5 -3
- package/dist/src/utils/redactor.js +1 -1
- package/dist/src/utils/settings.d.ts +180 -5
- package/dist/src/utils/settings.js +271 -31
- package/dist/src/utils/side-question.d.ts +1 -2
- package/dist/src/utils/side-question.js +2 -2
- 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 +52 -17
- package/dist/src/verify/orchestrator.d.ts +1 -1
- package/dist/src/verify/orchestrator.js +20 -3
- package/dist/src/verify/recipes.d.ts +13 -0
- package/dist/src/verify/recipes.js +15 -0
- package/package.json +134 -132
- package/dist/src/cli/bw-vault.d.ts +0 -55
- package/dist/src/cli/bw-vault.js +0 -133
- package/dist/src/mcp/ee-tools.d.ts +0 -46
- package/dist/src/mcp/ee-tools.js +0 -193
- package/dist/src/providers/auth/gcloud.d.ts +0 -28
- package/dist/src/providers/auth/gcloud.js +0 -102
- package/dist/src/providers/auth/gemini-oauth.d.ts +0 -82
- package/dist/src/providers/auth/gemini-oauth.js +0 -472
- package/dist/src/providers/gemini.d.ts +0 -11
- package/dist/src/providers/gemini.js +0 -45
- package/dist/src/providers/siliconflow-sse-repair.d.ts +0 -58
- package/dist/src/providers/siliconflow-sse-repair.js +0 -177
- package/dist/src/providers/strategies/google.strategy.d.ts +0 -22
- package/dist/src/providers/strategies/google.strategy.js +0 -174
- package/dist/src/providers/strategies/siliconflow.strategy.js +0 -29
- package/dist/src/ui/containers/chat-feed.d.ts +0 -40
- package/dist/src/ui/containers/chat-feed.js +0 -66
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// src/ee/who-am-i-brain.ts
|
|
2
|
+
//
|
|
3
|
+
// Brain-derived "Who Am I" fallback for THIN-CLIENTS.
|
|
4
|
+
//
|
|
5
|
+
// The device-local profile.yaml pipeline (src/ee/who-am-i.ts) is full-brain-only:
|
|
6
|
+
// the EE prompt interceptor bails early on remote mode (`if (isRemoteMode()) return`),
|
|
7
|
+
// no /api/profile endpoint exists, and signal-extraction from transcripts never runs
|
|
8
|
+
// on a thin-client. So on a thin-client getWhoAmIProfile() is structurally always
|
|
9
|
+
// null and the PIL loses every style signal.
|
|
10
|
+
//
|
|
11
|
+
// The user's working style IS reachable though — it lives in the `experience-behavioral`
|
|
12
|
+
// brain (their own authored rules: "recommend, don't ask", "keep it concise", etc.),
|
|
13
|
+
// which the runtime already queries via searchByText() over /api/search. This module
|
|
14
|
+
// derives the SAME WhoAmIProfile shape from those rules so all existing PIL wiring
|
|
15
|
+
// (outputStyleFromProfile, the layer4/5/6 dim reads) works unchanged.
|
|
16
|
+
//
|
|
17
|
+
// Design guarantees:
|
|
18
|
+
// • Agent-first (no keyword regex): the rule→dim mapping is decided by the brain LLM
|
|
19
|
+
// itself (classifyViaBrain), honouring the repo rule that classification is never
|
|
20
|
+
// regex. The only regex here is tolerant JSON extraction from the LLM's reply.
|
|
21
|
+
// • Privacy: dims are re-gated locally through selectWhoAmIDims — the positive
|
|
22
|
+
// name-allowlist + per-tier confidence floor. Brain rules are user-authored style
|
|
23
|
+
// guidance (Tang-2 equivalent), so we gate at the "standard" tier; emotional.* can
|
|
24
|
+
// never surface (not on the allowlist). This is decoupled from the EE file
|
|
25
|
+
// privacyLevel (which governs the *auto-derived* on-device profile — a different,
|
|
26
|
+
// more sensitive data source that is off by default on thin-clients).
|
|
27
|
+
// • Fail-open: any gap (no rules, classifier null, unparseable output, dep throws)
|
|
28
|
+
// returns null → the PIL keeps its own per-turn default. Never throws.
|
|
29
|
+
import { selectWhoAmIDims } from "./who-am-i.js";
|
|
30
|
+
const BEHAVIORAL_COLLECTION = "experience-behavioral";
|
|
31
|
+
const BRAIN_TOPK = 12;
|
|
32
|
+
/** Brain rules are style-level guidance → the standard tier (never emotional). */
|
|
33
|
+
const BRAIN_TIER = "standard";
|
|
34
|
+
/**
|
|
35
|
+
* System prompt override — REQUIRED. The EE brain proxy's default system prompt is a
|
|
36
|
+
* tier-classifier ("output ONE word: fast|balanced|premium … ignore the task content"),
|
|
37
|
+
* which actively hijacks any structured-output request → malformed JSON. Verified on the
|
|
38
|
+
* live VPS (2026-07-05): omitting this made even DeepSeek-V3 emit garbage; supplying it
|
|
39
|
+
* makes the DEFAULT server model (Qwen2.5-7B) emit clean, accurate dims JSON. We do NOT
|
|
40
|
+
* override the model/provider — that would hardcode a model id (Zero-Hardcode Rule) and
|
|
41
|
+
* cost the user's own provider; the server's default brain model + key does the work.
|
|
42
|
+
*/
|
|
43
|
+
const STYLE_SYSTEM_PROMPT = "You extract a developer's working-style profile from their accumulated behavioral " +
|
|
44
|
+
"rules. Follow the user message instructions EXACTLY and output ONLY the requested " +
|
|
45
|
+
"JSON object. Do not classify task complexity, do not output single words, do not " +
|
|
46
|
+
"add prose before or after the JSON.";
|
|
47
|
+
/**
|
|
48
|
+
* Probe the behavioral brain for working-style rules. Free-text; the server embeds
|
|
49
|
+
* + searches Qdrant. Intentionally broad — it should surface brevity / decision /
|
|
50
|
+
* feedback / delegation / risk / conflict guidance the user has accumulated.
|
|
51
|
+
*/
|
|
52
|
+
const STYLE_PROBE = "the user's preferred working style: communication brevity, decision speed, " +
|
|
53
|
+
"feedback and correction style, delegation style, risk tolerance, conflict style";
|
|
54
|
+
// The dims the brain may emit, with the EXACT value vocabulary. Source of truth is
|
|
55
|
+
// the EE profile renderer (~/.experience/src/profile-render.js DIRECTIVES) — the same
|
|
56
|
+
// values the device-local profile uses and that the PIL layers compare against
|
|
57
|
+
// literally (e.g. layer4 tests delegation === "autonomous", layer6 tests
|
|
58
|
+
// feedback_style === "precise-correction"). A value outside this set would populate a
|
|
59
|
+
// dim that no lever reads → silently inert. Keep in lockstep with the EE enum.
|
|
60
|
+
const DIM_VOCAB = {
|
|
61
|
+
"communication.brevity": ["concise", "moderate", "verbose"],
|
|
62
|
+
"communication.feedback_style": ["implicit", "precise-correction"],
|
|
63
|
+
"communication.question_style": ["comparison", "debugging", "exploratory", "directive"],
|
|
64
|
+
"personality.decision_speed": ["fast-intuitive", "measured", "deliberate"],
|
|
65
|
+
"personality.risk_tolerance": ["experimental"],
|
|
66
|
+
"personality.conflict_style": ["direct-constructive", "authoritative", "cautious"],
|
|
67
|
+
"work_patterns.energy": ["night-owl", "daytime", "mixed"],
|
|
68
|
+
"work_patterns.multitasking": ["task-switcher", "sequential-deep"],
|
|
69
|
+
"work_patterns.session_length": ["short", "medium", "long"],
|
|
70
|
+
"work_patterns.delegation_style": ["autonomous", "collaborative"],
|
|
71
|
+
};
|
|
72
|
+
/** Feature flag — default ON, opt out with MUONROI_WHOAMI_BRAIN=0. */
|
|
73
|
+
export function isBrainWhoAmIEnabled() {
|
|
74
|
+
return process.env.MUONROI_WHOAMI_BRAIN !== "0";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* PURE: build the classify prompt. Asks the brain to distil the retrieved rules into
|
|
78
|
+
* a strict dims JSON using only the allowed names + vocabulary. Emitting fewer dims
|
|
79
|
+
* (only the confident ones) is explicitly encouraged — downstream drops the rest.
|
|
80
|
+
*/
|
|
81
|
+
export function buildStyleClassifyPrompt(rules) {
|
|
82
|
+
const vocabLines = Object.entries(DIM_VOCAB)
|
|
83
|
+
.map(([name, values]) => ` "${name}": one of ${values.map((v) => `"${v}"`).join(" | ")}`)
|
|
84
|
+
.join("\n");
|
|
85
|
+
const ruleBlock = rules.length
|
|
86
|
+
? rules.map((r, i) => `${i + 1}. ${r}`).join("\n")
|
|
87
|
+
: "(no explicit rules retrieved — infer nothing; emit an empty dimensions object)";
|
|
88
|
+
return [
|
|
89
|
+
"You classify a developer's working style from their accumulated behavioral rules.",
|
|
90
|
+
"Output ONLY a JSON object of the form:",
|
|
91
|
+
'{"dimensions": {"<dim.name>": {"value": "<allowed value>", "confidence": 0.0-1.0, "sampleCount": <int>}}}',
|
|
92
|
+
"",
|
|
93
|
+
"Allowed dimensions and their vocabulary (use these names/values EXACTLY):",
|
|
94
|
+
vocabLines,
|
|
95
|
+
"",
|
|
96
|
+
"Rules:",
|
|
97
|
+
"- Include a dimension ONLY when the rules give clear evidence for it.",
|
|
98
|
+
"- Omit anything uncertain — a small, confident object beats a complete guess.",
|
|
99
|
+
"- confidence reflects how strongly the rules support the value; sampleCount = how many rules back it.",
|
|
100
|
+
"- Never invent dimension names or values outside the vocabulary above.",
|
|
101
|
+
"",
|
|
102
|
+
"Behavioral rules:",
|
|
103
|
+
ruleBlock,
|
|
104
|
+
].join("\n");
|
|
105
|
+
}
|
|
106
|
+
/** Tolerantly extract the first balanced JSON object from an LLM reply. */
|
|
107
|
+
function extractJsonObject(text) {
|
|
108
|
+
const start = text.indexOf("{");
|
|
109
|
+
if (start === -1)
|
|
110
|
+
return null;
|
|
111
|
+
let depth = 0;
|
|
112
|
+
let inStr = false;
|
|
113
|
+
let esc = false;
|
|
114
|
+
for (let i = start; i < text.length; i++) {
|
|
115
|
+
const ch = text[i];
|
|
116
|
+
if (inStr) {
|
|
117
|
+
if (esc)
|
|
118
|
+
esc = false;
|
|
119
|
+
else if (ch === "\\")
|
|
120
|
+
esc = true;
|
|
121
|
+
else if (ch === '"')
|
|
122
|
+
inStr = false;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (ch === '"')
|
|
126
|
+
inStr = true;
|
|
127
|
+
else if (ch === "{")
|
|
128
|
+
depth++;
|
|
129
|
+
else if (ch === "}") {
|
|
130
|
+
depth--;
|
|
131
|
+
if (depth === 0)
|
|
132
|
+
return text.slice(start, i + 1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* PURE: coerce a brain reply (JSON string, fenced block, or already-parsed object)
|
|
139
|
+
* into a privacy-gated WhoAmIProfile. Reuses selectWhoAmIDims for the allowlist +
|
|
140
|
+
* confidence floor. Returns null when nothing usable survives.
|
|
141
|
+
*/
|
|
142
|
+
export function parseBrainProfile(raw, level = BRAIN_TIER) {
|
|
143
|
+
let obj = raw;
|
|
144
|
+
if (typeof raw === "string") {
|
|
145
|
+
const json = extractJsonObject(raw);
|
|
146
|
+
if (!json)
|
|
147
|
+
return null;
|
|
148
|
+
try {
|
|
149
|
+
obj = JSON.parse(json);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!obj || typeof obj !== "object")
|
|
156
|
+
return null;
|
|
157
|
+
const gated = selectWhoAmIDims(obj, level);
|
|
158
|
+
// Value validation — the name allowlist in selectWhoAmIDims does NOT check the VALUE,
|
|
159
|
+
// and weaker brain models mis-spell the vocabulary (verified on the live VPS:
|
|
160
|
+
// Qwen2.5-7B emitted "precice-correction"). An off-vocab value populates a dim that
|
|
161
|
+
// the PIL layers — which compare literally — can never fire on, so it's worse than
|
|
162
|
+
// absent (looks set, does nothing). Drop any value not in DIM_VOCAB[name].
|
|
163
|
+
const dims = {};
|
|
164
|
+
for (const [name, dim] of Object.entries(gated)) {
|
|
165
|
+
const vocab = DIM_VOCAB[name];
|
|
166
|
+
if (vocab && !vocab.includes(dim.value))
|
|
167
|
+
continue;
|
|
168
|
+
dims[name] = dim;
|
|
169
|
+
}
|
|
170
|
+
if (Object.keys(dims).length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
return { level, dims };
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Off the hot path (fire-and-forget boot warm), so a wide budget. The server's
|
|
176
|
+
* brainExtractModel is a REASONING model (deepseek-v4-flash) and the who-am-i prompt is large
|
|
177
|
+
* (12 retrieved rules + the full dim-vocabulary schema), so the think+emit cycle runs ~10-15s
|
|
178
|
+
* — verified live that a 15s cap intermittently truncated to a timeout/null. 25s clears the
|
|
179
|
+
* tail; the cost is nil because this never blocks anything (background warm).
|
|
180
|
+
*/
|
|
181
|
+
const BRAIN_CLASSIFY_TIMEOUT_MS = 25000;
|
|
182
|
+
/**
|
|
183
|
+
* The dims JSON is tiny (~200 tokens), but the server's extract model (deepseek-v4-flash) is a
|
|
184
|
+
* REASONING model — its thinking tokens count against this same budget (landing in a separate
|
|
185
|
+
* reasoning_content field, not the JSON). A tight cap let the reasoning consume the budget and
|
|
186
|
+
* truncate the actual JSON to empty → intermittent null profiles. Give thinking ample headroom
|
|
187
|
+
* so the dims JSON always survives; extra tokens are only spent when the model reasons, and
|
|
188
|
+
* this is an off-hot-path boot warm.
|
|
189
|
+
*/
|
|
190
|
+
const BRAIN_CLASSIFY_MAX_TOKENS = 3000;
|
|
191
|
+
/**
|
|
192
|
+
* Derive a WhoAmIProfile from the behavioral brain. Search the user's style rules →
|
|
193
|
+
* classify them into dims via the brain LLM → privacy-gate locally. Fail-open null.
|
|
194
|
+
*/
|
|
195
|
+
export async function deriveWhoAmIFromBrain(deps, level = BRAIN_TIER) {
|
|
196
|
+
try {
|
|
197
|
+
const points = await deps.searchByText(STYLE_PROBE, [BEHAVIORAL_COLLECTION], BRAIN_TOPK);
|
|
198
|
+
const rules = points
|
|
199
|
+
.map((p) => (typeof p.payload?.text === "string" ? p.payload.text.trim() : ""))
|
|
200
|
+
.filter((t) => t.length > 0);
|
|
201
|
+
if (rules.length === 0)
|
|
202
|
+
return null;
|
|
203
|
+
const reply = await deps.classifyViaBrain(buildStyleClassifyPrompt(rules), BRAIN_CLASSIFY_TIMEOUT_MS, {
|
|
204
|
+
systemPrompt: STYLE_SYSTEM_PROMPT,
|
|
205
|
+
responseFormat: { type: "json_object" },
|
|
206
|
+
maxTokens: BRAIN_CLASSIFY_MAX_TOKENS,
|
|
207
|
+
// Structured multi-dim extraction needs the server's stronger brainExtractModel;
|
|
208
|
+
// the hot-path model mis-spells the vocabulary (verified on the live VPS).
|
|
209
|
+
useExtractModel: true,
|
|
210
|
+
});
|
|
211
|
+
if (!reply)
|
|
212
|
+
return null;
|
|
213
|
+
return parseBrainProfile(reply, level);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// Fail-open — a degraded brain must never break the PIL hot path.
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=who-am-i-brain.js.map
|
|
@@ -10,13 +10,13 @@ export interface WhoAmIProfile {
|
|
|
10
10
|
level: PrivacyLevel;
|
|
11
11
|
dims: Partial<Record<WhoAmIDimName, WhoAmIDim>>;
|
|
12
12
|
}
|
|
13
|
-
interface RawDim {
|
|
13
|
+
export interface RawDim {
|
|
14
14
|
value: string | null;
|
|
15
15
|
confidence?: number;
|
|
16
16
|
sampleCount?: number;
|
|
17
17
|
samples?: number;
|
|
18
18
|
}
|
|
19
|
-
interface RawProfile {
|
|
19
|
+
export interface RawProfile {
|
|
20
20
|
dimensions?: Record<string, RawDim>;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
@@ -38,4 +38,11 @@ export declare function outputStyleFromProfile(profile: WhoAmIProfile | null): O
|
|
|
38
38
|
export declare function getWhoAmIProfile(): WhoAmIProfile | null;
|
|
39
39
|
/** Clear the cache — test-only / after a known profile change. */
|
|
40
40
|
export declare function resetWhoAmICache(): void;
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Prime the per-process cache with an externally-derived profile (e.g. the
|
|
43
|
+
* thin-client brain fallback in who-am-i-brain.ts, wired via the bridge). Only
|
|
44
|
+
* overwrites when the device-local read produced nothing (`_cache` is null/unset)
|
|
45
|
+
* so a real on-device profile always wins over a brain-derived one. No-op when a
|
|
46
|
+
* device-local profile is already loaded.
|
|
47
|
+
*/
|
|
48
|
+
export declare function primeWhoAmICache(profile: WhoAmIProfile | null): void;
|
package/dist/src/ee/who-am-i.js
CHANGED
|
@@ -110,6 +110,18 @@ export function getWhoAmIProfile() {
|
|
|
110
110
|
export function resetWhoAmICache() {
|
|
111
111
|
_cache = undefined;
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Prime the per-process cache with an externally-derived profile (e.g. the
|
|
115
|
+
* thin-client brain fallback in who-am-i-brain.ts, wired via the bridge). Only
|
|
116
|
+
* overwrites when the device-local read produced nothing (`_cache` is null/unset)
|
|
117
|
+
* so a real on-device profile always wins over a brain-derived one. No-op when a
|
|
118
|
+
* device-local profile is already loaded.
|
|
119
|
+
*/
|
|
120
|
+
export function primeWhoAmICache(profile) {
|
|
121
|
+
if (_cache)
|
|
122
|
+
return;
|
|
123
|
+
_cache = profile;
|
|
124
|
+
}
|
|
113
125
|
function loadWhoAmIProfile() {
|
|
114
126
|
try {
|
|
115
127
|
const req = createRequire(import.meta.url);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/ee/workflow-event.ts
|
|
3
|
+
*
|
|
4
|
+
* Part C/D client for the EE `/api/workflow-event` write-during-execution
|
|
5
|
+
* channel (added in experience-engine Part D). Lets the council workflow persist
|
|
6
|
+
* experience MID-RUN — per-round debate outcomes, sprint results, decisions,
|
|
7
|
+
* mistakes — into the `workflow_*` collections, so a later run (or a later
|
|
8
|
+
* sprint in the SAME run) can recall it.
|
|
9
|
+
*
|
|
10
|
+
* Contract with the two Kill findings from the plan review:
|
|
11
|
+
* - Kill #7: on a 404 (endpoint disabled / older server) DROP the event — do
|
|
12
|
+
* NOT enqueue. Queuing 404s head-of-line-poisons the offline queue against a
|
|
13
|
+
* server that will never accept them.
|
|
14
|
+
* - Kill #4/#5: writes are fire-and-forget and off the critical path. Recall of
|
|
15
|
+
* these hot entries stays gated on the server side (tier:"intra-session").
|
|
16
|
+
*
|
|
17
|
+
* On a transient network failure the event IS enqueued to the offline queue so
|
|
18
|
+
* a later drain retries it. Never throws; never blocks the workflow.
|
|
19
|
+
*/
|
|
20
|
+
import { enqueue } from "./offline-queue.js";
|
|
21
|
+
export type WorkflowEventKind = "council-debate" | "sprint-execution" | "decision" | "mistake";
|
|
22
|
+
export interface WorkflowEventPayload {
|
|
23
|
+
kind: WorkflowEventKind;
|
|
24
|
+
/** Run/phase reference, e.g. `runs/<runId>` or `runs/<runId>#sprint-3`. */
|
|
25
|
+
phaseRef: string;
|
|
26
|
+
sessionId?: string;
|
|
27
|
+
/** Short embeddable summary; falls back to a derived string server-side. */
|
|
28
|
+
text?: string;
|
|
29
|
+
/** Arbitrary structured detail persisted alongside the entry. */
|
|
30
|
+
payload?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface FireWorkflowEventOpts {
|
|
33
|
+
baseUrl?: string;
|
|
34
|
+
authToken?: string;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
fetchImpl?: typeof fetch;
|
|
37
|
+
/** Test seam: override the offline-queue enqueue. */
|
|
38
|
+
enqueueImpl?: typeof enqueue;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* POST a workflow event. Returns `true` when the server accepted it, `false`
|
|
42
|
+
* otherwise (dropped on 404, enqueued on network error). Never throws.
|
|
43
|
+
*/
|
|
44
|
+
export declare function fireWorkflowEvent(payload: WorkflowEventPayload, opts?: FireWorkflowEventOpts): Promise<boolean>;
|
|
45
|
+
/** Fire-and-forget wrapper — never throws, never blocks the workflow. */
|
|
46
|
+
export declare function fireAndForgetWorkflowEvent(payload: WorkflowEventPayload, opts?: FireWorkflowEventOpts): void;
|
|
47
|
+
/** Test-only: reset the once-per-process warning latch. */
|
|
48
|
+
export declare function _resetWorkflowEventState(): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/ee/workflow-event.ts
|
|
3
|
+
*
|
|
4
|
+
* Part C/D client for the EE `/api/workflow-event` write-during-execution
|
|
5
|
+
* channel (added in experience-engine Part D). Lets the council workflow persist
|
|
6
|
+
* experience MID-RUN — per-round debate outcomes, sprint results, decisions,
|
|
7
|
+
* mistakes — into the `workflow_*` collections, so a later run (or a later
|
|
8
|
+
* sprint in the SAME run) can recall it.
|
|
9
|
+
*
|
|
10
|
+
* Contract with the two Kill findings from the plan review:
|
|
11
|
+
* - Kill #7: on a 404 (endpoint disabled / older server) DROP the event — do
|
|
12
|
+
* NOT enqueue. Queuing 404s head-of-line-poisons the offline queue against a
|
|
13
|
+
* server that will never accept them.
|
|
14
|
+
* - Kill #4/#5: writes are fire-and-forget and off the critical path. Recall of
|
|
15
|
+
* these hot entries stays gated on the server side (tier:"intra-session").
|
|
16
|
+
*
|
|
17
|
+
* On a transient network failure the event IS enqueued to the offline queue so
|
|
18
|
+
* a later drain retries it. Never throws; never blocks the workflow.
|
|
19
|
+
*/
|
|
20
|
+
import { classifyEeError, logEeFailure } from "../utils/ee-logger.js";
|
|
21
|
+
import { getCachedAuthToken, getCachedServerBaseUrl } from "./auth.js";
|
|
22
|
+
import { enqueue } from "./offline-queue.js";
|
|
23
|
+
const DEFAULT_BASE = "http://localhost:8082";
|
|
24
|
+
const DEFAULT_TIMEOUT_MS = 3000;
|
|
25
|
+
const ENDPOINT = "/api/workflow-event";
|
|
26
|
+
let _warnedOnce = false;
|
|
27
|
+
/**
|
|
28
|
+
* POST a workflow event. Returns `true` when the server accepted it, `false`
|
|
29
|
+
* otherwise (dropped on 404, enqueued on network error). Never throws.
|
|
30
|
+
*/
|
|
31
|
+
export async function fireWorkflowEvent(payload, opts = {}) {
|
|
32
|
+
const baseUrl = opts.baseUrl ?? getCachedServerBaseUrl() ?? DEFAULT_BASE;
|
|
33
|
+
const authToken = opts.authToken ?? getCachedAuthToken() ?? undefined;
|
|
34
|
+
const f = opts.fetchImpl ?? fetch;
|
|
35
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
36
|
+
const doEnqueue = opts.enqueueImpl ?? enqueue;
|
|
37
|
+
const headers = { "Content-Type": "application/json" };
|
|
38
|
+
if (authToken)
|
|
39
|
+
headers.Authorization = `Bearer ${authToken}`;
|
|
40
|
+
try {
|
|
41
|
+
const resp = await f(`${baseUrl}${ENDPOINT}`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers,
|
|
44
|
+
body: JSON.stringify(payload),
|
|
45
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
46
|
+
});
|
|
47
|
+
if (resp.ok)
|
|
48
|
+
return true;
|
|
49
|
+
// 404 = endpoint disabled or older server → DROP (Kill #7: never queue 404s).
|
|
50
|
+
if (resp.status === 404)
|
|
51
|
+
return false;
|
|
52
|
+
// Other non-OK (5xx, etc.) → treat like a transient failure: enqueue.
|
|
53
|
+
await doEnqueue({ endpoint: ENDPOINT, body: payload, enqueuedAt: Date.now() }).catch(() => { });
|
|
54
|
+
if (!_warnedOnce) {
|
|
55
|
+
_warnedOnce = true;
|
|
56
|
+
console.warn(`[ee] workflow-event non-OK ${resp.status}; queued (silenced after first warning)`);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
// Network error / timeout → enqueue for later drain.
|
|
62
|
+
await doEnqueue({ endpoint: ENDPOINT, body: payload, enqueuedAt: Date.now() }).catch(() => { });
|
|
63
|
+
if (!_warnedOnce) {
|
|
64
|
+
_warnedOnce = true;
|
|
65
|
+
console.warn(`[ee] workflow-event failed: ${err.message}; queued (silenced after first warning)`);
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Fire-and-forget wrapper — never throws, never blocks the workflow. */
|
|
71
|
+
export function fireAndForgetWorkflowEvent(payload, opts = {}) {
|
|
72
|
+
void fireWorkflowEvent(payload, opts).catch((err) => {
|
|
73
|
+
logEeFailure("workflow-event.fireAndForgetWorkflowEvent", classifyEeError(err), err);
|
|
74
|
+
/* swallow */
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/** Test-only: reset the once-per-process warning latch. */
|
|
78
|
+
export function _resetWorkflowEventState() {
|
|
79
|
+
_warnedOnce = false;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=workflow-event.js.map
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Serializes messages, extracts preserved blocks, compresses if over budget,
|
|
5
5
|
* then restores preserved blocks into the output.
|
|
6
6
|
*/
|
|
7
|
-
import type
|
|
7
|
+
import { type ModelMessage } from "ai";
|
|
8
8
|
import { type PreservedBlock } from "./preserve.js";
|
|
9
9
|
export interface CompressResult {
|
|
10
10
|
summary: string;
|
|
@@ -17,6 +17,6 @@ export interface CompressResult {
|
|
|
17
17
|
* 1. Serialize messages via serializeConversation().
|
|
18
18
|
* 2. Extract preserved blocks.
|
|
19
19
|
* 3. If under budget, return as-is (with preserved blocks restored).
|
|
20
|
-
* 4. If over budget,
|
|
20
|
+
* 4. If over budget, compress via LLM (if modelId given) or truncate, and restore blocks.
|
|
21
21
|
*/
|
|
22
|
-
export declare function compressChat(messages: ModelMessage[], _systemPrompt: string, tokenBudget: number,
|
|
22
|
+
export declare function compressChat(messages: ModelMessage[], _systemPrompt: string, tokenBudget: number, modelId?: string, customInstructions?: string, onFraction?: (fraction: number) => void): Promise<CompressResult>;
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* Serializes messages, extracts preserved blocks, compresses if over budget,
|
|
5
5
|
* then restores preserved blocks into the output.
|
|
6
6
|
*/
|
|
7
|
+
import { streamText } from "ai";
|
|
7
8
|
import { serializeConversation } from "../../orchestrator/compaction.js";
|
|
9
|
+
import { resolveModelRuntime, resolveTemperatureParam } from "../../providers/runtime.js";
|
|
10
|
+
import { logger } from "../../utils/logger.js";
|
|
11
|
+
import { capCompactionInput } from "./input-guard.js";
|
|
8
12
|
import { extractPreservedBlocks, restorePreservedBlocks } from "./preserve.js";
|
|
9
13
|
/**
|
|
10
14
|
* Compress chat messages within a token budget.
|
|
@@ -12,9 +16,9 @@ import { extractPreservedBlocks, restorePreservedBlocks } from "./preserve.js";
|
|
|
12
16
|
* 1. Serialize messages via serializeConversation().
|
|
13
17
|
* 2. Extract preserved blocks.
|
|
14
18
|
* 3. If under budget, return as-is (with preserved blocks restored).
|
|
15
|
-
* 4. If over budget,
|
|
19
|
+
* 4. If over budget, compress via LLM (if modelId given) or truncate, and restore blocks.
|
|
16
20
|
*/
|
|
17
|
-
export async function compressChat(messages, _systemPrompt, tokenBudget,
|
|
21
|
+
export async function compressChat(messages, _systemPrompt, tokenBudget, modelId, customInstructions, onFraction) {
|
|
18
22
|
const serialized = serializeConversation(messages);
|
|
19
23
|
const { cleaned, blocks } = extractPreservedBlocks(serialized);
|
|
20
24
|
// Estimate tokens of cleaned text
|
|
@@ -28,16 +32,62 @@ export async function compressChat(messages, _systemPrompt, tokenBudget, _provid
|
|
|
28
32
|
tokensAfter: Math.ceil(restored.length / 4),
|
|
29
33
|
};
|
|
30
34
|
}
|
|
31
|
-
// Over budget — truncate to fit budget while keeping preserved blocks
|
|
32
35
|
// Calculate space taken by preserved blocks
|
|
33
36
|
const preservedTokens = blocks.reduce((sum, b) => sum + Math.ceil(b.content.length / 4), 0);
|
|
34
37
|
const availableTokens = Math.max(0, tokenBudget - preservedTokens);
|
|
35
38
|
const availableChars = availableTokens * 4;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
let compressedContent = cleaned;
|
|
40
|
+
let usedLLM = false;
|
|
41
|
+
if (modelId) {
|
|
42
|
+
try {
|
|
43
|
+
const runtime = resolveModelRuntime(modelId);
|
|
44
|
+
const extraPrompt = customInstructions ? `\n\nUSER FOCUS/INSTRUCTIONS:\n${customInstructions}\n` : "";
|
|
45
|
+
// Guard the compaction INPUT against the model's own context window —
|
|
46
|
+
// compaction fires when history is large, which is exactly when the full
|
|
47
|
+
// serialized text can overflow the summarizer. Keep head + tail.
|
|
48
|
+
const guardedInput = capCompactionInput(cleaned, runtime.modelInfo?.contextWindow ?? 0);
|
|
49
|
+
// Streamed rather than awaited whole so the caller can report real
|
|
50
|
+
// progress: this pass is the bulk of a /compact's wall-clock, and a bar
|
|
51
|
+
// that freezes for a minute reads as a hang. The summary text is still
|
|
52
|
+
// only used once complete.
|
|
53
|
+
const result = streamText({
|
|
54
|
+
model: runtime.model,
|
|
55
|
+
system: "You are an AI context compaction agent. Your job is to heavily summarize a chat history. Keep the core outcomes, the final state, and the technical context. Remove verbose pleasantries, step-by-step thinking, and irrelevant intermediate steps. Do NOT wrap in markdown unless it's code.",
|
|
56
|
+
prompt: `The following conversation exceeds the token budget. Please summarize it concisely, maintaining the essence of what was discussed, what code was written, and what decisions were reached:${extraPrompt}\n\n${guardedInput}`,
|
|
57
|
+
...resolveTemperatureParam(runtime, 0.1),
|
|
58
|
+
});
|
|
59
|
+
let streamed = "";
|
|
60
|
+
for await (const delta of result.textStream) {
|
|
61
|
+
streamed += delta;
|
|
62
|
+
// availableChars is the size the model was ASKED to fit under, so it is
|
|
63
|
+
// the only honest denominator available — a concise summary finishes
|
|
64
|
+
// early and the caller jumps the bar to done rather than overshooting.
|
|
65
|
+
if (onFraction && availableChars > 0)
|
|
66
|
+
onFraction(Math.min(1, streamed.length / availableChars));
|
|
67
|
+
}
|
|
68
|
+
compressedContent = streamed.trim();
|
|
69
|
+
usedLLM = true;
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
// Fall back to deterministic truncation below, but do NOT swallow the
|
|
73
|
+
// reason — a hidden compaction-LLM failure (auth, overflow, provider
|
|
74
|
+
// 400) is exactly what makes "why did compaction do nothing" undebuggable.
|
|
75
|
+
logger.error("orchestrator", "compressChat LLM summarize failed — falling back to truncation", {
|
|
76
|
+
modelId,
|
|
77
|
+
inputChars: cleaned.length,
|
|
78
|
+
message: e?.message,
|
|
79
|
+
stack: e?.stack?.split("\n").slice(0, 3),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!usedLLM) {
|
|
84
|
+
// Over budget — truncate to fit budget while keeping preserved blocks
|
|
85
|
+
compressedContent =
|
|
86
|
+
cleaned.length > availableChars
|
|
87
|
+
? `${cleaned.slice(0, availableChars)}\n\n[... ${cleaned.length - availableChars} characters truncated]`
|
|
88
|
+
: cleaned;
|
|
89
|
+
}
|
|
90
|
+
const restored = restorePreservedBlocks(compressedContent, blocks);
|
|
41
91
|
return {
|
|
42
92
|
summary: restored,
|
|
43
93
|
preservedBlocks: blocks,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Scans for "Decision:", "Decided:", "Fact:", "Constraint:" patterns
|
|
6
6
|
* and content inside <!-- preserve --> blocks.
|
|
7
7
|
*/
|
|
8
|
-
import type
|
|
8
|
+
import { type ModelMessage } from "ai";
|
|
9
9
|
export interface ExtractedDecisions {
|
|
10
10
|
decisions: string[];
|
|
11
11
|
facts: string[];
|
|
@@ -14,10 +14,7 @@ export interface ExtractedDecisions {
|
|
|
14
14
|
/**
|
|
15
15
|
* Extract decisions, facts, and constraints from messages.
|
|
16
16
|
*
|
|
17
|
-
* Scans serialized conversation text for
|
|
18
|
-
*
|
|
19
|
-
* - Lines matching "Fact:" -> facts
|
|
20
|
-
* - Lines matching "Constraint:" -> constraints
|
|
21
|
-
* - All content inside <!-- preserve --> blocks -> decisions (verbatim)
|
|
17
|
+
* Scans serialized conversation text for explicit markers, but if modelId is
|
|
18
|
+
* given, it asks the LLM to intelligently extract them.
|
|
22
19
|
*/
|
|
23
|
-
export declare function extractDecisions(messages: ModelMessage[]): ExtractedDecisions
|
|
20
|
+
export declare function extractDecisions(messages: ModelMessage[], modelId?: string, customInstructions?: string): Promise<ExtractedDecisions>;
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
* Scans for "Decision:", "Decided:", "Fact:", "Constraint:" patterns
|
|
6
6
|
* and content inside <!-- preserve --> blocks.
|
|
7
7
|
*/
|
|
8
|
+
import { generateText } from "ai";
|
|
8
9
|
import { serializeConversation } from "../../orchestrator/compaction.js";
|
|
10
|
+
import { resolveModelRuntime, resolveTemperatureParam } from "../../providers/runtime.js";
|
|
11
|
+
import { logger } from "../../utils/logger.js";
|
|
12
|
+
import { capCompactionInput } from "./input-guard.js";
|
|
9
13
|
import { extractPreservedBlocks } from "./preserve.js";
|
|
10
14
|
const DECISION_RE = /(?:Decision|Decided):\s*(.+)/gi;
|
|
11
15
|
const FACT_RE = /Fact:\s*(.+)/gi;
|
|
@@ -23,13 +27,10 @@ function matchAll(text, re) {
|
|
|
23
27
|
/**
|
|
24
28
|
* Extract decisions, facts, and constraints from messages.
|
|
25
29
|
*
|
|
26
|
-
* Scans serialized conversation text for
|
|
27
|
-
*
|
|
28
|
-
* - Lines matching "Fact:" -> facts
|
|
29
|
-
* - Lines matching "Constraint:" -> constraints
|
|
30
|
-
* - All content inside <!-- preserve --> blocks -> decisions (verbatim)
|
|
30
|
+
* Scans serialized conversation text for explicit markers, but if modelId is
|
|
31
|
+
* given, it asks the LLM to intelligently extract them.
|
|
31
32
|
*/
|
|
32
|
-
export function extractDecisions(messages) {
|
|
33
|
+
export async function extractDecisions(messages, modelId, customInstructions) {
|
|
33
34
|
if (messages.length === 0) {
|
|
34
35
|
return { decisions: [], facts: [], constraints: [] };
|
|
35
36
|
}
|
|
@@ -37,10 +38,49 @@ export function extractDecisions(messages) {
|
|
|
37
38
|
// Extract preserved blocks as decisions
|
|
38
39
|
const { blocks } = extractPreservedBlocks(serialized);
|
|
39
40
|
const preservedDecisions = blocks.map((b) => b.content);
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
41
|
+
const decisions = [];
|
|
42
|
+
const facts = [];
|
|
43
|
+
const constraints = [];
|
|
44
|
+
let usedLLM = false;
|
|
45
|
+
if (modelId) {
|
|
46
|
+
try {
|
|
47
|
+
const runtime = resolveModelRuntime(modelId);
|
|
48
|
+
const extraPrompt = customInstructions ? `\n\nUSER FOCUS/INSTRUCTIONS:\n${customInstructions}\n` : "";
|
|
49
|
+
// Guard input against the summarizer's context window (see input-guard).
|
|
50
|
+
const guardedInput = capCompactionInput(serialized, runtime.modelInfo?.contextWindow ?? 0);
|
|
51
|
+
const result = await generateText({
|
|
52
|
+
model: runtime.model,
|
|
53
|
+
system: 'You are an AI context compaction agent. Extract all core decisions, technical facts, and project constraints from this conversation. Return strict JSON with { "decisions": string[], "facts": string[], "constraints": string[] }.',
|
|
54
|
+
prompt: `Current conversation messages:\n\n${guardedInput}\n\nExtract decisions, facts, and constraints.${extraPrompt} Return strict JSON ONLY.`,
|
|
55
|
+
...resolveTemperatureParam(runtime, 0.1),
|
|
56
|
+
});
|
|
57
|
+
const match = result.text.match(/\{[\s\S]*\}/);
|
|
58
|
+
if (match) {
|
|
59
|
+
const parsed = JSON.parse(match[0]);
|
|
60
|
+
if (Array.isArray(parsed.decisions))
|
|
61
|
+
decisions.push(...parsed.decisions);
|
|
62
|
+
if (Array.isArray(parsed.facts))
|
|
63
|
+
facts.push(...parsed.facts);
|
|
64
|
+
if (Array.isArray(parsed.constraints))
|
|
65
|
+
constraints.push(...parsed.constraints);
|
|
66
|
+
usedLLM = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
// Fall back to regex extraction, but log the reason — a swallowed failure
|
|
71
|
+
// here silently degrades /compact to marker-only extraction.
|
|
72
|
+
logger.error("orchestrator", "extractDecisions LLM failed — falling back to regex", {
|
|
73
|
+
modelId,
|
|
74
|
+
message: e?.message,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!usedLLM) {
|
|
79
|
+
decisions.push(...matchAll(serialized, DECISION_RE));
|
|
80
|
+
facts.push(...matchAll(serialized, FACT_RE));
|
|
81
|
+
constraints.push(...matchAll(serialized, CONSTRAINT_RE));
|
|
82
|
+
}
|
|
83
|
+
decisions.push(...preservedDecisions);
|
|
44
84
|
return { decisions, facts, constraints };
|
|
45
85
|
}
|
|
46
86
|
//# sourceMappingURL=extract.js.map
|
|
@@ -6,6 +6,19 @@
|
|
|
6
6
|
* Snapshot full chat to history/<timestamp>.md before compressing.
|
|
7
7
|
*/
|
|
8
8
|
import type { ModelMessage } from "ai";
|
|
9
|
+
import { type CompactProgressFn } from "./progress.js";
|
|
10
|
+
/**
|
|
11
|
+
* Anti-mù for the deliberate (/compact) path — parity with the auto/tool-loop
|
|
12
|
+
* compaction which persists every elided tool output via persistArtifact.
|
|
13
|
+
*
|
|
14
|
+
* deliberateCompact rewrites the whole history into a prose summary, so without
|
|
15
|
+
* this the model loses the ability to `ee_query "tool-artifact id=<id>"` a
|
|
16
|
+
* specific tool result after /compact. We record each tool result into the
|
|
17
|
+
* in-process + disk artifact cache (the tier ee_query reads FIRST, before EE),
|
|
18
|
+
* and fire a best-effort EE extract so cross-session rehydrate also survives.
|
|
19
|
+
* Fail-open: a cache/EE hiccup never blocks the compaction.
|
|
20
|
+
*/
|
|
21
|
+
export declare function recordToolArtifactsForRehydrate(messages: ModelMessage[], projectPath: string): number;
|
|
9
22
|
export interface CompactionResult {
|
|
10
23
|
decisionsExtracted: number;
|
|
11
24
|
tokensBeforeCompress: number;
|
|
@@ -21,4 +34,4 @@ export interface CompactionResult {
|
|
|
21
34
|
* 3. Pass 2: compressChat -> compressed output
|
|
22
35
|
* 4. Return metrics
|
|
23
36
|
*/
|
|
24
|
-
export declare function deliberateCompact(flowDir: string, messages: ModelMessage[], systemPrompt: string, tokenBudget: number,
|
|
37
|
+
export declare function deliberateCompact(flowDir: string, messages: ModelMessage[], systemPrompt: string, tokenBudget: number, modelId?: string, customInstructions?: string, onProgress?: CompactProgressFn): Promise<CompactionResult>;
|