mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 00:02:29 +00:00
fix(opencode): pass run prompts as positional messages
Preserve run flags and use the existing shell quoting and run-command detector to append the initial message after --, reusing an existing separator. TUI launches retain their version-selected prompt transport and draft behavior. Original run-order work: @coelho-doti (#13065, tracked in #17551).
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import type { AgentStartupPlan } from './tui-agent-startup'
|
||||
import type { SleepingAgentLaunchConfig } from './agent-session-resume'
|
||||
import type { SessionOptionValue } from './native-chat-session-options'
|
||||
import type { TuiAgent } from './tui-agent'
|
||||
import { TUI_AGENT_CONFIG } from './tui-agent-config'
|
||||
import { tokenizeStartupCommand, type AgentStartupShell } from './tui-agent-startup-shell'
|
||||
import { isOpenCodeRunCommand } from './opencode-headless-command'
|
||||
import { openCodeStartupPromptEnv } from './opencode-startup-prompt'
|
||||
|
||||
export function appliedSessionOptionProps(values: Record<string, SessionOptionValue>) {
|
||||
return Object.keys(values).length > 0 ? { sessionOptions: { ...values } } : {}
|
||||
}
|
||||
|
||||
export function buildFlagPromptStartupPlan(args: {
|
||||
agent: TuiAgent
|
||||
launchCommand: string
|
||||
quotedPrompt: string
|
||||
prompt: string
|
||||
shell: AgentStartupShell
|
||||
launchConfig: SleepingAgentLaunchConfig
|
||||
sessionOptions: Record<string, SessionOptionValue>
|
||||
agentEnv: Record<string, string> | null | undefined
|
||||
}): AgentStartupPlan {
|
||||
const parsed = tokenizeStartupCommand(args.launchCommand, args.shell)
|
||||
const isOpenCodeRun =
|
||||
(args.agent === 'opencode' || args.agent === 'opencode2') &&
|
||||
parsed.ok &&
|
||||
isOpenCodeRunCommand(parsed.tokens)
|
||||
// OpenCode run takes a positional message; --prompt belongs to its TUI.
|
||||
const promptSuffix = isOpenCodeRun
|
||||
? parsed.tokens.includes('--')
|
||||
? ` ${args.quotedPrompt}`
|
||||
: ` -- ${args.quotedPrompt}`
|
||||
: ` --prompt ${args.quotedPrompt}`
|
||||
return {
|
||||
agent: args.agent,
|
||||
launchCommand: `${args.launchCommand}${promptSuffix}`,
|
||||
expectedProcess: TUI_AGENT_CONFIG[args.agent].expectedProcess,
|
||||
followupPrompt: null,
|
||||
launchConfig: args.launchConfig,
|
||||
...appliedSessionOptionProps(args.sessionOptions),
|
||||
...openCodeStartupPromptEnv(
|
||||
args.agent,
|
||||
args.launchCommand,
|
||||
args.shell,
|
||||
args.prompt,
|
||||
args.agentEnv
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
OPENCODE_STARTUP_PROMPT_BODY_ENV,
|
||||
OPENCODE_STARTUP_PROMPT_SHELL_ENV
|
||||
} from './opencode-startup-prompt'
|
||||
import { tokenizeStartupCommand } from './tui-agent-startup-shell'
|
||||
|
||||
describe('native OpenCode startup submission intent', () => {
|
||||
it('binds the exact trimmed native prompt to host-selectable transport', () => {
|
||||
@@ -33,9 +34,63 @@ describe('native OpenCode startup submission intent', () => {
|
||||
platform: 'linux'
|
||||
})
|
||||
expect(plan?.env).toBeUndefined()
|
||||
expect(plan?.launchCommand).toContain('run --prompt')
|
||||
expect(plan?.launchCommand).toContain("run -- 'task'")
|
||||
})
|
||||
|
||||
it.each(['posix', 'powershell', 'cmd'] as const)(
|
||||
'keeps run and its flags before a positional message in %s',
|
||||
(shell) => {
|
||||
for (const agent of ['opencode', 'opencode2'] as const) {
|
||||
const prompt = '--literal task with unicode é'
|
||||
const plan = buildAgentStartupPlan({
|
||||
agent,
|
||||
prompt,
|
||||
cmdOverrides: { [agent]: 'opencode --log-level debug run --standalone' },
|
||||
platform: shell === 'posix' ? 'linux' : 'win32',
|
||||
shell,
|
||||
agentEnv: { CUSTOM_CONFIG: 'kept' }
|
||||
})
|
||||
expect(plan).not.toBeNull()
|
||||
const parsed = tokenizeStartupCommand(plan?.launchCommand ?? '', shell)
|
||||
expect(parsed.ok).toBe(true)
|
||||
if (!parsed.ok) {
|
||||
throw new Error(parsed.error)
|
||||
}
|
||||
expect(parsed.tokens).toEqual([
|
||||
'opencode',
|
||||
'--log-level',
|
||||
'debug',
|
||||
'run',
|
||||
'--standalone',
|
||||
'--',
|
||||
prompt
|
||||
])
|
||||
expect(plan?.env).toEqual({ CUSTOM_CONFIG: 'kept' })
|
||||
expect(plan?.followupPrompt).toBeNull()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
it.each(['posix', 'powershell', 'cmd'] as const)(
|
||||
'reuses an existing run message separator in %s',
|
||||
(shell) => {
|
||||
const plan = buildAgentStartupPlan({
|
||||
agent: 'opencode',
|
||||
prompt: '--literal task',
|
||||
cmdOverrides: { opencode: 'opencode run --standalone --' },
|
||||
platform: shell === 'posix' ? 'linux' : 'win32',
|
||||
shell
|
||||
})
|
||||
const parsed = tokenizeStartupCommand(plan?.launchCommand ?? '', shell)
|
||||
expect(parsed.ok).toBe(true)
|
||||
if (!parsed.ok) {
|
||||
throw new Error(parsed.error)
|
||||
}
|
||||
expect(parsed.tokens).toEqual(['opencode', 'run', '--standalone', '--', '--literal task'])
|
||||
expect(plan?.env).toBeUndefined()
|
||||
}
|
||||
)
|
||||
|
||||
it('never gives an editable draft or empty launch an automatic submission intent', () => {
|
||||
const args = { agent: 'opencode' as const, cmdOverrides: {}, platform: 'linux' as const }
|
||||
expect(
|
||||
|
||||
@@ -17,7 +17,7 @@ import { inlineAgentDraftFitsPlatform } from './agent-draft-platform-limit'
|
||||
import type { TuiAgent } from './tui-agent'
|
||||
import type { SessionOptionValue } from './native-chat-session-options'
|
||||
import { resolveAgentLaunchCommand } from './tui-agent-launch-command'
|
||||
import { openCodeStartupPromptEnv } from './opencode-startup-prompt'
|
||||
import { appliedSessionOptionProps, buildFlagPromptStartupPlan } from './flag-prompt-startup'
|
||||
|
||||
export { buildAgentResumeStartupPlan } from './tui-agent-resume-startup'
|
||||
|
||||
@@ -36,10 +36,6 @@ export type AgentStartupPlan = {
|
||||
sessionOptions?: Record<string, SessionOptionValue>
|
||||
}
|
||||
|
||||
function appliedSessionOptionProps(values: Record<string, SessionOptionValue>) {
|
||||
return Object.keys(values).length > 0 ? { sessionOptions: { ...values } } : {}
|
||||
}
|
||||
|
||||
export function buildAgentStartupPlan(args: {
|
||||
agent: TuiAgent
|
||||
prompt: string
|
||||
@@ -117,15 +113,16 @@ export function buildAgentStartupPlan(args: {
|
||||
}
|
||||
|
||||
if (config.promptInjectionMode === 'flag-prompt') {
|
||||
return {
|
||||
return buildFlagPromptStartupPlan({
|
||||
agent,
|
||||
launchCommand: `${launchCommand} --prompt ${quotedPrompt}`,
|
||||
expectedProcess: config.expectedProcess,
|
||||
followupPrompt: null,
|
||||
launchCommand,
|
||||
quotedPrompt,
|
||||
prompt: trimmedPrompt,
|
||||
shell,
|
||||
launchConfig,
|
||||
...appliedSessionOptionProps(baseCommand.appliedSessionOptions),
|
||||
...openCodeStartupPromptEnv(agent, launchCommand, shell, trimmedPrompt, args.agentEnv)
|
||||
}
|
||||
sessionOptions: baseCommand.appliedSessionOptions,
|
||||
agentEnv: args.agentEnv
|
||||
})
|
||||
}
|
||||
|
||||
if (config.promptInjectionMode === 'hermes-query') {
|
||||
|
||||
Reference in New Issue
Block a user