mirror of
https://github.com/stablyai/orca.git
synced 2026-10-13 08:02:52 +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>
106 lines
3.1 KiB
TypeScript
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
|
|
}
|