@neta-art/cohub-cli 8.1.1 → 8.3.0
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.
- package/dist/commands/runtime.d.ts +0 -12
- package/dist/commands/runtime.js +129 -119
- package/dist/commands/search.js +3 -9
- package/dist/commands/spaces.js +5 -2
- package/dist/output.d.ts +6 -0
- package/dist/output.js +11 -0
- package/dist/runtime/archive-store.d.ts +4 -0
- package/dist/runtime/archive-store.js +10 -6
- package/dist/runtime/codex-usage.d.ts +0 -2
- package/dist/runtime/codex-usage.js +0 -12
- package/dist/runtime/connection.d.ts +5 -5
- package/dist/runtime/connection.js +27 -16
- package/dist/runtime/harness.d.ts +8 -16
- package/dist/runtime/harness.js +1 -366
- package/dist/runtime/instance.d.ts +8 -1
- package/dist/runtime/instance.js +15 -8
- package/dist/runtime/launch.js +10 -5
- package/dist/runtime/native/adapters.d.ts +32 -0
- package/dist/runtime/native/adapters.js +79 -0
- package/dist/runtime/{native-archive.d.ts → native/archive.d.ts} +4 -3
- package/dist/runtime/{native-archive.js → native/archive.js} +7 -14
- package/dist/runtime/native/attach.d.ts +33 -0
- package/dist/runtime/native/attach.js +103 -0
- package/dist/runtime/native/codex-link.d.ts +40 -0
- package/dist/runtime/native/codex-link.js +249 -0
- package/dist/runtime/native/config.d.ts +16 -0
- package/dist/runtime/native/config.js +24 -0
- package/dist/runtime/native/daemon.d.ts +88 -0
- package/dist/runtime/native/daemon.js +367 -0
- package/dist/runtime/native/execution.d.ts +45 -0
- package/dist/runtime/native/execution.js +337 -0
- package/dist/runtime/native/identity.d.ts +9 -0
- package/dist/runtime/native/identity.js +15 -0
- package/dist/runtime/native/ingest.d.ts +241 -0
- package/dist/runtime/native/ingest.js +823 -0
- package/dist/runtime/native/install.d.ts +9 -0
- package/dist/runtime/native/install.js +105 -0
- package/dist/runtime/native/pi-extension.d.ts +35 -0
- package/dist/runtime/native/pi-extension.js +160 -0
- package/dist/runtime/native/pi-link.d.ts +67 -0
- package/dist/runtime/native/pi-link.js +238 -0
- package/dist/runtime/native/results.d.ts +41 -0
- package/dist/runtime/native/results.js +128 -0
- package/dist/runtime/native/sessions.d.ts +45 -0
- package/dist/runtime/native/sessions.js +92 -0
- package/dist/runtime/native/transcript.d.ts +63 -0
- package/dist/runtime/native/transcript.js +594 -0
- package/dist/runtime/native/translate.d.ts +44 -0
- package/dist/runtime/native/translate.js +263 -0
- package/dist/runtime/native/transport.d.ts +7 -0
- package/dist/runtime/native/transport.js +16 -0
- package/dist/runtime/native/version.d.ts +5 -0
- package/dist/runtime/native/version.js +18 -0
- package/dist/runtime/presentation.d.ts +7 -10
- package/dist/runtime/presentation.js +35 -10
- package/dist/runtime/projection-store.d.ts +6 -13
- package/dist/runtime/projection-store.js +11 -74
- package/dist/runtime/supervisor.d.ts +2 -0
- package/dist/runtime/supervisor.js +36 -86
- package/dist/runtime/turn-projection.d.ts +1 -3
- package/dist/runtime/turn-projection.js +3 -10
- package/package.json +4 -5
- package/dist/runtime/native-attach.d.ts +0 -28
- package/dist/runtime/native-attach.js +0 -47
- package/dist/runtime/native-codex-hook.d.ts +0 -1
- package/dist/runtime/native-codex-hook.js +0 -28
- package/dist/runtime/native-install.d.ts +0 -21
- package/dist/runtime/native-install.js +0 -130
- package/dist/runtime/native-ipc.d.ts +0 -37
- package/dist/runtime/native-ipc.js +0 -118
- package/dist/runtime/native-pi-extension.d.ts +0 -20
- package/dist/runtime/native-pi-extension.js +0 -47
- package/dist/runtime/native-sync-store.d.ts +0 -102
- package/dist/runtime/native-sync-store.js +0 -368
- package/dist/runtime/native-sync.d.ts +0 -50
- package/dist/runtime/native-sync.js +0 -221
- package/dist/runtime/native-transcript.d.ts +0 -35
- package/dist/runtime/native-transcript.js +0 -310
- package/dist/runtime/session-store.d.ts +0 -84
- package/dist/runtime/session-store.js +0 -587
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { readdir, readFile, rm } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { RUNTIME_RECOVERY_BATCH_SIZE, runtimeEventSchema } from "@neta-art/cohub";
|
|
4
|
+
import { atomicRuntimeJson } from "../archive-store.js";
|
|
5
|
+
import { confirmQuiescentProcessGroup } from "../process-group.js";
|
|
6
|
+
import { readTranscript } from "./adapters.js";
|
|
7
|
+
export class ContextRequiredError extends Error {
|
|
8
|
+
}
|
|
9
|
+
const missing = (error) => error?.code === "ENOENT";
|
|
10
|
+
/** One small receipt per Cohub-executed Turn until the server acknowledges its result. */
|
|
11
|
+
export class ExecutionResults {
|
|
12
|
+
root;
|
|
13
|
+
constructor(root) {
|
|
14
|
+
this.root = root;
|
|
15
|
+
}
|
|
16
|
+
path(sessionId) { return join(this.root, "executions", `${sessionId}.json`); }
|
|
17
|
+
async read(sessionId) {
|
|
18
|
+
try {
|
|
19
|
+
const receipt = JSON.parse(await readFile(this.path(sessionId), "utf8"));
|
|
20
|
+
if (receipt.version !== 2 || receipt.sessionId !== sessionId)
|
|
21
|
+
throw new Error("Invalid execution receipt");
|
|
22
|
+
return receipt;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (missing(error))
|
|
26
|
+
return null;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Admit a new Turn. An unacknowledged earlier Turn is released once the server has settled it;
|
|
32
|
+
* otherwise the server must decide first, so a result is never overwritten unseen.
|
|
33
|
+
*/
|
|
34
|
+
async admit(input) {
|
|
35
|
+
const receipt = await this.read(input.sessionId);
|
|
36
|
+
if (!receipt || receipt.turnId === input.turnId)
|
|
37
|
+
return null;
|
|
38
|
+
const { resolvedTurnIds, settledTurnIds, complete } = input.context;
|
|
39
|
+
const resolved = resolvedTurnIds?.includes(receipt.turnId) === true;
|
|
40
|
+
if (resolved || settledTurnIds?.includes(receipt.turnId)) {
|
|
41
|
+
await rm(this.path(input.sessionId), { force: true });
|
|
42
|
+
return resolved ? receipt.session.path : null;
|
|
43
|
+
}
|
|
44
|
+
if (complete === false)
|
|
45
|
+
throw new ContextRequiredError("Server resolution is required for the pending native execution");
|
|
46
|
+
throw new Error(`Local turn ${receipt.turnId} has unconfirmed results; reconcile it before continuing`);
|
|
47
|
+
}
|
|
48
|
+
async start(session, input, requestId) {
|
|
49
|
+
await atomicRuntimeJson(this.path(input.sessionId), { version: 2, requestId, sessionId: input.sessionId, turnId: input.turnId, session });
|
|
50
|
+
}
|
|
51
|
+
async record(session, input, requestId, events, uncertainCleanup) {
|
|
52
|
+
await atomicRuntimeJson(this.path(input.sessionId), { version: 2, requestId, sessionId: input.sessionId, turnId: input.turnId, session, events, ...(uncertainCleanup ? { uncertainCleanup } : {}) });
|
|
53
|
+
}
|
|
54
|
+
async recover(input, requestId) {
|
|
55
|
+
const receipt = await this.read(input.sessionId);
|
|
56
|
+
if (!receipt || receipt.turnId !== input.turnId || receipt.session.harness !== input.harness)
|
|
57
|
+
return null;
|
|
58
|
+
if (requestId && receipt.requestId != null && receipt.requestId !== requestId)
|
|
59
|
+
throw new Error("Runtime result execution identity mismatch");
|
|
60
|
+
if (receipt.events) {
|
|
61
|
+
// A quiescent process group upgrades the receipt to confirmed; a live one stays uncertain.
|
|
62
|
+
if (receipt.uncertainCleanup && !receipt.uncertainCleanup.confirmedAt) {
|
|
63
|
+
if (!await confirmQuiescentProcessGroup(receipt.uncertainCleanup.processGroupId))
|
|
64
|
+
return null;
|
|
65
|
+
receipt.uncertainCleanup.confirmedAt = new Date().toISOString();
|
|
66
|
+
await atomicRuntimeJson(this.path(input.sessionId), receipt);
|
|
67
|
+
}
|
|
68
|
+
return { session: receipt.session, events: receipt.events.map((event) => runtimeEventSchema.parse(event)) };
|
|
69
|
+
}
|
|
70
|
+
const events = await this.fromTranscript(receipt);
|
|
71
|
+
if (!events)
|
|
72
|
+
return null;
|
|
73
|
+
await this.record(receipt.session, receipt, receipt.requestId, events);
|
|
74
|
+
return { session: receipt.session, events };
|
|
75
|
+
}
|
|
76
|
+
async acknowledge(sessionId, turnId) {
|
|
77
|
+
const receipt = await this.read(sessionId);
|
|
78
|
+
if (receipt?.turnId !== turnId)
|
|
79
|
+
throw new Error("Runtime acknowledgement identity mismatch");
|
|
80
|
+
await rm(this.path(sessionId), { force: true });
|
|
81
|
+
}
|
|
82
|
+
async pendingTurnIds(sessionId) {
|
|
83
|
+
const receipt = await this.read(sessionId);
|
|
84
|
+
return receipt ? [receipt.turnId] : [];
|
|
85
|
+
}
|
|
86
|
+
async *pendingBatches() {
|
|
87
|
+
const names = await readdir(join(this.root, "executions")).catch((error) => { if (missing(error))
|
|
88
|
+
return []; throw error; });
|
|
89
|
+
let batch = [];
|
|
90
|
+
for (const name of names) {
|
|
91
|
+
if (!name.endsWith(".json"))
|
|
92
|
+
continue;
|
|
93
|
+
const receipt = await this.read(name.slice(0, -5)).catch(() => null);
|
|
94
|
+
if (!receipt)
|
|
95
|
+
continue;
|
|
96
|
+
batch.push({ sessionId: receipt.sessionId, turnId: receipt.turnId, harness: receipt.session.harness });
|
|
97
|
+
if (batch.length >= RUNTIME_RECOVERY_BATCH_SIZE) {
|
|
98
|
+
yield batch;
|
|
99
|
+
batch = [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (batch.length)
|
|
103
|
+
yield batch;
|
|
104
|
+
}
|
|
105
|
+
async fromTranscript(receipt) {
|
|
106
|
+
const transcript = await readTranscript(receipt.session.path, receipt.session.harness).catch(() => null);
|
|
107
|
+
const turn = transcript?.turns.find((entry) => entry.cloudTurnId === receipt.turnId);
|
|
108
|
+
const result = turn?.result;
|
|
109
|
+
if (!result || result.status === "interrupted" || turn !== transcript?.turns.at(-1))
|
|
110
|
+
return null;
|
|
111
|
+
const messages = result.messages.filter((message) => message.content.length);
|
|
112
|
+
if (!messages.length)
|
|
113
|
+
return null;
|
|
114
|
+
const message = (entry, ordinal) => ({
|
|
115
|
+
ordinal,
|
|
116
|
+
content: entry.content,
|
|
117
|
+
provider: entry.provider ?? null,
|
|
118
|
+
model: entry.model ?? null,
|
|
119
|
+
usage: (entry.usage ?? null),
|
|
120
|
+
stopReason: entry.stopReason ?? "stop",
|
|
121
|
+
errorMessage: entry.errorMessage ?? null,
|
|
122
|
+
});
|
|
123
|
+
return [
|
|
124
|
+
...messages.slice(0, -1).map((entry, index) => ({ type: "message.commit", message: message(entry, index) })),
|
|
125
|
+
{ type: "turn.end", message: message(messages.at(-1), messages.length - 1), resume: "native", archive: null },
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type RuntimeContext } from "@neta-art/cohub";
|
|
2
|
+
import type { SessionTurnProjectionClient } from "../turn-projection.js";
|
|
3
|
+
import type { RuntimeArchiveStore } from "../archive-store.js";
|
|
4
|
+
import type { NativeIngest, TranscriptState } from "./ingest.js";
|
|
5
|
+
/** How the native file for a Turn was obtained; reported with the Turn result. */
|
|
6
|
+
export type ResumeKind = "native" | "restored" | "handoff" | "new";
|
|
7
|
+
export type NativeSession = {
|
|
8
|
+
harness: "pi" | "codex";
|
|
9
|
+
nativeSessionId: string;
|
|
10
|
+
path: string;
|
|
11
|
+
cwd: string;
|
|
12
|
+
};
|
|
13
|
+
export type PreparedSession = {
|
|
14
|
+
session: NativeSession;
|
|
15
|
+
resume: ResumeKind;
|
|
16
|
+
};
|
|
17
|
+
/** Chooses the native file a Turn runs in. 1. */
|
|
18
|
+
export declare class NativeSessions {
|
|
19
|
+
private readonly options;
|
|
20
|
+
private readonly projections;
|
|
21
|
+
constructor(options: {
|
|
22
|
+
root: string;
|
|
23
|
+
spaceId: string;
|
|
24
|
+
projectionSource: SessionTurnProjectionClient;
|
|
25
|
+
archives: RuntimeArchiveStore;
|
|
26
|
+
ingest: NativeIngest;
|
|
27
|
+
onRestoreFailed?: (error: unknown, context: {
|
|
28
|
+
sessionId: string;
|
|
29
|
+
harness: "pi" | "codex";
|
|
30
|
+
unrestorable: boolean;
|
|
31
|
+
}) => void;
|
|
32
|
+
});
|
|
33
|
+
prepare(input: {
|
|
34
|
+
sessionId: string;
|
|
35
|
+
turnId: string;
|
|
36
|
+
harness: "pi" | "codex";
|
|
37
|
+
cwd: string;
|
|
38
|
+
provider?: string | null;
|
|
39
|
+
context: RuntimeContext;
|
|
40
|
+
resumable: (transcript: TranscriptState) => boolean;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}): Promise<PreparedSession>;
|
|
43
|
+
private restore;
|
|
44
|
+
private project;
|
|
45
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { serializeProjectionRecords } from "@neta-art/cohub";
|
|
6
|
+
import { ArchiveNotRestorableError, importNativeArchive } from "./archive.js";
|
|
7
|
+
import { piSessionDirectoryName, readTranscript } from "./adapters.js";
|
|
8
|
+
import { ProjectionStore, rebindProjectionNativeSession } from "../projection-store.js";
|
|
9
|
+
/** Chooses the native file a Turn runs in. 1. */
|
|
10
|
+
export class NativeSessions {
|
|
11
|
+
options;
|
|
12
|
+
projections;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.projections = new ProjectionStore(options.projectionSource);
|
|
16
|
+
}
|
|
17
|
+
async prepare(input) {
|
|
18
|
+
const existing = this.options.ingest.transcriptFor(input.sessionId, input.harness, input.context.throughTurnId);
|
|
19
|
+
if (existing && input.resumable(existing)) {
|
|
20
|
+
return { session: { harness: existing.harness, nativeSessionId: existing.nativeSessionId, path: existing.path, cwd: existing.cwd }, resume: "native" };
|
|
21
|
+
}
|
|
22
|
+
const archive = input.context.archive;
|
|
23
|
+
if (archive && archive.harness === input.harness && archive.sessionId === input.sessionId && archive.turnId === input.context.throughTurnId) {
|
|
24
|
+
const restored = await this.restore(input, archive, input.signal).catch((error) => {
|
|
25
|
+
input.signal?.throwIfAborted();
|
|
26
|
+
// A structurally unrestorable archive falls back to projection; so does a transient
|
|
27
|
+
// failure, which simply tries the archive again on the next Turn.
|
|
28
|
+
this.options.onRestoreFailed?.(error, { sessionId: input.sessionId, harness: input.harness, unrestorable: error instanceof ArchiveNotRestorableError });
|
|
29
|
+
return null;
|
|
30
|
+
});
|
|
31
|
+
if (restored) {
|
|
32
|
+
// A restored copy is history the server already has, even where it carries no markers.
|
|
33
|
+
const through = (await readTranscript(restored.path, restored.harness).catch(() => null))?.turns.at(-1)?.key ?? null;
|
|
34
|
+
this.options.ingest.adopt(restored, input.sessionId, { turnKey: through, turnId: input.context.throughTurnId });
|
|
35
|
+
return { session: restored, resume: "restored" };
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const projected = await this.project(input);
|
|
39
|
+
// A new Codex thread gets its file when it starts; the executor adopts it then.
|
|
40
|
+
if (projected.resume !== "new" || input.harness === "pi")
|
|
41
|
+
this.options.ingest.adopt(projected.session, input.sessionId);
|
|
42
|
+
return projected;
|
|
43
|
+
}
|
|
44
|
+
async restore(input, archive, signal) {
|
|
45
|
+
const id = randomUUID();
|
|
46
|
+
const raw = join(this.options.root, "native", "restored", `${id}.jsonl`);
|
|
47
|
+
const path = nativePath(input.harness, id, input.cwd);
|
|
48
|
+
try {
|
|
49
|
+
const restored = await this.options.archives.restore(archive, raw, signal);
|
|
50
|
+
const imported = await importNativeArchive({ source: raw, target: path, harness: input.harness, nativeSessionId: restored.nativeSessionId, id, cwd: input.cwd, signal });
|
|
51
|
+
return { harness: input.harness, nativeSessionId: imported.nativeSessionId, path, cwd: input.cwd };
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
await rm(raw, { force: true }).catch(() => undefined);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async project(input) {
|
|
58
|
+
const nativeSessionId = randomUUID();
|
|
59
|
+
const path = nativePath(input.harness, nativeSessionId, input.cwd);
|
|
60
|
+
const projection = rebindProjectionNativeSession(await this.projections.project({
|
|
61
|
+
spaceId: this.options.spaceId,
|
|
62
|
+
sessionId: input.sessionId,
|
|
63
|
+
turnId: input.turnId,
|
|
64
|
+
nativeSessionId,
|
|
65
|
+
cwd: input.cwd,
|
|
66
|
+
provider: input.provider,
|
|
67
|
+
target: input.harness,
|
|
68
|
+
throughTurnId: input.context.throughTurnId,
|
|
69
|
+
}, input.signal), nativeSessionId);
|
|
70
|
+
const session = { harness: input.harness, nativeSessionId, path, cwd: input.cwd };
|
|
71
|
+
// An empty Codex thread is created by Codex itself when the Turn starts.
|
|
72
|
+
if (!projection.turns.length && input.harness === "codex")
|
|
73
|
+
return { session, resume: "new" };
|
|
74
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
75
|
+
const temporary = `${path}.${randomUUID()}.projection`;
|
|
76
|
+
await writeFile(temporary, serializeProjectionRecords(projection.projection.records), { mode: 0o600 });
|
|
77
|
+
await rename(temporary, path);
|
|
78
|
+
return { session, resume: projection.turns.length ? "handoff" : "new" };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Where a harness keeps a new transcript for the bound directory. */
|
|
82
|
+
function nativePath(harness, nativeSessionId, cwd) {
|
|
83
|
+
const stamp = new Date().toISOString();
|
|
84
|
+
if (harness === "pi") {
|
|
85
|
+
const agent = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), ".pi", "agent");
|
|
86
|
+
const directory = process.env.PI_CODING_AGENT_SESSION_DIR?.trim() || join(agent, "sessions", piSessionDirectoryName(cwd));
|
|
87
|
+
return join(directory, `${stamp.replace(/[:.]/g, "-")}_${nativeSessionId}.jsonl`);
|
|
88
|
+
}
|
|
89
|
+
const home = process.env.CODEX_HOME?.trim() || join(homedir(), ".codex");
|
|
90
|
+
const day = stamp.replace(/\.\d{3}Z$/, "").replaceAll(":", "-");
|
|
91
|
+
return join(home, "sessions", day.slice(0, 4), day.slice(5, 7), day.slice(8, 10), `rollout-${day}-${nativeSessionId}.jsonl`);
|
|
92
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ContentBlock, NativeTurnComplete, NativeTurnMessage } from "@neta-art/cohub";
|
|
2
|
+
export type NativeTranscriptTurn = {
|
|
3
|
+
key: string;
|
|
4
|
+
parentKey: string | null;
|
|
5
|
+
cloudTurnId?: string;
|
|
6
|
+
userContent: ContentBlock[];
|
|
7
|
+
/**
|
|
8
|
+
* Codex records a prompt in several steps and the final form last; until this is set the user
|
|
9
|
+
* content may still change.
|
|
10
|
+
*/
|
|
11
|
+
userFinal?: boolean;
|
|
12
|
+
messages: NativeTurnMessage[];
|
|
13
|
+
startedAt: string;
|
|
14
|
+
startBytes: number;
|
|
15
|
+
endBytes: number;
|
|
16
|
+
contentEndBytes: number;
|
|
17
|
+
boundaries: Record<number, string>;
|
|
18
|
+
sha256: string;
|
|
19
|
+
result: NativeTurnComplete | null;
|
|
20
|
+
path?: string;
|
|
21
|
+
rolloutId?: string;
|
|
22
|
+
sequence?: number;
|
|
23
|
+
};
|
|
24
|
+
export type NativeTranscript = {
|
|
25
|
+
nativeSessionId: string;
|
|
26
|
+
cwd: string;
|
|
27
|
+
cloudSessionId?: string;
|
|
28
|
+
turns: NativeTranscriptTurn[];
|
|
29
|
+
prefixes: ReadonlyMap<number, string>;
|
|
30
|
+
lineagePaths?: string[];
|
|
31
|
+
lineageRolloutIds?: string[];
|
|
32
|
+
};
|
|
33
|
+
export declare const NATIVE_MAX_RECORD_BYTES: number;
|
|
34
|
+
export declare const NATIVE_MAX_TRANSCRIPT_BYTES: number;
|
|
35
|
+
export declare const codexSessionsDirectory: () => string;
|
|
36
|
+
export declare const codexArchivedSessionsDirectory: () => string;
|
|
37
|
+
/** Ordinary rollout names encode one id; reverted threads append `_rollout-id`. */
|
|
38
|
+
export declare function codexRolloutIdOf(fileName: string): string | null;
|
|
39
|
+
export type CodexHistoryBase = {
|
|
40
|
+
rolloutId: string;
|
|
41
|
+
endOrdinal: number;
|
|
42
|
+
endBytes: number;
|
|
43
|
+
};
|
|
44
|
+
export type NativeTranscriptHeader = {
|
|
45
|
+
nativeSessionId: string;
|
|
46
|
+
cwd: string;
|
|
47
|
+
rolloutId?: string;
|
|
48
|
+
historyBase?: CodexHistoryBase;
|
|
49
|
+
};
|
|
50
|
+
/** Read only the session header before deciding whether a global Codex file belongs to this project. */
|
|
51
|
+
export declare function readNativeTranscriptHeader(path: string, harness: "pi" | "codex", signal?: AbortSignal): Promise<NativeTranscriptHeader>;
|
|
52
|
+
/** Raw JSONL bytes of a rollout, transparently decompressing `.zst` and honoring a lineage cutoff. */
|
|
53
|
+
export declare function codexRolloutBytes(path: string, endBytes: number | null, signal?: AbortSignal): AsyncGenerator<Buffer>;
|
|
54
|
+
/** Cache location for a rollout's decompressed copy; shared by capture and archival. */
|
|
55
|
+
export declare function codexRolloutCachePath(source: string, cacheDirectory: string): string;
|
|
56
|
+
/** Archives need plain JSONL bytes; decompress a cold `.zst` rollout into a cache once. */
|
|
57
|
+
export declare function ensurePlainCodexRollout(path: string, cacheDirectory: string, signal?: AbortSignal, maxBytes?: number): Promise<string>;
|
|
58
|
+
/** Partial trailing records are retried, never parsed or acknowledged as complete. */
|
|
59
|
+
export declare function readNativeTranscript(path: string, harness: "pi" | "codex", options?: {
|
|
60
|
+
settled?: boolean;
|
|
61
|
+
leafId?: string | null;
|
|
62
|
+
signal?: AbortSignal;
|
|
63
|
+
}): Promise<NativeTranscript>;
|