Files
orca/src/shared/agent-launch-runtime-capability.ts
T
Brennan Benson 00e3027762 feat(agent-launch): show an agent's tab at once, where the caller asked (#25430)
* feat(agent-launch): host-assigned caller identity and a launch record written when the surface exists

Step 1 of the agent-launch unification, on main.

- The dispatcher stamps every request's caller from what its connection proved (runtime socket:
  the local CLI; the desktop's IPC: the desktop; a paired socket: its device). Params never set it.
- The launch record is written twice: once when the tab exists (what creation settled: on the
  launch command, a draft, or a submit still `unconfirmed`), and again once the prompt's fate is
  known. A restart in between finds the running agent instead of answering "unknown".
- A replay re-derives its terminal handle from the pane key in the running host, and shows
  `unconfirmed` only to callers that advertise agent.launch.prompt-unconfirmed.v1.
- The record store opens in its own slot, without building the chat host; the chat host is built
  on that same store.

Rebuilt from this PR's own commits (b9adf88da0, 0d7d9b5b30, c83f44dd72, 39d15d52c0) onto
main, without #24080/#24081. Conflicts: the delivery doc table (main's "line fits" row plus the
`unconfirmed` row), and main's journal-database open in install(), which now goes through the
record-store slot.

* feat(agent-launch): show an agent's tab at once, where the caller asked for it

An agent.launch now shows its terminal tab before admission and spawn, in
the requested placement (group and/or anchor tab), and the pane attaches to
the agent as soon as it runs. A pane whose agent can't start, or whose start
can't be confirmed, says so instead of becoming a plain shell, and keeps
saying so across restarts. A user's close of the tab or its pane during the
launch stops it and answers agent_launch_tab_closed. Whose view moves is
unchanged from main for every caller.

Rebuilt on main (with #24934) from the previous branch head 8f62858e60.

* style(runtime): one-line the tab-order map so the headless browser-tabs runtime stays under its line limit

The merge of main (#25724's emitMobileSessionTabsSnapshot metadata) plus this branch's close mark put
the file one line over max-lines. Formatting only.
2026-10-06 18:02:30 -07:00

59 lines
3.4 KiB
TypeScript

// Split out of protocol-version.ts, which spreads the list below into RUNTIME_CAPABILITIES in this
// order. Import these names from here: the mobile recording loader cannot follow `export *`.
/**
* `agent.launch` exists: one host-side method that decides structured-vs-terminal and creates the
* surface, instead of each client routing for itself.
*
* Negotiated rather than assumed because a client that cannot see it must keep using
* `worktree.create` + `startupAgent`, which stays supported verbatim. The reverse skew is the
* dangerous one: `worktree.create` returns `agentTerminalHandle` only when a startup agent was
* requested, so a host that quietly routed that call to a structured session would hand an old
* client a response with no handle and no error.
*
* Advertising it is a statement that the client understands EITHER outcome, since the host is what
* picks: a structured session it can open, or a terminal agent. A client that renders only one of
* the two keeps using the surface-specific methods.
*/
// v2 makes prompt delivery an outcome union and top-level warnings the only supported shape.
export const AGENT_LAUNCH_RUNTIME_CAPABILITY = 'agent.launch.v2' as const
// Optional identity support on agent.launch; mobile replay across replacement hosts requires the new method.
export const AGENT_LAUNCH_REPLAY_RUNTIME_CAPABILITY = 'agent.launch.replay.v1' as const
// A host that sends a launch prompt its typed startup line cannot carry to a paste after
// readiness; an older host folds any prompt into that line, so clients gate prompted launches on it.
export const AGENT_LAUNCH_PROMPT_CARRY_RUNTIME_CAPABILITY = 'agent.launch.prompt-carry.v1' as const
// agent.launchReplay requires the ledger; older replacement hosts must reject the method.
export const AGENT_LAUNCH_REPLAY_REQUIRED_RUNTIME_CAPABILITY =
'agent.launch.replay-required.v1' as const
// A client that reads `prompt.outcome: 'unconfirmed'` on a replayed launch. Without it, a launch
// whose host stopped mid-delivery replays as `agent_session_operation_unknown`, as it always has.
export const AGENT_LAUNCH_PROMPT_UNCONFIRMED_RUNTIME_CAPABILITY =
'agent.launch.prompt-unconfirmed.v1' as const
// Host-advertised: reads `placement` and `presentation`, reports the placement in the receipt, and
// may publish the launch's tab before it admits the launch.
export const AGENT_LAUNCH_PLACEMENT_RUNTIME_CAPABILITY = 'agent.launch.placement.v1' as const
// Client-advertised only: the client reads a listed launch tab with no terminal yet as "not
// started", never as proof its agent runs. The host publishes a paired caller's tab before the
// spawn only for a client that says so.
export const AGENT_LAUNCH_UNSTARTED_TAB_CLIENT_CAPABILITY = 'agent.launch.unstarted-tab.v1' as const
// Client-advertised only: the client reads `agent_launch_tab_closed` (the user closed the launch's
// tab while it started, so it was stopped) as a definite answer. Others get
// `agent_session_operation_unknown` for it, as before the host knew.
export const AGENT_LAUNCH_TAB_CLOSED_CLIENT_CAPABILITY = 'agent.launch.tab-closed.v1' as const
export const AGENT_LAUNCH_RUNTIME_CAPABILITIES = [
AGENT_LAUNCH_RUNTIME_CAPABILITY,
AGENT_LAUNCH_REPLAY_RUNTIME_CAPABILITY,
AGENT_LAUNCH_REPLAY_REQUIRED_RUNTIME_CAPABILITY,
AGENT_LAUNCH_PROMPT_CARRY_RUNTIME_CAPABILITY,
AGENT_LAUNCH_PROMPT_UNCONFIRMED_RUNTIME_CAPABILITY,
AGENT_LAUNCH_PLACEMENT_RUNTIME_CAPABILITY
] as const