Fix settings save blocking event loop and overwriting config keys
Some checks failed
Tests / Python Backend Tests (push) Successful in 5s
Tests / Frontend Tests (push) Successful in 8s
Tests / Rust Sidecar Tests (push) Has been cancelled

- Run apply_settings in thread pool executor to prevent engine reload
  from blocking the HTTP response (caused "TypeError: Failed to fetch")
- Flatten nested config objects into dot-notation keys before saving
  so partial updates don't wipe out unincluded keys like auth_token

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Developer
2026-04-10 19:40:51 -07:00
parent 7900d2d9f2
commit 94bc704950
2 changed files with 16 additions and 3 deletions

View File

@@ -212,7 +212,11 @@ class APIServer:
@app.put("/api/config") @app.put("/api/config")
async def update_config(update: ConfigUpdate): async def update_config(update: ConfigUpdate):
engine_reloaded, message = ctrl.apply_settings(update.settings) import asyncio
loop = asyncio.get_event_loop()
engine_reloaded, message = await loop.run_in_executor(
None, ctrl.apply_settings, update.settings
)
return { return {
"status": "ok", "status": "ok",
"message": message, "message": message,

View File

@@ -608,8 +608,17 @@ class AppController:
Returns (engine_reload_needed, message). Returns (engine_reload_needed, message).
""" """
if new_config: if new_config:
for key, value in new_config.items(): # Flatten nested dicts into dot-notation keys so we merge
self.config.set(key, value) # individual values instead of replacing entire sections
# (e.g. remote.mode instead of overwriting all of remote)
def _flatten(d, prefix=""):
for k, v in d.items():
full_key = f"{prefix}{k}" if not prefix else f"{prefix}.{k}"
if isinstance(v, dict):
_flatten(v, full_key)
else:
self.config.set(full_key, v)
_flatten(new_config)
# Update web server display settings # Update web server display settings
if self.web_server: if self.web_server: