You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Provider integration behavior is spread across parallel switch/case hubs for runtime construction, model defaults and selection, settings validation, model discovery and caching, profile handling, and CLI configuration. Adding or changing a provider requires coordinated edits across disconnected layers, increasing maintenance cost and allowing incomplete integrations or behavior drift.
Context (who is affected and when)
This primarily affects maintainers and contributors whenever a provider is added, changed, renamed, or retired. Each central branch knows implementation details for every provider, so a provider update can work in one environment while remain incomplete in another.
The current production hotspots concentrate these responsibilities:
Area
Responsibility concentrated in the central branch
Provider-specific knowledge carried there
API runtime
Chooses the concrete API handler, rejects retired providers, and handles special model-dependent routing
Every handler constructor and runtime implementation
Shared provider metadata
Resolves the default model
Provider model constants and regional rules
Webview model state
Reads provider-specific model fields, combines static and dynamic catalogs, and applies capability or pricing overrides
Model catalogs and provider-specific capability rules
Webview settings validation
Validates credentials, endpoints, selectors, authentication modes, and account state
Provider setting fields and user-facing validation messages
Profile validation
Extracts a model ID from differently named provider fields
The complete provider settings shape
Dynamic model discovery
Selects a model-list fetcher and adapts generic input to provider-specific arguments
Fetchers, key conventions, base URLs, and cache isolation rules
CLI settings construction
Maps generic CLI key and model input into provider-specific settings
Provider setting fields
CLI context-window resolution
Extracts the configured model ID
A duplicate of the profile model-field mapping
Embedding defaults
Chooses an embedding model default
Embedding-specific profiles and defaults
Embedding UI validation
Builds provider-specific indexing validation
Embedding credentials, endpoints, model fields, and validation rules
The highest-value API-provider hotspots are runtime construction, webview model resolution, webview validation, and dynamic model discovery because each commonly changes when a provider is introduced or its configuration evolves.
The duplicated model-ID extraction in profile validation and CLI context-window handling is a smaller concrete example: both locations independently encode which model field belongs to each provider.
Current dependency shape:
flowchart TB
Provider[Provider identifier]
Provider --> Runtime[API handler selection]
Provider --> Defaults[Default model selection]
Provider --> ModelState[Selected model resolution]
Provider --> Validation[Settings validation]
Provider --> Profiles[Profile model resolution]
Provider --> Discovery[Model discovery and cache policy]
Provider --> CLI[CLI settings and context]
Runtime --> Handlers[All runtime handlers]
Defaults --> Models[All provider model defaults]
ModelState --> Catalogs[All model catalogs and capability rules]
Validation --> Fields[All credential and endpoint fields]
Profiles --> Fields
Discovery --> Fetchers[All provider model fetchers]
CLI --> Fields
Loading
These branches act as parallel registries. A provider is threaded through several layers, and every layer must understand details belonging to that provider.
Related work demonstrates the need for a broader architectural discussion:
Add Novita AI provider #798 demonstrates how adding one provider currently requires registration across shared types, runtime handling, profiles, CLI, webview settings, model discovery, and model selection.
Desired behavior (conceptual, not technical)
Provider-specific decisions should be owned by provider modules and exposed through small, focused capabilities. Central orchestration should look up those capabilities through type-checked registries rather than contain exhaustive provider branches.
Use separate registries for each dependency boundary instead of one large provider base class:
A shared descriptor registry owns provider identity, configured model resolution, and default model resolution.
An extension runtime registry owns API handler construction, optional dynamic model discovery, and cache-isolation policy.
A webview registry owns settings validation and selected-model resolution.
A CLI registry owns mapping generic CLI input to provider-specific settings.
A separate embedding-provider registry owns embedding defaults and indexing UI behavior.
Proposed dependency shape:
flowchart LR
Settings[Provider settings] --> Id[Provider identifier]
Id --> Shared[Shared descriptor registry]
Id --> Runtime[Extension runtime registry]
Id --> Webview[Webview registry]
Id --> CLI[CLI registry]
Shared --> SharedCapabilities[Model ID and defaults]
Runtime --> RuntimeCapabilities[Handler, model discovery, cache policy]
Webview --> WebviewCapabilities[Validation and selected-model resolution]
CLI --> CLICapabilities[CLI input mapping]
SharedCapabilities --> Modules[Provider-owned behavior]
RuntimeCapabilities --> Modules
WebviewCapabilities --> Modules
CLICapabilities --> Modules
Loading
There may still be one lookup per environment, but it should be data-driven, exhaustive for the providers supported by that environment, and dependent on narrow capabilities. Provider modules should receive only the settings valid for that provider rather than the complete provider-settings union.
The current API-handler abstraction should remain responsible for inference operations such as creating messages, reporting model information, and counting tokens. The proposed runtime capability complements it by owning handler creation and surrounding provider integration policies. The existing public handler factory can remain as a compatibility facade while its dispatch moves behind registrations.
Validation capabilities should return stable domain outcomes rather than translated text. The webview can translate those outcomes, keeping shared provider behavior independent of UI and localization frameworks.
Chat/API providers and embedding providers should remain separate domains. Although some provider names overlap, their settings, model metadata, and validation behavior differ; combining them would create a broad interface dominated by optional capabilities.
Constraints / preferences (optional)
Treat this as an architectural discussion proposal before beginning a repository-wide migration.
Prefer composition and focused capabilities over one large inheritance hierarchy.
Keep shared descriptors independent of extension-runtime, React, localization, and validation-framework dependencies.
Preserve serialized provider values and compatibility with existing settings, profiles, imports, and extension state.
Preserve current behavior throughout incremental migration.
Only providers supporting dynamic model discovery should expose that capability; avoid required no-op implementations.
Keep model-fetch behavior and its cache discriminator together so key and base-URL isolation rules cannot drift.
Migrate selected-model behavior provider by provider because it contains the largest amount of policy and has the highest regression risk.
Keep API/chat and embedding provider registries separate.
Add regression coverage at the narrowest test layer appropriate for each migrated responsibility.
Request checklist
I have searched existing Issues and Discussions for duplicates
This describes a specific problem with clear context and impact
Acceptance criteria (optional)
A documented provider capability model and environment boundaries are agreed upon before broad implementation.
Shared provider descriptors resolve configured and default model IDs without requiring consumers to maintain provider switches.
Runtime handler construction is registered per provider while the existing public factory remains compatible.
Dynamic model discovery and cache-isolation policy can be registered together for providers that support discovery.
Webview settings validation and selected-model resolution can be moved behind provider-owned UI capabilities without introducing UI dependencies into shared packages.
CLI provider input mapping reuses provider-owned metadata or capabilities instead of maintaining a parallel field mapping.
Chat/API provider behavior and embedding provider behavior remain separate.
Adding a representative provider requires registering its capabilities rather than editing each migrated central switch.
Existing serialized settings and provider behavior remain compatible.
Focused regression tests cover each responsibility as it is migrated.
Proposed approach (optional)
Use an incremental migration rather than replacing all branches at once:
Introduce the shared provider descriptor contract.
Consolidate duplicated configured-model resolution from profile and CLI logic.
Register runtime handler factories while retaining the existing public factory facade.
Attach dynamic model discovery and cache-isolation policy to runtime registrations.
Extract webview validation capabilities while keeping translation in the UI layer.
Migrate selected-model resolution provider by provider.
Move CLI settings mapping behind provider-owned capabilities or declarative metadata.
Introduce a separate embedding-provider registry for embedding defaults and indexing validation.
Trade-offs / risks (optional)
A broad provider interface could become optional-heavy and reproduce the same coupling in another form; capabilities should remain small and environment-specific.
Registries introduce indirection and require clear ownership and exhaustiveness tests.
Moving high-policy model-selection behavior has significant regression risk and should happen incrementally.
Shared packages cannot import runtime or webview implementations without creating dependency-direction or circular-dependency problems.
Problem (one or two sentences)
Provider integration behavior is spread across parallel switch/case hubs for runtime construction, model defaults and selection, settings validation, model discovery and caching, profile handling, and CLI configuration. Adding or changing a provider requires coordinated edits across disconnected layers, increasing maintenance cost and allowing incomplete integrations or behavior drift.
Context (who is affected and when)
This primarily affects maintainers and contributors whenever a provider is added, changed, renamed, or retired. Each central branch knows implementation details for every provider, so a provider update can work in one environment while remain incomplete in another.
The current production hotspots concentrate these responsibilities:
The highest-value API-provider hotspots are runtime construction, webview model resolution, webview validation, and dynamic model discovery because each commonly changes when a provider is introduced or its configuration evolves.
The duplicated model-ID extraction in profile validation and CLI context-window handling is a smaller concrete example: both locations independently encode which model field belongs to each provider.
Current dependency shape:
flowchart TB Provider[Provider identifier] Provider --> Runtime[API handler selection] Provider --> Defaults[Default model selection] Provider --> ModelState[Selected model resolution] Provider --> Validation[Settings validation] Provider --> Profiles[Profile model resolution] Provider --> Discovery[Model discovery and cache policy] Provider --> CLI[CLI settings and context] Runtime --> Handlers[All runtime handlers] Defaults --> Models[All provider model defaults] ModelState --> Catalogs[All model catalogs and capability rules] Validation --> Fields[All credential and endpoint fields] Profiles --> Fields Discovery --> Fetchers[All provider model fetchers] CLI --> FieldsThese branches act as parallel registries. A provider is threaded through several layers, and every layer must understand details belonging to that provider.
Related work demonstrates the need for a broader architectural discussion:
Desired behavior (conceptual, not technical)
Provider-specific decisions should be owned by provider modules and exposed through small, focused capabilities. Central orchestration should look up those capabilities through type-checked registries rather than contain exhaustive provider branches.
Use separate registries for each dependency boundary instead of one large provider base class:
Proposed dependency shape:
flowchart LR Settings[Provider settings] --> Id[Provider identifier] Id --> Shared[Shared descriptor registry] Id --> Runtime[Extension runtime registry] Id --> Webview[Webview registry] Id --> CLI[CLI registry] Shared --> SharedCapabilities[Model ID and defaults] Runtime --> RuntimeCapabilities[Handler, model discovery, cache policy] Webview --> WebviewCapabilities[Validation and selected-model resolution] CLI --> CLICapabilities[CLI input mapping] SharedCapabilities --> Modules[Provider-owned behavior] RuntimeCapabilities --> Modules WebviewCapabilities --> Modules CLICapabilities --> ModulesThere may still be one lookup per environment, but it should be data-driven, exhaustive for the providers supported by that environment, and dependent on narrow capabilities. Provider modules should receive only the settings valid for that provider rather than the complete provider-settings union.
The current API-handler abstraction should remain responsible for inference operations such as creating messages, reporting model information, and counting tokens. The proposed runtime capability complements it by owning handler creation and surrounding provider integration policies. The existing public handler factory can remain as a compatibility facade while its dispatch moves behind registrations.
Validation capabilities should return stable domain outcomes rather than translated text. The webview can translate those outcomes, keeping shared provider behavior independent of UI and localization frameworks.
Chat/API providers and embedding providers should remain separate domains. Although some provider names overlap, their settings, model metadata, and validation behavior differ; combining them would create a broad interface dominated by optional capabilities.
Constraints / preferences (optional)
Request checklist
Acceptance criteria (optional)
Proposed approach (optional)
Use an incremental migration rather than replacing all branches at once:
Trade-offs / risks (optional)