feat(desktop): choose which agent config a chat runs as
RE
4h ago+1613+1613+0123456789012345678901234567890123456789-113-113-012345678901234567890123456789
Links
- Depends on #9506 (host side). This branch contains its commit; the two commits on top are this PR.
- Issue: #9505
Summary
- Chats opened from the app now run as the agent config the user picked, so two Claude configs with their own
CLAUDE_CONFIG_DIR(e.g. a work account and a personal account) chat on their own accounts. - The chat model picker shows an Account group in an agent's tab when several configs chat as that agent; picking another account offers fork or fresh, as switching provider does.
- Every agent config can set an icon (not only custom ones), and the picker shows each account's icon, so the two Claudes are told apart.
Why / Context
#9506 makes the host honour agentConfigId for chat sessions, but the renderer never sent it: a chat pane stored only the preset (agent: { id: "claude" }). A chat opened from the presets bar, the "+" menu or "new chat" therefore ran on the default account, and a custom agent that runs claude/codex could not open as a chat at all.
How It Works
ChatPaneData.agentgains an optionalconfigId. The launcher stores it,createSessionsends it asagentConfigId, and new chats, forks and agent switches keep it. "New chat" reopens the last chat's config (the existingchatLastAgentkey now holds a config id; a preset id from older builds still resolves).- A pane without a saved config (opened before this change, or adopted from the CLI) takes it from the host's session row (
session.agentConfigId), and shows no current account when neither knows it, instead of guessing. resolveChatLaunchPresetId(custom config runningclaude/codexchats as that agent) moves from host-service to@superset/shared/agent-models, so host and renderer use one rule.- A conversation cannot move between config dirs (each account keeps its own session files), so switching account mid-chat uses the existing fork-or-fresh dialog with account wording.
- Settings → Agents shows the icon picker for preset agents too; "Default" keeps the preset's icon.
Manual QA Checklist
Done in a packaged local build (2.0.6 + #9506 + this PR, macOS arm64):
- Chat model picker in a Claude chat shows the Account group with all configs that chat as Claude.
- A chat created via the CLI before this change shows its real account as current (taken from the host session row).
- Settings → Agents shows the icon picker for a preset (Claude) agent, with "Default" and the Claude icon.
Not yet exercised by hand (covered by unit tests only):
- Picking the other account mid-chat → fork / fresh dialog → new chat runs on that account.
- "+" → Chat / presets bar / "new chat" open on the chosen config.
- Uploaded icon on a preset agent shows in the picker tabs and Account rows.
Testing
bun run typecheckinapps/desktopandpackages/host-service, also against the 2.0.6 release basebun run lint(repo),bun run check:i18n(new dialog string translated in all locales)bun test: newchatPresetIdForConfig,chatAgentChoices,newChatConfig,resolveChatLaunchPresetIdtests; related desktop suites (59 tests), host-service agents (72), shared agent-models (90), i18n (169)
Compatibility
agentConfigIdis optional on a non-strict schema: an older host ignores it and the chat runs as before.- Older panes without
configIdbehave as before; resume still inherits the config on the host.
Known Limitations
- The new-workspace screen still resolves a custom config's preset with
resolveAgentLaunchPresetId, so a custom agent runningclaudedoes not start as a chat from there. That value also feeds automations, tasks and model/mode validation; left for a focused follow-up.
Summary by cubic
Chats opened from the app now run as the agent config the user picked, so two Claude configs with their own CLAUDE_CONFIG_DIR stay on their own accounts, and a custom agent that runs the claude/codex CLI can open as a chat.
- Chat panes store an optional
configIdand send it asagentConfigIdwhen creating sessions; new chats, forks, agent switches, and "new chat" keep it, and fork-to-worktree carries it. - The host persists the config on each session (new migration
0004_session_agent_config) and launches the chat with that config's env, so resumed, forked, rewound, and recovered chats reopen on the same account. If the config is gone or now runs another CLI, the chat falls back to the default account and shows a notice above the composer; that fallback passes an explicitagentConfigId: nullso it inherits no config from another chat on the same agent session. - The model picker shows an Account group when several configs chat as one agent; switching account uses the existing fork-or-fresh flow since a session can't move between config dirs.
- Preset agents can set a custom icon in Settings, and the picker shows each account's icon to tell them apart.
Compatibility
agentConfigIdis optional, so older hosts ignore it and chats behave as before.- Requires the new chat-runtime migration (
0004_session_agent_config) to persist the config.
Summary by CodeRabbit
- New Features
- Choose between configured accounts for an agent when starting a chat, and see which account is active.
- New chats can use the account from your most recent chat; resumed and forked conversations retain their account when available.
- Custom agents configured with Claude or Codex commands can launch chats with the corresponding chat experience.
- Agent icons can be customized for built-in agents as well as custom agents.
- Updates
- If an account can’t be changed during an active conversation, you’ll be prompted to start a new chat or fork it.
- If an agent or account is no longer available, chats use the default account and display a notice.