Files
orca/src/main/opencode/opencode-startup-prompt-owner.ts
T
e8310d5a4f fix(opencode): submit admitted native startup briefs without overwriting input (#24762)
* fix: wait for OpenCode worker composer before first dispatch

Reuse captured composer readiness on local and paired execution hosts and revoke launching-shell paste anchors.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>

* feat(opencode): probe execution-host CLI capabilities

* fix(opencode): select plugin default for execution host loader

* fix(opencode): limit prompt prefill capability to verified release

* feat(opencode): probe launch capabilities on the execution host

* fix(opencode): select plugin loader for the launched host binary

* fix(opencode): match WSL probe cwd and declared guest environment

* fix(opencode): preserve launch environment deletion boundaries

* wip(opencode): authorize native startup prompt intent at execution owner

* fix(opencode): atomically replace status plugin entrypoints

* fix(opencode): retain plugin permissions across restrictive umasks

* test(opencode): resolve permission fixture from primary cwd

* feat(opencode): install startup prompt plugin independently of status hooks

* fix(opencode): wait for admitted startup intent and preserve failed-launch briefs

* fix(opencode): unsubscribe hook settings during async host shutdown

* STRICT launch CI contract correction

* CAPS launch CI contract correction

* INTENT launch CI contract correction

* test: initialize Claude prompt state in output retention fixture

* Wait for OpenCode location hydration in intent startup

* Bind OpenCode startup readiness to the current location in intent startup

* Retry interrupted OpenCode startup prompt claims

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Co-authored-by: Ahmed Nagy <ahmednagy25t@gmail.com>
Co-authored-by: Orca startup hydration review <agents@stably.ai>
Co-authored-by: Orca <dev@stably.ai>
2026-10-04 01:41:01 -07:00

112 lines
3.4 KiB
TypeScript

import { agentHookServer } from '../agent-hooks/server'
import type { OrcaRuntimeService } from '../runtime/orca-runtime'
import type { IPtyProvider, PtySpawnResult } from '../providers/types'
import { ptyIncarnationById, ptyOwnership } from '../ipc/pty/provider/ownership-state'
import { isPtyIncarnationId } from '../../shared/pty-incarnation'
import {
OPENCODE_STARTUP_PROMPT_NONCE_ENV,
OPENCODE_STARTUP_PROMPT_SHA256_ENV
} from '../../shared/opencode-startup-prompt'
import { OpenCodeStartupPromptClaims } from './opencode-startup-prompt-claims'
type OpenCodePromptRuntime = Pick<
OrcaRuntimeService,
| 'terminalRunFacts'
| 'readOpenCodeStartupPromptOwner'
| 'isPtyStopRequested'
| 'subscribeToPtyExit'
>
const claims = new OpenCodeStartupPromptClaims()
export function reserveOpenCodeStartupPrompt(nonce: string, digest: string): boolean {
agentHookServer.setStartupPromptClaimListener(
(body) => claims.claim(body),
() => claims.clear()
)
return claims.register(nonce, digest, () => 'pending')
}
export async function commitPtyWithOpenCodePromptIntent<Result extends PtySpawnResult>(
context: {
env?: Record<string, string>
spawnEnv?: Record<string, string>
deps: { runtime?: OpenCodePromptRuntime }
result: PtySpawnResult
provider: Pick<IPtyProvider, 'hasPty'>
args: { connectionId?: string | null }
},
commit: () => Promise<Result>
): Promise<Result> {
const options = {
env: context.spawnEnv ?? context.env,
runtime: context.deps.runtime,
result: context.result,
provider: context.provider,
connectionId: context.args.connectionId
}
const facts = options.runtime?.terminalRunFacts
facts?.reserveSpawnCommit(options.result)
try {
const result = await commit()
bindOpenCodeStartupPromptOwner({ ...options, result })
return result
} catch (error) {
const nonce = options.env?.[OPENCODE_STARTUP_PROMPT_NONCE_ENV]
if (nonce) {
claims.cancel(nonce)
}
throw error
} finally {
facts?.discardSpawnCommit(options.result)
}
}
export function bindOpenCodeStartupPromptOwner(options: {
env: Record<string, string> | undefined
result: PtySpawnResult
runtime: OpenCodePromptRuntime | undefined
provider: Pick<IPtyProvider, 'hasPty'>
connectionId?: string | null
}): void {
const { env, result, runtime, provider } = options
const nonce = env?.[OPENCODE_STARTUP_PROMPT_NONCE_ENV]
const digest = env?.[OPENCODE_STARTUP_PROMPT_SHA256_ENV]
const launchToken = env?.ORCA_AGENT_LAUNCH_TOKEN
const incarnation = result.incarnationId
if (
options.connectionId ||
!runtime ||
result.isReattach ||
result.agentSessionEnsure?.disposition === 'adopted' ||
!isPtyIncarnationId(incarnation) ||
!nonce ||
!digest ||
!launchToken
) {
if (nonce) {
claims.cancel(nonce)
}
return
}
let unsubscribe = () => {}
if (
claims.admit(
nonce,
() => {
if (
ptyOwnership.get(result.id) !== null ||
ptyIncarnationById.get(result.id) !== incarnation ||
provider.hasPty?.(result.id) !== true ||
runtime.isPtyStopRequested(result.id)
) {
return null
}
return runtime.readOpenCodeStartupPromptOwner(result.id, incarnation, launchToken)
},
() => unsubscribe()
)
) {
unsubscribe = runtime.subscribeToPtyExit(result.id, () => claims.cancel(nonce))
}
}