import { fail } from "./fail"; import { EnvContext } from "./env-context"; import { tmpdir } from "os"; import { join } from "node:path"; import { readFile, mkdtemp } from "fs/promises"; import { resolveWorkspacePath } from "./github-workspace"; /** * Runs the Codex CLI with the provided prompt and returns the output written * to the "last message" file. */ export async function runCodex( prompt: string, ctx: EnvContext, ): Promise { const OPENAI_API_KEY = ctx.get("OPENAI_API_KEY"); const tempDirPath = await mkdtemp(join(tmpdir(), "codex-")); const lastMessageOutput = join(tempDirPath, "codex-prompt.md"); const args = ["/usr/local/bin/codex-exec"]; const inputCodexArgs = ctx.tryGet("INPUT_CODEX_ARGS")?.trim(); if (inputCodexArgs) { args.push(...inputCodexArgs.split(/\s+/)); } args.push("--output-last-message", lastMessageOutput, prompt); const env: Record = { ...process.env, OPENAI_API_KEY }; const INPUT_CODEX_HOME = ctx.tryGet("INPUT_CODEX_HOME"); if (INPUT_CODEX_HOME) { env.CODEX_HOME = resolveWorkspacePath(INPUT_CODEX_HOME, ctx); } console.log(`Running Codex: ${JSON.stringify(args)}`); const result = Bun.spawnSync(args, { stdout: "inherit", stderr: "inherit", env, }); if (!result.success) { fail(`Codex failed: see above for details.`); } // Read the output generated by Codex. let lastMessage: string; try { lastMessage = await readFile(lastMessageOutput, "utf8"); } catch (err) { fail(`Failed to read Codex output at '${lastMessageOutput}': ${err}`); } return lastMessage; }