import { PAPERCLIP_RUNNER_DEFAULT_MODELS, } from "@paperclipai/adapter-utils"; export const type = "codex_local"; export const label = "Codex"; export const SANDBOX_INSTALL_COMMAND = "npm install -g @openai/codex"; // Use the concrete `gpt-5.6-sol` slug (Codex's own default for the 5.6 family) rather than the // bare `gpt-5.6` alias: OpenAI ships no model metadata for the bare slug, so passing it makes the // Codex CLI warn ("Model metadata for `gpt-5.6` not found") and fall back to generic context limits. export const DEFAULT_CODEX_LOCAL_MODEL = PAPERCLIP_RUNNER_DEFAULT_MODELS.codex; export const DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX = true; export const CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS = [ "gpt-6-astra", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.5", "gpt-5.4", ] as const; function normalizeModelId(model: string | null | undefined): string { return typeof model === "string" ? model.trim() : ""; } // Legacy model aliases with no OpenAI-published metadata are rewritten to the concrete slug the // Codex CLI actually knows. Without this, agents still configured with the bare `gpt-5.6` alias // (the old default) keep triggering "Model metadata for `gpt-5.6` not found" warnings and Codex // falls back to generic context-window limits, even on a Codex build that ships the 5.6 family. const CODEX_LOCAL_MODEL_ALIASES: Readonly> = { "gpt-5.6": "gpt-5.6-sol", }; const CODEX_LOCAL_DEFAULT_REASONING_EFFORTS = [ "minimal", "low", "medium", "high", "xhigh", ] as const; const CODEX_LOCAL_ASTRA_REASONING_EFFORTS = [ "low", "medium", "high", "xhigh", "max", "ultra", ] as const; export type CodexLocalReasoningEffort = | (typeof CODEX_LOCAL_DEFAULT_REASONING_EFFORTS)[number] | (typeof CODEX_LOCAL_ASTRA_REASONING_EFFORTS)[number]; export function normalizeCodexModel(model: string | null | undefined): string { const normalizedModel = normalizeModelId(model); return CODEX_LOCAL_MODEL_ALIASES[normalizedModel] ?? normalizedModel; } export function codexLocalReasoningEffortsForModel( model: string | null | undefined, ): readonly CodexLocalReasoningEffort[] { return normalizeCodexModel(model) === "gpt-6-astra" ? CODEX_LOCAL_ASTRA_REASONING_EFFORTS : CODEX_LOCAL_DEFAULT_REASONING_EFFORTS; } export function isCodexLocalKnownModel(model: string | null | undefined): boolean { const normalizedModel = normalizeModelId(model); if (!normalizedModel) return false; return models.some((entry) => entry.id === normalizedModel); } export function isCodexLocalManualModel(model: string | null | undefined): boolean { const normalizedModel = normalizeModelId(model); return Boolean(normalizedModel) && !isCodexLocalKnownModel(normalizedModel); } export function isCodexLocalFastModeSupported(model: string | null | undefined): boolean { if (isCodexLocalManualModel(model)) return true; const normalizedModel = typeof model === "string" ? model.trim() : ""; // Empty means we're omitting --model so the Codex CLI picks its own default. // Manual model IDs are also treated as supported: pass the fast-mode overrides // through and let the CLI reject them if the chosen model can't use them. if (!normalizedModel) return true; return CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS.includes( normalizedModel as (typeof CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS)[number], ); } export const models = [ // DEFAULT_CODEX_LOCAL_MODEL is gpt-5.6-sol, so it doubles as the first (default) 5.6 entry. { id: DEFAULT_CODEX_LOCAL_MODEL, label: DEFAULT_CODEX_LOCAL_MODEL }, { id: "gpt-6-astra", label: "gpt-6-astra" }, { id: "gpt-5.6-terra", label: "gpt-5.6-terra" }, { id: "gpt-5.6-luna", label: "gpt-5.6-luna" }, { id: "gpt-5.4", label: "gpt-5.4" }, { id: "gpt-5.4-mini", label: "gpt-5.4-mini" }, { id: "gpt-5", label: "gpt-5" }, { id: "o3", label: "o3" }, { id: "o4-mini", label: "o4-mini" }, { id: "gpt-5-mini", label: "gpt-5-mini" }, { id: "gpt-5-nano", label: "gpt-5-nano" }, { id: "o3-mini", label: "o3-mini" }, { id: "codex-mini-latest", label: "Codex Mini" }, ]; export const agentConfigurationDoc = `# codex_local agent configuration Adapter: codex_local Core fields: - engine (string, optional): defaults to ACP, including legacy unset/"auto" values. Missing prerequisites and execution failures fail the run without changing engines. Set "cli" to explicitly select the CLI engine. - cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible) - instructionsFilePath (string, optional): absolute path to a markdown instructions file prepended to stdin prompt at runtime - model (string, optional): Codex model id - modelReasoningEffort (string, optional): reasoning effort override passed via -c model_reasoning_effort=...; GPT-6 Astra supports low|medium|high|xhigh|max|ultra - promptTemplate (string, optional): run prompt template - search (boolean, optional): run codex with --search - fastMode (boolean, optional): enable Codex Fast mode; supported on GPT-6 Astra, GPT-5.6 (sol/terra/luna), GPT-5.5, GPT-5.4 and passed through for manual model IDs - dangerouslyBypassApprovalsAndSandbox (boolean, optional): run with bypass flag - command (string, optional): defaults to "codex" - extraArgs (string[], optional): additional CLI args - env (object, optional): KEY=VALUE environment variables - workspaceStrategy (object, optional): execution workspace strategy; currently supports { type: "git_worktree", baseRef?, branchTemplate?, worktreeParentDir? } - workspaceRuntime (object, optional): reserved for workspace runtime metadata; workspace runtime services are manually controlled from the workspace UI and are not auto-started by heartbeats - filesystemScope (string, optional): set to "workspace" to confine local CLI filesystem access with Bubblewrap. Off by default. The workspace and managed CODEX_HOME remain writable; other host paths are hidden. - filesystemExtraPaths (array, optional): additional absolute host paths exposed inside the workspace sandbox. String entries are read-only; object entries use { path: "/absolute/path", access: "ro" | "rw" }. - filesystemSandboxCommand (string, optional): Bubblewrap executable name or absolute path; defaults to "bwrap". Linux only. - networkScope (string, optional): "deny" blocks all network egress; "allowlist" permits only networkAllowlist targets through Paperclip's HTTP(S) proxy. Off by default. - networkAllowlist (string[], optional): exact hostnames, hostname:port entries, or origin URLs. Include the configured Codex provider origin, such as "api.openai.com" or a custom model provider gateway. Operational fields: - timeoutSec (number, optional): run timeout in seconds - graceSec (number, optional): SIGTERM grace period in seconds - outputInactivityTimeoutMs (number | null, optional): inactivity monitor around the codex child. Resets whenever the child emits stdout/stderr bytes or, on Linux, its process group shows meaningful CPU, disk I/O, or child-process churn during a silent build. Defaults to 30 * 60_000 ms when unset or non-positive. Set to \`null\` to disable the monitor entirely (only do this for known-slow tasks; the platform-level 1h silent-run safety net still applies). On fire, the adapter sends SIGTERM to the process group, waits 5s, then SIGKILL, and surfaces the run as failed with errorMessage "monitor: no codex activity (output or process) for {N}m {S}s". - agentCommand (string, optional): ACP server command override used only when engine="acp"; defaults to the package-local codex-acp binary - mode (string, optional): ACP session mode when engine="acp"; persistent or oneshot - nonInteractivePermissions (string, optional): ACP non-interactive permission fallback when engine="acp"; deny or fail - stateDir (string, optional): ACP state directory override when engine="acp" - warmHandleIdleMs (number, optional): warm ACP process idle timeout when engine="acp"; defaults to 0 Notes: - filesystemScope and networkScope are spawn-level confinement and are orthogonal to Codex approval/sandbox flags. Both require Bubblewrap on the host and explicit engine="cli"; default or explicit ACP is rejected because ACP confinement is not yet supported. networkScope="allowlist" injects HTTP_PROXY/HTTPS_PROXY for the CLI while its private network namespace blocks direct sockets, so every required provider/API hostname must be listed explicitly. - Prompts are piped via stdin (Codex receives "-" prompt argument). - If instructionsFilePath is configured, Paperclip prepends that file's contents to the stdin prompt on every run. - Codex exec automatically applies repo-scoped AGENTS.md instructions from the active workspace. Paperclip cannot suppress that discovery in exec mode, so repo AGENTS.md files may still apply even when you only configured an explicit instructionsFilePath. - Paperclip injects desired local skills into the effective CODEX_HOME/skills/ directory at execution time so Codex can discover "$paperclip" and related skills without polluting the project working directory. For new and updated agents, Paperclip assigns an isolated managed home at ~/.paperclip/instances//companies//agents//codex-home/skills/; when CODEX_HOME is explicitly overridden in adapter config, that override is used instead. - New and updated codex_local agents persist an empty OPENAI_API_KEY override by default so a host-level OPENAI_API_KEY cannot leak into Codex runs through process inheritance. Explicit CODEX_HOME overrides must not point at the shared company codex-home, $CODEX_HOME, or ~/.codex. - Some model/tool combinations reject certain effort levels (for example minimal with web search enabled). - Fast mode is supported on GPT-6 Astra, GPT-5.6 (sol/terra/luna), GPT-5.5, GPT-5.4 and manual model IDs. When enabled for those models, Paperclip applies \`service_tier="fast"\` and \`features.fast_mode=true\`. - When Paperclip realizes a workspace/runtime for a run, it injects PAPERCLIP_WORKSPACE_* and PAPERCLIP_RUNTIME_* env vars for agent-side tooling. - The ACP engine keeps its workspace sandbox and enables network access on each turn. Explicit sandbox_workspace_write.network_access overrides in extraArgs (or env.PAPERCLIP_CODEX_ACP_NETWORK_ACCESS="false") disable it; execution-target network denial wins. The bundled ACP patch is needed because upstream mode presets override Codex config.toml on every turn. - The CLI engine defaults to a writable workspace sandbox with network access for unattended work and Paperclip API calls. It does not enable the dangerous bypass flag. Explicit sandbox modes/profiles and network overrides in extraArgs retain their meaning. An execution-target network denial remains enforced. - Codex ACP is the preferred auto lane when Node >=24.11.0 and the Codex ACP server are available. It reuses shared ACP prompt/runtime guidance, selected skill materialization into CODEX_HOME/skills, model/reasoning/fast-mode session config, and existing quota-window reporting. Missing ACP prerequisites fail both default and explicit ACP runs with an actionable setup error; the adapter never switches engines automatically. `;