mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 16:02:29 +00:00
* 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>
112 lines
3.4 KiB
TypeScript
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))
|
|
}
|
|
}
|