wip(omp): prove fresh settings overlay without redirecting storage

This commit is contained in:
Neil
2026-09-19 01:36:58 -07:00
parent 14cddfeda7
commit 2f07add793
9 changed files with 236 additions and 13 deletions
@@ -275,6 +275,8 @@ describe('PiTitlebarExtensionService', () => {
const content = 'agent.db credentials'
expect(env.PI_CODING_AGENT_DIR).toBeUndefined()
expect(readFileSync(env.ORCA_OMP_FRESH_CONFIG, 'utf8')).toBe('autoResume: false\n')
expect(env.ORCA_OMP_FRESH_CONFIG.startsWith(userDataDir)).toBe(true)
expect(env.ORCA_OMP_SOURCE_AGENT_DIR).toBe(piHome)
expect(env.ORCA_OMP_STATUS_EXTENSION).toBe(join(piHome, 'extensions', 'orca-agent-status.ts'))
expect(existsSync(sourcePath)).toBe(false)
+22 -3
View File
@@ -1,3 +1,8 @@
import {
OMP_FRESH_CONFIG_FILENAME,
OMP_FRESH_CONFIG_SOURCE,
ORCA_OMP_FRESH_CONFIG_ENV
} from '../../shared/omp-fresh-launch'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { homedir } from 'node:os'
import { join } from 'node:path'
@@ -183,7 +188,19 @@ export class PiTitlebarExtensionService {
// The caller resolves the effective launch environment. Reading the
// daemon's ambient PI_CONFIG_DIR here can select the host profile for a
// guest/WSL launch whose environment has not been hydrated yet.
const sourceAgentDir = existingAgentDir || getDefaultPiAgentDir(kind, options?.configDirName)
const freshConfigEnv: Record<string, string> = {}
if (kind === 'omp') {
const configDir = join(
getAppEnvironment().getPath('userData'),
OMP_MANAGED_STATUS_EXTENSION_DIR
)
mkdirSync(configDir, { recursive: true })
const configPath = join(configDir, OMP_FRESH_CONFIG_FILENAME)
writeFileSync(configPath, OMP_FRESH_CONFIG_SOURCE)
freshConfigEnv[ORCA_OMP_FRESH_CONFIG_ENV] = configPath
}
const sourceAgentDir =
existingAgentDir || getDefaultPiAgentDir(kind, options?.configDirName)
if (kind !== 'prime-agent') {
try {
this.safeRemoveOverlay(this.getPtyOverlayDir(ptyId, kind), kind)
@@ -203,7 +220,9 @@ export class PiTitlebarExtensionService {
if (kind === 'omp') {
const statusSource = withOrcaManagedExtensionMarker(getPiAgentStatusExtensionSource(kind))
const statusExtensionPath = this.writeOmpFallbackStatusExtension(statusSource)
return statusExtensionPath ? { ORCA_OMP_STATUS_EXTENSION: statusExtensionPath } : {}
return statusExtensionPath
? { ...freshConfigEnv, ORCA_OMP_STATUS_EXTENSION: statusExtensionPath }
: freshConfigEnv
}
return {}
}
@@ -213,7 +232,7 @@ export class PiTitlebarExtensionService {
}
const installed = this.installManagedExtensions(sourceAgentDir, kind)
const env: Record<string, string> = {}
const env: Record<string, string> = { ...freshConfigEnv }
if (kind === 'omp') {
env.ORCA_OMP_SOURCE_AGENT_DIR = installed.sourceAgentDir
if (installed.statusExtensionPath) {
+2
View File
@@ -63,6 +63,7 @@ describe('addOrcaWslInteropEnv', () => {
ORCA_USER_DATA_PATH: 'C:\\Users\\jin\\AppData\\Roaming\\Orca',
ORCA_CLI_COMMAND: 'orca-ide',
ORCA_CODEX_LAUNCH_PREFLIGHT: 'C:\\Program Files\\Orca\\resources\\bin\\orca.exe',
ORCA_OMP_FRESH_CONFIG: 'C:\\Orca\\fresh-session.yml',
ORCA_OMP_STATUS_EXTENSION: 'C:\\Users\\jin\\.omp\\agent\\extensions\\orca-agent-status.ts',
ORCA_PRIME_AGENT_STATUS_EXTENSION: 'C:\\stale\\orca-agent-status.ts',
ORCA_PANE_KEY: 'tab-1:leaf-1',
@@ -87,6 +88,7 @@ describe('addOrcaWslInteropEnv', () => {
expect(env.WSLENV).toContain('ORCA_CLI_COMMAND/u')
expect(env.WSLENV).toContain('ORCA_CODEX_LAUNCH_PREFLIGHT/p')
expect(env.WSLENV).toContain('ORCA_OMP_STATUS_EXTENSION/p')
expect(env.WSLENV).toContain('ORCA_OMP_FRESH_CONFIG/p')
expect(env.WSLENV).not.toContain('ORCA_PRIME_AGENT_STATUS_EXTENSION')
expect(env.WSLENV).toContain('ORCA_PANE_KEY/u')
expect(env.WSLENV).toContain('ORCA_TAB_ID/u')
+1 -1
View File
@@ -99,8 +99,8 @@ export function addOrcaWslInteropEnv(env: Record<string, string>): void {
'ORCA_WSL_HOOK_INSTANCE/u',
'ORCA_OMP_SOURCE_AGENT_DIR/p',
'ORCA_OMP_STATUS_EXTENSION/p',
// A protocol name, never a path; in-guest agents read it to pick an image encoder.
`${ORCA_IMAGE_PROTOCOL_ENV}/u`,
'ORCA_OMP_FRESH_CONFIG/p',
...worktreeSetupWslenvEntries(env)
]
applyWslenvPassthrough(env, passthroughEntries)
+61
View File
@@ -0,0 +1,61 @@
import { describe, expect, it } from 'vitest'
import { withFreshOmpLaunch } from './omp-fresh-launch'
import { buildAgentStartupPlan } from './tui-agent-startup'
describe('OMP fresh launch intent', () => {
it.each(['omp', 'omp launch', 'omp --model provider/model', 'omp --config user.yml'])(
'%s adds the final overlay',
(command) => {
expect(withFreshOmpLaunch(command, 'posix')).toBe(
`${command} --config "$ORCA_OMP_FRESH_CONFIG"`
)
}
)
it.each([
'omp --resume id',
'omp -r id',
'omp --continue',
'omp -c',
'omp --session-dir /custom',
'omp --no-session',
'omp --fork id',
'omp models',
'omp config',
'omp wt',
'omp --help',
'omp --unknown foo',
'omp --model',
'omp -- hello',
'echo omp',
'omp && echo hi'
])('preserves %s', (command) => {
expect(withFreshOmpLaunch(command, 'posix')).toBe(command)
})
it('quotes the host config path for each Windows shell', () => {
expect(withFreshOmpLaunch('omp', 'powershell')).toBe(
'omp --config "$env:ORCA_OMP_FRESH_CONFIG"'
)
expect(withFreshOmpLaunch('omp', 'cmd')).toBe('omp --config "%ORCA_OMP_FRESH_CONFIG%"')
})
it('keeps fresh intent out of saved resume command and environment', () => {
const plan = buildAgentStartupPlan({
agent: 'omp',
prompt: 'new task',
cmdOverrides: {},
platform: 'linux'
})
expect(plan?.launchCommand).toContain('--config "$ORCA_OMP_FRESH_CONFIG"')
expect(JSON.stringify(plan?.launchConfig)).not.toContain('ORCA_OMP_FRESH_CONFIG')
expect(plan?.env).toBeUndefined()
})
it('does not require a new environment field from an older SSH relay', () => {
const plan = buildAgentStartupPlan({
agent: 'omp',
prompt: 'new task',
cmdOverrides: {},
platform: 'linux',
isRemote: true
})
expect(plan?.launchCommand).not.toContain('ORCA_OMP_FRESH_CONFIG')
})
})
+55
View File
@@ -0,0 +1,55 @@
import { tokenizeStartupCommand, type AgentStartupShell } from './tui-agent-startup-shell'
export const ORCA_OMP_FRESH_CONFIG_ENV = 'ORCA_OMP_FRESH_CONFIG'
export const OMP_FRESH_CONFIG_FILENAME = 'fresh-session.yml'
export const OMP_FRESH_CONFIG_SOURCE = 'autoResume: false\n'
// Unknown flags may consume values or select a subcommand; leave those commands intact.
const VALUE_FLAGS = new Set([
'--model',
'--provider',
'--thinking',
'--config',
'--profile',
'--extension',
'-e',
'--system-prompt',
'--append-system-prompt',
'--tools',
'--skill',
'--theme',
'--api-key'
])
const SWITCH_FLAGS = new Set(['--no-extensions', '--no-skills', '--no-prompt-templates'])
/** Apply fresh intent to one launch command, never the saved resume configuration. */
export function withFreshOmpLaunch(command: string, shell: AgentStartupShell): string {
const parsed = tokenizeStartupCommand(command, shell)
if (!parsed.ok) {
return command
}
const executable = parsed.tokens[0]?.split(/[\\/]/).at(-1)?.toLowerCase()
if (!['omp', 'omp.exe', 'omp.cmd', 'omp.bat', 'omp.sh', 'omp.js'].includes(executable ?? '')) {
return command
}
let index = parsed.tokens[1] === 'launch' ? 2 : 1
for (; index < parsed.tokens.length; index++) {
const token = parsed.tokens[index]
const equals = token.indexOf('=')
const flag = equals === -1 ? token : token.slice(0, equals)
if (VALUE_FLAGS.has(flag)) {
if (equals === -1 && ++index >= parsed.tokens.length) {
return command
}
} else if (!SWITCH_FLAGS.has(token)) {
return command
}
}
const path =
shell === 'cmd'
? `"%${ORCA_OMP_FRESH_CONFIG_ENV}%"`
: shell === 'powershell'
? `"$env:${ORCA_OMP_FRESH_CONFIG_ENV}"`
: `"$${ORCA_OMP_FRESH_CONFIG_ENV}"`
return `${command} --config ${path}`
}
+1 -1
View File
@@ -667,7 +667,7 @@ describe('tui agent startup plans', () => {
expect(plan?.env).toEqual({ ORCA_OMP_PREFILL: 'fix the omp regression' })
expect(plan?.expectedProcess).toBe('omp')
expect(plan?.launchCommand).toBe(
`omp; command test -n "$fish_pid" && set --erase -g ORCA_OMP_PREFILL; command test -z "$fish_pid" && unset ORCA_OMP_PREFILL; true`
`omp --config "$ORCA_OMP_FRESH_CONFIG"; command test -n "$fish_pid" && set --erase -g ORCA_OMP_PREFILL; command test -z "$fish_pid" && unset ORCA_OMP_PREFILL; true`
)
})
+17 -8
View File
@@ -1,3 +1,4 @@
import { withFreshOmpLaunch } from './omp-fresh-launch'
import { isShellProcess } from './agent-detection'
import type { SleepingAgentLaunchConfig } from './agent-session-resume'
import {
@@ -70,6 +71,10 @@ export function buildAgentStartupPlan(args: {
if (!baseCommand.ok) {
return null
}
const launchCommand =
agent === 'omp' && !args.isRemote
? withFreshOmpLaunch(baseCommand.command, shell)
: baseCommand.command
const launchConfig = buildSleepingAgentLaunchConfig({
...args,
// Why: picker flags are a one-time launch choice; a resumed provider
@@ -83,7 +88,7 @@ export function buildAgentStartupPlan(args: {
}
return {
agent,
launchCommand: baseCommand.command,
launchCommand,
expectedProcess: config.expectedProcess,
followupPrompt: null,
launchConfig,
@@ -98,7 +103,7 @@ export function buildAgentStartupPlan(args: {
const promptSeparator = config.argvPromptSeparator ? ` ${config.argvPromptSeparator}` : ''
return {
agent,
launchCommand: `${baseCommand.command}${promptSeparator} ${quotedPrompt}`,
launchCommand: `${launchCommand}${promptSeparator} ${quotedPrompt}`,
expectedProcess: config.expectedProcess,
followupPrompt: null,
launchConfig,
@@ -111,7 +116,7 @@ export function buildAgentStartupPlan(args: {
if (config.promptInjectionMode === 'flag-prompt') {
return {
agent,
launchCommand: `${baseCommand.command} --prompt ${quotedPrompt}`,
launchCommand: `${launchCommand} --prompt ${quotedPrompt}`,
expectedProcess: config.expectedProcess,
followupPrompt: null,
launchConfig,
@@ -149,7 +154,7 @@ export function buildAgentStartupPlan(args: {
if (config.promptInjectionMode === 'flag-prompt-interactive') {
return {
agent,
launchCommand: `${baseCommand.command} --prompt-interactive ${quotedPrompt}`,
launchCommand: `${launchCommand} --prompt-interactive ${quotedPrompt}`,
expectedProcess: config.expectedProcess,
followupPrompt: null,
launchConfig,
@@ -161,7 +166,7 @@ export function buildAgentStartupPlan(args: {
if (config.promptInjectionMode === 'flag-interactive') {
return {
agent,
launchCommand: `${baseCommand.command} -i ${quotedPrompt}`,
launchCommand: `${launchCommand} -i ${quotedPrompt}`,
expectedProcess: config.expectedProcess,
followupPrompt: null,
launchConfig,
@@ -172,7 +177,7 @@ export function buildAgentStartupPlan(args: {
return {
agent,
launchCommand: baseCommand.command,
launchCommand,
expectedProcess: config.expectedProcess,
followupPrompt: trimmedPrompt,
launchConfig,
@@ -222,6 +227,10 @@ export function buildAgentDraftLaunchPlan(args: {
if (!baseCommand.ok) {
return null
}
const launchCommand =
agent === 'omp' && !args.isRemote
? withFreshOmpLaunch(baseCommand.command, shell)
: baseCommand.command
const launchConfig = buildSleepingAgentLaunchConfig({
...args,
// Why: see the new-session path above — resume must not replay picker flags.
@@ -232,7 +241,7 @@ export function buildAgentDraftLaunchPlan(args: {
const quoted = quoteStartupArg(trimmed, shell)
plan = {
agent,
launchCommand: `${baseCommand.command} ${config.draftPromptFlag} ${quoted}`,
launchCommand: `${launchCommand} ${config.draftPromptFlag} ${quoted}`,
expectedProcess: config.expectedProcess,
launchConfig,
...appliedSessionOptionProps(baseCommand.appliedSessionOptions),
@@ -244,7 +253,7 @@ export function buildAgentDraftLaunchPlan(args: {
const clearVar = clearEnvCommand(config.draftPromptEnvVar, shell)
plan = {
agent,
launchCommand: `${baseCommand.command}${commandSeparator(shell)}${clearVar}`,
launchCommand: `${launchCommand}${commandSeparator(shell)}${clearVar}`,
expectedProcess: config.expectedProcess,
launchConfig,
...appliedSessionOptionProps(baseCommand.appliedSessionOptions),
@@ -0,0 +1,75 @@
// Bun, with a read-only OMP source checkout as argv[2]. No model requests.
import assert from 'node:assert/strict'
import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { pathToFileURL } from 'node:url'
import { OMP_FRESH_CONFIG_SOURCE } from '../../src/shared/omp-fresh-launch.ts'
assert.ok(process.argv[2], 'Pass a read-only OMP checkout path')
const scratch = await mkdtemp(join(tmpdir(), 'orca-omp-fresh-proof-'))
process.env.HOME = join(scratch, 'home')
process.env.USERPROFILE = process.env.HOME
process.env.XDG_CONFIG_HOME = join(scratch, 'xdg-config')
process.env.XDG_DATA_HOME = join(scratch, 'xdg-data')
process.env.XDG_STATE_HOME = join(scratch, 'xdg-state')
process.env.OMP_CODING_AGENT_DIR = join(scratch, 'agent')
delete process.env.PI_CONFIG_FILES
const source = (path) =>
pathToFileURL(join(resolve(process.argv[2]), 'packages/coding-agent/src', path)).href
const managers = []
try {
await mkdir(process.env.HOME, { recursive: true })
const { SessionManager } = await import(source('session/session-manager.ts'))
const { Settings, resetSettingsForTest } = await import(source('config/settings.ts'))
const { createSessionManager } = await import(source('main.ts'))
const cwd = join(scratch, 'project')
await mkdir(cwd)
const previous = SessionManager.create(cwd)
managers.push(previous)
previous.appendMessage({ role: 'user', content: 'previous task', timestamp: Date.now() })
await previous.ensureOnDisk()
await previous.flush()
const config = join(scratch, 'fresh.yml')
const userConfig = join(scratch, 'user.yml')
await writeFile(config, OMP_FRESH_CONFIG_SOURCE)
await writeFile(userConfig, 'autoResume: true\n')
const settings = await Settings.init({ cwd, configFiles: [userConfig] })
const resumed = await createSessionManager({}, cwd, settings)
managers.push(resumed)
assert.equal(resumed.getSessionId(), previous.getSessionId())
resetSettingsForTest()
const freshSettings = await Settings.init({ cwd, configFiles: [userConfig, config] })
assert.equal(freshSettings.get('autoResume'), false)
assert.equal(settings.get('autoResume'), true)
const defaultSelection = await createSessionManager({}, cwd, freshSettings)
assert.equal(defaultSelection, undefined, 'SDK creates a fresh session after undefined selection')
const fresh = SessionManager.create(cwd)
managers.push(fresh)
assert.notEqual(fresh.getSessionId(), previous.getSessionId())
assert.equal(fresh.getSessionDir(), previous.getSessionDir())
const explicit = await createSessionManager(
{ resume: previous.getSessionFile() },
cwd,
freshSettings
)
managers.push(explicit)
assert.equal(explicit.getSessionId(), previous.getSessionId())
console.log(
JSON.stringify({
platform: process.platform,
autoResumeReproduced: true,
freshSelected: true,
storageDirectoryPreserved: true,
explicitResumePreserved: true,
modelCalls: 0,
scope:
'Actual OMP Settings overlays, persistent SessionManager and createSessionManager; no rendered UI'
})
)
} finally {
for (const manager of managers) {
await manager?.close()
}
await rm(scratch, { recursive: true, force: true })
}