Files
orca/src/shared/native-chat-initial-view-mode.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

74 lines
2.6 KiB
TypeScript

import type { GlobalSettings } from './global-settings-types'
import { agentTabsDefaultToNativeChat } from './structured-native-chat-launch-route'
import type { Tab } from './tab-types'
import type { TuiAgent } from './tui-agent'
import { canMirrorLaunchDraftToNativeChat } from './native-chat-launch-draft-mirrorability'
import {
isNativeChatSupportedAgent,
nativeChatRequiresLocalTranscript
} from './native-chat-agent-support'
export type NativeChatLaunchPromptDelivery = 'auto-submit' | 'draft' | 'submit-after-ready'
/**
* Decide the initial `viewMode` for a newly launched agent tab from the
* opt-in `openAgentTabsInChatByDefault` setting.
*
* Returns `'chat'` only when the setting is explicitly on and the launched
* agent has a native-chat renderer. A draft launch opens in chat only when its
* unsent context can be mirrored into the composer — gated on the same
* predicate as seeding so the view never opens empty beside a filled TUI input.
*/
export function decideInitialAgentTabViewMode(args: {
experimentalNativeChat?: boolean
openAgentTabsInChatByDefault?: boolean
agent?: TuiAgent | null
promptDelivery?: NativeChatLaunchPromptDelivery
/** The unsent launch context, when `promptDelivery` is `'draft'`. */
launchDraftText?: string
nativeChatTranscriptIsLocalReadable?: boolean
}): Tab['viewMode'] {
if (!agentTabsDefaultToNativeChat(args)) {
return undefined
}
if (!isNativeChatSupportedAgent(args.agent)) {
return undefined
}
if (
nativeChatRequiresLocalTranscript(args.agent) &&
args.nativeChatTranscriptIsLocalReadable !== true
) {
return undefined
}
if (
args.promptDelivery === 'draft' &&
!canMirrorLaunchDraftToNativeChat(args.launchDraftText ?? '')
) {
return undefined
}
return 'chat'
}
export function initialAgentTabViewModeProps(
settings:
| Pick<GlobalSettings, 'experimentalNativeChat' | 'openAgentTabsInChatByDefault'>
| null
| undefined,
options: {
agent?: TuiAgent | null
promptDelivery?: NativeChatLaunchPromptDelivery
launchDraftText?: string
nativeChatTranscriptIsLocalReadable?: boolean
} = {}
): { viewMode?: Tab['viewMode'] } {
const viewMode = decideInitialAgentTabViewMode({
experimentalNativeChat: settings?.experimentalNativeChat,
openAgentTabsInChatByDefault: settings?.openAgentTabsInChatByDefault,
agent: options.agent,
promptDelivery: options.promptDelivery,
launchDraftText: options.launchDraftText,
nativeChatTranscriptIsLocalReadable: options.nativeChatTranscriptIsLocalReadable
})
return viewMode ? { viewMode } : {}
}