Files
orca/src/preload/api/agent-status-api.ts
T
eb92222e7f feat: support Antigravity as supervised worker (#21705)
* feat: add supervised Antigravity worker support

* fix: address Antigravity worker review findings

* fix: stabilize Antigravity readiness detection

* fix: allow Antigravity resume footer after readiness

* fix(antigravity): make agy reach worker_done as a supervised worker

Three defects each blocked `orchestration worker-start --agent antigravity
--worktree new-child` at the agent_readiness stage.

1. Readiness never fired. The composer check required the trimmed line to be
   exactly one character, but agy 1.2.7 launches in accept-edits mode and paints
   it into the caret row (`> Accept-edits mode: ...`). Widened narrowly to a bare
   `>` or `> <name> mode:`; matching any `> <text>` would make every menu dialog
   read as ready, since they all prefix their highlighted row the same way.

2. No trust artifact for agy. Added markAntigravityWorkspaceTrusted, writing
   ~/.gemini/antigravity-cli/settings.json under `trustedWorkspaces` — verified
   empirically against agy 1.2.7, and distinct from the Gemini CLI's
   trustedFolders.json, which agy does not consult. Trust is exact-path and not
   inherited by subdirectories, so each child worktree needs its own entry.

3. The orchestration path skipped the preset. Orca has two trust dispatch
   chains: the renderer's preflightAgentTrust and the main-process
   markLocalWorktreeTrusted. worker-start only takes the second, which matched
   cursor/copilot/codex and fell through for antigravity, so the trust write
   never happened while renderer-side tests passed.

Verified live end to end: the dispatch settles `succeeded` with worker_done
carrying the right task and dispatch ids, and the worktree is appended to agy's
settings with sibling keys untouched.

Known gap: remote-agent-trust-presets.ts has no antigravity branch. The SSH
artifact path is unverified, so agy over SSH still stalls at agent_readiness.
Recorded in a comment there rather than guessed at.

* fix(antigravity): wire trust preset through preload safely

* fix: preserve Antigravity readiness across transcript tails

---------

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: LielinaH <lielinah@gmail.com>
2026-09-21 20:22:08 -07:00

63 lines
3.4 KiB
TypeScript

import type {
AgentStatusCacheIdentity,
AgentStatusClearIpcPayload,
AgentStatusIpcPayload,
MigrationUnsupportedPtyEntry
} from '../../shared/agent-status-types'
import type { AgentInterruptInferenceRequest } from '../../shared/agent-interrupt-intent'
import type { AgentQuestionAnsweredInferenceRequest } from '../../shared/agent-question-answered-intent'
import type { ComputerAwakeStatus } from '../../shared/computer-awake-mode'
export type AgentStatusApi = {
/** Listen for agent status updates forwarded from native hook receivers. */
onSet: (callback: (data: AgentStatusIpcPayload) => void) => () => void
/** Listen for main-process cleanup that evicted cached hook status. */
onClear: (callback: (data: AgentStatusClearIpcPayload) => void) => () => void
/** Return the current main-process hook cache after renderer hydration. */
getSnapshot: () => Promise<AgentStatusIpcPayload[]>
inferInterrupt: (request: AgentInterruptInferenceRequest) => Promise<boolean>
/** Guarded clear for an answered AskUserQuestion wait — the CLI emits no hook at answer time, so the renderer reports the submit keystroke. */
inferQuestionAnswered: (request: AgentQuestionAnsweredInferenceRequest) => Promise<boolean>
/** Listen for PTYs on a legacy numeric pane key that have registry-backed UUID pane proof. */
onMigrationUnsupported: (callback: (entry: MigrationUnsupportedPtyEntry) => void) => () => void
onMigrationUnsupportedClear: (callback: (data: { ptyId: string }) => void) => () => void
onLegacyWorkerTerminalRecovery: (
callback: (data: {
paneKey: string
resolution: 'adopted' | 'exited' | 'rolled_back'
ptyId?: string
}) => void
) => () => void
getMigrationUnsupportedSnapshot: () => Promise<MigrationUnsupportedPtyEntry[]>
/** Drop a paneKey from the main-process hook cache and on-disk last-status file. Fire-and-forget. */
drop: (paneKey: string) => void
/** Evict a previously-cleared status only when its identity still matches the main-process cache. */
dropPersisted: (identity: AgentStatusCacheIdentity) => void
/** Same as dropPersisted for many identities in one IPC message and one listener notification. */
dropPersistedBatch?: (identities: readonly AgentStatusCacheIdentity[]) => void
/** Retire a pane whose agent process is proven gone — clears the row AND the per-pane caches a
* dismissal deliberately keeps. Not `drop`: that one is a user dismissal of a live pane's row. */
reconcileEndedProcess: (paneKey: string) => void
/** Drop every cached hook status under one terminal tab prefix. Fire-and-forget. */
dropByTabPrefix: (tabId: string) => void
/** Permanently retire one pane's hook authority while siblings stay live. */
retirePaneAuthority: (paneKey: string, retirementId?: string) => void
/** Lift one pane's retirement fence when a live PTY re-attaches to it. Closed tabs stay retired. */
restorePaneAuthority: (paneKey: string) => void
/** Move hook authority when a live pane is detached into another tab. */
transferPaneAuthority: (args: { fromPaneKey: string; toPaneKey: string; ptyId?: string }) => void
}
export type AgentTrustApi = {
markTrusted: (args: {
preset: 'cursor' | 'copilot' | 'codex' | 'antigravity'
workspacePath: string
connectionId?: string
}) => Promise<void>
}
export type AgentAwakeApi = {
getStatus: () => Promise<ComputerAwakeStatus>
onChanged: (callback: (status: ComputerAwakeStatus) => void) => () => void
}