diff --git a/packages/sdk/src/adapters/codex.ts b/packages/sdk/src/adapters/codex.ts index 3b1beb3f8..f709174e6 100644 --- a/packages/sdk/src/adapters/codex.ts +++ b/packages/sdk/src/adapters/codex.ts @@ -38,7 +38,12 @@ export const codexAdapter: HeadlessAdapter = { buildAgentInvocation(instruction: string, model?: string): CliInvocation { return { args: [ - 'exec', '--ephemeral', '--skip-git-repo-check', + // Real steps must retain Codex's native session under CODEX_HOME (or + // ~/.codex). Hosted Relayflow teardown captures that provider history + // and uploads it to Relayhistory; --ephemeral silently leaves nothing + // for the bounded flush to capture. Readiness probes above stay + // ephemeral because they are diagnostics, not workflow steps. + 'exec', '--skip-git-repo-check', // Agent-mode is where the flow explicitly delegates code changes to // the CLI. Without this flag codex prompts for approval on every // write, gets nothing (no TTY), and completes "successfully" without @@ -54,7 +59,7 @@ export const codexAdapter: HeadlessAdapter = { buildLlmInvocation(prompt: string, model?: string): CliInvocation { return { - args: ['exec', '--ephemeral', '--sandbox', 'read-only', '--skip-git-repo-check', + args: ['exec', '--sandbox', 'read-only', '--skip-git-repo-check', ...(model === undefined ? [] : ['--model', model]), prompt], timeoutMs: 0, }; diff --git a/packages/sdk/tests/adapters/codex.test.ts b/packages/sdk/tests/adapters/codex.test.ts index 7299a92a9..4bce9e074 100644 --- a/packages/sdk/tests/adapters/codex.test.ts +++ b/packages/sdk/tests/adapters/codex.test.ts @@ -27,10 +27,10 @@ describe('codexAdapter — HeadlessAdapter contract', () => { expect(inv.args).toContain('gpt-6-astra'); }); - it('buildAgentInvocation uses exec --ephemeral --skip-git-repo-check with instruction at the tail', () => { + it('buildAgentInvocation persists provider history and keeps the instruction at the tail', () => { const inv = codexAdapter.buildAgentInvocation('build the thing', 'gpt-6-astra'); expect(inv.args[0]).toBe('exec'); - expect(inv.args).toContain('--ephemeral'); + expect(inv.args).not.toContain('--ephemeral'); expect(inv.args).toContain('--skip-git-repo-check'); expect(inv.args).toContain('--model'); expect(inv.args).toContain('gpt-6-astra'); @@ -44,8 +44,9 @@ describe('codexAdapter — HeadlessAdapter contract', () => { expect(inv.args).not.toContain('--sandbox'); }); - it('buildLlmInvocation adds --sandbox read-only', () => { + it('buildLlmInvocation persists provider history in its read-only sandbox', () => { const inv = codexAdapter.buildLlmInvocation('summarize'); + expect(inv.args).not.toContain('--ephemeral'); expect(inv.args).toContain('--sandbox'); expect(inv.args).toContain('read-only'); }); diff --git a/packages/sdk/tests/cli-adapter.test.ts b/packages/sdk/tests/cli-adapter.test.ts index 0fd07ac73..ef4348463 100644 --- a/packages/sdk/tests/cli-adapter.test.ts +++ b/packages/sdk/tests/cli-adapter.test.ts @@ -55,7 +55,7 @@ describe('typed CLI adapters', () => { timeoutMs: 60_000, }); expect(agentExecution(kind, 'Review.', 'gpt-model')).toEqual({ - args: ['exec', '--ephemeral', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', + args: ['exec', '--skip-git-repo-check', '--dangerously-bypass-approvals-and-sandbox', '--model', 'gpt-model', 'Review.'], timeoutMs: 0, }); diff --git a/packages/sdk/tests/live-kernel.test.ts b/packages/sdk/tests/live-kernel.test.ts index 6f5865e45..a51786f17 100644 --- a/packages/sdk/tests/live-kernel.test.ts +++ b/packages/sdk/tests/live-kernel.test.ts @@ -1106,7 +1106,7 @@ process.stdout.write('{"must_not":"execute"}'); it.each([ ['claude', '-p --dangerously-skip-permissions --model declared-model-xyz'], - ['codex', 'exec --ephemeral --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox --model declared-model-xyz'], + ['codex', 'exec --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox --model declared-model-xyz'], ] as const)('AgentWorker executes the raw %s adapter with its real model flag', async (name, prefix) => { const dataDir = temporaryDirectory(`flows-live-${name}-adapter-`); await startDaemon(dataDir);