feat(desktop): an agent with no plan has a page of its own, standing in the plan's place as the Inbox does

Merged
DA
4d ago
+510-60

Step 8 (last part) of the automations plan (docs/proposals/automations-scope.md): the desktop agent page. #2713, which it built on, has merged.

What changes

An agent an automation's run starts has no plan, so there's no plan column for its tab. It gets a page of its own instead, a new window place standing where the plan would, beside the sidebar, as the Inbox does.

  • DesktopAgentPage (desktop/desktop-agent-page.tsx):
    • It draws the agent's tab whole (AgentTab): transcript, composer, model and servers, and what it published. The toolbar title names the agent as its tab would.
    • A read that doesn't land shows a Retry.
    • Workers open nowhere yet, since a worker opens in the side panel that a plan's column keeps.
  • useCodingAgents takes an agentId. With no plan open, its list is that one agent, read through #2710's codingAgents.page act and held as a list of one. Every answer that already patches a plan's agents (status and title from the transcript, model, rename, archive, servers) moves the page's agent the same way, with no second store.
  • One stand-in state in use-plans-tab.ts. The Inbox's own state becomes "what stands in the plan's place": the Inbox with its chosen item, or one agent's page.
    • Every navigation that already left the Inbox (any plan, home, a new plan, a file, a source, a pinned tab, the version history) now leaves the agent page too, without touching each call site.
    • agentView (agentId, onOpen, onClose) joins inboxView.
    • Main is told the page's agent is the one shown, so its notices hold off as they do for an open tab.
  • The rest of the window treats it like the Inbox:
    • Shell: no side-panel toggle, no plan looks, and a column-dock key.
    • Sidebar: no plan or Home marked current.
    • Back/forward: PLACE_KIND.AGENT by agent id.
    • Escape: a new EXIT_AGENT_PAGE command beside EXIT_INBOX, in the shortcuts list and Escape chain.

What opens the page comes next (step 9): a planless Inbox item from #2688's planless keys, and the agent's notice.

Bundle budget: renderer.js re-baselined

Dean approved a re-baseline on 2026-10-15 for Factory and the planless agent page. A perf PR lazy-loading posthog-js and the markdown HTML parser will win the space back.

Measured after rebasing onto main, with #2738's lazy Settings chunk included:

  • main's renderer.js is 795,229 gzipped bytes against a ceiling of 795,845 (baseline 757,948 + 5%).
  • This PR makes it 795,917: 688 bytes for the page and its window place, 72 over the ceiling.
  • Lazy-loading the page itself made it larger (the split moves shared code into an up-front chunk and loses cross-file compression), so that isn't the way.

Only renderer/renderer.js moves, to 795,917; the other bundles keep their baselines. Factory (#2608) is re-baselining at the same time, so whichever of the two lands second must rebase and re-record from main rather than keep a stale number.

Tests

  • desktop-agent-page.test.ts (new): the page reads the agent by id and titles it. A read that fails shows Retry, and Retry reads again and draws it.
  • use-coding-agents.test.ts: with no plan open, only the named agent is read (no plan list), and a title from a transcript page moves it.
  • Further fixes from review: another agent's page holds nothing of the last (the hook's list is held per agent, and the page is keyed by it); an archived agent offers Unarchive, and a refused Unarchive says why; a teammate's agent names the teammate's key; and the page covers the call bar as the Inbox does, so the call card floats clear of the page's composer.
  • All renderer test files pass.

pnpm check:affected passes. This is UI: CI cannot verify the Mac UI, and ./scripts/verify.sh was not run (LUKE-159 stands in before the first release).

šŸ¤– Generated with Claude Code