import { execFile } from 'node:child_process' import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync, } from 'node:fs' import { rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { delimiter, join, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { promisify } from 'node:util' import { Context } from '@deepseek-ai/cordis' import { afterEach, describe, expect, it, vi } from 'vitest' import type { Agent } from '@deepseek-ai/dsh-agent' import SubagentRuntime from '@deepseek-ai/dsh-subagent' import type { SubprocessHandle } from '@deepseek-ai/dsh-subprocess' import LocalSubprocessRuntime from '@deepseek-ai/dsh-subprocess-local' import * as codex from '../src/index.ts' import { startResponsesFixture, type ResponsesBehavior, type ResponsesFixture, } from './responses-fixture.ts' const execFileAsync = promisify(execFile) const packageRoot = resolve(fileURLToPath(new URL('..', import.meta.url))) const codexBinDir = join(packageRoot, 'node_modules', '.bin') const codexEntry = join(packageRoot, 'node_modules', '@openai', 'codex', 'bin', 'codex.js') const codexPackage = JSON.parse(readFileSync( join(packageRoot, 'node_modules', '@openai', 'codex', 'package.json'), 'utf8', )) as { version: string } const roots: string[] = [] const fixtures: ResponsesFixture[] = [] const contexts: Context[] = [] afterEach(async () => { await Promise.all(contexts.splice(0).map(ctx => ctx.fiber.dispose())) await Promise.all(fixtures.splice(0).map(fixture => fixture.close())) for (const root of roots.splice(0)) { await rm(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }) } }) interface RealHarness { readonly ctx: Context readonly handles: SubprocessHandle[] readonly parent: Agent readonly env: Record readonly workspace: string } async function realHarness(script: readonly ResponsesBehavior[]): Promise<{ readonly harness: RealHarness readonly fixture: ResponsesFixture }> { const root = mkdtempSync(join(tmpdir(), 'dsh-codex-real-')) roots.push(root) const workspace = join(root, 'workspace') const codexHome = join(root, 'codex-home') const fixture = await startResponsesFixture(script) fixtures.push(fixture) mkdirSync(workspace) mkdirSync(codexHome) writeFileSync(join(codexHome, 'config.toml'), [ 'model = "fixture-model"', 'model_provider = "fixture"', 'approval_policy = "on-request"', 'sandbox_mode = "read-only"', 'disable_response_storage = true', 'check_for_update_on_startup = false', '', '[model_providers.fixture]', 'name = "Fixture Responses"', `base_url = "${fixture.baseUrl}"`, 'env_key = "OPENAI_API_KEY"', 'wire_api = "responses"', 'requires_openai_auth = false', '', '[analytics]', 'enabled = false', '', ].join('\n')) const env = { OPENAI_API_KEY: 'dsh-fake-openai-key', CODEX_HOME: codexHome, HOME: root, XDG_CONFIG_HOME: join(root, 'xdg'), PATH: `${codexBinDir}${delimiter}${process.env.PATH ?? ''}`, HTTP_PROXY: '', HTTPS_PROXY: '', ALL_PROXY: '', NO_PROXY: '127.0.0.1,localhost', } const ctx = new Context() contexts.push(ctx) await ctx.plugin(SubagentRuntime) await ctx.plugin(LocalSubprocessRuntime) const handles: SubprocessHandle[] = [] const spawn = ctx.subprocess.spawn.bind(ctx.subprocess) vi.spyOn(ctx.subprocess, 'spawn').mockImplementation((spec) => { const handle = spawn(spec) handles.push(handle) return handle }) await ctx.plugin(codex, { env, disposeGraceMs: 2_000 }) const parent = { id: 'real-parent', session: { header: { cwd: workspace } }, } as unknown as Agent return { harness: { ctx, handles, parent, env, workspace }, fixture } } async function expectQuiescent(handles: readonly SubprocessHandle[]): Promise { expect(handles.length).toBeGreaterThan(0) for (const handle of handles) { await expect(handle.waitForExit()).resolves.toBe(true) const outcome = await handle.done expect(outcome).toHaveProperty('exitCode') expect(outcome).toHaveProperty('signal') } } function responseInputTexts(body: Record): string[] { if (!Array.isArray(body.input)) return [] return body.input.flatMap((item): string[] => { if (item === null || typeof item !== 'object') return [] const content = (item as Record).content if (!Array.isArray(content)) return [] return content.flatMap((part): string[] => ( part !== null && typeof part === 'object' && typeof (part as Record).text === 'string' ? [(part as Record).text as string] : [] )) }) } describe('real @openai/codex 0.147.0 product', () => { it('passes the exact task and fake authentication to local Responses and returns exact text', async () => { const sentinel = 'REAL_CODEX_SENTINEL_0_147_0' const task = 'Return the fixture sentinel exactly.' const { harness, fixture } = await realHarness([ { kind: 'complete', text: sentinel }, ]) expect(codexPackage.version).toBe('0.147.0') const version = await execFileAsync(process.execPath, [codexEntry, '--version'], { env: { ...process.env, ...harness.env }, }) expect(version.stdout.trim()).toBe('codex-cli 0.147.0') const run = await harness.ctx.subagents.start('codex', { prompt: [{ type: 'text', text: task }], parent: harness.parent, signal: new AbortController().signal, }) await expect(run.result).resolves.toEqual({ output: [{ type: 'text', text: sentinel }], stopReason: 'completed', }) await run.dispose() expect(fixture.requests).toHaveLength(1) const recorded = fixture.requests[0]! expect(recorded.method).toBe('POST') expect(recorded.path).toBe('/v1/responses') expect(recorded.headers.authorization).toBe('Bearer dsh-fake-openai-key') expect(responseInputTexts(recorded.body)).toContain(task) await expectQuiescent(harness.handles) }, 60_000) it('cancels a real app-server command approval without executing the command', async () => { const command = process.platform === 'win32' ? 'cmd /c type nul > approval-side-effect' : 'touch approval-side-effect' const commandCalls = [ { name: 'exec_command', arguments: { cmd: command, sandbox_permissions: 'require_escalated', justification: 'exercise the unattended approval boundary', }, }, { name: 'shell_command', arguments: { command, sandbox_permissions: 'require_escalated', justification: 'exercise the unattended approval boundary', }, }, ] as const const { harness, fixture } = await realHarness([ { kind: 'advertisedFunctionCall', choices: commandCalls, }, ]) const sideEffect = join(harness.workspace, 'approval-side-effect') const run = await harness.ctx.subagents.start('codex', { prompt: [{ type: 'text', text: 'Attempt the fixture command.' }], parent: harness.parent, signal: new AbortController().signal, }) await expect(run.result).resolves.toEqual({ output: [], stopReason: 'error', }) await run.dispose() expect(existsSync(sideEffect)).toBe(false) expect(fixture.requests).toHaveLength(1) const tools = fixture.requests[0]!.body.tools as Array> expect(commandCalls.some(call => tools.some(tool => ( tool.type === 'function' && tool.name === call.name )))).toBe(true) expect(fixture.requests.every(requestEntry => requestEntry.headers.authorization === 'Bearer dsh-fake-openai-key', )).toBe(true) await expectQuiescent(harness.handles) }, 60_000) it('settles cancellation locally and leaves the real app-server tree quiescent', async () => { const { harness, fixture } = await realHarness([{ kind: 'hold' }]) const controller = new AbortController() const run = await harness.ctx.subagents.start('codex', { prompt: [{ type: 'text', text: 'Wait for cancellation.' }], parent: harness.parent, signal: controller.signal, }) await fixture.requestStarted controller.abort(new Error('real product cancellation')) await expect(run.result).resolves.toMatchObject({ stopReason: 'aborted' }) await run.dispose() await expectQuiescent(harness.handles) }, 60_000) })