mirror of
https://github.com/stablyai/orca.git
synced 2026-10-09 08:02:35 +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>
83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import { OpenCodeHookService, openCodeHookService, openCode2HookService } from './hook-service'
|
|
import { OPENCODE_STARTUP_PROMPT_PLUGIN_DIRECTORY } from '../../shared/opencode-startup-prompt-install'
|
|
import { join } from 'node:path'
|
|
import { resolveOpenCodeConfigDirectory } from '../../shared/opencode-config-directory'
|
|
import { isOverlayOpenCodePluginCurrent } from '../../shared/opencode-installed-plugin'
|
|
import { getOpenCodeStartupPromptSource } from './opencode-startup-prompt-source'
|
|
import { resolveOpenCodeSourceConfigDir } from '../ipc/pty/host-env/pi-agent'
|
|
import {
|
|
OPENCODE_STARTUP_PROMPT_NONCE_ENV,
|
|
OPENCODE_STARTUP_PROMPT_SHA256_ENV,
|
|
OPENCODE_STARTUP_PROMPT_BODY_ENV,
|
|
OPENCODE_STARTUP_PROMPT_ENDPOINT_ENV
|
|
} from '../../shared/opencode-startup-prompt'
|
|
|
|
export function createOpenCodeStartupPromptInstaller(source: () => string): OpenCodeHookService {
|
|
return new OpenCodeHookService({
|
|
pluginFileName: `${OPENCODE_STARTUP_PROMPT_PLUGIN_DIRECTORY}.js`,
|
|
legacyHooksDir: 'opencode-startup-prompt-hooks',
|
|
overlayDir: 'opencode-startup-prompt-overlays',
|
|
pluginSource: source,
|
|
tuiOnlyDirectory: OPENCODE_STARTUP_PROMPT_PLUGIN_DIRECTORY
|
|
})
|
|
}
|
|
|
|
const installer = createOpenCodeStartupPromptInstaller(getOpenCodeStartupPromptSource)
|
|
|
|
export function installOpenCodeStartupPromptForLaunch(
|
|
env: Record<string, string>,
|
|
restoreAfterShellStartup = true,
|
|
sourceEnvironment: NodeJS.ProcessEnv = { ...process.env, ...env }
|
|
): boolean {
|
|
const nonce = env[OPENCODE_STARTUP_PROMPT_NONCE_ENV]
|
|
if (!nonce || env.ORCA_OPENCODE_PLUGIN_API !== 'v2') {
|
|
return false
|
|
}
|
|
const source =
|
|
resolveOpenCodeSourceConfigDir(env, sourceEnvironment) ||
|
|
resolveOpenCodeConfigDirectory(sourceEnvironment)
|
|
const statusOwner =
|
|
env.ORCA_OPENCODE_AGENT === 'opencode2' ? openCode2HookService : openCodeHookService
|
|
const existing =
|
|
env.OPENCODE_CONFIG_DIR && env.OPENCODE_CONFIG_DIR === env.ORCA_OPENCODE_CONFIG_DIR
|
|
? installer.installIntoSourceOverlay(env.OPENCODE_CONFIG_DIR, source, statusOwner)
|
|
: 'unmatched'
|
|
const overlay =
|
|
existing === 'installed'
|
|
? env.OPENCODE_CONFIG_DIR
|
|
: existing === 'failed'
|
|
? undefined
|
|
: installer.buildPtyEnv(nonce, source).OPENCODE_CONFIG_DIR
|
|
if (
|
|
!overlay ||
|
|
!isOverlayOpenCodePluginCurrent(
|
|
join(overlay, 'plugins', OPENCODE_STARTUP_PROMPT_PLUGIN_DIRECTORY, 'tui.js'),
|
|
getOpenCodeStartupPromptSource()
|
|
)
|
|
) {
|
|
for (const key of [
|
|
OPENCODE_STARTUP_PROMPT_NONCE_ENV,
|
|
OPENCODE_STARTUP_PROMPT_SHA256_ENV,
|
|
OPENCODE_STARTUP_PROMPT_BODY_ENV,
|
|
OPENCODE_STARTUP_PROMPT_ENDPOINT_ENV
|
|
]) {
|
|
delete env[key]
|
|
}
|
|
return false
|
|
}
|
|
env.OPENCODE_CONFIG_DIR = overlay
|
|
env.ORCA_OPENCODE_SOURCE_CONFIG_DIR = source
|
|
if (restoreAfterShellStartup || existing === 'installed') {
|
|
env.ORCA_OPENCODE_CONFIG_DIR = overlay
|
|
} else {
|
|
delete env.ORCA_OPENCODE_CONFIG_DIR
|
|
}
|
|
return true
|
|
}
|
|
|
|
export function ensureOpenCodeStartupPromptForLaunch(env: Record<string, string>): void {
|
|
if (env[OPENCODE_STARTUP_PROMPT_NONCE_ENV] && !installOpenCodeStartupPromptForLaunch(env)) {
|
|
throw new Error('Cannot prepare OpenCode startup prompt; launch was canceled.')
|
|
}
|
|
}
|