fix: background tasks follow the live model selection

TaskWorker resolved its model from LLM_MODEL env (frozen at MCP spawn),
so after a live set_model switch in the UI, dispatched background tasks
still asked for the old model. On local-vl-models (llama-swap
--models-max 1) that forces a swap against the loaded conversation
model; a force-kill mid-load surfaces as 400 'model failed to load'.

The agent now writes the selected model to <task_dir>/model.txt at
session start and on every switch; TaskWorker reads it with the env
value as fallback.
This commit is contained in:
snowspeeder committed 2026-09-12 07:16:08 -04:00
1 parent 436b3fc8b1
commit b01ee6478d
3 files changed
+37 -1

No files matched your search

+19
View File
@@ -750,6 +750,20 @@ def build_mcp_toolsets(user_profile: dict, task_dir: str) -> list[mcp.MCPToolset
return toolsets
def _sync_task_model(task_dir: str, model: str) -> None:
"""Record the live model choice where background task workers can read it.
The dispatch MCP subprocess inherits its environment at spawn time, so it
can never see later UI model switches. The worker instead reads
<task_dir>/model.txt (falling back to LLM_MODEL env) when it starts a task.
"""
try:
os.makedirs(task_dir, exist_ok=True)
with open(os.path.join(task_dir, "model.txt"), "w") as f:
f.write((model or "").strip())
except OSError as e:
logger.warning("failed to record selected model for background tasks: %s", e)
class VoiceAssistant(Agent):
"""The conversational agent. LLM is the brain; STT/TTS are senses."""
@@ -824,6 +838,10 @@ async def handle_job(ctx: JobContext) -> None:
# into it for live model switching.
voice_assistant = VoiceAssistant(user_profile, task_dir)
# Background task workers (dispatch MCP subprocess) read this file so
# they use the same model as the conversation, even after live switches.
_sync_task_model(task_dir, voice_assistant.llm.model)
# Publish the chat-capable model list so the web UI can offer a picker.
async def _publish_models() -> None:
models = await list_available_models()
@@ -1009,6 +1027,7 @@ async def handle_job(ctx: JobContext) -> None:
ack, reliable=True, topic="voice-control"
)
)
_sync_task_model(task_dir, llm.model)
except Exception as e: # noqa: BLE001
logger.warning("Failed to update model: %s", e)