VS Code Agentic Chat shows model selection dropdown with full list of SaaS models when self-hosted AI Gateway is configured
## Summary On cloud-connected self-managed instances (online license) with a self-hosted AI Gateway and all features assigned to self-hosted models, the VS Code Agentic Chat model picker dropdown displays the full SaaS model catalog instead of being hidden. This creates compliance concerns for customers who need to demonstrate that their instance is not using SaaS models. See this discussion for full context: https://gitlab.com/gitlab-org/gitlab/-/work_items/594381#note_3296406511 ## Current Behavior When a self-managed instance is configured with a self-hosted AI Gateway and a self-hosted model is assigned to the `duo_agent_platform_agentic_chat` feature: 1. The VS Code model picker dropdown shows the full SaaS model list. 2. The IDE receives `{ selectableModels: [full SaaS list], pinnedModel: null }` from the `aiChatAvailableModels` GraphQL query. 3. The IDE interprets this as "user can pick from these models, nothing is locked" and renders the dropdown. **Note:** The data flow itself is correct — regardless of which model a user selects in the picker, the actual request routes to the self-hosted AI Gateway and the admin-configured self-hosted model. The dropdown is cosmetic but misleading. ## Root Cause The `AvailableModelsResolver` (`ee/app/graphql/resolvers/ai/chat/available_models_resolver.rb`) returns `pinnedModel: null` when a self-hosted model is configured. The chain of events: 1. `FeatureSettingSelectionService` returns an `Ai::FeatureSetting` object for the `duo_agent_platform_agentic_chat` feature. 2. The resolver calls `pinned_model_data`, which checks `feature_setting.user_model_selection_available?`. 3. `Ai::FeatureSetting` overrides this method to return `false` (`ee/app/models/ai/feature_setting.rb`, line 183–185), even though the `FeatureConfigurable` concern it includes defines it as `true`. 4. Because `user_model_selection_available?` returns `false`, `pinned_model_data` short-circuits and returns `nil` before checking whether a model is pinned. Meanwhile, `FetchModelDefinitionsService` successfully fetches the cloud model catalog (since the instance is cloud-connected), so `selectableModels` is fully populated with SaaS models. The intent of `user_model_selection_available?` returning `false` was to signal "users can't select models," but the effect is the opposite: it prevents the pinning signal that would tell the IDE to hide the dropdown. The Rails web UI handles this correctly by [passing a `userModelSelectionEnabled` flag to the frontend](https://gitlab.com/gitlab-org/gitlab/-/blob/d0cda8715026524900e7973e87609a17bb391e0d/ee/app/assets/javascripts/ai/duo_agentic_chat/components/duo_agentic_chat_state_manager.vue#L275-278), which is used both to hide the model dropdown and to skip the `aiChatAvailableModels` query when user model selection is not available. The IDE (LSP) does not appear to receive or respect this flag. ## Expected Behavior When a self-hosted AI Gateway is configured and a self-hosted model is assigned to the agentic chat feature: - The model picker dropdown should **not** be shown in the IDE. - The `aiChatAvailableModels` query should either not be called, or should return a response that signals to the IDE that model selection is unavailable (e.g., empty `selectableModels` and a populated `pinnedModel`). ## Steps to Reproduce 1. Set up a self-managed GitLab instance (online license, Duo Enterprise) with a self-hosted AI Gateway. 2. Configure a self-hosted model and assign it to the `duo_agent_platform_agentic_chat` feature. 3. Open VS Code with the GitLab Duo extension and start an Agentic Chat session. 4. Observe the model picker dropdown — it shows the full SaaS model list. ## Impact Customers with compliance requirements who need to demonstrate that their instance is not using SaaS models see a misleading UI that suggests SaaS models are available and selectable. This creates unnecessary compliance concerns and erodes trust in the self-hosted configuration. ## Relevant Code - Resolver: `ee/app/graphql/resolvers/ai/chat/available_models_resolver.rb` - Feature setting model: `ee/app/models/ai/feature_setting.rb` (line 183–185, `user_model_selection_available?`) - Model definitions service: `ee/app/services/ai/model_selection/fetch_model_definitions_service.rb` - Web UI flag: `ee/app/assets/javascripts/ai/duo_agentic_chat/components/duo_agentic_chat_state_manager.vue` (line 275–278)
issue