import type { InterruptibleEngine, EngineRunOpts, EngineResult, ResolvedMcpConfig } from "../shared/types.js"; import { type ModelUsage } from "../shared/model-pricing.js"; export interface CodexEngineOpts { codexSessionsDir?: string; /** Base dir for per-session CODEX_HOME overlays. Defaults to CODEX_HOMES_DIR; * overridable so tests never write under the real ~/.jinn. */ codexHomesBaseDir?: string; } export declare function codexCliFlags(flags: string[] | undefined): string[]; export declare function codexMcpConfigArgs(resolvedMcp: ResolvedMcpConfig | undefined, opts?: { skipJinn?: boolean; }): string[]; /** * A per-session Codex `CODEX_HOME` overlay. Codex 0.141 dropped the legacy * `profile` config key, so `codex exec resume` cannot layer a `--profile` file — * the old profile mechanism lost the jinn MCP server after the first resume. The * fix unifies fresh + resume onto ONE mechanism: both point `CODEX_HOME` at this * stable per-session dir, whose auto-loaded `config.toml` carries the builtin-jinn * stanza (capability in the 0600 file, NEVER on argv). Because the codex thread * rollout lives under `CODEX_HOME`, fresh and every resume of the same jinn * session MUST share this dir — that's a correctness requirement, not cosmetics. */ export interface CodexSessionHome { /** Absolute path to point `CODEX_HOME` at for this session's turns. */ home: string; /** Remove the whole per-session dir. Call on SESSION end, never per-turn. */ cleanup: () => void; } /** The operator's real codex home — source of `auth.json` + base `config.toml`. */ export declare function realCodexHome(codexHomesBaseDir?: string): string; export declare function codexSessionHomeDir(sessionId: string, baseDir?: string): string; /** * Ensure the per-session CODEX_HOME overlay exists and its `config.toml` carries * the builtin-jinn MCP stanza. Idempotent across turns; the `config.toml` is * REWRITTEN each turn so a rotated capability takes effect. Returns `undefined` * (→ default ~/.codex home, jinn MCP via argv) when there is no builtin-jinn * server carrying a capability token — third-party / no-capability behaviour is * unchanged. */ export declare function prepareCodexSessionHome(resolvedMcp: ResolvedMcpConfig | undefined, sessionId: string, opts?: { baseDir?: string; }): CodexSessionHome | undefined; /** * Remove a session's CODEX_HOME overlay. Idempotent and safe on non-codex / * already-removed sessions — call it from the session-teardown path (not per * turn: the dir must persist across a session's turns so resume finds the thread). */ export declare function removeCodexSessionHome(sessionId: string, baseDir?: string): void; /** * Retention sweep for per-session CODEX_HOME overlays. Homes are removed on * session teardown, but a session whose record is gone (crash, hard delete, * pre-fix accumulation) leaves its overlay behind forever — that leak grew to * 276 dirs / 2.4GB. * * Age decides, not the session row: `config.toml` is rewritten on every turn, so * its mtime is an exact last-activity stamp needing no DB read, and a thread that * has not taken a turn in `maxAgeDays` is not worth resuming. `knownSessionIds` * only breaks the tie for an overlay with no stamp at all (a crash between the * mkdir and the first write) — pass EVERY session id, archived and * workflow-phase included, since those resume too. Never touches the shared * caches (dot-entries / SHARED_CODEX_HOME_DIRS / SHARED_CODEX_HOME_FILES live * alongside overlays), at any age. Returns the number of overlays removed. */ export declare function sweepOrphanCodexSessionHomes(knownSessionIds: Iterable, baseDir?: string, maxAgeDays?: number): number; /** * Run the overlay sweep now and every 24h thereafter. Session rows outlive their * overlays' usefulness and nothing else reaps them, so a boot-only sweep leaves a * long-running gateway accumulating dead homes indefinitely. `listSessionIds` is * re-read on every run so sessions created since the last one are honoured. * Returns the interval timer (already `unref`'d — this must never hold the * process open) so a caller can stop it. */ export declare function startCodexSessionHomeSweeps(opts: { listSessionIds: () => Iterable; baseDir?: string; maxAgeDays?: number; intervalMs?: number; }): NodeJS.Timeout; /** * Build `codex exec` argv for a FRESH turn. When `homeActive` is true the builtin * jinn server rides the per-session CODEX_HOME config.toml, so it is skipped from * the argv `-c` overrides (its capability must never touch argv). No `--profile`: * codex 0.141 dropped it, and fresh/resume are unified on the CODEX_HOME overlay. * * The prompt is user text, so it goes behind `--`. Without the separator codex's * parser reads a leading dash as a flag and exits 2 (`unexpected argument '- '`), * and a prompt of "resume" or "review" would dispatch a subcommand instead. */ export declare function buildCodexFreshArgs(opts: EngineRunOpts, prompt: string, homeActive: boolean): string[]; /** * Build `codex exec resume` argv. `codex exec resume` accepts neither `--profile` * nor `-C`; the per-session CODEX_HOME (shared with the fresh turn) carries the * jinn MCP config and locates the thread rollout. Both positionals sit behind `--` * for the same reason the fresh turn's prompt does. */ export declare function buildCodexResumeArgs(opts: EngineRunOpts, prompt: string, homeActive: boolean): string[]; /** * The child-process env for a codex spawn: strip inherited CLAUDE_ and CODEX_ * env (a clean baseline — see GRS-018), then set JINN_SESSION_ID and, when a per-session * overlay is active, point CODEX_HOME at it. CODEX_HOME is set AFTER the strip so * it survives. */ export declare function codexChildEnv(baseEnv: NodeJS.ProcessEnv, sessionId?: string, codexHome?: string): Record; /** * Most-recent-turn input-context size from a codex per-turn usage object. * codex's `cached_input_tokens` is a SUBSET of `input_tokens` (OpenAI semantics), * so the window fill is `input_tokens` alone — summing would double-count. * Best-effort: returns undefined on any shape mismatch. */ export declare function extractCodexContextTokens(usage: unknown): number | undefined; export interface CodexTokenUsage { inputTokens: number; cachedInputTokens: number; outputTokens: number; } export declare function extractCodexTokenUsage(usage: unknown): CodexTokenUsage | undefined; export declare function codexUsageDelta(start: CodexTokenUsage, end: CodexTokenUsage): ModelUsage; export declare function lastCodexTranscriptContextTokens(sessionId: string, root?: string): number | undefined; export declare class CodexEngine implements InterruptibleEngine { private readonly opts; name: "codex"; private liveProcesses; private totalUsage; constructor(opts?: CodexEngineOpts); kill(sessionId: string, reason?: string): void; killAll(): void; /** Batch engine: no warm-PTY reuse, every live process is an in-flight turn. * Nothing idle to recycle on org-reload — no-op. */ killIdle(): void; isAlive(sessionId: string): boolean; run(opts: EngineRunOpts): Promise; private buildFreshArgs; private buildResumeArgs; private processJsonlLine; private buildCleanEnv; private signalProcess; } //# sourceMappingURL=codex.d.ts.map