refactor: move allow_chat_override to top-level config and improve datetime parsing

- Move allow_chat_override from chat_model to top-level configuration - Update all references to use new config path - Set default to true in default_config.yaml, false in migration - Fix datetime parsing to handle timezone-less ISO strings by appending 'Z' - Remove inline style from tune icon in config.html

frdel committed Mar 19, 2026 at 21:17 UTC 31ddee713ccfa253c8435a728e5c9644e2afff09
6 files changed +16 -9
extensions/python/banners/_20_missing_api_key.py
+1 -1
@@ -54,7 +54,7 @@ class MissingApiKeyCheck(Extension):
54 })
55
56 # Check preset providers for missing API keys (warning level)
57 - if cfg.get("chat_model", {}).get("allow_chat_override"):
57 + if cfg.get("allow_chat_override"):
58 preset_missing = []
59 seen = set()
60 for preset in cfg.get("model_presets", []):
plugins/_model_config/default_config.yaml
+2 -1
@@ -1,3 +1,5 @@
1 +allow_chat_override: true
2 +
3 chat_model:
4 provider: "openrouter"
5 name: "anthropic/claude-sonnet-4.6"
@@ -9,7 +11,6 @@ chat_model:
11 rl_input: 0
12 rl_output: 0
13 kwargs: {}
12 - allow_chat_override: false
14
15 utility_model:
16 provider: "openrouter"
plugins/_model_config/extensions/python/initialize_migration_start/_10_migrate_model_config.py
+1 -1
@@ -51,6 +51,7 @@ class MigrateModelConfig(Extension):
51
52 # Build plugin config from legacy settings
53 plugin_config = {
54 + "allow_chat_override": False,
55 "chat_model": {
56 "provider": raw.get("chat_model_provider", "openrouter"),
57 "name": raw.get("chat_model_name", ""),
@@ -62,7 +63,6 @@ class MigrateModelConfig(Extension):
63 "rl_input": raw.get("chat_model_rl_input", 0),
64 "rl_output": raw.get("chat_model_rl_output", 0),
65 "kwargs": raw.get("chat_model_kwargs", {}),
65 - "allow_chat_override": False,
66 },
67 "utility_model": {
68 "provider": raw.get("util_model_provider", "openrouter"),
plugins/_model_config/helpers/model_config.py
+1 -2
@@ -127,8 +127,7 @@ def get_browser_http_headers(agent=None) -> dict:
127 def is_chat_override_allowed(agent=None) -> bool:
128 """Check if per-chat model override is enabled."""
129 cfg = get_config(agent)
130 - chat_cfg = cfg.get("chat_model", {})
131 - return bool(chat_cfg.get("allow_chat_override", False))
130 + return bool(cfg.get("allow_chat_override", False))
131
132
133 def get_ctx_history(agent=None) -> float:
plugins/_model_config/webui/config.html
+3 -3
@@ -35,15 +35,15 @@
35 </div>
36 <div class="field-control">
37 <label class="toggle">
38 - <input type="checkbox" x-model="config.chat_model.allow_chat_override" />
38 + <input type="checkbox" x-model="config.allow_chat_override" />
39 <span class="toggler"></span>
40 </label>
41 </div>
42 </div>
43
44 - <div class="override-presets-link" x-show="config.chat_model.allow_chat_override">
44 + <div class="override-presets-link" x-show="config.allow_chat_override">
45 <button class="text-button" @click="openModal('/plugins/_model_config/webui/main.html')">
46 - <span class="material-symbols-outlined" style="font-size:15px;">tune</span>
46 + <span class="material-symbols-outlined">tune</span>
47 <span>Edit Presets</span>
48 </button>
49 </div>
plugins/_plugin_installer/webui/pluginInstallStore.js
+8 -1
@@ -654,7 +654,14 @@ const model = {
654 formatUserLocaleDateTime(value) {
655 if (!value || typeof value !== "string") return "";
656
657 - const normalizedValue = /t/i.test(value) ? value : value.replace(" ", "T");
657 + const trimmedValue = value.trim();
658 + const hasExplicitTimezone = /([zZ]|[+-]\d{2}:?\d{2})$/.test(trimmedValue);
659 + let normalizedValue = /t/i.test(trimmedValue) ? trimmedValue : trimmedValue.replace(" ", "T");
660 +
661 + if (!hasExplicitTimezone && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$/.test(normalizedValue)) {
662 + normalizedValue = `${normalizedValue}Z`;
663 + }
664 +
665 const date = new Date(normalizedValue);
666 if (Number.isNaN(date.getTime())) return value;
667