Files
orca/src/shared/runtime-client-events.ts
T
Neil 6a9ba9d733 Keep remote worktree creation from navigating paired clients (#25793)
* fix(workspaces): keep remote creation from navigating paired viewers

* fix(workspaces): revoke pending navigation after connection replacement

* fix(workspaces): provision when the host renderer is unavailable

* test: align navigation and cache-scan expectations with current behavior

* fix(workspaces): provision broadcast creates without a host renderer
2026-10-06 00:38:53 -07:00

90 lines
3.2 KiB
TypeScript

import type { CreateWorktreeResult } from './worktree/create-types'
import type {
WorktreeDefaultTabsLaunch,
WorktreeSetupLaunch,
WorktreeStartupLaunch
} from './worktree/launch-types'
import type { SshConnectionState } from './ssh-types'
import type { TerminalSideEffectBatch } from './terminal-side-effect-facts'
import type { RuntimeNativeChatLaunchDraftResolution } from './runtime-types'
import type { RuntimeNavigationTarget } from './runtime-navigation'
export type RuntimeClientEvent =
| { type: 'reposChanged' }
| { type: 'worktreesChanged'; repoId: string }
| ({ type: 'nativeChatLaunchDraftResolved' } & RuntimeNativeChatLaunchDraftResolution)
| { type: 'terminalSideEffects'; batch: TerminalSideEffectBatch }
// Why: SSH connections live on the runtime host; paired clients have no IPC
// channel for ssh:state-changed, so without this event their reconnect
// overlays never learn the host connected (STA-1468).
| { type: 'sshStateChanged'; targetId: string; state: SshConnectionState }
| {
type: 'worktreeTerminalSleepState'
worktreeId: string
generation: number
phase: 'started' | 'committed' | 'cancelled' | 'woken'
ptyIds: string[]
terminalHandles: string[]
}
// Why: automation stores are authority-owned, so clients cannot learn about a
// run/usage/definition write without the owning authority announcing it.
| {
type: 'automationsChanged'
selector?: { kind: 'self' } | { kind: 'ssh'; targetId: string } | { kind: 'orphan' }
reason?: 'definition' | 'run' | 'usage'
}
| {
type: 'linearLinkedIssueUpdated'
worktreeId: string
identifier: string
workspaceId: string
}
| {
type: 'activateWorktree'
repoId: string
worktreeId: string
setup?: WorktreeSetupLaunch
startup?: WorktreeStartupLaunch
defaultTabs?: WorktreeDefaultTabsLaunch
/** Absent on older hosts; clients must not infer navigation intent from a broadcast. */
navigation?: RuntimeNavigationTarget
}
export type RuntimeClientEventStreamMessage =
| ({ type: 'ready'; subscriptionId: string } & {
snapshot?: {
repos?: unknown[]
sshStates?: { targetId: string; state: SshConnectionState }[]
}
})
| RuntimeClientEvent
| { type: 'end' }
export type RuntimeActivateWorktreeEvent = Extract<RuntimeClientEvent, { type: 'activateWorktree' }>
export type AutomationsChangedEvent = Extract<RuntimeClientEvent, { type: 'automationsChanged' }>
/** Publisher payload; `selector` scoping is added by a later host-scope step. */
export type AutomationsChangedPayload = Omit<AutomationsChangedEvent, 'type'>
export type PublishAutomationsChanged = (payload: AutomationsChangedPayload) => void
export function toRuntimeActivateWorktreeEvent(
repoId: string,
worktreeId: string,
setup?: CreateWorktreeResult['setup'],
startup?: WorktreeStartupLaunch,
defaultTabs?: CreateWorktreeResult['defaultTabs'],
navigation?: RuntimeNavigationTarget
): RuntimeActivateWorktreeEvent {
return {
type: 'activateWorktree',
repoId,
worktreeId,
...(navigation ? { navigation } : {}),
...(setup ? { setup } : {}),
...(startup ? { startup } : {}),
...(defaultTabs ? { defaultTabs } : {})
}
}