@agentex/agent 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Claude Code writes a durable JSONL transcript for every session under
3
+ * `<claudeHome>/projects/<sanitized-cwd>/<sessionId>.jsonl`. The on-disk lines
4
+ * use the same JSON shape Claude streams over stdout, so {@link parseStreamLine}
5
+ * handles them unchanged. These helpers cover the two parts the consuming
6
+ * host can't easily derive itself: where the file lives, and how to stream
7
+ * it back as `StreamEvent`s.
8
+ *
9
+ * Encoding rules are verified against Claude Code's open-source source
10
+ * (`sessionStoragePortable.ts:sanitizePath`):
11
+ * 1. Replace EVERY non-alphanumeric character with `-`
12
+ * (not just `/` and `.` — also `_`, space, `:`, etc.)
13
+ * 2. If the sanitized name exceeds {@link MAX_SANITIZED_LENGTH} (200),
14
+ * truncate and append a hash suffix
15
+ * 3. Canonicalize the cwd via `realpath` + NFC first so symlinks
16
+ * (e.g. macOS `/tmp` → `/private/tmp`) resolve to the same project dir
17
+ *
18
+ * The CLI does not expose a flag for the transcript path; the only source of
19
+ * truth is the open-source `sessionStoragePortable.ts`.
20
+ */
21
+ import { createReadStream } from "node:fs";
22
+ import { readdir, realpath, stat, open as fsOpen } from "node:fs/promises";
23
+ import * as os from "node:os";
24
+ import * as path from "node:path";
25
+ import * as readline from "node:readline";
26
+ import { getDefaultRuntimeHome, getRuntimeHomeEnvVar } from "../../utils/runtime-homes.js";
27
+ import { parseStreamLine } from "./parse.js";
28
+ /**
29
+ * Maximum length of a sanitized project-directory name before truncation +
30
+ * hash suffix kicks in. Mirrors Claude Code's `MAX_SANITIZED_LENGTH`. Most
31
+ * filesystems cap individual filename segments at 255 bytes; the gap leaves
32
+ * room for the hash suffix.
33
+ */
34
+ export const MAX_SANITIZED_LENGTH = 200;
35
+ /** Bytes scanned from the tail of the file in {@link peekClaudeTranscript}. */
36
+ const PEEK_TAIL_BYTES = 16 * 1024;
37
+ /** Filter rule: skip these Claude wrapper-event types when streaming a transcript. */
38
+ const SKIP_ON_DISK_TYPES = new Set([
39
+ // Internal enqueue/dequeue bookkeeping that Claude writes for its own
40
+ // scheduler; the on-disk file is the only place these surface. They carry
41
+ // no user-visible content and shouldn't be replayed.
42
+ "queue-operation",
43
+ ]);
44
+ /**
45
+ * djb2 string hash returning an unsigned base-36 string. Deterministic across
46
+ * runtimes — Claude Code's source uses `Bun.hash` under Bun (a different
47
+ * algorithm), so for cwd paths longer than {@link MAX_SANITIZED_LENGTH} the
48
+ * exact directory name will differ between Bun and Node. {@link getClaudeTranscriptPath}
49
+ * compensates with a prefix-match fallback when the exact path is missing.
50
+ */
51
+ function djb2Base36(input) {
52
+ let hash = 0;
53
+ for (let i = 0; i < input.length; i++) {
54
+ hash = ((hash << 5) - hash + input.charCodeAt(i)) | 0;
55
+ }
56
+ return Math.abs(hash).toString(36);
57
+ }
58
+ /**
59
+ * Encode an absolute path into Claude's project-directory name. Mirrors
60
+ * `sanitizePath` in Claude Code's open-source `sessionStoragePortable.ts`.
61
+ *
62
+ * @example
63
+ * sanitizeProjectPath("/Users/foo/bar") // → "-Users-foo-bar"
64
+ * sanitizeProjectPath("/Users/foo/.config") // → "-Users-foo--config"
65
+ * sanitizeProjectPath("/Users/foo/my_app") // → "-Users-foo-my-app"
66
+ * // (underscore is non-alphanumeric)
67
+ */
68
+ export function sanitizeProjectPath(name) {
69
+ const sanitized = name.replace(/[^a-zA-Z0-9]/g, "-");
70
+ if (sanitized.length <= MAX_SANITIZED_LENGTH)
71
+ return sanitized;
72
+ return `${sanitized.slice(0, MAX_SANITIZED_LENGTH)}-${djb2Base36(name)}`;
73
+ }
74
+ /**
75
+ * Resolve Claude's config home directory. Mirrors `getClaudeConfigHomeDir` in
76
+ * Claude Code, including the NFC normalization needed to keep paths consistent
77
+ * with macOS HFS+/APFS Unicode handling.
78
+ */
79
+ export function resolveClaudeHome(override) {
80
+ if (override)
81
+ return override.normalize("NFC");
82
+ const envVar = getRuntimeHomeEnvVar("claude");
83
+ const fromEnv = envVar ? process.env[envVar] : undefined;
84
+ const base = fromEnv ?? getDefaultRuntimeHome("claude") ?? path.join(os.homedir(), ".claude");
85
+ return base.normalize("NFC");
86
+ }
87
+ /**
88
+ * Canonicalize a cwd path to match what Claude Code stores. `realpath`
89
+ * resolves symlinks (`/tmp` → `/private/tmp` on macOS) and NFC unifies the
90
+ * two Unicode normalizations macOS accepts for filenames with accents.
91
+ *
92
+ * Returns the NFC-normalized input on `realpath` failure (e.g., directory
93
+ * was deleted after the session ran), since the directory name on disk was
94
+ * computed against whatever the cwd was at session start.
95
+ */
96
+ export async function canonicalizeCwd(cwd) {
97
+ try {
98
+ return (await realpath(cwd)).normalize("NFC");
99
+ }
100
+ catch {
101
+ return cwd.normalize("NFC");
102
+ }
103
+ }
104
+ /**
105
+ * Compute the on-disk JSONL path for a Claude session. Performs `realpath`
106
+ * canonicalization on the cwd and applies the same encoding rules Claude
107
+ * Code uses internally.
108
+ *
109
+ * For cwd paths sanitized longer than {@link MAX_SANITIZED_LENGTH}, the
110
+ * deterministic djb2 hash suffix may not match what Claude wrote (Claude Code
111
+ * uses `Bun.hash` under Bun). If the exact path doesn't exist and the
112
+ * sanitized name was truncated, this function falls back to a prefix scan
113
+ * under `<claudeHome>/projects/` and returns the first matching directory.
114
+ */
115
+ export async function getClaudeTranscriptPath(opts) {
116
+ if (!opts.sessionId)
117
+ throw new Error("getClaudeTranscriptPath: sessionId is required");
118
+ if (!opts.cwd)
119
+ throw new Error("getClaudeTranscriptPath: cwd is required");
120
+ const claudeHome = resolveClaudeHome(opts.claudeHome);
121
+ const canonicalCwd = await canonicalizeCwd(opts.cwd);
122
+ const sanitized = sanitizeProjectPath(canonicalCwd);
123
+ const fileName = `${opts.sessionId}.jsonl`;
124
+ const projectsRoot = path.join(claudeHome, "projects");
125
+ // Primary: exact match. Covers the common case (short paths, same hash algorithm).
126
+ const exactPath = path.join(projectsRoot, sanitized, fileName);
127
+ if (await pathExists(exactPath)) {
128
+ return { filePath: exactPath, projectDir: sanitized, canonicalCwd, claudeHome };
129
+ }
130
+ // Long-path fallback: Claude under Bun uses `Bun.hash` for the suffix;
131
+ // we use djb2. The truncated prefix is identical, so prefix-scan to find
132
+ // the actual on-disk directory. Mirrors open-source `findProjectDir`.
133
+ if (sanitized.length > MAX_SANITIZED_LENGTH) {
134
+ const prefix = sanitized.slice(0, MAX_SANITIZED_LENGTH);
135
+ try {
136
+ const entries = await readdir(projectsRoot, { withFileTypes: true });
137
+ for (const entry of entries) {
138
+ if (!entry.isDirectory())
139
+ continue;
140
+ if (!entry.name.startsWith(`${prefix}-`))
141
+ continue;
142
+ const candidate = path.join(projectsRoot, entry.name, fileName);
143
+ if (await pathExists(candidate)) {
144
+ return { filePath: candidate, projectDir: entry.name, canonicalCwd, claudeHome };
145
+ }
146
+ }
147
+ }
148
+ catch {
149
+ // projectsRoot missing or unreadable — fall through to deterministic path.
150
+ }
151
+ }
152
+ return { filePath: exactPath, projectDir: sanitized, canonicalCwd, claudeHome };
153
+ }
154
+ /**
155
+ * Scan `<claudeHome>/projects/*` looking for `<sessionId>.jsonl`. Use this
156
+ * when you have a session ID but don't know which cwd Claude was launched
157
+ * in — typical for resume-by-id flows.
158
+ *
159
+ * Session IDs are unique across project directories, so the first match is
160
+ * authoritative. The original cwd is recovered from the transcript's first
161
+ * `system.init` event (Claude writes one at session start carrying `cwd`).
162
+ *
163
+ * Returns `null` if no project directory contains the session file.
164
+ */
165
+ export async function findClaudeTranscriptBySessionId(opts) {
166
+ if (!opts.sessionId) {
167
+ throw new Error("findClaudeTranscriptBySessionId: sessionId is required");
168
+ }
169
+ const claudeHome = resolveClaudeHome(opts.claudeHome);
170
+ const projectsRoot = path.join(claudeHome, "projects");
171
+ const fileName = `${opts.sessionId}.jsonl`;
172
+ let entries;
173
+ try {
174
+ entries = await readdir(projectsRoot, { withFileTypes: true });
175
+ }
176
+ catch {
177
+ return null;
178
+ }
179
+ for (const entry of entries) {
180
+ if (!entry.isDirectory())
181
+ continue;
182
+ const candidate = path.join(projectsRoot, entry.name, fileName);
183
+ if (!(await pathExists(candidate)))
184
+ continue;
185
+ const cwd = await readCwdFromTranscript(candidate);
186
+ return { filePath: candidate, projectDir: entry.name, cwd };
187
+ }
188
+ return null;
189
+ }
190
+ /**
191
+ * Read the cwd field from the first transcript line that carries one.
192
+ *
193
+ * Claude's on-disk format does NOT emit a `system.init` event the way the
194
+ * stream wire format does. Instead, every event line (`user`, `assistant`,
195
+ * etc.) carries its own `cwd`, `sessionId`, `gitBranch`, `version` envelope.
196
+ * Read the first few lines raw, extract the first `cwd` we find.
197
+ *
198
+ * Returns `null` if no line in the first ~50 carries a `cwd` field.
199
+ */
200
+ async function readCwdFromTranscript(filePath) {
201
+ const fh = await fsOpen(filePath, "r").catch(() => null);
202
+ if (!fh)
203
+ return null;
204
+ try {
205
+ const stream = fh.createReadStream({ encoding: "utf8", autoClose: false });
206
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
207
+ let count = 0;
208
+ try {
209
+ for await (const raw of rl) {
210
+ if (++count > 50)
211
+ break;
212
+ const trimmed = raw.trim();
213
+ if (!trimmed)
214
+ continue;
215
+ try {
216
+ const obj = JSON.parse(trimmed);
217
+ // Outer envelope: every Claude line carries `cwd` at the top level.
218
+ if (typeof obj["cwd"] === "string" && obj["cwd"]) {
219
+ return obj["cwd"];
220
+ }
221
+ // Forward-compat: streaming-style init events also have cwd.
222
+ if (obj["type"] === "system" &&
223
+ obj["subtype"] === "init" &&
224
+ typeof obj["cwd"] === "string") {
225
+ return obj["cwd"];
226
+ }
227
+ }
228
+ catch {
229
+ // skip malformed
230
+ }
231
+ }
232
+ }
233
+ finally {
234
+ rl.close();
235
+ stream.destroy();
236
+ }
237
+ }
238
+ finally {
239
+ await fh.close();
240
+ }
241
+ return null;
242
+ }
243
+ async function pathExists(filePath) {
244
+ try {
245
+ await stat(filePath);
246
+ return true;
247
+ }
248
+ catch {
249
+ return false;
250
+ }
251
+ }
252
+ /**
253
+ * Stream-read a Claude transcript JSONL, yielding parsed `StreamEvent`s.
254
+ *
255
+ * Behavior:
256
+ * - Returns an empty async iterable if the file doesn't exist (no throw).
257
+ * - Skips wrapper types in {@link SKIP_ON_DISK_TYPES} (currently `queue-operation`).
258
+ * - Skips lines that fail to parse as JSON (`parseStreamLine` returns []).
259
+ * - Seeks into the file with `createReadStream` so multi-megabyte transcripts
260
+ * don't load fully into memory.
261
+ *
262
+ * The yielded `offset` lets the caller checkpoint after each event and
263
+ * resume from that offset on the next call.
264
+ */
265
+ export async function* readClaudeTranscript(opts) {
266
+ const { filePath, fromOffset = 0, sinceEventId } = opts;
267
+ // Fast-path: file missing → empty iterable, no throw.
268
+ if (!(await pathExists(filePath)))
269
+ return;
270
+ const stream = createReadStream(filePath, { start: fromOffset, encoding: undefined });
271
+ // Suppress stray ENOENT (file deleted between stat and open) — readline
272
+ // raises the same condition through its own iterator, which we catch below.
273
+ stream.on("error", () => { });
274
+ const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
275
+ let pos = fromOffset;
276
+ let stillSkippingPastSince = !!sinceEventId;
277
+ try {
278
+ for await (const line of rl) {
279
+ // readline strips the trailing `\n` (and the `\r` from `\r\n`). Claude
280
+ // writes Unix line endings, so we account for `\n` only. A `\r\n` file
281
+ // would yield offsets 1 byte short per line — accepted as a corner
282
+ // case; resume from such an offset would skip one stray `\r`.
283
+ const lineByteLen = Buffer.byteLength(line, "utf8");
284
+ pos += lineByteLen + 1;
285
+ if (!line)
286
+ continue;
287
+ const trimmed = line.trim();
288
+ if (!trimmed)
289
+ continue;
290
+ if (looksLikeSkippedType(trimmed))
291
+ continue;
292
+ const events = parseStreamLine(trimmed);
293
+ if (events.length === 0)
294
+ continue;
295
+ if (stillSkippingPastSince) {
296
+ if (events.some((e) => e.eventId === sinceEventId)) {
297
+ // Found the boundary line — skip ALL events on it and resume from the next.
298
+ stillSkippingPastSince = false;
299
+ }
300
+ continue;
301
+ }
302
+ for (const event of events) {
303
+ yield { event, offset: pos };
304
+ }
305
+ }
306
+ }
307
+ catch (err) {
308
+ // Swallow ENOENT (race: file deleted after the existence check); rethrow others.
309
+ const e = err;
310
+ if (e?.code !== "ENOENT")
311
+ throw err;
312
+ }
313
+ finally {
314
+ rl.close();
315
+ stream.destroy();
316
+ }
317
+ }
318
+ /**
319
+ * Quick pre-parse check for wrapper types we want to skip. Cheaper than a
320
+ * full `JSON.parse`; falls through to the parser if uncertain.
321
+ */
322
+ function looksLikeSkippedType(line) {
323
+ for (const t of SKIP_ON_DISK_TYPES) {
324
+ if (line.includes(`"type":"${t}"`) || line.includes(`"type": "${t}"`)) {
325
+ return true;
326
+ }
327
+ }
328
+ return false;
329
+ }
330
+ /**
331
+ * Drift-check primitive. Reads up to {@link PEEK_TAIL_BYTES} from the end of
332
+ * the file, parses the last complete line, and returns the last event plus
333
+ * total file size.
334
+ *
335
+ * Does NOT stream the whole file — designed to be called frequently as a
336
+ * cheap "has this changed since I last checked?" probe. Walks back through
337
+ * the buffer if the last line is a skipped wrapper type or fails to parse.
338
+ *
339
+ * Returns `{ lastEvent: null, size }` if the tail buffer holds no parseable
340
+ * line — caller should fall back to a full read if it needs guaranteed data.
341
+ */
342
+ export async function peekClaudeTranscript(filePath) {
343
+ let size;
344
+ try {
345
+ const s = await stat(filePath);
346
+ size = s.size;
347
+ }
348
+ catch {
349
+ return { lastEvent: null, size: null };
350
+ }
351
+ if (size === 0)
352
+ return { lastEvent: null, size: 0 };
353
+ const readBytes = Math.min(PEEK_TAIL_BYTES, size);
354
+ const start = size - readBytes;
355
+ const startedMidFile = start > 0;
356
+ let handle;
357
+ try {
358
+ handle = await fsOpen(filePath, "r");
359
+ }
360
+ catch {
361
+ return { lastEvent: null, size };
362
+ }
363
+ try {
364
+ const buf = Buffer.alloc(readBytes);
365
+ await handle.read(buf, 0, readBytes, start);
366
+ const text = buf.toString("utf8");
367
+ // Split on `\n`, drop the trailing empty entry from a final newline.
368
+ const lines = text.split("\n");
369
+ if (lines.length > 0 && lines[lines.length - 1] === "")
370
+ lines.pop();
371
+ // If we started mid-file, line[0] is partial — never trust it.
372
+ const minIdx = startedMidFile ? 1 : 0;
373
+ for (let i = lines.length - 1; i >= minIdx; i--) {
374
+ const raw = lines[i];
375
+ if (raw === undefined)
376
+ continue;
377
+ const trimmed = raw.trim();
378
+ if (!trimmed)
379
+ continue;
380
+ if (looksLikeSkippedType(trimmed))
381
+ continue;
382
+ const events = parseStreamLine(trimmed);
383
+ const last = events[events.length - 1];
384
+ if (!last)
385
+ continue;
386
+ return { lastEvent: last, size };
387
+ }
388
+ return { lastEvent: null, size };
389
+ }
390
+ finally {
391
+ await handle.close();
392
+ }
393
+ }
394
+ // ---------------------------------------------------------------------------
395
+ // Polymorphic facade
396
+ // ---------------------------------------------------------------------------
397
+ /**
398
+ * Polymorphic transcript ops for Claude. Delegates to the named functions
399
+ * above; mounted as `claudeProvider.transcript` so apps doing runtime-
400
+ * dispatched recovery can call `getProvider(name).transcript.find(...)`
401
+ * without a switch statement.
402
+ *
403
+ * Apps that know they're on Claude at compile time should prefer the named
404
+ * helpers (`getClaudeTranscriptPath`, `findClaudeTranscriptBySessionId`) —
405
+ * they return richer types (`canonicalCwd`, `projectDir`, `claudeHome`) that
406
+ * the polymorphic interface flattens away.
407
+ */
408
+ export const claudeTranscriptOps = {
409
+ async find(opts) {
410
+ // Fast path: cwd hint provided → direct O(1) lookup.
411
+ if (opts.cwd) {
412
+ const loc = await getClaudeTranscriptPath({
413
+ sessionId: opts.sessionId,
414
+ cwd: opts.cwd,
415
+ });
416
+ if (await pathExists(loc.filePath)) {
417
+ return { filePath: loc.filePath, cwd: loc.canonicalCwd };
418
+ }
419
+ // cwd was wrong (e.g. session was launched in a different worktree);
420
+ // fall through to scan.
421
+ }
422
+ const found = await findClaudeTranscriptBySessionId({ sessionId: opts.sessionId });
423
+ if (!found)
424
+ return null;
425
+ return { filePath: found.filePath, cwd: found.cwd };
426
+ },
427
+ read(opts) {
428
+ return readClaudeTranscript(opts);
429
+ },
430
+ peek(filePath) {
431
+ return peekClaudeTranscript(filePath);
432
+ },
433
+ };
434
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../../src/providers/claude/transcript.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
1
  import type { ProviderModule } from "../../types.js";
