feat(desktop): one agent pane for a task's agent and an agent's own page

Merged
DA
3d ago
+402-75

Summary

Chain C, step C2a (items 10 and 11). The page of an agent an automation started (DesktopAgentPage) mounted AgentTab with nothing around it. It ran the full window width, ⌘F did nothing, an @ in its box offered nothing, and / had no skills. It now draws the task column's own agent pane, so a one-off agent reads, finds, and is written to the same way a task's agent is.

  • AgentPane (main-tabs.tsx): the .desktop-agent reading-width section around MainTabContent. The task column now draws its agent and draft tabs through it, and the agent page draws its agent through it.
  • ⌘F: the agent page wraps the pane in a FindScope. FindSubject gains a { agent } form beside { plan, tab }. C3 widens it to every page.
  • @ with no plan: planlessMentions (plan-mentions.tsx) is the page's mention source. It offers the repository's files, the skills, and the MCP servers, and no plan sections (planRows returns nothing for NO_PLAN). The picker reads the tree with { workspaceId, repository }, the form #2936 added.
  • / skills: useCodingAgents keeps the page agent's repository beside its workspace (both from the page read) and reads the skills through them. The page hands its transcripts those skills (SkillFiles). A skill chip opens its SKILL.md on GitHub, the same way a file mention opens where no File tab stands.
  • Dictation keywords come from the agent's repository and title.
  • Rows that open a tab: an inbox call's row opens the window's Inbox. Agent and worker rows get their cards (planCards).
  • Not in this PR: the side panel on the agent page (opening workers and Changes there). That's C2b, stacked on this one. useAgentComposer is untouched, since #333 keys drafts by agent id.

Based on main (#2936 has merged).

Evidence

Before / after: main vs this branch, the real renderer over a scripted bridge (330's show harness). The red "message box could not be loaded" line is the harness not serving the editor bundle, the same in both.

LightDark
Before (main)
After: reading width
After: ⌘F
  • pnpm check:affected: exit 0.
  • New tests, each failing on the base sources:
    • desktop-agent-page.test.ts: the page draws the agent pane at the reading width, and ⌘F opens the find bar over its transcript.
    • agent-composer-mentions.test.ts: on a no-plan page, an @ offers the repository's files read through { workspaceId, repository }, and no plan sections.
    • use-coding-agents.test.ts: with no plan open, the skills are read through the workspace and repository the page read named.
    • desktop-agent-page.test.ts: a /release in a message is its chip, and pressing it opens …/blob/HEAD/.agents/skills/release/SKILL.md on GitHub.
  • CI is Linux only. It couldn't verify the Mac, and nothing here was run on a Mac.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens unchanged.
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
  • Gateway envelope goldens unchanged.
  • No new as type assertion outside the allowlisted files.
  • No Effect.runPromise/runSync/runFork outside the runtime edges.
  • No new raw async primitives.
  • No discarded Effect.
  • Test count: +4.
  • No hand-rolled file replaced.
  • No CLAUDE.md/AGENTS.md sentence names a changed part.
  • PRIVACY.md unchanged. Session replay is unaffected: no new attribute carries words.
  • Deps unchanged.
  • Barrel/door rule unaffected.

Notes

  • Blockers or follow-up verification: C2b (the side panel on the agent page: workers and Changes) and C3 (⌘F on every page) stack on this.

🤖 Generated with Claude Code