fix(desktop,mcp): honor device-local agent preset overrides in MCP-launched sessions

Closed
JE
3mo ago
+391-8

Problem

In Superset, a user can customize each agent's launch command in the desktop UI (e.g. set claude to claude --permission-mode plan --dangerously-skip-permissions). The desktop UI honors these overrides, but MCP-launched sessions ignore them — an agent started via start_agent_session / start_agent_session_with_prompt always ran the hardcoded builtin command, so the user's plan-mode / custom flags never took effect.

Root cause: user overrides (agentPresetOverrides, agentCustomDefinitions) are stored device-local in SQLite (packages/local-db settings). They are not in Postgres, so the cloud MCP server can't read them and bakes the command from builtins only. The device command-watcher trusts that baked command verbatim, even though the device has the presets via settings.getAgentPresets.

Approach — device re-resolves; additive & rolling-update-safe

Overrides only exist on the device, so the effective command can only be resolved there. The change is additive over the server→device agent_commands queue so it stays compatible across rolling updates:

  • The MCP server keeps sending the baked builtin command as a fallback, and now additionally carries what the device needs to re-resolve: the raw prompt (prompt launches) and taskPromptContent/taskPromptFileName (task launches, matching how UI task launches already behave).
  • A new device prefers local re-resolution from the user's presets via the existing resolveAgentConfigs path; it falls back to the baked command when the presets, a matching enabled terminal config, or the prompt fields are absent.
  • An old device ignores the new fields and runs the baked command (unchanged). A new device tolerates old-server requests that lack the fields.

Only the command string is overwritten — server-provided name/paneId/files/taskPromptContent stay authoritative. Chat/superset launches are never touched.

Changes

  • packages/shared/src/agent-launch.ts — add optional prompt to terminalLaunchConfigSchema.
  • packages/mcp/.../start-agent-session/shared.ts — prompt launch carries prompt; task launch switched to the UI file-command shape (buildAgentFileCommand + taskPromptContent + taskPromptFileName).
  • .../useCommandWatcher/tools/types.ts — add optional getResolvedAgentConfigsById getter to ToolContext.
  • .../useCommandWatcher/useCommandWatcher.ts — wire settings.getAgentPresets → memoized indexResolvedAgentConfigs → the toolContext getter.
  • .../useCommandWatcher/tools/start-agent-session.ts — resolveDeviceLocalCommand re-resolves the terminal command from local presets (task → file command, prompt → prompt command), falling back to the baked command in every gap.

Tests

  • New device test (tools/start-agent-session.test.ts): override prompt/task launches use the overridden command; authoritative fields preserved; baked-command fallback for disabled config, missing config, absent resolver getter, and old-server requests; chat/superset untouched.
  • MCP test: prompt request carries terminal.prompt; task request uses file command + prompt content/filename.
  • Shared schema round-trip test for prompt.
  • Full suites green (shared 697, mcp 7, AgentHooks 17); desktop tsc --noEmit, shared/mcp typechecks, and biome all clean.

Out of scope (separate follow-up)

The cwd/worktree-readiness spawn race — create_workspace returns before the worktree dir exists (initializeWorkspaceWorktree is fire-and-forget), so a PTY spawned immediately after can die. It's a different code path (main-process init vs renderer command resolution) and should ship as its own change.


Summary by cubic

MCP-launched agent sessions now honor device-local agent preset overrides from the desktop UI. Commands are resolved on the device using local presets with baked fallbacks, and MCP command processing is deferred until presets load to avoid a startup race that could ignore overrides.

  • Bug Fixes
    • Server continues sending a baked builtin command and now also includes terminal.prompt or taskPromptContent/taskPromptFileName; the device prefers local re-resolution and falls back when data or presets are missing (rolling-update safe).
    • Added optional prompt to terminalLaunchConfigSchema in @superset/shared to carry raw prompts for device-side resolution.
    • Desktop command watcher indexes presets, defers MCP command processing until the presets query settles, and exposes getResolvedAgentConfigsById; only terminal.command is replaced, while name/paneId/files remain authoritative. Chat/superset launches are untouched.
    • Tests cover override application, fallbacks for old servers/devices, and schema round-trips.

Summary by CodeRabbit

  • New Features

    • Terminal-based agent sessions now use the latest device-local agent settings when available.
    • Prompt and task launches preserve the information needed to rebuild commands locally.
    • Task sessions now reference their associated prompt files for more reliable launches.
    • Older devices and unsupported configurations continue using the original launch command.
  • Tests

    • Added coverage for prompt, task, chat, fallback, and compatibility scenarios.