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,258 @@
|
|
|
1
|
+
import { getModelInfo, getVisionProxyRouting, MODELS, SWITCH_PROVIDER_ORDER } from "../models/registry.js";
|
|
2
|
+
import { apiBaseFor } from "./endpoints.js";
|
|
3
|
+
import { loadKeyForProvider } from "./keychain.js";
|
|
4
|
+
const REQUEST_TIMEOUT_MS = 90_000;
|
|
5
|
+
const DEFAULT_VISION_PROXY = {
|
|
6
|
+
default: { provider: "zai", model_id: "glm-4.6v-flash" },
|
|
7
|
+
ocr: { provider: "zai", model_id: "glm-4.6v-flash" },
|
|
8
|
+
design: { provider: "zai", model_id: "glm-5.2" },
|
|
9
|
+
fallback_chain: [
|
|
10
|
+
{ provider: "xai", model_id: "grok-4.5" },
|
|
11
|
+
{ provider: "zai", model_id: "glm-5.2" },
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
const OCR_INTENT_RE = /\b(ocr|transcribe|read\s+(all\s+)?text|extract\s+text|text\s+in\s+(the\s+)?image|copy\s+text|what\s+(does|do)\s+it\s+say)\b/i;
|
|
15
|
+
export function looksLikeOcrIntent(text) {
|
|
16
|
+
return OCR_INTENT_RE.test(text);
|
|
17
|
+
}
|
|
18
|
+
export function resolveVisionChain(kind) {
|
|
19
|
+
const routing = getVisionProxyRouting() ?? DEFAULT_VISION_PROXY;
|
|
20
|
+
const chain = [];
|
|
21
|
+
const primary = routing[kind] ?? routing.default;
|
|
22
|
+
if (primary)
|
|
23
|
+
chain.push(primary);
|
|
24
|
+
for (const slot of routing.fallback_chain ?? []) {
|
|
25
|
+
if (!chain.some((s) => s.provider === slot.provider && s.model_id === slot.model_id)) {
|
|
26
|
+
chain.push(slot);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (chain.length === 0 && routing.default)
|
|
30
|
+
return [routing.default];
|
|
31
|
+
return chain;
|
|
32
|
+
}
|
|
33
|
+
async function slotHasAvailableKey(slot) {
|
|
34
|
+
try {
|
|
35
|
+
await loadKeyForProvider(slot.provider);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Vision-proxy chain filtered to providers that currently have API keys. */
|
|
43
|
+
export async function resolveAvailableVisionChain(kind = "default") {
|
|
44
|
+
const available = [];
|
|
45
|
+
for (const slot of resolveVisionChain(kind)) {
|
|
46
|
+
if (await slotHasAvailableKey(slot))
|
|
47
|
+
available.push(slot);
|
|
48
|
+
}
|
|
49
|
+
return available;
|
|
50
|
+
}
|
|
51
|
+
export async function isVisionBackendAvailable(kind = "default") {
|
|
52
|
+
return (await resolveAvailableVisionChain(kind)).length > 0;
|
|
53
|
+
}
|
|
54
|
+
async function tryNativeVisionModel(modelId, source, excludeModelId) {
|
|
55
|
+
if (excludeModelId && modelId === excludeModelId)
|
|
56
|
+
return null;
|
|
57
|
+
const info = getModelInfo(modelId);
|
|
58
|
+
if (!info?.supportsVision)
|
|
59
|
+
return null;
|
|
60
|
+
const provider = info.provider;
|
|
61
|
+
const { isModelDisabled, isProviderDisabled } = await import("../utils/settings.js");
|
|
62
|
+
if (isProviderDisabled(provider) || isModelDisabled(modelId))
|
|
63
|
+
return null;
|
|
64
|
+
if (!(await slotHasAvailableKey({ provider, model_id: modelId })))
|
|
65
|
+
return null;
|
|
66
|
+
return { modelId, provider, source };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* When vision-proxy backends have no keys, pick a catalog vision model (with key)
|
|
70
|
+
* so images can be sent natively instead of failing on a text-only primary.
|
|
71
|
+
*/
|
|
72
|
+
export async function findNativeVisionFallback(opts) {
|
|
73
|
+
const exclude = opts?.excludeModelId;
|
|
74
|
+
const seen = new Set();
|
|
75
|
+
for (const kind of ["default", "ocr", "design"]) {
|
|
76
|
+
for (const slot of resolveVisionChain(kind)) {
|
|
77
|
+
if (seen.has(slot.model_id))
|
|
78
|
+
continue;
|
|
79
|
+
seen.add(slot.model_id);
|
|
80
|
+
const hit = await tryNativeVisionModel(slot.model_id, "vision_proxy_slot", exclude);
|
|
81
|
+
if (hit)
|
|
82
|
+
return hit;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const visionByProvider = new Map();
|
|
86
|
+
for (const m of MODELS) {
|
|
87
|
+
if (!m.supportsVision || !m.provider)
|
|
88
|
+
continue;
|
|
89
|
+
const list = visionByProvider.get(m.provider) ?? [];
|
|
90
|
+
list.push(m);
|
|
91
|
+
visionByProvider.set(m.provider, list);
|
|
92
|
+
}
|
|
93
|
+
for (const provider of SWITCH_PROVIDER_ORDER) {
|
|
94
|
+
for (const m of visionByProvider.get(provider) ?? []) {
|
|
95
|
+
if (seen.has(m.id))
|
|
96
|
+
continue;
|
|
97
|
+
seen.add(m.id);
|
|
98
|
+
const hit = await tryNativeVisionModel(m.id, "catalog_vision", exclude);
|
|
99
|
+
if (hit)
|
|
100
|
+
return hit;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const m of MODELS) {
|
|
104
|
+
if (!m.supportsVision)
|
|
105
|
+
continue;
|
|
106
|
+
if (seen.has(m.id))
|
|
107
|
+
continue;
|
|
108
|
+
const hit = await tryNativeVisionModel(m.id, "catalog_vision", exclude);
|
|
109
|
+
if (hit)
|
|
110
|
+
return hit;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
export async function collectVisionUnavailableReasons(kind = "default") {
|
|
115
|
+
const reasons = [];
|
|
116
|
+
for (const slot of resolveVisionChain(kind)) {
|
|
117
|
+
if (await slotHasAvailableKey(slot)) {
|
|
118
|
+
reasons.push(`${slot.model_id}@${slot.provider}: API key present but backend unreachable`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
reasons.push(`${slot.model_id}@${slot.provider}: no API key`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
reasons.push("no other vision-capable catalog model has a configured API key");
|
|
125
|
+
return reasons;
|
|
126
|
+
}
|
|
127
|
+
export async function callVisionBackend(chain, content, signal, responseFormat) {
|
|
128
|
+
const failureReasons = [];
|
|
129
|
+
if (chain.length === 0) {
|
|
130
|
+
return { ok: false, reason: "no vision backend available — configure ZAI_API_KEY or XAI_API_KEY" };
|
|
131
|
+
}
|
|
132
|
+
for (const slot of chain) {
|
|
133
|
+
const provider = slot.provider;
|
|
134
|
+
let apiKey;
|
|
135
|
+
try {
|
|
136
|
+
apiKey = await loadKeyForProvider(provider);
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
140
|
+
failureReasons.push(`${slot.model_id}@${provider}: no API key (${msg})`);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const base = apiBaseFor(provider);
|
|
144
|
+
const result = await callVisionModelAt(base, slot.model_id, content, apiKey, signal, responseFormat);
|
|
145
|
+
if (result.ok) {
|
|
146
|
+
return { ok: true, text: result.text, model: slot.model_id, provider };
|
|
147
|
+
}
|
|
148
|
+
failureReasons.push(`${slot.model_id}@${provider}: ${result.reason}`);
|
|
149
|
+
console.warn(`[vision-backend] ${slot.model_id}@${provider} failed (${result.reason}), trying next...`);
|
|
150
|
+
}
|
|
151
|
+
return { ok: false, reason: failureReasons.join(" | ") || "no vision backend configured" };
|
|
152
|
+
}
|
|
153
|
+
async function callVisionModelAt(baseURL, model, content, apiKey, signal, responseFormat) {
|
|
154
|
+
const controller = new AbortController();
|
|
155
|
+
let timedOut = false;
|
|
156
|
+
const timeout = setTimeout(() => {
|
|
157
|
+
timedOut = true;
|
|
158
|
+
controller.abort();
|
|
159
|
+
}, REQUEST_TIMEOUT_MS);
|
|
160
|
+
if (signal) {
|
|
161
|
+
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
162
|
+
}
|
|
163
|
+
const url = `${baseURL.replace(/\/$/, "")}/chat/completions`;
|
|
164
|
+
let res;
|
|
165
|
+
try {
|
|
166
|
+
res = await fetch(url, {
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: {
|
|
169
|
+
"Content-Type": "application/json",
|
|
170
|
+
Authorization: `Bearer ${apiKey}`,
|
|
171
|
+
},
|
|
172
|
+
body: JSON.stringify({
|
|
173
|
+
model,
|
|
174
|
+
messages: [{ role: "user", content }],
|
|
175
|
+
max_tokens: 3072,
|
|
176
|
+
temperature: 0.1,
|
|
177
|
+
...(responseFormat ? { response_format: responseFormat } : {}),
|
|
178
|
+
}),
|
|
179
|
+
signal: controller.signal,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
clearTimeout(timeout);
|
|
184
|
+
if (timedOut)
|
|
185
|
+
return { ok: false, reason: `timeout after ${REQUEST_TIMEOUT_MS}ms` };
|
|
186
|
+
if (signal?.aborted)
|
|
187
|
+
throw err;
|
|
188
|
+
return { ok: false, reason: `network error: ${err instanceof Error ? err.message : String(err)}` };
|
|
189
|
+
}
|
|
190
|
+
clearTimeout(timeout);
|
|
191
|
+
if (!res.ok) {
|
|
192
|
+
const errText = await res.text().catch(() => "");
|
|
193
|
+
return { ok: false, reason: `HTTP ${res.status} ${errText.slice(0, 200)}` };
|
|
194
|
+
}
|
|
195
|
+
const data = (await res.json().catch(() => null));
|
|
196
|
+
const text = data?.choices?.[0]?.message?.content;
|
|
197
|
+
if (!text)
|
|
198
|
+
return { ok: false, reason: "empty response body" };
|
|
199
|
+
return { ok: true, text };
|
|
200
|
+
}
|
|
201
|
+
/** Ask the vision model to write as direct sight for the primary (text-only) agent. */
|
|
202
|
+
export function wrapAnalyzerInstructions(userPrompt, kind) {
|
|
203
|
+
const style = kind === "design"
|
|
204
|
+
? "Output ONLY valid JSON matching the requested schema. No markdown fences."
|
|
205
|
+
: "Write in clear markdown. Use first-person present tense ('I see…', 'The screenshot shows…').";
|
|
206
|
+
return [
|
|
207
|
+
userPrompt,
|
|
208
|
+
"",
|
|
209
|
+
"IMPORTANT — output style for the primary coding agent:",
|
|
210
|
+
"- Write as a DIRECT visual observation. The reader will treat your words as its own native sight.",
|
|
211
|
+
"- Do NOT mention vision proxy, backend models, or that you are a separate model.",
|
|
212
|
+
`- ${style}`,
|
|
213
|
+
"- If something is illegible, cropped, or ambiguous, say exactly what is unclear and what would help (closer crop, higher resolution, different angle).",
|
|
214
|
+
].join("\n");
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Envelope injected into text-only model context — reads as native vision, not third-party analysis.
|
|
218
|
+
*/
|
|
219
|
+
export function formatNativeVisionObservation(observation, opts) {
|
|
220
|
+
const subject = opts.imageCount > 1 ? `these ${opts.imageCount} images` : "this image";
|
|
221
|
+
const cacheHint = opts.cachedIds && opts.cachedIds.length > 0
|
|
222
|
+
? `- Cached as ${opts.cachedIds.join(", ")} — use ask_vision_proxy with a specific question to inspect a detail`
|
|
223
|
+
: "";
|
|
224
|
+
return [
|
|
225
|
+
"<vision-observation>",
|
|
226
|
+
`You are viewing ${subject}. Treat everything below as your direct visual observation — reason and respond as if you saw it yourself.`,
|
|
227
|
+
"",
|
|
228
|
+
observation.trim(),
|
|
229
|
+
"",
|
|
230
|
+
"If any detail is unclear, cropped, or you need another angle:",
|
|
231
|
+
"- ask_vision_proxy with a precise question (region, color, text, UI element)",
|
|
232
|
+
"- analyze_image on the file path to re-inspect or compare a fresh screenshot",
|
|
233
|
+
"- ask the user to share another image or clarify what to focus on",
|
|
234
|
+
cacheHint,
|
|
235
|
+
"</vision-observation>",
|
|
236
|
+
]
|
|
237
|
+
.filter((line) => line !== "")
|
|
238
|
+
.join("\n");
|
|
239
|
+
}
|
|
240
|
+
export function formatNativeVisionUnavailable(imageCount, reasons, cachedIds) {
|
|
241
|
+
const types = imageCount > 1 ? `${imageCount} images` : "1 image";
|
|
242
|
+
const cacheHint = cachedIds && cachedIds.length > 0 ? `Cached IDs: ${cachedIds.join(", ")} — try ask_vision_proxy anyway.` : "";
|
|
243
|
+
const detail = reasons.length > 0 ? reasons.join(" | ") : "vision backend unreachable";
|
|
244
|
+
return [
|
|
245
|
+
'<vision-observation status="unavailable">',
|
|
246
|
+
`${types} could not be analyzed (${detail}).`,
|
|
247
|
+
"Do NOT guess what the image contains.",
|
|
248
|
+
"Setup: configure ZAI_API_KEY or XAI_API_KEY for vision proxy, or switch to a vision-capable default model.",
|
|
249
|
+
"- Retry with analyze_image and the file path once a vision key is configured",
|
|
250
|
+
"- Use ask_vision_proxy if a cached image exists",
|
|
251
|
+
"- Ask the user to re-share the screenshot or describe what you need to see",
|
|
252
|
+
cacheHint,
|
|
253
|
+
"</vision-observation>",
|
|
254
|
+
]
|
|
255
|
+
.filter(Boolean)
|
|
256
|
+
.join("\n");
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=vision-backend.js.map
|
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vision proxy layer for text-only models (e.g. DeepSeek V4).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* structured text descriptions before the message reaches the primary model.
|
|
4
|
+
* Image parts in messages are sent to the catalog-configured vision backend
|
|
5
|
+
* (default: Z.ai glm-4.6v-flash) and replaced with native-sight observations
|
|
6
|
+
* so the primary model reasons as if it saw the image directly.
|
|
8
7
|
*/
|
|
9
8
|
import type { ModelMessage } from "ai";
|
|
9
|
+
import { type NativeVisionFallback, type VisionTaskKind } from "./vision-backend.js";
|
|
10
10
|
export interface VisionProxyResult {
|
|
11
11
|
messages: ModelMessage[];
|
|
12
12
|
proxied: boolean;
|
|
13
13
|
imageCount: number;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* Returns true when the model cannot handle image content natively.
|
|
17
|
-
*/
|
|
18
15
|
export declare function needsVisionProxy(modelId: string): boolean;
|
|
16
|
+
export type ImageHandlingPlan = {
|
|
17
|
+
strategy: "proxy";
|
|
18
|
+
} | {
|
|
19
|
+
strategy: "native_model";
|
|
20
|
+
fallback: NativeVisionFallback;
|
|
21
|
+
} | {
|
|
22
|
+
strategy: "unavailable";
|
|
23
|
+
notice: string;
|
|
24
|
+
};
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
26
|
+
* Decide how to handle images when the active model is text-only:
|
|
27
|
+
* proxy backend, switch to a native vision model, or surface unavailable.
|
|
22
28
|
*/
|
|
29
|
+
export declare function planImageHandlingForTextOnlyModel(opts: {
|
|
30
|
+
primaryModelId: string;
|
|
31
|
+
imageCount: number;
|
|
32
|
+
kind?: VisionTaskKind;
|
|
33
|
+
}): Promise<ImageHandlingPlan>;
|
|
34
|
+
/** True when proxy backend or a native vision model can handle images for this text-only model. */
|
|
35
|
+
export declare function canHandleImagesForTextOnlyModel(modelId: string): Promise<boolean>;
|
|
23
36
|
export declare function proxyVision(messages: ModelMessage[], modelId: string, signal?: AbortSignal): Promise<VisionProxyResult>;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vision proxy layer for text-only models (e.g. DeepSeek V4).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* structured text descriptions before the message reaches the primary model.
|
|
4
|
+
* Image parts in messages are sent to the catalog-configured vision backend
|
|
5
|
+
* (default: Z.ai glm-4.6v-flash) and replaced with native-sight observations
|
|
6
|
+
* so the primary model reasons as if it saw the image directly.
|
|
8
7
|
*/
|
|
9
8
|
import { getModelInfo } from "../models/registry.js";
|
|
10
|
-
import { apiBaseFor } from "./endpoints.js";
|
|
11
|
-
import { loadKeyForProvider } from "./keychain.js";
|
|
12
9
|
import { UI_LAYOUT_SCHEMA_HINT } from "./mcp-vision-bridge.js";
|
|
10
|
+
import { callVisionBackend, collectVisionUnavailableReasons, findNativeVisionFallback, formatNativeVisionObservation, formatNativeVisionUnavailable, isVisionBackendAvailable, looksLikeOcrIntent, resolveAvailableVisionChain, wrapAnalyzerInstructions, } from "./vision-backend.js";
|
|
13
11
|
const DESIGN_INTENT_PATTERNS = [
|
|
14
12
|
/\bredesign\b/i,
|
|
15
13
|
/\bdesign\s*(system|token|spec|review)?\b/i,
|
|
@@ -26,24 +24,40 @@ function looksLikeDesignIntent(text) {
|
|
|
26
24
|
return false;
|
|
27
25
|
return DESIGN_INTENT_PATTERNS.some((re) => re.test(text));
|
|
28
26
|
}
|
|
29
|
-
const VISION_MODELS = [
|
|
30
|
-
"Qwen/Qwen3-VL-8B-Instruct",
|
|
31
|
-
"Qwen/Qwen3-VL-30B-A3B-Instruct",
|
|
32
|
-
"Qwen/Qwen3-VL-32B-Instruct",
|
|
33
|
-
];
|
|
34
|
-
const SILICONFLOW_BASE = apiBaseFor("siliconflow");
|
|
35
|
-
const REQUEST_TIMEOUT_MS = 90_000;
|
|
36
|
-
/**
|
|
37
|
-
* Returns true when the model cannot handle image content natively.
|
|
38
|
-
*/
|
|
39
27
|
export function needsVisionProxy(modelId) {
|
|
40
28
|
const info = getModelInfo(modelId);
|
|
41
29
|
return info?.supportsVision === false;
|
|
42
30
|
}
|
|
43
31
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
32
|
+
* Decide how to handle images when the active model is text-only:
|
|
33
|
+
* proxy backend, switch to a native vision model, or surface unavailable.
|
|
46
34
|
*/
|
|
35
|
+
export async function planImageHandlingForTextOnlyModel(opts) {
|
|
36
|
+
if (!needsVisionProxy(opts.primaryModelId)) {
|
|
37
|
+
return { strategy: "proxy" };
|
|
38
|
+
}
|
|
39
|
+
const kind = opts.kind ?? "default";
|
|
40
|
+
if (await isVisionBackendAvailable(kind)) {
|
|
41
|
+
return { strategy: "proxy" };
|
|
42
|
+
}
|
|
43
|
+
const fallback = await findNativeVisionFallback({ excludeModelId: opts.primaryModelId });
|
|
44
|
+
if (fallback) {
|
|
45
|
+
return { strategy: "native_model", fallback };
|
|
46
|
+
}
|
|
47
|
+
const reasons = await collectVisionUnavailableReasons(kind);
|
|
48
|
+
return {
|
|
49
|
+
strategy: "unavailable",
|
|
50
|
+
notice: formatNativeVisionUnavailable(opts.imageCount, reasons),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** True when proxy backend or a native vision model can handle images for this text-only model. */
|
|
54
|
+
export async function canHandleImagesForTextOnlyModel(modelId) {
|
|
55
|
+
if (!needsVisionProxy(modelId))
|
|
56
|
+
return true;
|
|
57
|
+
if (await isVisionBackendAvailable())
|
|
58
|
+
return true;
|
|
59
|
+
return (await findNativeVisionFallback({ excludeModelId: modelId })) !== null;
|
|
60
|
+
}
|
|
47
61
|
export async function proxyVision(messages, modelId, signal) {
|
|
48
62
|
if (!needsVisionProxy(modelId)) {
|
|
49
63
|
return { messages, proxied: false, imageCount: 0 };
|
|
@@ -66,6 +80,7 @@ export async function proxyVision(messages, modelId, signal) {
|
|
|
66
80
|
totalImages += imageParts.length;
|
|
67
81
|
const userText = textParts.map((t) => t.text).join("\n");
|
|
68
82
|
const designIntent = looksLikeDesignIntent(userText);
|
|
83
|
+
const ocrIntent = looksLikeOcrIntent(userText);
|
|
69
84
|
const svgFast = trySvgFastPath(imageParts, designIntent);
|
|
70
85
|
if (svgFast) {
|
|
71
86
|
processed.push({
|
|
@@ -74,27 +89,22 @@ export async function proxyVision(messages, modelId, signal) {
|
|
|
74
89
|
});
|
|
75
90
|
continue;
|
|
76
91
|
}
|
|
77
|
-
const
|
|
92
|
+
const kind = designIntent ? "design" : ocrIntent ? "ocr" : "default";
|
|
93
|
+
const descriptions = await describeImages(imageParts, textParts, signal, kind);
|
|
78
94
|
const newContent = [...textParts, { type: "text", text: descriptions }];
|
|
79
95
|
processed.push({ ...msg, content: newContent });
|
|
80
96
|
}
|
|
81
97
|
return { messages: processed, proxied: totalImages > 0, imageCount: totalImages };
|
|
82
98
|
}
|
|
83
|
-
async function describeImages(images, contextTexts, signal,
|
|
84
|
-
let apiKey;
|
|
85
|
-
try {
|
|
86
|
-
apiKey = await loadKeyForProvider("siliconflow");
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
return buildFallbackDescription(images, ["SILICONFLOW_API_KEY not configured"]);
|
|
90
|
-
}
|
|
99
|
+
async function describeImages(images, contextTexts, signal, kind = "default") {
|
|
91
100
|
const userContext = contextTexts.map((t) => t.text).join("\n");
|
|
101
|
+
const designIntent = kind === "design";
|
|
92
102
|
const visionContent = [];
|
|
93
103
|
visionContent.push({
|
|
94
104
|
type: "text",
|
|
95
|
-
text: designIntent
|
|
105
|
+
text: wrapAnalyzerInstructions(designIntent
|
|
96
106
|
? buildDesignPrompt(userContext, images.length)
|
|
97
|
-
: buildAnalysisPrompt(userContext, images.length),
|
|
107
|
+
: buildAnalysisPrompt(userContext, images.length, kind === "ocr"), kind),
|
|
98
108
|
});
|
|
99
109
|
for (const img of images) {
|
|
100
110
|
visionContent.push({
|
|
@@ -106,24 +116,12 @@ async function describeImages(images, contextTexts, signal, designIntent = false
|
|
|
106
116
|
});
|
|
107
117
|
}
|
|
108
118
|
const responseFormat = designIntent ? { type: "json_object" } : undefined;
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (result.ok)
|
|
114
|
-
return formatVisionResult(result.text, images.length, model, designIntent);
|
|
115
|
-
failureReasons.push(`${model}: ${result.reason}`);
|
|
116
|
-
console.warn(`[vision-proxy] ${model} failed (${result.reason}), trying next...`);
|
|
117
|
-
}
|
|
118
|
-
catch (err) {
|
|
119
|
-
if (signal?.aborted)
|
|
120
|
-
throw err;
|
|
121
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
122
|
-
failureReasons.push(`${model}: ${msg}`);
|
|
123
|
-
console.warn(`[vision-proxy] ${model} threw (${msg}), trying next...`);
|
|
124
|
-
}
|
|
119
|
+
const chain = await resolveAvailableVisionChain(kind);
|
|
120
|
+
const result = await callVisionBackend(chain, visionContent, signal, responseFormat);
|
|
121
|
+
if (result.ok) {
|
|
122
|
+
return formatNativeVisionObservation(result.text, { imageCount: images.length });
|
|
125
123
|
}
|
|
126
|
-
return
|
|
124
|
+
return formatNativeVisionUnavailable(images.length, [result.reason]);
|
|
127
125
|
}
|
|
128
126
|
function trySvgFastPath(images, designIntent) {
|
|
129
127
|
if (images.length === 0)
|
|
@@ -142,64 +140,23 @@ function trySvgFastPath(images, designIntent) {
|
|
|
142
140
|
return svg.length > 32_000 ? `${svg.slice(0, 32_000)}\n<!-- truncated -->` : svg;
|
|
143
141
|
})
|
|
144
142
|
.join("\n\n");
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
return `\n${header}${guidance}\n\`\`\`svg\n${decoded}\n\`\`\`\n[/Vision Proxy]\n`;
|
|
143
|
+
const observation = designIntent
|
|
144
|
+
? `I see ${images.length} SVG source(s). The vector markup below is exact — use element attributes (x, y, width, fill, text) directly.\n\nMap to layout schema:\n${UI_LAYOUT_SCHEMA_HINT}\n\n\`\`\`svg\n${decoded}\n\`\`\``
|
|
145
|
+
: `I see ${images.length} SVG source(s). Vector markup (read attributes directly):\n\n\`\`\`svg\n${decoded}\n\`\`\``;
|
|
146
|
+
return formatNativeVisionObservation(observation, { imageCount: images.length });
|
|
150
147
|
}
|
|
151
|
-
|
|
152
|
-
const controller = new AbortController();
|
|
153
|
-
let timedOut = false;
|
|
154
|
-
const timeout = setTimeout(() => {
|
|
155
|
-
timedOut = true;
|
|
156
|
-
controller.abort();
|
|
157
|
-
}, REQUEST_TIMEOUT_MS);
|
|
158
|
-
if (signal) {
|
|
159
|
-
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
160
|
-
}
|
|
161
|
-
let res;
|
|
162
|
-
try {
|
|
163
|
-
res = await fetch(`${SILICONFLOW_BASE}/chat/completions`, {
|
|
164
|
-
method: "POST",
|
|
165
|
-
headers: {
|
|
166
|
-
"Content-Type": "application/json",
|
|
167
|
-
Authorization: `Bearer ${apiKey}`,
|
|
168
|
-
},
|
|
169
|
-
body: JSON.stringify({
|
|
170
|
-
model,
|
|
171
|
-
messages: [{ role: "user", content }],
|
|
172
|
-
max_tokens: 3072,
|
|
173
|
-
temperature: 0.1,
|
|
174
|
-
...(responseFormat ? { response_format: responseFormat } : {}),
|
|
175
|
-
}),
|
|
176
|
-
signal: controller.signal,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
catch (err) {
|
|
180
|
-
clearTimeout(timeout);
|
|
181
|
-
if (timedOut)
|
|
182
|
-
return { ok: false, reason: `timeout after ${REQUEST_TIMEOUT_MS}ms` };
|
|
183
|
-
if (signal?.aborted)
|
|
184
|
-
throw err;
|
|
185
|
-
return { ok: false, reason: `network error: ${err instanceof Error ? err.message : String(err)}` };
|
|
186
|
-
}
|
|
187
|
-
clearTimeout(timeout);
|
|
188
|
-
if (!res.ok) {
|
|
189
|
-
const errText = await res.text().catch(() => "unknown error");
|
|
190
|
-
return { ok: false, reason: `HTTP ${res.status} ${errText.slice(0, 200)}` };
|
|
191
|
-
}
|
|
192
|
-
const data = (await res.json().catch(() => null));
|
|
193
|
-
const text = data?.choices?.[0]?.message?.content;
|
|
194
|
-
if (!text)
|
|
195
|
-
return { ok: false, reason: "empty response body" };
|
|
196
|
-
return { ok: true, text };
|
|
197
|
-
}
|
|
198
|
-
function buildAnalysisPrompt(userContext, imageCount) {
|
|
148
|
+
function buildAnalysisPrompt(userContext, imageCount, ocrFocus) {
|
|
199
149
|
const plural = imageCount > 1 ? `${imageCount} images` : "the image";
|
|
150
|
+
const ocrBlock = ocrFocus
|
|
151
|
+
? [
|
|
152
|
+
"OCR focus: transcribe ALL visible text exactly (preserve line breaks, labels, error codes).",
|
|
153
|
+
"Note any text that is blurry or partially cut off.",
|
|
154
|
+
"",
|
|
155
|
+
]
|
|
156
|
+
: [];
|
|
200
157
|
return [
|
|
201
|
-
`
|
|
202
|
-
|
|
158
|
+
`Analyze ${plural} for a software developer working in a coding CLI.`,
|
|
159
|
+
...ocrBlock,
|
|
203
160
|
"Focus on:",
|
|
204
161
|
"- UI layout and component structure (if screenshot)",
|
|
205
162
|
"- All visible text, labels, buttons, and form elements",
|
|
@@ -212,45 +169,19 @@ function buildAnalysisPrompt(userContext, imageCount) {
|
|
|
212
169
|
userContext ? `\nDeveloper's context: "${userContext}"` : "",
|
|
213
170
|
].join("\n");
|
|
214
171
|
}
|
|
215
|
-
function formatVisionResult(description, imageCount, model, designIntent = false) {
|
|
216
|
-
const usedModel = model ?? VISION_MODELS[0];
|
|
217
|
-
const tag = designIntent ? "design contract via" : "analyzed via";
|
|
218
|
-
const single = designIntent ? "design contract via" : "analyzed via";
|
|
219
|
-
const header = imageCount > 1
|
|
220
|
-
? `[Vision Proxy — ${imageCount} images ${tag} ${usedModel}]`
|
|
221
|
-
: `[Vision Proxy — image ${single} ${usedModel}]`;
|
|
222
|
-
return `\n${header}\n${description}\n[/Vision Proxy]\n`;
|
|
223
|
-
}
|
|
224
172
|
function buildDesignPrompt(userContext, imageCount) {
|
|
225
173
|
const plural = imageCount > 1 ? `${imageCount} images` : "the image";
|
|
226
174
|
return [
|
|
227
|
-
`Analyze ${plural} as a UI/UX design contract for a software developer
|
|
228
|
-
"
|
|
229
|
-
"",
|
|
230
|
-
"Return ONLY a single JSON object matching this exact shape (no markdown, no commentary, no code fences):",
|
|
175
|
+
`Analyze ${plural} as a UI/UX design contract for a software developer.`,
|
|
176
|
+
"Return ONLY a single JSON object matching this exact shape (no markdown, no commentary):",
|
|
231
177
|
UI_LAYOUT_SCHEMA_HINT,
|
|
232
178
|
"",
|
|
233
179
|
"Extraction rules:",
|
|
234
|
-
"- bbox: pixel coordinates relative to the visible image (origin top-left).
|
|
235
|
-
"- Colors: 6-digit lowercase hex (#rrggbb).
|
|
236
|
-
"-
|
|
237
|
-
"- spacingScalePx / radiusScalePx: distinct observed values, sorted ascending.",
|
|
238
|
-
"- components[]: every visible interactive or content element. Stable IDs like 'btn_signup'.",
|
|
239
|
-
"- children[]: component IDs nested inside this component.",
|
|
240
|
-
"- hierarchy[]: visual reading order of headings — level 1 hero, 2 section, 3 sub.",
|
|
180
|
+
"- bbox: pixel coordinates relative to the visible image (origin top-left).",
|
|
181
|
+
"- Colors: 6-digit lowercase hex (#rrggbb).",
|
|
182
|
+
"- components[]: every visible interactive or content element.",
|
|
241
183
|
"- text: EXACT visible string. null only when no text (icon-only).",
|
|
242
|
-
"- notes[]: things schema cannot capture — gradients, illustrations, motion.",
|
|
243
|
-
"",
|
|
244
|
-
"If a field is genuinely not determinable, use null. Never invent values.",
|
|
245
184
|
userContext ? `\nDeveloper's context: "${userContext}"` : "",
|
|
246
185
|
].join("\n");
|
|
247
186
|
}
|
|
248
|
-
function buildFallbackDescription(images, reasons = []) {
|
|
249
|
-
const count = images.length;
|
|
250
|
-
const types = [...new Set(images.map((i) => i.mediaType))].join(", ");
|
|
251
|
-
const detail = reasons.length > 0
|
|
252
|
-
? `Reason(s): ${reasons.join(" | ")}`
|
|
253
|
-
: "Reason: unknown — check SILICONFLOW_API_KEY and model availability.";
|
|
254
|
-
return `\n[Vision Proxy — unavailable, ${count} image(s) (${types}) could not be analyzed. ${detail}]\n`;
|
|
255
|
-
}
|
|
256
187
|
//# sourceMappingURL=vision-proxy.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/providers/warm.ts
|
|
3
|
+
*
|
|
4
|
+
* Boot-time warm-up of the provider factory registry.
|
|
5
|
+
*
|
|
6
|
+
* Root cause it addresses (measured live, 2026-07-16, session 0c6728ba1a25):
|
|
7
|
+
* an xai session POSTed model `gpt-5.4` to api.x.ai and got 404 "The model
|
|
8
|
+
* gpt-5.4 does not exist" — an openai model sent to the xai endpoint. The
|
|
9
|
+
* factory/model guard in `runtime.ts` DID spot the mismatch and tried to
|
|
10
|
+
* redirect the request to openai's own factory, but the registry had no openai
|
|
11
|
+
* entry: a session only ever built the factory for ITS OWN provider, so any
|
|
12
|
+
* sub-task that resolved a model from another provider had nothing to redirect
|
|
13
|
+
* to and fell through to the wrong endpoint.
|
|
14
|
+
*
|
|
15
|
+
* That is the actual hole. Model ids and provider factories travel as two
|
|
16
|
+
* independent values, so "borrow the session's factory" is the silent default
|
|
17
|
+
* for every sub-task (compaction, classify, sub-agents, mode switches) and only
|
|
18
|
+
* some paths remember to re-derive the provider. Warming the registry for every
|
|
19
|
+
* credentialed provider closes it at the source: the factory for a model's own
|
|
20
|
+
* provider is then always present, so `resolveModelRuntime` can derive it from
|
|
21
|
+
* the model itself instead of trusting whatever factory a caller passed.
|
|
22
|
+
*
|
|
23
|
+
* Best-effort by construction: a provider that fails to warm is simply absent
|
|
24
|
+
* (the same state as today), never a boot failure.
|
|
25
|
+
*/
|
|
26
|
+
import { type ProviderId } from "./types.js";
|
|
27
|
+
/** Outcome of {@link warmProviderFactories}, for logging and tests. */
|
|
28
|
+
export interface WarmResult {
|
|
29
|
+
/** Providers whose factory is now registered. */
|
|
30
|
+
warmed: ProviderId[];
|
|
31
|
+
/** Providers left out, with the reason (no credentials, disabled, or an error). */
|
|
32
|
+
skipped: Array<{
|
|
33
|
+
id: ProviderId;
|
|
34
|
+
reason: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build and register a factory for every provider the user has credentials for.
|
|
39
|
+
*
|
|
40
|
+
* Runs providers concurrently — each is an independent credential read, and a
|
|
41
|
+
* serial loop would add every provider's latency to boot.
|
|
42
|
+
*
|
|
43
|
+
* Skips providers that already have a factory: the session builds its own with
|
|
44
|
+
* session-specific options (custom baseURL, OAuth headers), and rebuilding it
|
|
45
|
+
* from bare defaults here would silently downgrade the live session's wiring.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Rebuild ONE provider's factory after its credentials changed mid-session.
|
|
49
|
+
*
|
|
50
|
+
* `createProviderFactoryAsync` reads OAuth tokens at CONSTRUCTION and bakes the
|
|
51
|
+
* resulting auth headers into the factory (runtime.ts: `loadTokensWithRefresh()`
|
|
52
|
+
* then `authHeaders(tokens)`). Boot warms openai/xai even with no tokens —
|
|
53
|
+
* `getOAuthProviderConfig` only reports that a provider SUPPORTS OAuth — so the
|
|
54
|
+
* entry built at boot is an API-key-path factory. Signing in later saved tokens
|
|
55
|
+
* that nothing re-read: the stale factory stayed registered and the provider
|
|
56
|
+
* kept failing until the next process start. That is the "OAuth only works
|
|
57
|
+
* after I restart the session" report; the same held for a key set via `K` on a
|
|
58
|
+
* provider skipped at boot for "no credentials".
|
|
59
|
+
*
|
|
60
|
+
* warmProviderFactories() cannot be reused for this: it deliberately SKIPS a
|
|
61
|
+
* provider that already has a factory. The registry is last-built-wins, so
|
|
62
|
+
* building again is what replaces the stale entry.
|
|
63
|
+
*/
|
|
64
|
+
export declare function rewarmProviderFactory(id: ProviderId): Promise<boolean>;
|
|
65
|
+
export declare function warmProviderFactories(): Promise<WarmResult>;
|