@codexview/adapters
v0.7.0
Published
Stateless adapters that convert AI coding agent transcript logs (Codex exec JSONL, Codex rollouts, AgentWeb codex-team status, Claude Code, OpenCode, GitHub Copilot, and live transcripts) into the CodexView ChatStreamEvent schema. Zero runtime dependencie
Maintainers
Readme
@codexview/adapters
Stateless adapters that convert AI coding agent transcript logs into the @codexview/react ChatStreamEvent schema.
Zero runtime dependencies, ESM only, Node ≥ 20.
Install
pnpm add @codexview/adaptersUse
Auto-detect (umbrella entry)
import { readFileSync } from 'node:fs';
import { adapt, parseJsonl } from '@codexview/adapters';
const lines = parseJsonl(readFileSync('rollout-xyz.jsonl', 'utf8'));
const { format, events } = adapt(lines);
// format: 'codex-exec' | 'rollout' | 'codex-team' | 'claude-code'
// | 'opencode' | 'github-copilot' | 'unknown'Per-source (tree-shakeable)
import { adaptClaudeCode } from '@codexview/adapters/claude-code';
import { adaptCodexExec } from '@codexview/adapters/codex-exec';
import { adaptRollout } from '@codexview/adapters/rollout';
import { adaptCodexTeam } from '@codexview/adapters/codex-team';
const events = adaptClaudeCode(lines);Supported formats
| Format | Detection | Typical file location |
|---------------|------------------------------------------------|--------------------------------------------------------------------|
| codex-exec | documented dotted events such as thread.started | output of codex exec --json ... |
| rollout | session_meta / event_msg / response_item | ~/.codex/sessions/.../rollout-*.jsonl |
| claude-code | first line has sessionId | ~/.claude/projects/<repo>/<sessionId>.jsonl |
| codex-team | first line has event + at | ~/Projects/agentweb/.codex-team/runs/*/events.jsonl |
codex-exec is the stable machine-readable stream documented by Codex. A
saved rollout is the richer session-persistence format and remains a
separate compatibility adapter. The exec stream does not include the original
prompt or timestamps; adaptCodexExec therefore synthesizes turn ids and
monotonic line-index event times starting at zero. Pass { startAt } when a
different base timestamp is useful to the host.
The normalized exec_command_end contract currently requires a numeric exit
code. A Codex command that is declined or otherwise ends without an exit code
is represented with exit code 1; this intentionally preserves failure
semantics but cannot distinguish a decline from a process failure.
Live-host adapter: AgentWeb transcript
Apps that store chat history in a database and stream new turns live (rather
than reading a JSONL log) need to merge two sources into one ChatStreamEvent
stream. adaptAgentWebTranscript does that bridge for hosts shaped like
AgentWeb — persisted
ChatMessage[] plus an in-flight StreamingState.
import { adaptAgentWebTranscript } from '@codexview/adapters/agentweb-transcript';
import { CodexTranscript } from '@codexview/react';
const { events, status, error } = adaptAgentWebTranscript({
sessionId, // → thread_started.threadId
messages, // ChatMessage[] from your DB
streaming, // StreamingState atom (or null)
// now, // optional clock override for tests
});
<CodexTranscript events={events} status={status} />Input shapes (AgentWebMessage, AgentWebStreamingState, AgentWebToolCall)
are structural — adapters has no AgentWeb dependency. The adapter:
- emits
thread_startedforsessionIdand synthesizesturn_started/turn_completedboundaries around eachturnIdgroup; - preserves the same
turnIdacross user message → live partial assistant text → final persisted assistant row so they render in one turn; - maps
run_commandtool calls toexec_command_begin+exec_command_end, and everything else tofunction_call+function_call_output; - maps AgentWeb
{ input, cachedInput, output }to CodexViewTokenUsage; - surfaces
streaming.status = 'failed' | 'disconnected' | 'gaveUp'asturn_failed/turn_abortedevents plus aTranscriptStatus(working,failed,stopped,completed,idle) on the result.
In-flight tool calls (completed: false) get their _begin event but no
_end — the open call renders with a running indicator until the next adapter
call sees the completed shape. Approval / reconnect / gave-up UI stays
host-owned and renders next to <CodexTranscript>.
adapt() options
adapt(lines, {
format?: 'codex-exec' | 'rollout' | 'codex-team' | 'claude-code' | 'opencode' | 'github-copilot',
startAt?: number, // Codex exec JSONL only
patchMode?: 'function_call' | 'patch_apply_end', // Claude Code only
subagents?: SubagentInput[], // Claude Code only
closeOpenTurn?: boolean, // Codex rollout only
});format— skipdetectFormat()and use the given format directly.startAt— base timestamp for a Codex exec JSONL stream, whose wire events have no timestamps. Defaults to0for deterministic output.patchMode— controls how Claude Code'sEdit/Write/MultiEdittool calls are rendered.'function_call'(default) — emit as opaquefunction_callentries. Matches the cli's compact output.'patch_apply_end'— defer until the matchingtool_result, then emit apatch_apply_endwith a synthesizedPatchFile[]containing diff text. Use when downstream rendering (e.g.<PatchBlock>) needs the diff.
subagents— list of Claude Code subagent transcripts associated with this session. When supplied, eachAgenttool'stool_resultis rewritten to embed a Markdown summary of the matching subagent (description, agent type, tool counts, token totals, final reply). Pairing strategy: primary bytoolUseResult.agentIdon the parent's user-typetool_resultline; FIFO fallback over unconsumed entries.closeOpenTurn— controls Codex rollout EOF behavior. Defaults totruefor static files, preserving the historical behavior of synthesizingturn_completedif the log ends mid-turn. Set tofalsewhen tailing a currently-written rollout so the final turn remainsworkinguntil a realtask_complete/ abort event appears.
interface SubagentInput {
agentId: string;
meta?: { agentType?: string; description?: string } | null;
lines: unknown[]; // raw JSONL rows from agent-<agentId>.jsonl
}Versioning
Independent semver from @codexview/react. The two packages share no runtime dependencies; the ChatStreamEvent types are duplicated and kept in sync by a CI guard (planned).
License
MIT.
