/** * Codex transcript tailer — Codex has no hook system, so this file *is* its * entire analytics eventSource (see HarnessAdapter.eventSource === * "transcript-tail" on CodexAdapter). It incrementally reads a rollout JSONL * file as Codex appends to it and translates each entry into the same * `{hookEvent, payload}` shape Claude Code's hooks would have produced for * equivalent activity — so the existing ingest pipeline * (core/collector/normalizer.ts's `normalizeHookEvent`) can consume both * harnesses unchanged, with zero Codex-specific branching in the normalizer. * * Self-contained by design: no imports from server/, session-manager.ts, or * the rest of core/collector/ (only types, imported for shape-compatibility * with the normalizer this feeds). Not wired into the server — see the * "Wiring this in" section of the PR description for the integration * contract (what to call, and when). */ import type { ClaudeHookEvent, RawHookPayload } from "./normalizer.js"; export type CodexEventListener = (hookEvent: ClaudeHookEvent, payload: RawHookPayload) => void; export interface CodexTailerOptions { /** Path to the rollout JSONL file. It's fine if this doesn't exist yet — * the tailer polls until Codex creates it (there's an unavoidable race * between spawning `codex` and it creating its rollout file). */ rolloutPath: string; onEvent: CodexEventListener; onError?: (err: unknown) => void; pollIntervalMs?: number; /** * Tail from byte 0 regardless of the file's current size — for a fresh * launch, where the caller discovered this rollout file *because* it * already contains the session_meta line the caller cares about (a * find-then-tail race: by the time a poll-based discovery step returns a * path, Codex has necessarily already written to it). Without this, the * default "start from current size" baseline (correct for a genuine * resume, where prior content really is history to skip) would silently * swallow that already-written SessionStart. Defaults to false (resume * semantics: skip whatever's already there, only emit new activity). */ startFromBeginning?: boolean; } export interface CodexTailerHandle { /** Stop polling without emitting anything further. */ stop(): void; /** * Synthesize a SessionEnd hook-shaped event and stop polling. Codex's * rollout format has no "session ended" line of its own — call this when * the harness detects the underlying pty has exited. */ emitSessionEnd(reason?: string): void; } /** * Incrementally tail a Codex rollout file, translating each new line into a * Claude-hook-shaped `(hookEvent, payload)` pair via `onEvent`. Only emits * for content appended *after* the tailer starts (matching hook semantics — * hooks only fire for new activity, never backfill); use * `CodexAdapter.listPastSessions` for history. */ export declare function tailCodexRollout(options: CodexTailerOptions): CodexTailerHandle; export interface FindRolloutFileOptions { /** Match a rollout file whose session_meta.cwd equals this exactly. */ cwd: string; /** Only consider sessions created at/after this time (ms epoch) — * disambiguates a freshly-launched session from older ones sharing a cwd. * Ignored when `agentSessionId` is given (an exact id match is a strictly * stronger signal than a time-window heuristic). */ sinceMs?: number; /** * Match a rollout file by its exact session_meta.id (the rollout/agent * session id) instead of by recency — needed when resuming a session, * where `sinceMs` can't disambiguate it from other sessions sharing the * same cwd that happen to have been touched more recently. */ agentSessionId?: string; /** Overridable for tests. */ homeDir?: string; /** Exact paths already owned by another live Harness runtime. */ excludePaths?: ReadonlySet; /** Exact first-turn marker required for a coordinator-owned fresh runtime. */ requiredRuntimeMarker?: string; /** Ordinary runtimes must wait for an unmarked user turn before claiming. */ excludeRuntimeMarkers?: boolean; } export interface CodexRolloutCandidate { path: string; agentSessionId: string | null; timestampMs: number | null; mtimeMs: number; } /** * Finds a rollout file matching `cwd`. With `agentSessionId`, matches that * exact session (for resume — cwd alone is ambiguous when multiple sessions * share a directory). Otherwise returns the most-recently-modified match, * optionally bounded by `sinceMs`. Intended to be polled by the integrator * right after spawning a fresh `codex` process — there's no way to know the * exact rollout path in advance (it's a timestamp+UUID Codex generates itself). */ export declare function findRolloutFile(options: FindRolloutFileOptions): Promise; /** Returns every compatible rollout in deterministic chronological order. */ export declare function findRolloutCandidates(options: FindRolloutFileOptions): Promise; //# sourceMappingURL=codex-tailer.d.ts.map