feat(desktop): chat v3 polish: collapsed tool runs, command and mention chips, background work across chats

Merged
HA
22d ago
+808-209

Links

Summary

  1. Tool runs start collapsed (SUPER-2622). A run of tool calls is one summary line ("Ran 4 commands") while the turn runs, as in Codex. A run opened for an approval stays open after the approval.
  2. Agent icon in the chat pane header (SUPER-2627) and reply actions (SUPER-2616): tooltips, a split icon for Branch, and the date on a reply from an earlier day. No hidden action row under a running turn's latest message, which used to leave a 22px gap above the live run.
  3. Commands, files and pages as chips (SUPER-2664). A picked /command or skill, an @file, and a new @page read as a dashed-underlined chip, in the composer and in sent messages. Hover shows the full /name with the agent's description, the file path, or the page URL.
  4. Background work across several chats. A job started by a subagent no longer stays in the activity menu forever, and each row names its chat when several chats have work.

How It Works

  • Collapse: transcriptRows defaults every run to collapsed unless it waits on an approval. Transcript records an approval-opened run as expanded so approving does not collapse it. lastReplyKeys only gives a settled turn a last reply; the working row carries running from the turn status, since completedAtMs is optional on settled turns.
  • Chips: the composer records each chip's place in the sent text as protocol elements (UTF-8 byte range, kind, and a new optional label). UserMessageRow splits the text back into chips. Older messages without elements fall back to a leading /command the agent advertises, so a path stays plain text. The look lives in a shared @superset/chat-ui/Chip. Picking a command only inserts it; Enter no longer sends.
  • Slash menu, after Zed: groups by ACP _meta.command_category ("Commands", "MCP Server Commands"), shows the argument hint, and refuses an unknown leading /command with a toast while keeping the text (onSubmit may return false to keep the draft). Claude does not set the category yet, so its commands share one heading, as in Zed.
  • Background work: the Claude ACP adapter routes a subagent's task updates to the subagent's session and drops them once it finishes (native-subagents.js, routeOfToolCall), so the "finished" update never came. AcpAdapter now ends a subagent's jobs when the subagent finishes.

Manual QA Checklist

Done in the dev app over CDP with real Claude sessions:

  • A 9-step turn (about 35 tool calls): every run collapsed at every 15-second sample, the live one included, and after a reload
  • No gap above the live run; the final reply gets Copy, Branch and the time once the turn ends
  • Chat pane header shows the Claude logo; Copy and Branch tooltips; split icon
  • /goal then Enter inserts the chip and sends nothing (12 user messages before and after)
  • Command chip hover shows /goal and its description; file chip shows notes/release-plan.md; page chip shows the page URL
  • File and page chips stay chips after a full reload; the agent read the file by its path
  • /notacommand hello is refused with a toast and the text stays; /Users/me/file.ts style text still sends
  • Two Claude chats: the activity menu counted 5 (3 processes, 2 subagents), each row named its chat, a click opened the owning chat, Stop stopped only that chat's job
  • A subagent's background sleep left the list when the subagent ended (it stayed for 273 s before)
  • Not seen in the app: a run waiting on an approval (the session auto-approved; covered by unit tests), the dated time for an older reply (formatter output checked)

Testing

  • bun test: desktop v2-workspace suites 500 pass; chat 54, chat-ui 10, chat-runtime ACP adapter 59, all pass. New tests: approval-opened runs, running turns have no last reply, a subagent's job ends with it, command category passthrough, command chip labels, element byte ranges with non-ASCII text.
  • typecheck: chat, chat-ui and chat-runtime are clean. Desktop's only errors are in packages/auth and packages/trpc better-auth types in this worktree, none in changed files.
  • Biome clean. bun run check:i18n: two new strings ("MCP Server Commands", "Unknown command /{name}"), translated in all 16 locales.

Known Limitations

  • A process a subagent leaves running drops off the activity menu when the subagent ends; the adapter sends nothing more about it. The real fix is upstream: route those updates to the main chat instead of dropping them.
  • The agent receives a page as its URL. A plain HTTP fetch of a page needs a signed-in viewer, so an agent without the Superset CLI cannot read it.
  • File and page chips come from elements stored with the message. They survive a window reload, but after a host-service restart the chat is rebuilt from the agent's own replay, which has plain text, so those messages show the path or URL as text. A leading /command still shows as a chip.
  • Mid-turn, finished messages have no Copy or Branch until the turn ends (the trade-off for removing the gap).
  • "Goal set" still reads as an agent reply. claude-agent-acp sends structured goal data only to JetBrains AIR clients; a goal banner is follow-up work.

Summary by CodeRabbit

  • New Features
    • Chat supports mentions for cloud pages and workspace files, plus slash-command chips with descriptions and hints.
    • Available commands are grouped by type, and workspace activity can identify the pane associated with background work.
    • Copy and branch controls display tooltips.
  • Improvements
    • Message timestamps show the time for today and the date for older messages, with the year when needed; hovering reveals the full timestamp.
    • Tool runs are collapsed by default unless they need approval.
    • Replies from still-running turns are excluded from the latest completed reply.
    • Terminal pane icons can reflect the associated agent.
    • Unknown slash commands are flagged, and rejected submissions keep the draft in the editor.
    • Failed mention searches clear stale results and stop showing as pending.