framework
Version:
The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.
99 lines • 4.64 kB
TypeScript
import { type AgentCliParser, type SpawnLike } from './cli-session.js';
import type { Driver, DriverEvent, DriverPromptOptions, DriverSession, DriverStartOptions, DriverTurn, DriverUsage } from './types.js';
/**
* Codex's sandbox policy for the shell commands the model writes.
* `workspace-write` is our default: the agent can edit the workspace it was
* pointed at, but not the rest of the machine. It is the counterpart of Claude
* Code's `acceptEdits`, and the reason we never pass Codex's
* `--dangerously-bypass-approvals-and-sandbox`.
*/
export type CodexSandbox = 'read-only' | 'workspace-write' | 'danger-full-access';
/** Options for {@link CodexDriver}. */
export interface CodexDriverOptions {
/** CLI binary to spawn. Default `"codex"` (resolved on `PATH`). */
bin?: string;
/** Sandbox policy. Default `"workspace-write"`. */
sandbox?: CodexSandbox;
/** Extra CLI args appended verbatim (escape hatch). */
extraArgs?: string[];
/** Environment for the child process. Default `process.env`. */
env?: NodeJS.ProcessEnv;
/** `spawn` override for tests. Default `node:child_process.spawn`. */
spawn?: SpawnLike;
}
/**
* The second real {@link Driver} (#539): wraps the **Codex CLI** in its
* non-interactive mode (`codex exec --json`), on the user's own ChatGPT
* subscription — no API key (#495's "bring your own subscription").
*
* The seam always said "Claude Code today, Codex later", and this is that. Same
* black box: prompt it, let its own loop run, read the code it wrote.
*
* Three ways it differs from Claude Code, all of them the agent's business
* rather than ours:
*
* - **No system-prompt flag.** Codex has no `--append-system-prompt`, so the
* framing is prepended to the prompt instead. Same words reach the agent.
* - **Tokens, no price.** Codex reports token counts but never a price, so usage
* carries the counts and omits `costUsd` rather than claim a turn cost `$0`,
* which would read as free (#540). The budget cap (#322) gates on a price, so
* it cannot fire here; the CLI says so at startup instead of implying it.
* - **No quota read.** No `readQuota`, for the same reason: the seam is optional
* precisely so an agent that can't report one simply doesn't.
*/
export declare class CodexDriver implements Driver {
private readonly opts;
readonly id = "codex";
constructor(opts?: CodexDriverOptions);
start(opts: DriverStartOptions): Promise<DriverSession>;
}
/** One workspace-bound Codex session. `prompt` is a fresh CLI invocation. */
export declare class CodexSession implements DriverSession {
private readonly config;
private readonly startOpts;
readonly id: string;
readonly cwd: string;
constructor(config: CodexDriverOptions, startOpts: DriverStartOptions);
prompt(text: string, opts?: DriverPromptOptions): Promise<DriverTurn>;
readCode(path: string): Promise<string>;
dispose(): Promise<void>;
private buildArgs;
}
/**
* Parses Codex's `exec --json` output: one JSON event per line.
*
* The dialect, as observed on codex-cli 0.144.4:
* ```
* {"type":"thread.started","thread_id":"019f..."}
* {"type":"turn.started"}
* {"type":"item.completed","item":{"type":"agent_message","text":"..."}}
* {"type":"item.started","item":{"type":"file_change","status":"in_progress"}}
* {"type":"turn.completed","usage":{"input_tokens":12210,"output_tokens":5}}
* ```
*/
export declare class CodexJsonParser implements AgentCliParser {
private text;
private sessionId;
private usage;
push(line: string): DriverEvent[];
result(): DriverTurn;
}
/**
* Map Codex's `turn.completed` usage onto {@link DriverUsage}. The dialect is
* OpenAI's Responses API shape, flattened:
* `{input_tokens, cached_input_tokens, output_tokens, reasoning_output_tokens}`.
*
* Two things that shape the mapping, both verified against codex-cli 0.144.4:
*
* - `input_tokens` is the **total** input, cached included. Repeating one prompt
* held it at 12218 while `cached_input_tokens` rose 9984 -> 12032; a non-cached
* count would have fallen. So the uncached part is the difference, which is what
* `inputTokens` means here.
* - `reasoning_output_tokens` is a **subset** of `output_tokens` (as
* `cached_input_tokens` is of `input_tokens`), so adding it would double-count.
*
* No price, and no cache-*write* count: OpenAI caches implicitly and bills no
* separate write, so `cacheCreationTokens` is honestly 0 rather than a guess.
*/
export declare function parseCodexUsage(raw: unknown): DriverUsage | undefined;
//# sourceMappingURL=codex.d.ts.map