mirror of
https://github.com/stablyai/orca.git
synced 2026-10-13 16:02:49 +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>
91 lines
3.0 KiB
TypeScript
91 lines
3.0 KiB
TypeScript
import { mkdirSync } from 'node:fs'
|
|
import {
|
|
writeCanonicalOpenCodePluginAtomically,
|
|
writeOverlayOpenCodePluginAtomically
|
|
} from './opencode-plugin-atomic-write'
|
|
import { dirname, join } from 'node:path'
|
|
import {
|
|
InvalidOpenCodeTuiConfigError,
|
|
registerOpenCodeTuiPlugin
|
|
} from './opencode-tui-config-registration'
|
|
import {
|
|
isInstalledOpenCodePluginCurrent,
|
|
isOverlayOpenCodePluginCurrent
|
|
} from './opencode-installed-plugin'
|
|
|
|
/**
|
|
* Directory holding the TUI copy of a status plugin file. OpenCode 2 loads a
|
|
* `tui` entrypoint from a plugins/ subdirectory; 1.x needs explicit config registration.
|
|
*/
|
|
export function openCodeTuiPluginDirName(pluginFileName: string): string {
|
|
return `${pluginFileName.replace(/\.js$/, '')}-tui`
|
|
}
|
|
|
|
/**
|
|
* Install the TUI copy beside the server plugin file. The same module serves
|
|
* both: its setup() tells a TUI context from a server context. Call it before
|
|
* writing the server file, which decides at load whether to stand down.
|
|
*/
|
|
export function writeOpenCodeTuiPlugin(
|
|
pluginsDir: string,
|
|
pluginFileName: string,
|
|
source: string,
|
|
ownership: 'canonical' | 'overlay' = 'canonical'
|
|
): void {
|
|
writeOpenCodeTuiPluginDirectory(
|
|
pluginsDir,
|
|
openCodeTuiPluginDirName(pluginFileName),
|
|
source,
|
|
ownership
|
|
)
|
|
}
|
|
|
|
export function writeOpenCodeTuiPluginDirectory(
|
|
pluginsDir: string,
|
|
directoryName: string,
|
|
source: string,
|
|
ownership: 'canonical' | 'overlay' = 'canonical'
|
|
): void {
|
|
const dir = join(pluginsDir, directoryName)
|
|
const entry = join(dir, 'tui.js')
|
|
// The 1.x TUI loader rejects a default object that also exposes server().
|
|
const tuiSource =
|
|
source.includes('const ORCA_STATUS_AGENT = "opencode";') &&
|
|
source.includes('async function setupLegacyOpenCodeTui(')
|
|
? `${source.replace(/^export default /m, 'const orcaServerPlugin = ')}\nconst { server: _orcaServerOnly, ...orcaTuiPlugin } = orcaServerPlugin;\nexport default { id: ${JSON.stringify(directoryName.replace(/-tui$/, ''))}, setup: setupOpenCode2Status, ...orcaTuiPlugin, tui: setupLegacyOpenCodeTui };\n`
|
|
: source
|
|
const isCurrent =
|
|
ownership === 'canonical' ? isInstalledOpenCodePluginCurrent : isOverlayOpenCodePluginCurrent
|
|
if (isCurrent(entry, tuiSource)) {
|
|
if (tuiSource !== source) {
|
|
registerTuiPlugin(pluginsDir, entry, ownership)
|
|
}
|
|
return
|
|
}
|
|
mkdirSync(dir, { recursive: true })
|
|
const write =
|
|
ownership === 'canonical'
|
|
? writeCanonicalOpenCodePluginAtomically
|
|
: writeOverlayOpenCodePluginAtomically
|
|
write(entry, tuiSource)
|
|
if (tuiSource !== source) {
|
|
registerTuiPlugin(pluginsDir, entry, ownership)
|
|
}
|
|
}
|
|
|
|
function registerTuiPlugin(
|
|
pluginsDir: string,
|
|
entry: string,
|
|
ownership: 'canonical' | 'overlay'
|
|
): void {
|
|
try {
|
|
registerOpenCodeTuiPlugin(dirname(pluginsDir), entry, ownership)
|
|
} catch (error) {
|
|
if (!(error instanceof InvalidOpenCodeTuiConfigError)) {
|
|
throw error
|
|
}
|
|
// Invalid TUI settings must not block the separate server status plugin.
|
|
console.warn('[OpenCode] Failed to register TUI status plugin:', entry, error)
|
|
}
|
|
}
|