Clear provider-specific kwargs on provider change
Reset additional parameters together with the custom API base when a model provider changes, preventing stale provider-specific options from leaking into the new provider. Update the model-config contract and README, and extend the focused frontend regression check.
Alessandro committed
Jul 10, 2026 at 19:11 UTC
948409c2449e5d1998b0561e5ab640bdc9369776
4 files changed
+7
-4
plugins/_model_config/AGENTS.md
+1
@@ -19,6 +19,7 @@
19
- Coordinate OAuth-backed providers with `_oauth` instead of hardcoding provider-specific auth here.
20
- `model_config_get` exposes `model_configured` as a derived chat-model readiness flag from provider, model name, and API-key availability.
21
- Applying a model preset may inherit durable tuning such as context windows and rate limits, but must replace or clear per-slot `kwargs` so provider-specific extra params never leak across model providers.
22
+- Changing a model provider in the settings UI must clear `api_base` and `kwargs` because both may be provider-specific.
23
- Repair provider-specific model-config aliases at the model-config read/build boundary; keep provider-specific repairs out of provider-agnostic core wrappers such as `models.py`.
24
- `modelConfig.createPresetEditor()` owns local preset drafts, row actions, and stable UI-only row keys so deletion or renaming cannot rebind nested model fields.
25
- Model-name catalogs open below the input from either a field click or the embedded magnifier.
plugins/_model_config/README.md
+1
-1
@@ -77,7 +77,7 @@ The project preset file uses the same plain YAML list schema as global presets.
77
name: openai/gpt-5.4-mini
78
```
79
80
-Preset slots are partial overlays. Missing fields inherit from the current effective config, so a preset can switch only the model identity while preserving tuned context windows, rate limits, and nested `kwargs`. The `utility` and `embedding` slots are optional and only apply when they declare a provider or model name; otherwise those configured models are inherited. Selecting a preset for a project writes the merged result into the project's `config.json`.
80
+Preset slots are partial overlays. Missing fields inherit from the current effective config, so a preset can switch only the model identity while preserving tuned context windows and rate limits. Provider-specific `kwargs` are replaced or cleared. The `utility` and `embedding` slots are optional and only apply when they declare a provider or model name; otherwise those configured models are inherited. Selecting a preset for a project writes the merged result into the project's `config.json`.
81
82
## Plugin Metadata
83
plugins/_model_config/webui/model-field.html
+1
-1
@@ -28,7 +28,7 @@
28
<div class="field-control">
29
<select x-model="model.provider"
30
x-effect="$nextTick(() => { if (providers.length) $el.value = model.provider })"
31
- @change="model.api_base = ''">
31
+ @change="model.api_base = ''; model.kwargs = {}; model._kwargs_text = ''">
32
<option value="">— select —</option>
33
<template x-for="p in providers" :key="p.value">
34
<option :value="p.value" x-text="p.label"></option>
tests/test_model_config_api_keys.py
+4
-2
@@ -231,7 +231,7 @@ def test_connector_model_switcher_notifies_state_sync(monkeypatch):
231
assert calls == [("ctx-1", "a0_connector.model_switcher")]
232
233
234
-def test_model_config_provider_switch_resets_custom_api_base():
234
+def test_model_config_provider_switch_resets_provider_specific_fields():
235
model_field_path = PROJECT_ROOT / "plugins" / "_model_config" / "webui" / "model-field.html"
236
content = model_field_path.read_text(encoding="utf-8")
237
select_start = content.index('<select x-model="model.provider"')
@@ -239,7 +239,9 @@ def test_model_config_provider_switch_resets_custom_api_base():
239
provider_select = content[select_start:select_end]
240
241
assert 'x-model="model.provider"' in provider_select
242
- assert '@change="model.api_base = \'\'"' in provider_select
242
+ assert "model.api_base = ''" in provider_select
243
+ assert "model.kwargs = {}" in provider_select
244
+ assert "model._kwargs_text = ''" in provider_select
245
246
247
def test_model_config_model_field_opens_search_on_click():