Files
orca/src/shared/opencode-headless-command.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

106 lines
3.1 KiB
TypeScript

import { extractLeadingEnvAssignments } from './command-environment'
import { getCommandTokenPathBasename } from './command-token-scanner'
import type { AgentStartupShell } from './tui-agent-startup-shell'
const RUN_VALUE_FLAGS = new Set([
'--log-level',
'--completions',
'--server',
'--session',
'-s',
'--model',
'-m',
'--agent',
'--format',
'--file',
'-f',
'--title'
])
const ENV_VALUE_FLAGS = new Set(['-u', '--unset', '-C', '--chdir', '-P'])
const ENV_EMPTY_FLAGS = new Set(['-i', '--ignore-environment', '-'])
function envCommandPosition(tokens: readonly string[], offset: number): number {
let index = offset
while (index < tokens.length) {
const token = tokens[index]
if (token === '--') {
index += 1
break
}
if (ENV_EMPTY_FLAGS.has(token)) {
index += 1
} else if (ENV_VALUE_FLAGS.has(token)) {
index += 2
} else if (/^(?:-[uCP].+|--(?:unset|chdir)=)/.test(token)) {
index += 1
} else if (token.startsWith('-')) {
// Split-string options need another parse before their executable is known.
return tokens.length
} else {
break
}
}
return tokens.length - extractLeadingEnvAssignments(tokens.slice(index)).rest.length
}
function openCodeCommandPosition(tokens: readonly string[], shell: AgentStartupShell): number {
if (shell === 'powershell' && tokens[0] === '&') {
return 1
}
if (shell !== 'posix') {
return 0
}
let index = tokens.length - extractLeadingEnvAssignments(tokens.slice()).rest.length
if (getCommandTokenPathBasename(tokens[index] ?? '') === 'env') {
index = envCommandPosition(tokens, index + 1)
}
return index
}
export function findOpenCodeRunCommand(
tokens: readonly string[],
shell: AgentStartupShell = 'posix'
): { runIndex: number; messageSeparatorIndex: number | null } | null {
const commandPosition = openCodeCommandPosition(tokens, shell)
if (commandPosition > 0) {
const binary = getCommandTokenPathBasename(tokens[commandPosition] ?? '')
.toLowerCase()
.replace(/\.(?:exe|cmd)$/, '')
if (binary !== 'opencode' && binary !== 'opencode2') {
return null
}
}
for (let index = commandPosition + 1; index < tokens.length; index += 1) {
const token = tokens[index]
if (!token.startsWith('-')) {
if (token !== 'run') {
return null
}
for (let argumentIndex = index + 1; argumentIndex < tokens.length; argumentIndex += 1) {
const argument = tokens[argumentIndex]
if (argument === '--') {
return { runIndex: index, messageSeparatorIndex: argumentIndex }
}
if (RUN_VALUE_FLAGS.has(argument)) {
argumentIndex += 1
}
}
return { runIndex: index, messageSeparatorIndex: null }
}
// Other valued global options fail closed at their first positional value.
if (token === '--log-level') {
index += 1
}
}
return null
}
// OpenCode run's process lifetime is its turn; v1 still reports through its plugin.
export function isOpenCodeRunCommand(
tokens: readonly string[],
shell: AgentStartupShell = 'posix'
): boolean {
return findOpenCodeRunCommand(tokens, shell) !== null
}