Files
orca/src/shared/opencode-tui-plugin-install.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

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)
}
}