2
2
  export declare const codexProvider: ProviderModule;
3
+ export { getCodexTranscriptPath, readCodexTranscript, peekCodexTranscript, readCodexCwd, codexTranscriptOps, parseCodexLine, resolveCodexHome, } from "./transcript.js";
4
+ export type { GetCodexTranscriptPathOptions, CodexTranscriptLocation, ReadCodexTranscriptOptions, CodexTranscriptYield, CodexTranscriptLine, CodexPeekResult, } from "./transcript.js";
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/codex/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAgC,MAAM,gBAAgB,CAAC;AAMnF,eAAO,MAAM,aAAa,EAAE,cAgB3B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/codex/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAgC,MAAM,gBAAgB,CAAC;AAOnF,eAAO,MAAM,aAAa,EAAE,cAiB3B,CAAC;AAEF,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,6BAA6B,EAC7B,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
@@ -2,6 +2,7 @@ import { executeCodexProvider } from "./execute.js";
2
2
  import { createCodexSession } from "./session.js";
3
3
  import { codexSessionCodec } from "./codec.js";
4
4
  import { resolveAuthForProvider } from "../../utils/auth.js";
5
+ import { codexTranscriptOps } from "./transcript.js";
5
6
  export const codexProvider = {
6
7
  type: "codex",
7
8
  capabilities: {
@@ -18,5 +19,7 @@ export const codexProvider = {
18
19
  createSession: (ctx) => createCodexSession(ctx),
19
20
  resolveAuth: (ctx) => resolveAuthForProvider("codex", ctx),
20
21
  sessionCodec: codexSessionCodec,
22
+ transcript: codexTranscriptOps,
21
23
  };
24
+ export { getCodexTranscriptPath, readCodexTranscript, peekCodexTranscript, readCodexCwd, codexTranscriptOps, parseCodexLine, resolveCodexHome, } from "./transcript.js";
22
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/codex/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,IAAI,EAAE,OAAO;IACb,YAAY,EAAE;QACZ,QAAQ,EAAE,IAAI;QACd,cAAc,EAAE,KAAK;QACrB,YAAY,EAAE,KAAK;QACnB,GAAG,EAAE,KAAK;QACV,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,IAAI;KACf;IACD,OAAO,EAAE,oBAAoB;IAC7B,aAAa,EAAE,CAAC,GAAmB,EAAyB,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC;IACtF,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,GAAG,CAAC;IAC1D,YAAY,EAAE,iBAAiB;CAChC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/codex/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAmB;IAC3C,IAAI,EAAE,OAAO;IACb,YAAY,EAAE;QACZ,QAAQ,EAAE,IAAI;QACd,cAAc,EAAE,KAAK;QACrB,YAAY,EAAE,KAAK;QACnB,GAAG,EAAE,KAAK;QACV,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,SAAS,EAAE,IAAI;QACf,QAAQ,EAAE,IAAI;KACf;IACD,OAAO,EAAE,oBAAoB;IAC7B,aAAa,EAAE,CAAC,GAAmB,EAAyB,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC;IACtF,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,GAAG,CAAC;IAC1D,YAAY,EAAE,iBAAiB;IAC/B,UAAU,EAAE,kBAAkB;CAC/B,CAAC;AAEF,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Codex writes a durable JSONL rollout for every session under
3
+ * `<codexHome>/sessions/YYYY/MM/DD/rollout-<TIMESTAMP>-<sessionId>.jsonl`.
4
+ *
5
+ * Unlike Claude's project-keyed layout, Codex organizes rollouts by start
6
+ * date. The session ID is encoded at the end of the filename, after the
7
+ * launch timestamp. Locating a rollout by sessionId therefore requires a
8
+ * filename scan; there is no deterministic single-path-from-sessionId
9
+ * computation.
10
+ *
11
+ * On-disk format diverges from Codex's stream wire format. The wire format
12
+ * (handled by {@link parseCodexStreamLine}) emits either JSON-RPC
13
+ * notifications (`{method, params}`) or NDJSON events (`{type: "thread.started", ...}`).
14
+ * The on-disk format uses one of two shapes depending on Codex version:
15
+ *
16
+ * 1. Newer (≥0.10): `{timestamp, type: "session_meta"|"event_msg"|"response_item", payload: {...}}`
17
+ * 2. Older (pre-0.10): unwrapped — first line is `{id, timestamp, instructions}`,
18
+ * subsequent lines are `{type: "message"|"reasoning"|..., ...}` directly
19
+ *
20
+ * These helpers expose path discovery + raw-line streaming. Translating the
21
+ * on-disk types into `StreamEvent`s requires knowing the full Codex internal
22
+ * event vocabulary (which differs across versions and is not externally
23
+ * documented), so that work is left to consumers — they read structured raw
24
+ * lines and interpret payloads against the version they care about.
25
+ */
26
+ import type { TranscriptOps } from "../../types.js";
27
+ /**
28
+ * Resolve Codex's config home directory. Honors `$CODEX_HOME` first, falls
29
+ * back to `~/.codex`.
30
+ */
31
+ export declare function resolveCodexHome(override?: string): string;
32
+ export interface GetCodexTranscriptPathOptions {
33
+ /** Codex session ID (UUID). Matches the `id` field in the session_meta line. */
34
+ sessionId: string;
35
+ /** Override the Codex home. Defaults to `$CODEX_HOME` or `~/.codex`. */
36
+ codexHome?: string;
37
+ /**
38
+ * Also search `<codexHome>/archived_sessions/`. Default `true`. Codex moves
39
+ * old rollouts here during cleanup; without this fallback, recovery of
40
+ * older sessions would fail.
41
+ */
42
+ searchArchived?: boolean;
43
+ }
44
+ export interface CodexTranscriptLocation {
45
+ /** Absolute path to the rollout JSONL. */
46
+ filePath: string;
47
+ /** Which subtree it was found in. */
48
+ source: "active" | "archived";
49
+ /** The codex home that was searched. */
50
+ codexHome: string;
51
+ }
52
+ /**
53
+ * Read the literal cwd Codex was launched with, recovered from the first
54
+ * `session_meta` line in a rollout (or the legacy unwrapped first line for
55
+ * pre-0.10 transcripts).
56
+ *
57
+ * Returns `null` if the file has no recoverable cwd (truncated transcript,
58
+ * unrecognized format, etc.). Stops scanning after the first ~50 lines —
59
+ * `session_meta` is always the first line, but the older format may need a
60
+ * few lines to find the `environment_context` user_message with the cwd.
61
+ */
62
+ export declare function readCodexCwd(filePath: string): Promise<string | null>;
63
+ /**
64
+ * Locate a Codex rollout file by session ID. Scans the date-organized tree
65
+ * under `<codexHome>/sessions/` in reverse-chronological order (newest first,
66
+ * since recent sessions are the common lookup target), then optionally
67
+ * `<codexHome>/archived_sessions/`.
68
+ *
69
+ * Returns `null` if no matching rollout is found. The session ID must be
70
+ * the exact UUID Codex assigned — partial matches are not accepted.
71
+ */
72
+ export declare function getCodexTranscriptPath(opts: GetCodexTranscriptPathOptions): Promise<CodexTranscriptLocation | null>;
73
+ /**
74
+ * Best-effort parsed view of a single Codex transcript line, normalized
75
+ * across the wrapped (≥0.10) and unwrapped (pre-0.10) on-disk formats.
76
+ */
77
+ export interface CodexTranscriptLine {
78
+ /** Raw JSON-parsed object verbatim from the file. */
79
+ raw: Record<string, unknown>;
80
+ /**
81
+ * Outer wrapper type when present:
82
+ * - "session_meta", "event_msg", "response_item" — wrapped (≥0.10) lines
83
+ * - For unwrapped lines, falls back to the line's own `type` field
84
+ * (e.g., "message", "reasoning", "function_call_output").
85
+ * - `null` for lines with no `type` field (e.g., the older
86
+ * `{record_type: "state"}` markers or the bare-meta first line).
87
+ */
88
+ type: string | null;
89
+ /** ISO timestamp from the line's `timestamp` field, or null if absent. */
90
+ timestamp: string | null;
91
+ /**
92
+ * Inner payload as a parsed object, when the wrapped format is used.
93
+ * `null` for unwrapped lines — in that case the meaningful fields are on
94
+ * {@link raw} directly.
95
+ */
96
+ payload: Record<string, unknown> | null;
97
+ }
98
+ export interface ReadCodexTranscriptOptions {
99
+ /** Absolute path to the rollout JSONL. */
100
+ filePath: string;
101
+ /**
102
+ * Byte offset to resume from. Must be line-aligned. Use an offset previously
103
+ * yielded by this function. Defaults to 0 (start of file).
104
+ */
105
+ fromOffset?: number;
106
+ }
107
+ export interface CodexTranscriptYield {
108
+ /**
109
+ * Parsed line, normalized for the consumer. Named `event` for symmetry
110
+ * with Claude's `readClaudeTranscript` and the polymorphic
111
+ * `provider.transcript.read` interface — both yield `{event, offset}`.
112
+ * The underlying type is provider-specific (`CodexTranscriptLine` here,
113
+ * `StreamEvent` for Claude).
114
+ */
115
+ event: CodexTranscriptLine;
116
+ /**
117
+ * Byte offset immediately AFTER the trailing `\n` of this line. Pass back
118
+ * as {@link ReadCodexTranscriptOptions.fromOffset} to resume on the next line.
119
+ */
120
+ offset: number;
121
+ }
122
+ /**
123
+ * Stream-read a Codex rollout JSONL, yielding parsed lines.
124
+ *
125
+ * Behavior:
126
+ * - Empty async iterable if the file doesn't exist (no throw).
127
+ * - Silently skips lines that fail to JSON.parse.
128
+ * - Does not interpret payloads — that's the consumer's responsibility,
129
+ * since the on-disk event vocabulary is version-specific.
130
+ */
131
+ export declare function readCodexTranscript(opts: ReadCodexTranscriptOptions): AsyncIterable<CodexTranscriptYield>;
132
+ /**
133
+ * Parse a single Codex transcript line into a normalized view. Returns
134
+ * `null` for lines that don't parse as JSON objects.
135
+ *
136
+ * Exported because consumers reading the file by other means (e.g. tailing
137
+ * a write stream) can use it to get the same shape this module yields.
138
+ */
139
+ export declare function parseCodexLine(line: string): CodexTranscriptLine | null;
140
+ export interface CodexPeekResult {
141
+ /**
142
+ * Last successfully parsed line, or null if the file is empty/missing/unparseable.
143
+ * Named `lastEvent` for symmetry with Claude's `peekClaudeTranscript` and
144
+ * the polymorphic `provider.transcript.peek` interface.
145
+ */
146
+ lastEvent: CodexTranscriptLine | null;
147
+ /** Total size of the file in bytes, or null if missing. */
148
+ size: number | null;
149
+ }
150
+ /**
151
+ * Cheap drift-check: reads up to {@link PEEK_TAIL_BYTES} from the tail,
152
+ * walks back to the last parseable line, returns it plus the file size.
153
+ */
154
+ export declare function peekCodexTranscript(filePath: string): Promise<CodexPeekResult>;
155
+ /**
156
+ * Polymorphic transcript ops for Codex. Delegates to the named functions
157
+ * above; mounted as `codexProvider.transcript`. The `cwd` hint to `find` is
158
+ * accepted for interface symmetry with Claude but is ignored — Codex
159
+ * rollouts are organized by date, not by cwd.
160
+ */
161
+ export declare const codexTranscriptOps: TranscriptOps<CodexTranscriptLine>;
162
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../../src/providers/codex/transcript.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AASH,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAKrE;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1D;AAMD,MAAM,WAAW,6BAA6B;IAC5C,gFAAgF;IAChF,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC9B,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmC3E;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAkBzC;AAmFD;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B;;;;;;;OAOG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,0BAA0B;IACzC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;OAMG;IACH,KAAK,EAAE,mBAAmB,CAAC;IAC3B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAuB,mBAAmB,CACxC,IAAI,EAAE,0BAA0B,GAC/B,aAAa,CAAC,oBAAoB,CAAC,CA6BrC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAoBvE;AAeD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACtC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA4CpF;AAMD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,mBAAmB,CAajE,CAAC"}