@gajae-code/coding-agent 0.11.1 → 0.11.2
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/CHANGELOG.md +54 -0
- package/dist/types/cli/config-cli.d.ts +11 -1
- package/dist/types/cli/notify-cli.d.ts +1 -0
- package/dist/types/cli/session-picker.d.ts +2 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/commands/mcp-serve.d.ts +33 -0
- package/dist/types/commands/mcp.d.ts +1 -1
- package/dist/types/commands/notify.d.ts +0 -2
- package/dist/types/commands/sdk.d.ts +1 -1
- package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
- package/dist/types/config/file-lock.d.ts +14 -4
- package/dist/types/config/keybindings.d.ts +42 -1
- package/dist/types/config/model-auth.d.ts +3 -0
- package/dist/types/config/model-bindings-applier.d.ts +13 -0
- package/dist/types/config/model-discovery-manager.d.ts +49 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-registry.d.ts +16 -15
- package/dist/types/config/model-resolver.d.ts +28 -18
- package/dist/types/config/models-config-schema.d.ts +11 -0
- package/dist/types/config/settings-schema.d.ts +56 -1
- package/dist/types/config/settings.d.ts +14 -11
- package/dist/types/coordinator-mcp/policy.d.ts +5 -0
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
- package/dist/types/coordinator-mcp/server.d.ts +4 -0
- package/dist/types/discovery/helpers.d.ts +0 -6
- package/dist/types/edit/index.d.ts +3 -0
- package/dist/types/eval/py/env.d.ts +9 -0
- package/dist/types/extensibility/extensions/loader.d.ts +2 -1
- package/dist/types/extensibility/extensions/runner.d.ts +2 -2
- package/dist/types/extensibility/extensions/types.d.ts +34 -3
- package/dist/types/extensibility/hooks/runner.d.ts +1 -1
- package/dist/types/extensibility/shared-events.d.ts +2 -0
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
- package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
- package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
- package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
- package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
- package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
- package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
- package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
- package/dist/types/gjc-runtime/team-store.d.ts +160 -0
- package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
- package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
- package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
- package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
- package/dist/types/goals/runtime.d.ts +1 -0
- package/dist/types/goals/state.d.ts +8 -0
- package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
- package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
- package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
- package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
- package/dist/types/hindsight/state.d.ts +11 -4
- package/dist/types/lsp/lspmux.d.ts +5 -3
- package/dist/types/lsp/path-trust.d.ts +1 -0
- package/dist/types/main.d.ts +3 -2
- package/dist/types/memories/storage.d.ts +1 -0
- package/dist/types/modes/action-registry.d.ts +29 -0
- package/dist/types/modes/components/chrome.d.ts +14 -0
- package/dist/types/modes/components/command-palette.d.ts +27 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
- package/dist/types/modes/components/index.d.ts +2 -1
- package/dist/types/modes/components/pet-selector.d.ts +1 -1
- package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
- package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
- package/dist/types/modes/components/queue-pane.d.ts +12 -0
- package/dist/types/modes/components/read-tool-group.d.ts +6 -0
- package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
- package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
- package/dist/types/modes/components/settings-selector.d.ts +1 -1
- package/dist/types/modes/components/show-images-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/types.d.ts +1 -1
- package/dist/types/modes/components/status-line.d.ts +1 -94
- package/dist/types/modes/components/tasks-pane.d.ts +15 -0
- package/dist/types/modes/components/theme-selector.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +15 -0
- package/dist/types/modes/components/tool-status-header.d.ts +111 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
- package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
- package/dist/types/modes/controllers/input-controller.d.ts +8 -1
- package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
- package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
- package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
- package/dist/types/modes/interactive-mode.d.ts +19 -17
- package/dist/types/modes/jobs-observer.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
- package/dist/types/modes/tasks-aggregator.d.ts +39 -0
- package/dist/types/modes/transcript-item-registry.d.ts +60 -0
- package/dist/types/modes/types.d.ts +20 -13
- package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
- package/dist/types/runtime-mcp/manager.d.ts +1 -1
- package/dist/types/sdk/broker/broker.d.ts +78 -12
- package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
- package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
- package/dist/types/sdk/broker/session-index.d.ts +0 -1
- package/dist/types/sdk/broker/state-version.d.ts +2 -0
- package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
- package/dist/types/sdk/bus/config-commands.d.ts +1 -1
- package/dist/types/sdk/bus/config.d.ts +11 -0
- package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
- package/dist/types/sdk/bus/html-format.d.ts +3 -2
- package/dist/types/sdk/bus/index.d.ts +27 -0
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/notification-service.d.ts +20 -0
- package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
- package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
- package/dist/types/sdk/bus/rich-document.d.ts +7 -0
- package/dist/types/sdk/bus/rich-render.d.ts +18 -41
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
- package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
- package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
- package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/session-directory.d.ts +56 -0
- package/dist/types/session/agent-session.d.ts +82 -47
- package/dist/types/session/agent-storage.d.ts +7 -0
- package/dist/types/session/fallback-chain-controller.d.ts +10 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
- package/dist/types/session/messages.d.ts +16 -0
- package/dist/types/session/session-manager-internal.d.ts +14 -0
- package/dist/types/session/session-manager.d.ts +82 -12
- package/dist/types/session/session-storage.d.ts +43 -3
- package/dist/types/session/volatile-context-pruning.d.ts +15 -0
- package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
- package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
- package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
- package/dist/types/system-prompt.d.ts +2 -11
- package/dist/types/task/executor.d.ts +3 -1
- package/dist/types/thinking.d.ts +7 -0
- package/dist/types/tool-discovery/tool-index.d.ts +1 -50
- package/dist/types/tools/ask.d.ts +64 -2
- package/dist/types/tools/bash.d.ts +3 -0
- package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
- package/dist/types/tools/cron.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -0
- package/dist/types/tools/index.d.ts +30 -15
- package/dist/types/tools/output-meta.d.ts +1 -0
- package/dist/types/tools/read.d.ts +3 -0
- package/dist/types/tools/search-tool-bm25.d.ts +3 -4
- package/dist/types/utils/event-bus.d.ts +1 -1
- package/dist/types/web/search/index.d.ts +3 -1
- package/package.json +21 -9
- package/scripts/build-sdk-package-smoke.ts +34 -1
- package/scripts/generate-hotkeys-docs.ts +74 -0
- package/scripts/generate-sdk-operation-inventory.ts +64 -20
- package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
- package/src/async/job-manager.ts +49 -6
- package/src/cli/config-cli.ts +75 -2
- package/src/cli/notify-cli.ts +92 -26
- package/src/cli/session-picker.ts +20 -3
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli.ts +1 -1
- package/src/commands/config.ts +1 -1
- package/src/commands/harness.ts +34 -106
- package/src/commands/launch.ts +6 -4
- package/src/commands/mcp-serve.ts +85 -8
- package/src/commands/mcp.ts +2 -2
- package/src/commands/notify.ts +8 -4
- package/src/commands/sdk.ts +61 -40
- package/src/commands/ultragoal.ts +4 -1
- package/src/config/atomic-yaml-patch.ts +80 -13
- package/src/config/file-lock.ts +105 -43
- package/src/config/keybindings.ts +64 -20
- package/src/config/model-auth.ts +9 -0
- package/src/config/model-bindings-applier.ts +139 -0
- package/src/config/model-discovery-manager.ts +224 -0
- package/src/config/model-equivalence.ts +66 -0
- package/src/config/model-registry.ts +169 -302
- package/src/config/model-resolver.ts +361 -369
- package/src/config/models-config-schema.ts +5 -4
- package/src/config/settings-schema.ts +159 -2
- package/src/config/settings.ts +458 -482
- package/src/coordinator-mcp/policy.ts +76 -11
- package/src/coordinator-mcp/question-gate-codec.ts +274 -0
- package/src/coordinator-mcp/question-state.ts +778 -0
- package/src/coordinator-mcp/server.ts +1702 -238
- package/src/debug/index.ts +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
- package/src/defaults/gjc/skills/team/SKILL.md +16 -0
- package/src/discovery/helpers.ts +1 -50
- package/src/edit/index.ts +64 -0
- package/src/eval/py/env.ts +26 -0
- package/src/eval/py/kernel.ts +5 -3
- package/src/extensibility/extensions/loader.ts +9 -1
- package/src/extensibility/extensions/runner.ts +12 -3
- package/src/extensibility/extensions/types.ts +39 -1
- package/src/extensibility/gjc-plugins/installer.ts +16 -16
- package/src/extensibility/hooks/runner.ts +2 -2
- package/src/extensibility/runtime-skill-discovery.ts +33 -13
- package/src/extensibility/shared-events.ts +2 -0
- package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
- package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
- package/src/gjc-runtime/deep-interview-state.ts +317 -5
- package/src/gjc-runtime/goal-mode-request.ts +55 -8
- package/src/gjc-runtime/launch-tmux.ts +2 -5
- package/src/gjc-runtime/launch-worktree.ts +5 -5
- package/src/gjc-runtime/linux-proc.ts +71 -0
- package/src/gjc-runtime/ralplan-runtime.ts +74 -90
- package/src/gjc-runtime/session-resolution.ts +18 -3
- package/src/gjc-runtime/session-state-sidecar.ts +6 -107
- package/src/gjc-runtime/state-migrations.ts +1 -1
- package/src/gjc-runtime/state-runtime.ts +320 -249
- package/src/gjc-runtime/state-writer.ts +36 -40
- package/src/gjc-runtime/team-launch.ts +319 -0
- package/src/gjc-runtime/team-notify.ts +326 -0
- package/src/gjc-runtime/team-runtime.ts +1099 -1482
- package/src/gjc-runtime/team-store.ts +828 -0
- package/src/gjc-runtime/team-workers.ts +962 -0
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
- package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
- package/src/gjc-runtime/tmux-sessions.ts +4 -21
- package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
- package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
- package/src/gjc-runtime/ultragoal-guard.ts +29 -5
- package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
- package/src/gjc-runtime/workflow-cli-common.ts +30 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
- package/src/gjc-runtime/workflow-manifest.ts +18 -0
- package/src/goals/continuation-timeout-guard.ts +79 -0
- package/src/goals/runtime.ts +7 -5
- package/src/goals/state.ts +18 -0
- package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
- package/src/harness-control-plane/phase-rollup.ts +4 -7
- package/src/harness-control-plane/receipt-ingest.ts +5 -0
- package/src/harness-control-plane/receipt-spool.ts +51 -7
- package/src/harness-control-plane/session-lease.ts +12 -130
- package/src/hindsight/backend.ts +26 -27
- package/src/hindsight/state.ts +101 -32
- package/src/hooks/skill-state.ts +17 -11
- package/src/internal-urls/docs-index.generated.ts +21 -18
- package/src/lsp/client.ts +1 -1
- package/src/lsp/config.ts +145 -26
- package/src/lsp/index.ts +1 -1
- package/src/lsp/lspmux.ts +39 -10
- package/src/lsp/path-trust.ts +81 -0
- package/src/main.ts +28 -8
- package/src/memories/index.ts +1 -0
- package/src/memories/storage.ts +6 -2
- package/src/modes/action-registry.ts +165 -0
- package/src/modes/components/chrome.ts +40 -0
- package/src/modes/components/command-palette.ts +168 -0
- package/src/modes/components/custom-editor.ts +1 -1
- package/src/modes/components/custom-provider-wizard.ts +51 -14
- package/src/modes/components/index.ts +2 -1
- package/src/modes/components/pet-selector.ts +11 -17
- package/src/modes/components/plan-preview-overlay.ts +295 -0
- package/src/modes/components/queue-mode-selector.ts +10 -27
- package/src/modes/components/queue-pane.ts +79 -0
- package/src/modes/components/read-tool-group.ts +13 -0
- package/src/modes/components/session-observer-overlay.ts +207 -772
- package/src/modes/components/sessions-dashboard.ts +181 -0
- package/src/modes/components/settings-selector.ts +1 -1
- package/src/modes/components/show-images-selector.ts +10 -24
- package/src/modes/components/status-line/types.ts +1 -1
- package/src/modes/components/status-line.ts +1 -969
- package/src/modes/components/tasks-pane.ts +73 -0
- package/src/modes/components/theme-selector.ts +11 -31
- package/src/modes/components/tool-execution.ts +22 -0
- package/src/modes/components/tool-status-header.ts +1056 -0
- package/src/modes/components/transcript-viewer-overlay.ts +384 -0
- package/src/modes/controllers/btw-controller.ts +1 -0
- package/src/modes/controllers/event-controller.ts +3 -2
- package/src/modes/controllers/extension-ui-controller.ts +24 -1
- package/src/modes/controllers/goal-mode-controller.ts +474 -0
- package/src/modes/controllers/input-controller.ts +764 -229
- package/src/modes/controllers/mode-gate.ts +24 -0
- package/src/modes/controllers/plan-mode-controller.ts +517 -0
- package/src/modes/controllers/selector-controller.ts +225 -10
- package/src/modes/controllers/stt-controller.ts +125 -0
- package/src/modes/interactive-mode.ts +289 -1150
- package/src/modes/jobs-observer.ts +3 -0
- package/src/modes/runtime-init.ts +8 -0
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
- package/src/modes/tasks-aggregator.ts +199 -0
- package/src/modes/transcript-item-registry.ts +229 -0
- package/src/modes/types.ts +45 -18
- package/src/modes/utils/ui-helpers.ts +17 -9
- package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
- package/src/prompts/agent-fragments/restricted-bash.md +1 -0
- package/src/prompts/agents/architect.md +2 -8
- package/src/prompts/agents/critic.md +2 -8
- package/src/prompts/agents/executor.md +3 -0
- package/src/prompts/agents/planner.md +4 -12
- package/src/prompts/system/custom-system-prompt.md +1 -23
- package/src/prompts/system/plan-mode-approved.md +8 -0
- package/src/prompts/system/system-prompt.md +17 -96
- package/src/prompts/tools/bash.md +4 -4
- package/src/prompts/tools/browser.md +15 -52
- package/src/prompts/tools/find.md +2 -2
- package/src/prompts/tools/hashline.md +13 -55
- package/src/prompts/tools/read.md +3 -6
- package/src/prompts/tools/search-tool-bm25.md +0 -2
- package/src/prompts/tools/search.md +2 -4
- package/src/prompts/tools/skill-discovery.md +1 -2
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-mcp/manager.ts +1 -1
- package/src/sdk/broker/broker.ts +206 -78
- package/src/sdk/broker/discovery.ts +1 -1
- package/src/sdk/broker/ensure.ts +3 -1
- package/src/sdk/broker/lifecycle-codec.ts +11 -0
- package/src/sdk/broker/lifecycle-ledger.ts +371 -74
- package/src/sdk/broker/lifecycle.ts +1399 -142
- package/src/sdk/broker/process-incarnation.ts +5 -13
- package/src/sdk/broker/session-index.ts +145 -56
- package/src/sdk/broker/state-version.ts +21 -0
- package/src/sdk/broker/transport.ts +1 -1
- package/src/sdk/bus/chat-daemon-cli.ts +2 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -28
- package/src/sdk/bus/chat-effect-journal.ts +10 -2
- package/src/sdk/bus/config-commands.ts +5 -4
- package/src/sdk/bus/config.ts +98 -0
- package/src/sdk/bus/conversation-store.ts +5 -29
- package/src/sdk/bus/daemon-paths.ts +2 -0
- package/src/sdk/bus/html-format.ts +20 -3
- package/src/sdk/bus/index.ts +778 -93
- package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
- package/src/sdk/bus/natives-augment.d.ts +26 -1
- package/src/sdk/bus/notification-service.ts +168 -20
- package/src/sdk/bus/rate-limit-pool.ts +58 -14
- package/src/sdk/bus/recent-activity.ts +188 -74
- package/src/sdk/bus/rich-document.ts +258 -0
- package/src/sdk/bus/rich-render.ts +62 -70
- package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
- package/src/sdk/bus/telegram-daemon.ts +1389 -237
- package/src/sdk/bus/threaded-inbound.ts +8 -3
- package/src/sdk/bus/threaded-render.ts +57 -1
- package/src/sdk/bus/topic-registry.ts +120 -13
- package/src/sdk/host/control/dispatch.ts +14 -2
- package/src/sdk/host/control/operations.ts +6 -1
- package/src/sdk/host/host.ts +31 -1
- package/src/sdk/host/query/handlers.ts +20 -22
- package/src/sdk/host/query/revision-store.ts +80 -57
- package/src/sdk/index.ts +1 -0
- package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
- package/src/sdk/session-directory.ts +141 -0
- package/src/sdk/session.ts +458 -479
- package/src/session/agent-session.ts +1700 -583
- package/src/session/agent-storage.ts +18 -0
- package/src/session/cache-economics.ts +25 -8
- package/src/session/fallback-chain-controller.ts +53 -3
- package/src/session/internal/managed-session-scope.ts +2226 -0
- package/src/session/internal/managed-session-storage.ts +453 -0
- package/src/session/messages.ts +91 -2
- package/src/session/session-manager-internal.ts +33 -0
- package/src/session/session-manager.ts +1112 -333
- package/src/session/session-storage.ts +444 -39
- package/src/session/volatile-context-pruning.ts +78 -0
- package/src/setup/credential-auto-import.ts +2 -1
- package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
- package/src/setup/provider-onboarding.ts +36 -61
- package/src/setup/provider-presets.json +5 -0
- package/src/skill-state/active-state.ts +3 -13
- package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
- package/src/skill-state/workflow-state-contract.ts +6 -41
- package/src/slash-commands/builtin-registry.ts +46 -11
- package/src/system-prompt.ts +37 -44
- package/src/task/agents.ts +19 -1
- package/src/task/executor.ts +90 -6
- package/src/task/index.ts +36 -21
- package/src/thinking.ts +21 -6
- package/src/tool-discovery/tool-index.ts +2 -134
- package/src/tools/ask.ts +157 -21
- package/src/tools/ast-edit.ts +1 -1
- package/src/tools/bash.ts +38 -0
- package/src/tools/browser/dead-tab-recovery.ts +78 -0
- package/src/tools/browser/tab-supervisor.ts +282 -36
- package/src/tools/computer.ts +10 -3
- package/src/tools/cron.ts +30 -16
- package/src/tools/eval.ts +1 -2
- package/src/tools/fetch.ts +11 -4
- package/src/tools/index.ts +76 -24
- package/src/tools/output-meta.ts +13 -5
- package/src/tools/read.ts +37 -1
- package/src/tools/resource-gc.ts +2 -2
- package/src/tools/search-tool-bm25.ts +11 -74
- package/src/utils/event-bus.ts +9 -4
- package/src/web/search/index.ts +3 -3
- package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
- package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
- package/src/discovery/plugin-dir-roots.ts +0 -28
- package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
|
@@ -40,11 +40,18 @@ import { isValidThemeColor, type ThemeColor } from "../modes/theme/theme";
|
|
|
40
40
|
import type { AuthStorage, OAuthCredential } from "../session/auth-storage";
|
|
41
41
|
import type { ActiveSearchModelContext, WebSearchMode } from "../web/search/types";
|
|
42
42
|
import { type ConfigError, ConfigFile } from "./config-file";
|
|
43
|
+
import { isAuthenticated, kNoAuth } from "./model-auth";
|
|
44
|
+
import { ModelBindingsApplier } from "./model-bindings-applier";
|
|
45
|
+
import { ModelDiscoveryManager, type ProviderDiscoveryState } from "./model-discovery-manager";
|
|
46
|
+
|
|
47
|
+
export type { ProviderDiscoveryState, ProviderDiscoveryStatus } from "./model-discovery-manager";
|
|
48
|
+
|
|
43
49
|
import {
|
|
44
50
|
buildCanonicalModelIndex,
|
|
45
51
|
type CanonicalModelIndex,
|
|
46
52
|
type CanonicalModelRecord,
|
|
47
53
|
type CanonicalModelVariant,
|
|
54
|
+
compareEquivalentModelVariants,
|
|
48
55
|
formatCanonicalVariantSelector,
|
|
49
56
|
type ModelEquivalenceConfig,
|
|
50
57
|
} from "./model-equivalence";
|
|
@@ -53,8 +60,8 @@ import {
|
|
|
53
60
|
type ModelProfileDefinition,
|
|
54
61
|
mergeModelProfiles,
|
|
55
62
|
} from "./model-profiles";
|
|
56
|
-
import { type ModelSelectorValue, normalizeModelSelectorValue } from "./model-selector-value";
|
|
57
63
|
import {
|
|
64
|
+
GJC_MODEL_ASSIGNMENT_TARGET_IDS,
|
|
58
65
|
type ModelOverride,
|
|
59
66
|
type ModelProfileConfig,
|
|
60
67
|
type ModelsConfig,
|
|
@@ -67,10 +74,20 @@ import { type Settings, settings } from "./settings";
|
|
|
67
74
|
|
|
68
75
|
export type { CanonicalModelIndex, CanonicalModelRecord, CanonicalModelVariant, ModelEquivalenceConfig };
|
|
69
76
|
|
|
70
|
-
export
|
|
77
|
+
export { isAuthenticated, kNoAuth };
|
|
71
78
|
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
const MAX_SESSION_CANONICAL_VARIANTS = 64;
|
|
80
|
+
|
|
81
|
+
function envAvailabilityFingerprint(): string {
|
|
82
|
+
return Object.entries(process.env)
|
|
83
|
+
.filter(
|
|
84
|
+
([name]) =>
|
|
85
|
+
/(?:_API_KEY|_OAUTH_TOKEN|_ACCESS_TOKEN)$/.test(name) ||
|
|
86
|
+
/^(?:GH_TOKEN|GITHUB_TOKEN|HF_TOKEN|COPILOT_GITHUB_TOKEN)$/.test(name),
|
|
87
|
+
)
|
|
88
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
89
|
+
.map(([name, value]) => `${name}=${value ?? ""}`)
|
|
90
|
+
.join("\u0000");
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
export type ModelRole = "default";
|
|
@@ -88,20 +105,14 @@ export const MODEL_ROLES: Record<ModelRole, ModelRoleInfo> = {
|
|
|
88
105
|
export const MODEL_ROLE_IDS: ModelRole[] = ["default"];
|
|
89
106
|
export const MODEL_PROFILE_NAME_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
90
107
|
export const MODEL_PROFILE_NAME_PATTERN_DESCRIPTION = "lowercase letters, numbers, dots, underscores, or hyphens";
|
|
91
|
-
export type GjcModelAssignmentTargetId =
|
|
108
|
+
export type GjcModelAssignmentTargetId = (typeof GJC_MODEL_ASSIGNMENT_TARGET_IDS)[number];
|
|
92
109
|
|
|
93
110
|
export interface GjcModelAssignmentTargetInfo extends ModelRoleInfo {
|
|
94
111
|
id: GjcModelAssignmentTargetId;
|
|
95
112
|
settingsPath: "modelRoles" | "task.agentModelOverrides";
|
|
96
113
|
}
|
|
97
114
|
|
|
98
|
-
export
|
|
99
|
-
"default",
|
|
100
|
-
"executor",
|
|
101
|
-
"architect",
|
|
102
|
-
"planner",
|
|
103
|
-
"critic",
|
|
104
|
-
];
|
|
115
|
+
export { GJC_MODEL_ASSIGNMENT_TARGET_IDS };
|
|
105
116
|
|
|
106
117
|
export const GJC_MODEL_ASSIGNMENT_TARGETS: Record<GjcModelAssignmentTargetId, GjcModelAssignmentTargetInfo> = {
|
|
107
118
|
default: { id: "default", tag: "DEFAULT", name: "Default", color: "success", settingsPath: "modelRoles" },
|
|
@@ -515,21 +526,11 @@ interface DiscoveryProviderConfig {
|
|
|
515
526
|
optional?: boolean;
|
|
516
527
|
}
|
|
517
528
|
|
|
518
|
-
export type ProviderDiscoveryStatus = "idle" | "ok" | "empty" | "cached" | "unavailable" | "unauthenticated";
|
|
519
|
-
|
|
520
|
-
export interface ProviderDiscoveryState {
|
|
521
|
-
provider: string;
|
|
522
|
-
status: ProviderDiscoveryStatus;
|
|
523
|
-
optional: boolean;
|
|
524
|
-
stale: boolean;
|
|
525
|
-
fetchedAt?: number;
|
|
526
|
-
models: string[];
|
|
527
|
-
error?: string;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
529
|
export interface CanonicalModelQueryOptions {
|
|
531
530
|
availableOnly?: boolean;
|
|
532
531
|
candidates?: readonly Model<Api>[];
|
|
532
|
+
/** Stable session identity used to keep a canonical variant sticky within a session. */
|
|
533
|
+
sessionId?: string;
|
|
533
534
|
}
|
|
534
535
|
|
|
535
536
|
/** Result of loading custom models from models.json */
|
|
@@ -1008,32 +1009,27 @@ function getConfiguredProviderOrderFromSettings(): string[] {
|
|
|
1008
1009
|
export class ModelRegistry {
|
|
1009
1010
|
#models: Model<Api>[] = [];
|
|
1010
1011
|
#canonicalIndex: CanonicalModelIndex = { records: [], byId: new Map(), bySelector: new Map() };
|
|
1012
|
+
#availableModelsCache: Model<Api>[] | undefined;
|
|
1013
|
+
#availableModelsDisabledProviders: string | undefined;
|
|
1014
|
+
#availableModelsEnvFingerprint: string | undefined;
|
|
1015
|
+
#sessionCanonicalVariants = new Map<string, string>();
|
|
1011
1016
|
#customProviderApiKeys: Map<string, string> = new Map();
|
|
1012
1017
|
#providerWebSearchModes: Map<string, WebSearchMode> = new Map();
|
|
1013
1018
|
#keylessProviders: Set<string> = new Set();
|
|
1014
|
-
#
|
|
1019
|
+
#discoveryManager = new ModelDiscoveryManager<DiscoveryProviderConfig>();
|
|
1015
1020
|
#customModelOverlays: CustomModelOverlay[] = [];
|
|
1016
1021
|
#providerOverrides: Map<string, ProviderOverride> = new Map();
|
|
1017
1022
|
#modelOverrides: Map<string, Map<string, ModelOverride>> = new Map();
|
|
1018
1023
|
#equivalenceConfig: ModelEquivalenceConfig | undefined;
|
|
1019
|
-
#
|
|
1024
|
+
#modelBindingsApplier = new ModelBindingsApplier();
|
|
1020
1025
|
#modelProfiles: Map<string, ModelProfileDefinition> = mergeModelProfiles();
|
|
1021
|
-
#modelBindingsTargetSettings: Settings | undefined;
|
|
1022
|
-
#appliedModelBindingRoles = new Set<string>();
|
|
1023
|
-
#appliedAgentModelBindingOverrides = new Set<string>();
|
|
1024
|
-
#modelBindingRoleBaselines = new Map<string, ModelSelectorValue | undefined>();
|
|
1025
|
-
#agentModelBindingBaselines = new Map<string, ModelSelectorValue | undefined>();
|
|
1026
|
-
#lastAppliedModelBindingRoles = new Map<string, ModelSelectorValue>();
|
|
1027
|
-
#lastAppliedAgentModelBindingOverrides = new Map<string, ModelSelectorValue>();
|
|
1028
1026
|
#configError: ConfigError | undefined = undefined;
|
|
1029
1027
|
#modelsConfigFile: ConfigFile<ModelsConfig>;
|
|
1030
1028
|
#lastStaticLoadMtime: number | null = null;
|
|
1031
1029
|
#registeredProviderSources: Set<string> = new Set();
|
|
1032
|
-
#providerDiscoveryStates: Map<string, ProviderDiscoveryState> = new Map();
|
|
1033
1030
|
#cacheDbPath?: string;
|
|
1034
1031
|
#suppressedSelectors: Map<string, number> = new Map();
|
|
1035
1032
|
#backgroundRefresh?: Promise<void>;
|
|
1036
|
-
#lastDiscoveryWarnings: Map<string, string> = new Map();
|
|
1037
1033
|
// Runtime extension model overlays — persist across refresh() cycles so that
|
|
1038
1034
|
// models registered by extensions survive the model selector's offline reload.
|
|
1039
1035
|
#runtimeModelOverlays: CustomModelOverlay[] = [];
|
|
@@ -1058,6 +1054,7 @@ export class ModelRegistry {
|
|
|
1058
1054
|
const keyConfig = this.#customProviderApiKeys.get(provider);
|
|
1059
1055
|
return keyConfig;
|
|
1060
1056
|
});
|
|
1057
|
+
this.authStorage.onGenerationChanged(() => this.#invalidateAvailableModels());
|
|
1061
1058
|
// Load models synchronously in constructor
|
|
1062
1059
|
this.#loadModels();
|
|
1063
1060
|
}
|
|
@@ -1071,7 +1068,7 @@ export class ModelRegistry {
|
|
|
1071
1068
|
this.#reloadStaticModels();
|
|
1072
1069
|
this.#suppressedSelectors.clear();
|
|
1073
1070
|
await this.#refreshRuntimeDiscoveries(strategy);
|
|
1074
|
-
this.#
|
|
1071
|
+
this.#modelBindingsApplier.apply();
|
|
1075
1072
|
} finally {
|
|
1076
1073
|
this.#resumeRebuild();
|
|
1077
1074
|
}
|
|
@@ -1105,7 +1102,7 @@ export class ModelRegistry {
|
|
|
1105
1102
|
}
|
|
1106
1103
|
}
|
|
1107
1104
|
await this.#refreshRuntimeDiscoveries(strategy, new Set([providerId]));
|
|
1108
|
-
this.#
|
|
1105
|
+
this.#modelBindingsApplier.apply();
|
|
1109
1106
|
} finally {
|
|
1110
1107
|
this.#resumeRebuild();
|
|
1111
1108
|
}
|
|
@@ -1121,7 +1118,7 @@ export class ModelRegistry {
|
|
|
1121
1118
|
this.#customProviderApiKeys.clear();
|
|
1122
1119
|
this.#providerWebSearchModes.clear();
|
|
1123
1120
|
this.#keylessProviders.clear();
|
|
1124
|
-
this.#
|
|
1121
|
+
this.#discoveryManager.reset();
|
|
1125
1122
|
// Drop config-sourced apiKeys from AuthStorage before reload; entries
|
|
1126
1123
|
// removed from models.yml must actually disappear from the resolver, not
|
|
1127
1124
|
// linger from the previous parse. The post-load setters below repopulate.
|
|
@@ -1134,9 +1131,8 @@ export class ModelRegistry {
|
|
|
1134
1131
|
this.#providerOverrides.clear();
|
|
1135
1132
|
this.#modelOverrides.clear();
|
|
1136
1133
|
this.#equivalenceConfig = undefined;
|
|
1137
|
-
this.#
|
|
1134
|
+
this.#modelBindingsApplier.setBindings(undefined);
|
|
1138
1135
|
this.#configError = undefined;
|
|
1139
|
-
this.#providerDiscoveryStates.clear();
|
|
1140
1136
|
this.#loadModels();
|
|
1141
1137
|
}
|
|
1142
1138
|
|
|
@@ -1163,12 +1159,12 @@ export class ModelRegistry {
|
|
|
1163
1159
|
} = this.#loadCustomModels();
|
|
1164
1160
|
this.#configError = configError;
|
|
1165
1161
|
this.#keylessProviders = keylessProviders;
|
|
1166
|
-
this.#discoverableProviders
|
|
1162
|
+
this.#discoveryManager.setProviders(discoverableProviders);
|
|
1167
1163
|
this.#customModelOverlays = customModels;
|
|
1168
1164
|
this.#providerOverrides = overrides;
|
|
1169
1165
|
this.#modelOverrides = modelOverrides;
|
|
1170
1166
|
this.#equivalenceConfig = equivalence;
|
|
1171
|
-
this.#
|
|
1167
|
+
this.#modelBindingsApplier.setBindings(modelBindings);
|
|
1172
1168
|
this.#modelProfiles = mergeModelProfiles(profiles);
|
|
1173
1169
|
|
|
1174
1170
|
this.#addImplicitDiscoverableProviders(configuredProviders);
|
|
@@ -1283,7 +1279,7 @@ export class ModelRegistry {
|
|
|
1283
1279
|
}
|
|
1284
1280
|
|
|
1285
1281
|
#loadCachedStandardProviderModels(): Model<Api>[] {
|
|
1286
|
-
const configuredDiscoveryProviders = new Set(this.#
|
|
1282
|
+
const configuredDiscoveryProviders = new Set(this.#discoveryManager.providers.map(provider => provider.provider));
|
|
1287
1283
|
const cachedModels: Model<Api>[] = [];
|
|
1288
1284
|
for (const descriptor of PROVIDER_DESCRIPTORS) {
|
|
1289
1285
|
if (configuredDiscoveryProviders.has(descriptor.providerId)) {
|
|
@@ -1310,34 +1306,16 @@ export class ModelRegistry {
|
|
|
1310
1306
|
|
|
1311
1307
|
#loadCachedDiscoverableModels(): Model<Api>[] {
|
|
1312
1308
|
const cachedModels: Model<Api>[] = [];
|
|
1313
|
-
for (const providerConfig of this.#
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
this.#providerDiscoveryStates.set(providerConfig.provider, {
|
|
1317
|
-
provider: providerConfig.provider,
|
|
1318
|
-
status: "idle",
|
|
1319
|
-
optional: providerConfig.optional ?? false,
|
|
1320
|
-
stale: false,
|
|
1321
|
-
models: [],
|
|
1322
|
-
});
|
|
1323
|
-
continue;
|
|
1324
|
-
}
|
|
1325
|
-
const models = this.#applyProviderModelOverrides(
|
|
1309
|
+
for (const providerConfig of this.#discoveryManager.providers) {
|
|
1310
|
+
const models = this.#discoveryManager.loadCached(providerConfig, this.#cacheDbPath);
|
|
1311
|
+
const normalized = this.#applyProviderModelOverrides(
|
|
1326
1312
|
providerConfig.provider,
|
|
1327
1313
|
this.#normalizeDiscoverableModels(
|
|
1328
1314
|
providerConfig,
|
|
1329
|
-
this.#applyProviderCompat(providerConfig.compat,
|
|
1315
|
+
this.#applyProviderCompat(providerConfig.compat, [...models]),
|
|
1330
1316
|
),
|
|
1331
1317
|
);
|
|
1332
|
-
cachedModels.push(...
|
|
1333
|
-
this.#providerDiscoveryStates.set(providerConfig.provider, {
|
|
1334
|
-
provider: providerConfig.provider,
|
|
1335
|
-
status: "cached",
|
|
1336
|
-
optional: providerConfig.optional ?? false,
|
|
1337
|
-
stale: !cache.fresh || !cache.authoritative,
|
|
1338
|
-
fetchedAt: cache.updatedAt,
|
|
1339
|
-
models: models.map(model => model.id),
|
|
1340
|
-
});
|
|
1318
|
+
cachedModels.push(...normalized);
|
|
1341
1319
|
}
|
|
1342
1320
|
return cachedModels;
|
|
1343
1321
|
}
|
|
@@ -1368,7 +1346,7 @@ export class ModelRegistry {
|
|
|
1368
1346
|
#addImplicitDiscoverableProviders(configuredProviders: Set<string>): void {
|
|
1369
1347
|
const disabledProviders = getDisabledProviderIdsFromSettings();
|
|
1370
1348
|
if (!configuredProviders.has("ollama") && !disabledProviders.has("ollama")) {
|
|
1371
|
-
this.#
|
|
1349
|
+
this.#discoveryManager.addProvider({
|
|
1372
1350
|
provider: "ollama",
|
|
1373
1351
|
api: "openai-responses",
|
|
1374
1352
|
baseUrl: Bun.env.OLLAMA_BASE_URL || "http://127.0.0.1:11434",
|
|
@@ -1378,7 +1356,7 @@ export class ModelRegistry {
|
|
|
1378
1356
|
this.#keylessProviders.add("ollama");
|
|
1379
1357
|
}
|
|
1380
1358
|
if (!configuredProviders.has("llama.cpp") && !disabledProviders.has("llama.cpp")) {
|
|
1381
|
-
this.#
|
|
1359
|
+
this.#discoveryManager.addProvider({
|
|
1382
1360
|
provider: "llama.cpp",
|
|
1383
1361
|
api: "openai-responses",
|
|
1384
1362
|
baseUrl: Bun.env.LLAMA_CPP_BASE_URL || "http://127.0.0.1:8080",
|
|
@@ -1391,7 +1369,7 @@ export class ModelRegistry {
|
|
|
1391
1369
|
}
|
|
1392
1370
|
}
|
|
1393
1371
|
if (!configuredProviders.has("lm-studio") && !disabledProviders.has("lm-studio")) {
|
|
1394
|
-
this.#
|
|
1372
|
+
this.#discoveryManager.addProvider({
|
|
1395
1373
|
provider: "lm-studio",
|
|
1396
1374
|
api: "openai-completions",
|
|
1397
1375
|
baseUrl: Bun.env.LM_STUDIO_BASE_URL || "http://127.0.0.1:1234/v1",
|
|
@@ -1696,95 +1674,7 @@ export class ModelRegistry {
|
|
|
1696
1674
|
this.#reloadStaticModels();
|
|
1697
1675
|
}
|
|
1698
1676
|
applyConfiguredModelBindings(targetSettings: Settings): void {
|
|
1699
|
-
this.#
|
|
1700
|
-
this.#applyConfiguredModelBindingsToTarget();
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
#cloneModelSelectorValue(value: ModelSelectorValue | undefined): ModelSelectorValue | undefined {
|
|
1704
|
-
return Array.isArray(value) ? [...value] : value;
|
|
1705
|
-
}
|
|
1706
|
-
|
|
1707
|
-
#modelSelectorValuesEqual(left: ModelSelectorValue | undefined, right: ModelSelectorValue | undefined): boolean {
|
|
1708
|
-
const leftSelectors = normalizeModelSelectorValue(left);
|
|
1709
|
-
const rightSelectors = normalizeModelSelectorValue(right);
|
|
1710
|
-
return (
|
|
1711
|
-
leftSelectors.length === rightSelectors.length &&
|
|
1712
|
-
leftSelectors.every((selector, index) => selector === rightSelectors[index])
|
|
1713
|
-
);
|
|
1714
|
-
}
|
|
1715
|
-
|
|
1716
|
-
#applyConfiguredModelBindingsToTarget(): void {
|
|
1717
|
-
const targetSettings = this.#modelBindingsTargetSettings;
|
|
1718
|
-
if (!targetSettings) return;
|
|
1719
|
-
const bindings = this.#configuredModelBindings;
|
|
1720
|
-
const nextModelRoles = { ...targetSettings.get("modelRoles") };
|
|
1721
|
-
const configuredModelRoles = bindings?.modelRoles ?? {};
|
|
1722
|
-
const configuredModelRoleKeys = new Set(Object.keys(configuredModelRoles));
|
|
1723
|
-
for (const role of this.#appliedModelBindingRoles) {
|
|
1724
|
-
if (configuredModelRoleKeys.has(role)) continue;
|
|
1725
|
-
const lastApplied = this.#lastAppliedModelBindingRoles.get(role);
|
|
1726
|
-
if (lastApplied !== undefined && this.#modelSelectorValuesEqual(nextModelRoles[role], lastApplied)) {
|
|
1727
|
-
const baseline = this.#modelBindingRoleBaselines.get(role);
|
|
1728
|
-
if (baseline === undefined) {
|
|
1729
|
-
delete nextModelRoles[role];
|
|
1730
|
-
} else {
|
|
1731
|
-
nextModelRoles[role] = this.#cloneModelSelectorValue(baseline)!;
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
this.#modelBindingRoleBaselines.delete(role);
|
|
1735
|
-
this.#lastAppliedModelBindingRoles.delete(role);
|
|
1736
|
-
}
|
|
1737
|
-
for (const [role, selector] of Object.entries(configuredModelRoles)) {
|
|
1738
|
-
const previousApplied = this.#lastAppliedModelBindingRoles.get(role);
|
|
1739
|
-
if (!this.#modelBindingRoleBaselines.has(role)) {
|
|
1740
|
-
this.#modelBindingRoleBaselines.set(role, this.#cloneModelSelectorValue(nextModelRoles[role]));
|
|
1741
|
-
}
|
|
1742
|
-
if (previousApplied === undefined || this.#modelSelectorValuesEqual(nextModelRoles[role], previousApplied)) {
|
|
1743
|
-
nextModelRoles[role] = this.#cloneModelSelectorValue(selector)!;
|
|
1744
|
-
this.#lastAppliedModelBindingRoles.set(role, this.#cloneModelSelectorValue(selector)!);
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
targetSettings.override("modelRoles", nextModelRoles);
|
|
1748
|
-
this.#appliedModelBindingRoles = new Set(Object.keys(configuredModelRoles));
|
|
1749
|
-
|
|
1750
|
-
const nextAgentModelOverrides = { ...targetSettings.get("task.agentModelOverrides") };
|
|
1751
|
-
const configuredAgentModelOverrides = bindings?.agentModelOverrides ?? {};
|
|
1752
|
-
const configuredAgentModelOverrideKeys = new Set(Object.keys(configuredAgentModelOverrides));
|
|
1753
|
-
for (const agentName of this.#appliedAgentModelBindingOverrides) {
|
|
1754
|
-
if (configuredAgentModelOverrideKeys.has(agentName)) continue;
|
|
1755
|
-
const lastApplied = this.#lastAppliedAgentModelBindingOverrides.get(agentName);
|
|
1756
|
-
if (
|
|
1757
|
-
lastApplied !== undefined &&
|
|
1758
|
-
this.#modelSelectorValuesEqual(nextAgentModelOverrides[agentName], lastApplied)
|
|
1759
|
-
) {
|
|
1760
|
-
const baseline = this.#agentModelBindingBaselines.get(agentName);
|
|
1761
|
-
if (baseline === undefined) {
|
|
1762
|
-
delete nextAgentModelOverrides[agentName];
|
|
1763
|
-
} else {
|
|
1764
|
-
nextAgentModelOverrides[agentName] = this.#cloneModelSelectorValue(baseline)!;
|
|
1765
|
-
}
|
|
1766
|
-
}
|
|
1767
|
-
this.#agentModelBindingBaselines.delete(agentName);
|
|
1768
|
-
this.#lastAppliedAgentModelBindingOverrides.delete(agentName);
|
|
1769
|
-
}
|
|
1770
|
-
for (const [agentName, selector] of Object.entries(configuredAgentModelOverrides)) {
|
|
1771
|
-
const previousApplied = this.#lastAppliedAgentModelBindingOverrides.get(agentName);
|
|
1772
|
-
if (!this.#agentModelBindingBaselines.has(agentName)) {
|
|
1773
|
-
this.#agentModelBindingBaselines.set(
|
|
1774
|
-
agentName,
|
|
1775
|
-
this.#cloneModelSelectorValue(nextAgentModelOverrides[agentName]),
|
|
1776
|
-
);
|
|
1777
|
-
}
|
|
1778
|
-
if (
|
|
1779
|
-
previousApplied === undefined ||
|
|
1780
|
-
this.#modelSelectorValuesEqual(nextAgentModelOverrides[agentName], previousApplied)
|
|
1781
|
-
) {
|
|
1782
|
-
nextAgentModelOverrides[agentName] = this.#cloneModelSelectorValue(selector)!;
|
|
1783
|
-
this.#lastAppliedAgentModelBindingOverrides.set(agentName, this.#cloneModelSelectorValue(selector)!);
|
|
1784
|
-
}
|
|
1785
|
-
}
|
|
1786
|
-
targetSettings.override("task.agentModelOverrides", nextAgentModelOverrides);
|
|
1787
|
-
this.#appliedAgentModelBindingOverrides = new Set(Object.keys(configuredAgentModelOverrides));
|
|
1677
|
+
this.#modelBindingsApplier.applyTo(targetSettings);
|
|
1788
1678
|
}
|
|
1789
1679
|
|
|
1790
1680
|
async #refreshRuntimeDiscoveries(
|
|
@@ -1794,8 +1684,8 @@ export class ModelRegistry {
|
|
|
1794
1684
|
const disabledProviders = getDisabledProviderIdsFromSettings();
|
|
1795
1685
|
const selectedDiscoverableProviders = (
|
|
1796
1686
|
providerFilter
|
|
1797
|
-
? this.#
|
|
1798
|
-
: this.#
|
|
1687
|
+
? this.#discoveryManager.providers.filter(provider => providerFilter.has(provider.provider))
|
|
1688
|
+
: this.#discoveryManager.providers
|
|
1799
1689
|
).filter(provider => !disabledProviders.has(provider.provider));
|
|
1800
1690
|
const configuredDiscoveriesPromise =
|
|
1801
1691
|
selectedDiscoverableProviders.length === 0
|
|
@@ -1833,74 +1723,26 @@ export class ModelRegistry {
|
|
|
1833
1723
|
providerConfig: DiscoveryProviderConfig,
|
|
1834
1724
|
strategy: ModelRefreshStrategy,
|
|
1835
1725
|
): Promise<Model<Api>[]> {
|
|
1836
|
-
const
|
|
1837
|
-
const cachedModels = applyFinalCodexGpt56ContextCap(cached?.models ?? []);
|
|
1838
|
-
const requiresAuth = !this.#keylessProviders.has(providerConfig.provider);
|
|
1839
|
-
if (requiresAuth) {
|
|
1840
|
-
const apiKey = await this.#peekApiKeyForProvider(providerConfig.provider);
|
|
1841
|
-
if (!isAuthenticated(apiKey)) {
|
|
1842
|
-
this.#providerDiscoveryStates.set(providerConfig.provider, {
|
|
1843
|
-
provider: providerConfig.provider,
|
|
1844
|
-
status: "unauthenticated",
|
|
1845
|
-
optional: providerConfig.optional ?? false,
|
|
1846
|
-
stale: cached !== null,
|
|
1847
|
-
fetchedAt: cached?.updatedAt,
|
|
1848
|
-
models: cachedModels.map(model => model.id),
|
|
1849
|
-
});
|
|
1850
|
-
this.#lastDiscoveryWarnings.delete(providerConfig.provider);
|
|
1851
|
-
return cachedModels;
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
const providerId = providerConfig.provider;
|
|
1856
|
-
let discoveryError: string | undefined;
|
|
1857
|
-
const fetchDynamicModels = async (): Promise<readonly Model<Api>[] | null> => {
|
|
1858
|
-
try {
|
|
1859
|
-
const models = await this.#discoverModelsByProviderType(providerConfig);
|
|
1860
|
-
this.#lastDiscoveryWarnings.delete(providerId);
|
|
1861
|
-
return models;
|
|
1862
|
-
} catch (error) {
|
|
1863
|
-
discoveryError = error instanceof Error ? error.message : String(error);
|
|
1864
|
-
return null;
|
|
1865
|
-
}
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
|
-
const manager = createModelManager<Api>({
|
|
1869
|
-
providerId,
|
|
1870
|
-
staticModels: [],
|
|
1726
|
+
const mergeInput = await this.#discoveryManager.discover(providerConfig, strategy, {
|
|
1871
1727
|
cacheDbPath: this.#cacheDbPath,
|
|
1872
|
-
|
|
1873
|
-
|
|
1728
|
+
requiresAuth: provider => !this.#keylessProviders.has(provider.provider),
|
|
1729
|
+
peekApiKey: provider => this.#peekApiKeyForProvider(provider.provider),
|
|
1730
|
+
isAuthenticated,
|
|
1731
|
+
fetchModels: provider => this.#discoverModelsByProviderType(provider),
|
|
1874
1732
|
});
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
:
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
? "cached"
|
|
1883
|
-
: "idle"
|
|
1884
|
-
: result.models.length > 0
|
|
1885
|
-
? "ok"
|
|
1886
|
-
: "empty";
|
|
1887
|
-
this.#providerDiscoveryStates.set(providerId, {
|
|
1888
|
-
provider: providerId,
|
|
1889
|
-
status,
|
|
1890
|
-
optional: providerConfig.optional ?? false,
|
|
1891
|
-
stale: result.stale || status === "cached",
|
|
1892
|
-
fetchedAt: discoveryError ? cached?.updatedAt : Date.now(),
|
|
1893
|
-
models: result.models.map(model => model.id),
|
|
1894
|
-
error: discoveryError,
|
|
1895
|
-
});
|
|
1896
|
-
if (discoveryError) {
|
|
1897
|
-
this.#warnProviderDiscoveryFailure(providerConfig, discoveryError);
|
|
1733
|
+
if (!mergeInput.current) return [];
|
|
1734
|
+
if (mergeInput.warning) {
|
|
1735
|
+
logger.warn("model discovery failed for provider", {
|
|
1736
|
+
provider: providerConfig.provider,
|
|
1737
|
+
url: providerConfig.baseUrl,
|
|
1738
|
+
error: mergeInput.warning,
|
|
1739
|
+
});
|
|
1898
1740
|
}
|
|
1899
1741
|
return this.#applyProviderModelOverrides(
|
|
1900
|
-
|
|
1742
|
+
providerConfig.provider,
|
|
1901
1743
|
this.#normalizeDiscoverableModels(
|
|
1902
1744
|
providerConfig,
|
|
1903
|
-
this.#applyProviderCompat(providerConfig.compat,
|
|
1745
|
+
this.#applyProviderCompat(providerConfig.compat, [...mergeInput.models]),
|
|
1904
1746
|
),
|
|
1905
1747
|
);
|
|
1906
1748
|
}
|
|
@@ -1917,25 +1759,12 @@ export class ModelRegistry {
|
|
|
1917
1759
|
}
|
|
1918
1760
|
}
|
|
1919
1761
|
|
|
1920
|
-
#warnProviderDiscoveryFailure(providerConfig: DiscoveryProviderConfig, error: string): void {
|
|
1921
|
-
const previous = this.#lastDiscoveryWarnings.get(providerConfig.provider);
|
|
1922
|
-
if (previous === error) {
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
this.#lastDiscoveryWarnings.set(providerConfig.provider, error);
|
|
1926
|
-
logger.warn("model discovery failed for provider", {
|
|
1927
|
-
provider: providerConfig.provider,
|
|
1928
|
-
url: providerConfig.baseUrl,
|
|
1929
|
-
error,
|
|
1930
|
-
});
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
1762
|
async #discoverBuiltInProviderModels(
|
|
1934
1763
|
strategy: ModelRefreshStrategy,
|
|
1935
1764
|
providerFilter?: ReadonlySet<string>,
|
|
1936
1765
|
): Promise<Model<Api>[]> {
|
|
1937
1766
|
// Skip providers already handled by configured discovery (e.g. user-configured ollama with discovery.type)
|
|
1938
|
-
const configuredDiscoveryProviders = new Set(this.#
|
|
1767
|
+
const configuredDiscoveryProviders = new Set(this.#discoveryManager.providers.map(p => p.provider));
|
|
1939
1768
|
const managerOptions = (await this.#collectBuiltInModelManagerOptions()).filter(opts => {
|
|
1940
1769
|
if (configuredDiscoveryProviders.has(opts.providerId)) {
|
|
1941
1770
|
return false;
|
|
@@ -2424,9 +2253,16 @@ export class ModelRegistry {
|
|
|
2424
2253
|
return;
|
|
2425
2254
|
}
|
|
2426
2255
|
this.#canonicalIndex = buildCanonicalModelIndex(this.#models, this.#equivalenceConfig);
|
|
2256
|
+
this.#invalidateAvailableModels();
|
|
2427
2257
|
this.#rebuildPending = false;
|
|
2428
2258
|
}
|
|
2429
2259
|
|
|
2260
|
+
#invalidateAvailableModels(): void {
|
|
2261
|
+
this.#availableModelsCache = undefined;
|
|
2262
|
+
this.#availableModelsDisabledProviders = undefined;
|
|
2263
|
+
this.#availableModelsEnvFingerprint = undefined;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2430
2266
|
#suspendRebuild(): void {
|
|
2431
2267
|
this.#rebuildSuspended += 1;
|
|
2432
2268
|
}
|
|
@@ -2438,6 +2274,7 @@ export class ModelRegistry {
|
|
|
2438
2274
|
if (this.#rebuildSuspended === 0 && this.#rebuildPending) {
|
|
2439
2275
|
this.#rebuildPending = false;
|
|
2440
2276
|
this.#canonicalIndex = buildCanonicalModelIndex(this.#models, this.#equivalenceConfig);
|
|
2277
|
+
this.#invalidateAvailableModels();
|
|
2441
2278
|
}
|
|
2442
2279
|
}
|
|
2443
2280
|
|
|
@@ -2488,8 +2325,7 @@ export class ModelRegistry {
|
|
|
2488
2325
|
return this.#models;
|
|
2489
2326
|
}
|
|
2490
2327
|
|
|
2491
|
-
#isModelAvailable(model: Model<Api
|
|
2492
|
-
const disabledProviders = getDisabledProviderIdsFromSettings();
|
|
2328
|
+
#isModelAvailable(model: Model<Api>, disabledProviders = getDisabledProviderIdsFromSettings()): boolean {
|
|
2493
2329
|
return (
|
|
2494
2330
|
!disabledProviders.has(model.provider) &&
|
|
2495
2331
|
(this.#keylessProviders.has(model.provider) || this.authStorage.hasAuth(model.provider))
|
|
@@ -2503,13 +2339,10 @@ export class ModelRegistry {
|
|
|
2503
2339
|
const candidateKeys = options?.candidates
|
|
2504
2340
|
? new Set(options.candidates.map(candidate => formatCanonicalVariantSelector(candidate)))
|
|
2505
2341
|
: undefined;
|
|
2342
|
+
const disabledProviders = options?.availableOnly ? getDisabledProviderIdsFromSettings() : undefined;
|
|
2506
2343
|
return record.variants.filter(variant => {
|
|
2507
|
-
if (candidateKeys && !candidateKeys.has(variant.selector))
|
|
2508
|
-
|
|
2509
|
-
}
|
|
2510
|
-
if (options?.availableOnly && !this.#isModelAvailable(variant.model)) {
|
|
2511
|
-
return false;
|
|
2512
|
-
}
|
|
2344
|
+
if (candidateKeys && !candidateKeys.has(variant.selector)) return false;
|
|
2345
|
+
if (options?.availableOnly && !this.#isModelAvailable(variant.model, disabledProviders)) return false;
|
|
2513
2346
|
return true;
|
|
2514
2347
|
});
|
|
2515
2348
|
}
|
|
@@ -2537,13 +2370,26 @@ export class ModelRegistry {
|
|
|
2537
2370
|
return result;
|
|
2538
2371
|
}
|
|
2539
2372
|
|
|
2373
|
+
#rememberCanonicalVariant(sessionId: string, selector: string): void {
|
|
2374
|
+
this.#sessionCanonicalVariants.delete(sessionId);
|
|
2375
|
+
this.#sessionCanonicalVariants.set(sessionId, selector);
|
|
2376
|
+
if (this.#sessionCanonicalVariants.size > MAX_SESSION_CANONICAL_VARIANTS) {
|
|
2377
|
+
this.#sessionCanonicalVariants.delete(this.#sessionCanonicalVariants.keys().next().value!);
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2540
2380
|
#resolveCanonicalVariant(
|
|
2541
2381
|
variants: readonly CanonicalModelVariant[],
|
|
2542
2382
|
allCandidates: readonly Model<Api>[],
|
|
2383
|
+
sessionId?: string,
|
|
2543
2384
|
): CanonicalModelVariant | undefined {
|
|
2544
|
-
if (variants.length === 0)
|
|
2545
|
-
|
|
2546
|
-
|
|
2385
|
+
if (variants.length === 0) return undefined;
|
|
2386
|
+
const stickySelector = sessionId ? this.#sessionCanonicalVariants.get(sessionId) : undefined;
|
|
2387
|
+
const stickyVariant = stickySelector ? variants.find(variant => variant.selector === stickySelector) : undefined;
|
|
2388
|
+
if (stickyVariant) {
|
|
2389
|
+
this.#rememberCanonicalVariant(sessionId!, stickyVariant.selector);
|
|
2390
|
+
return stickyVariant;
|
|
2391
|
+
}
|
|
2392
|
+
if (sessionId && stickySelector) this.#sessionCanonicalVariants.delete(sessionId);
|
|
2547
2393
|
const providerRank = this.#providerRank(allCandidates);
|
|
2548
2394
|
const modelOrder = new Map<string, number>();
|
|
2549
2395
|
for (let index = 0; index < allCandidates.length; index += 1) {
|
|
@@ -2555,35 +2401,16 @@ export class ModelRegistry {
|
|
|
2555
2401
|
heuristic: 2,
|
|
2556
2402
|
fallback: 3,
|
|
2557
2403
|
};
|
|
2558
|
-
return [...variants].sort((left, right) =>
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
const rightProviderRank = providerRank.get(right.model.provider.toLowerCase()) ?? Number.MAX_SAFE_INTEGER;
|
|
2569
|
-
if (leftProviderRank !== rightProviderRank) {
|
|
2570
|
-
return leftProviderRank - rightProviderRank;
|
|
2571
|
-
}
|
|
2572
|
-
const leftExact = left.model.id === left.canonicalId ? 0 : 1;
|
|
2573
|
-
const rightExact = right.model.id === right.canonicalId ? 0 : 1;
|
|
2574
|
-
if (leftExact !== rightExact) {
|
|
2575
|
-
return leftExact - rightExact;
|
|
2576
|
-
}
|
|
2577
|
-
if (sourceRank[left.source] !== sourceRank[right.source]) {
|
|
2578
|
-
return sourceRank[left.source] - sourceRank[right.source];
|
|
2579
|
-
}
|
|
2580
|
-
if (left.model.id.length !== right.model.id.length) {
|
|
2581
|
-
return left.model.id.length - right.model.id.length;
|
|
2582
|
-
}
|
|
2583
|
-
const leftOrder = modelOrder.get(left.selector) ?? Number.MAX_SAFE_INTEGER;
|
|
2584
|
-
const rightOrder = modelOrder.get(right.selector) ?? Number.MAX_SAFE_INTEGER;
|
|
2585
|
-
return leftOrder - rightOrder;
|
|
2586
|
-
})[0];
|
|
2404
|
+
return [...variants].sort((left, right) =>
|
|
2405
|
+
compareEquivalentModelVariants(left.model, right.model, {
|
|
2406
|
+
providerRank,
|
|
2407
|
+
canonicalId: left.canonicalId === right.canonicalId ? left.canonicalId : undefined,
|
|
2408
|
+
leftSourceRank: sourceRank[left.source],
|
|
2409
|
+
rightSourceRank: sourceRank[right.source],
|
|
2410
|
+
includeCost: true,
|
|
2411
|
+
modelOrder,
|
|
2412
|
+
}),
|
|
2413
|
+
)[0];
|
|
2587
2414
|
}
|
|
2588
2415
|
|
|
2589
2416
|
getCanonicalModels(options?: CanonicalModelQueryOptions): CanonicalModelRecord[] {
|
|
@@ -2612,23 +2439,49 @@ export class ModelRegistry {
|
|
|
2612
2439
|
|
|
2613
2440
|
resolveCanonicalModel(canonicalId: string, options?: CanonicalModelQueryOptions): Model<Api> | undefined {
|
|
2614
2441
|
const variants = this.getCanonicalVariants(canonicalId, options);
|
|
2615
|
-
if (variants.length === 0)
|
|
2616
|
-
return undefined;
|
|
2617
|
-
}
|
|
2442
|
+
if (variants.length === 0) return undefined;
|
|
2618
2443
|
const candidates = options?.candidates ?? (options?.availableOnly ? this.getAvailable() : this.getAll());
|
|
2619
|
-
|
|
2444
|
+
const resolved = this.#resolveCanonicalVariant(variants, candidates, options?.sessionId);
|
|
2445
|
+
if (resolved && options?.sessionId) this.#rememberCanonicalVariant(options.sessionId, resolved.selector);
|
|
2446
|
+
return resolved?.model;
|
|
2620
2447
|
}
|
|
2621
2448
|
|
|
2622
2449
|
getCanonicalId(model: Model<Api>): string | undefined {
|
|
2623
2450
|
return this.#canonicalIndex.bySelector.get(formatCanonicalVariantSelector(model).toLowerCase());
|
|
2624
2451
|
}
|
|
2625
2452
|
|
|
2453
|
+
/**
|
|
2454
|
+
* Seed a child canonical scope from a concrete parent model without touching
|
|
2455
|
+
* the parent's canonical selection.
|
|
2456
|
+
*/
|
|
2457
|
+
seedCanonicalVariant(sessionId: string, model: Model<Api>): boolean {
|
|
2458
|
+
const scope = sessionId.trim();
|
|
2459
|
+
if (!scope) return false;
|
|
2460
|
+
const selector = formatCanonicalVariantSelector(model);
|
|
2461
|
+
if (!this.#canonicalIndex.bySelector.has(selector.toLowerCase())) return false;
|
|
2462
|
+
this.#rememberCanonicalVariant(scope, selector);
|
|
2463
|
+
return true;
|
|
2464
|
+
}
|
|
2465
|
+
|
|
2626
2466
|
/**
|
|
2627
2467
|
* Get only models that have auth configured.
|
|
2628
2468
|
* This is a fast check that doesn't refresh OAuth tokens.
|
|
2629
2469
|
*/
|
|
2630
2470
|
getAvailable(): Model<Api>[] {
|
|
2631
|
-
|
|
2471
|
+
const disabledProviders = getDisabledProviderIdsFromSettings();
|
|
2472
|
+
const disabledProviderKey = [...disabledProviders].sort().join("\u0000");
|
|
2473
|
+
const envFingerprint = envAvailabilityFingerprint();
|
|
2474
|
+
if (
|
|
2475
|
+
this.#availableModelsCache &&
|
|
2476
|
+
this.#availableModelsDisabledProviders === disabledProviderKey &&
|
|
2477
|
+
this.#availableModelsEnvFingerprint === envFingerprint
|
|
2478
|
+
) {
|
|
2479
|
+
return this.#availableModelsCache;
|
|
2480
|
+
}
|
|
2481
|
+
this.#availableModelsCache = this.#models.filter(model => this.#isModelAvailable(model, disabledProviders));
|
|
2482
|
+
this.#availableModelsDisabledProviders = disabledProviderKey;
|
|
2483
|
+
this.#availableModelsEnvFingerprint = envFingerprint;
|
|
2484
|
+
return this.#availableModelsCache;
|
|
2632
2485
|
}
|
|
2633
2486
|
|
|
2634
2487
|
/**
|
|
@@ -2646,13 +2499,13 @@ export class ModelRegistry {
|
|
|
2646
2499
|
|
|
2647
2500
|
getDiscoverableProviders(): string[] {
|
|
2648
2501
|
const disabledProviders = getDisabledProviderIdsFromSettings();
|
|
2649
|
-
return this.#
|
|
2502
|
+
return this.#discoveryManager.providers
|
|
2650
2503
|
.filter(provider => !disabledProviders.has(provider.provider))
|
|
2651
2504
|
.map(provider => provider.provider);
|
|
2652
2505
|
}
|
|
2653
2506
|
|
|
2654
2507
|
getProviderDiscoveryState(provider: string): ProviderDiscoveryState | undefined {
|
|
2655
|
-
return this.#
|
|
2508
|
+
return this.#discoveryManager.getState(provider);
|
|
2656
2509
|
}
|
|
2657
2510
|
|
|
2658
2511
|
/**
|
|
@@ -2688,6 +2541,13 @@ export class ModelRegistry {
|
|
|
2688
2541
|
};
|
|
2689
2542
|
}
|
|
2690
2543
|
|
|
2544
|
+
async #getApiKeyOrNoAuth(provider: string, lookup: () => Promise<string | undefined>): Promise<string | undefined> {
|
|
2545
|
+
if (this.#keylessProviders.has(provider) && !this.authStorage.hasAuth(provider)) {
|
|
2546
|
+
return kNoAuth;
|
|
2547
|
+
}
|
|
2548
|
+
return lookup();
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2691
2551
|
/**
|
|
2692
2552
|
* Get API key for a model.
|
|
2693
2553
|
*/
|
|
@@ -2696,14 +2556,13 @@ export class ModelRegistry {
|
|
|
2696
2556
|
sessionId?: string,
|
|
2697
2557
|
options: { credentialSelector?: AuthCredentialSelector } = {},
|
|
2698
2558
|
): Promise<string | undefined> {
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
});
|
|
2559
|
+
return this.#getApiKeyOrNoAuth(model.provider, () =>
|
|
2560
|
+
this.authStorage.getApiKey(model.provider, sessionId, {
|
|
2561
|
+
baseUrl: model.baseUrl,
|
|
2562
|
+
modelId: model.id,
|
|
2563
|
+
credentialSelector: options.credentialSelector,
|
|
2564
|
+
}),
|
|
2565
|
+
);
|
|
2707
2566
|
}
|
|
2708
2567
|
|
|
2709
2568
|
/**
|
|
@@ -2715,20 +2574,16 @@ export class ModelRegistry {
|
|
|
2715
2574
|
baseUrl?: string,
|
|
2716
2575
|
options: { credentialSelector?: AuthCredentialSelector } = {},
|
|
2717
2576
|
): Promise<string | undefined> {
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
});
|
|
2577
|
+
return this.#getApiKeyOrNoAuth(provider, () =>
|
|
2578
|
+
this.authStorage.getApiKey(provider, sessionId, {
|
|
2579
|
+
baseUrl,
|
|
2580
|
+
credentialSelector: options.credentialSelector,
|
|
2581
|
+
}),
|
|
2582
|
+
);
|
|
2725
2583
|
}
|
|
2726
2584
|
|
|
2727
2585
|
async #peekApiKeyForProvider(provider: string): Promise<string | undefined> {
|
|
2728
|
-
|
|
2729
|
-
return kNoAuth;
|
|
2730
|
-
}
|
|
2731
|
-
return this.authStorage.peekApiKey(provider);
|
|
2586
|
+
return this.#getApiKeyOrNoAuth(provider, () => this.authStorage.peekApiKey(provider));
|
|
2732
2587
|
}
|
|
2733
2588
|
|
|
2734
2589
|
/**
|
|
@@ -2963,6 +2818,18 @@ export class ModelRegistry {
|
|
|
2963
2818
|
}
|
|
2964
2819
|
return true;
|
|
2965
2820
|
}
|
|
2821
|
+
|
|
2822
|
+
/** Return whether a selector has an active, expired, or no rate-limit suppression. */
|
|
2823
|
+
getSelectorSuppressionStatus(selector: string): "active" | "expired" | "none" {
|
|
2824
|
+
const normalizedSelector = normalizeSuppressedSelector(selector);
|
|
2825
|
+
const suppressedUntil = this.#suppressedSelectors.get(normalizedSelector);
|
|
2826
|
+
if (!suppressedUntil) return "none";
|
|
2827
|
+
if (suppressedUntil <= Date.now()) {
|
|
2828
|
+
this.#suppressedSelectors.delete(normalizedSelector);
|
|
2829
|
+
return "expired";
|
|
2830
|
+
}
|
|
2831
|
+
return "active";
|
|
2832
|
+
}
|
|
2966
2833
|
}
|
|
2967
2834
|
|
|
2968
2835
|
/**
|