@agentic-kit/run-log 0.2.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/esm/record.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * The run log record: four platform-owned fields around a verbatim pi entry.
3
+ *
4
+ * The wrapper exists to give an entry identity (which run) and order (which
5
+ * position) across hosts — nothing else. It deliberately does not re-encode pi's
6
+ * semantics, because pi already versions and migrates its own session format;
7
+ * `piSessionVersion` records which version an entry was written under so a
8
+ * reader can hand old entries to pi's migrations instead of guessing.
9
+ */
10
+ import { assertPiSessionEntry } from './pi-entry';
11
+ /** Version of the wrapper itself — bumped only if these four fields change. */
12
+ export const RUN_LOG_WRAPPER_VERSION = 1;
13
+ /** The pi session format version this package projects without migration. */
14
+ export const SUPPORTED_PI_SESSION_VERSION = 3;
15
+ export function wrapEntry(options) {
16
+ if (!options.runId)
17
+ throw new TypeError('a run log record needs a runId');
18
+ if (!Number.isInteger(options.seq) || options.seq < 1) {
19
+ throw new TypeError(`run log seq must be a positive integer, received ${String(options.seq)}`);
20
+ }
21
+ return {
22
+ runId: options.runId,
23
+ seq: options.seq,
24
+ recordedAt: options.recordedAt ?? new Date().toISOString(),
25
+ piSessionVersion: options.piSessionVersion ?? SUPPORTED_PI_SESSION_VERSION,
26
+ entry: assertPiSessionEntry(options.entry)
27
+ };
28
+ }
29
+ /**
30
+ * Narrow an untrusted record (database row, HTTP body). Throws on anything
31
+ * unreadable — a log that cannot be parsed must fail loudly, never silently
32
+ * render as an empty conversation.
33
+ */
34
+ export function assertRunEventRecord(value) {
35
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
36
+ throw new TypeError(`run log record must be an object, received ${typeof value}`);
37
+ }
38
+ const record = value;
39
+ if (typeof record.runId !== 'string' || record.runId.length === 0) {
40
+ throw new TypeError('run log record must carry a non-empty runId');
41
+ }
42
+ if (!Number.isInteger(record.seq) || record.seq < 1) {
43
+ throw new TypeError(`run log record ${record.runId} has an invalid seq: ${String(record.seq)}`);
44
+ }
45
+ if (typeof record.recordedAt !== 'string') {
46
+ throw new TypeError(`run log record ${record.runId}#${String(record.seq)} must carry recordedAt`);
47
+ }
48
+ if (!Number.isInteger(record.piSessionVersion)) {
49
+ throw new TypeError(`run log record ${record.runId}#${String(record.seq)} must carry an integer piSessionVersion`);
50
+ }
51
+ return {
52
+ runId: record.runId,
53
+ seq: record.seq,
54
+ recordedAt: record.recordedAt,
55
+ piSessionVersion: record.piSessionVersion,
56
+ entry: assertPiSessionEntry(record.entry)
57
+ };
58
+ }
59
+ /**
60
+ * The de-duplication key for an append. pi entry ids are unique within a
61
+ * session, so a retried append (a Job restart re-emitting its tail, a
62
+ * reconnecting writer) is recognised rather than duplicated.
63
+ */
64
+ export function idempotencyKey(runId, entry) {
65
+ const id = typeof entry.id === 'string' ? entry.id : null;
66
+ if (id)
67
+ return `${runId}:${entry.type}:${id}`;
68
+ // Session headers carry no tree id; there is exactly one per session file.
69
+ return `${runId}:${entry.type}:${String(entry.id ?? 'header')}`;
70
+ }
71
+ /** Records must be contiguous and in order before anything projects them. */
72
+ export function assertOrdered(records) {
73
+ for (let i = 1; i < records.length; i += 1) {
74
+ const previous = records[i - 1];
75
+ const current = records[i];
76
+ if (current.runId !== previous.runId) {
77
+ throw new Error(`run log records mix runs: ${previous.runId} then ${current.runId} at index ${String(i)}`);
78
+ }
79
+ if (current.seq <= previous.seq) {
80
+ throw new Error(`run log records out of order in ${current.runId}: seq ${String(previous.seq)} followed by ${String(current.seq)}`);
81
+ }
82
+ }
83
+ }
package/esm/store.d.ts ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The storage contract. A run log is append-only and read by cursor, so the
3
+ * interfaces are deliberately two: a writer (the agent host) and a reader
4
+ * (every UI surface, the resume path, the usage rollup). Concrete stores live
5
+ * with their storage — Postgres in constructive-db, JSONL in `./file-store`,
6
+ * memory here for tests and for a run that has not been persisted yet.
7
+ */
8
+ import type { PiSessionEntry } from './pi-entry';
9
+ import { type RunEventRecord } from './record';
10
+ /** Read position: `afterSeq` is exclusive, so `0` means "from the start". */
11
+ export interface RunLogCursor {
12
+ afterSeq: number;
13
+ }
14
+ export declare const START: RunLogCursor;
15
+ export declare const cursorAfter: (records: readonly RunEventRecord[], from?: RunLogCursor) => RunLogCursor;
16
+ export interface RunLogPage {
17
+ records: RunEventRecord[];
18
+ cursor: RunLogCursor;
19
+ }
20
+ export interface AppendOptions {
21
+ /** pi session format version the entries were produced under. */
22
+ piSessionVersion?: number;
23
+ recordedAt?: string;
24
+ }
25
+ export interface RunLogAppendStore {
26
+ /**
27
+ * Append entries to a run, returning the records actually written. Entries
28
+ * already present (matched by pi entry id) are skipped, which makes an append
29
+ * safe to retry.
30
+ */
31
+ append(runId: string, entries: readonly PiSessionEntry[], options?: AppendOptions): Promise<RunEventRecord[]>;
32
+ }
33
+ export interface RunLogReadStore {
34
+ read(runId: string, cursor?: RunLogCursor, limit?: number): Promise<RunLogPage>;
35
+ }
36
+ export type RunLogStore = RunLogAppendStore & RunLogReadStore;
37
+ /** In-memory store: the reference implementation and the test double. */
38
+ export declare class MemoryRunLogStore implements RunLogStore {
39
+ private readonly runs;
40
+ private readonly seen;
41
+ append(runId: string, entries: readonly PiSessionEntry[], options?: AppendOptions): Promise<RunEventRecord[]>;
42
+ read(runId: string, cursor?: RunLogCursor, limit?: number): Promise<RunLogPage>;
43
+ /** Test/debug helper: every record of a run, ignoring cursors. */
44
+ snapshot(runId: string): RunEventRecord[];
45
+ runIds(): string[];
46
+ }
package/esm/store.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The storage contract. A run log is append-only and read by cursor, so the
3
+ * interfaces are deliberately two: a writer (the agent host) and a reader
4
+ * (every UI surface, the resume path, the usage rollup). Concrete stores live
5
+ * with their storage — Postgres in constructive-db, JSONL in `./file-store`,
6
+ * memory here for tests and for a run that has not been persisted yet.
7
+ */
8
+ import { assertOrdered, idempotencyKey, SUPPORTED_PI_SESSION_VERSION, wrapEntry } from './record';
9
+ export const START = { afterSeq: 0 };
10
+ export const cursorAfter = (records, from = START) => records.length === 0 ? from : { afterSeq: records[records.length - 1].seq };
11
+ /** In-memory store: the reference implementation and the test double. */
12
+ export class MemoryRunLogStore {
13
+ runs = new Map();
14
+ seen = new Map();
15
+ async append(runId, entries, options = {}) {
16
+ const records = this.runs.get(runId) ?? [];
17
+ const seen = this.seen.get(runId) ?? new Set();
18
+ const written = [];
19
+ for (const entry of entries) {
20
+ const key = idempotencyKey(runId, entry);
21
+ if (seen.has(key))
22
+ continue;
23
+ const record = wrapEntry({
24
+ runId,
25
+ seq: records.length + written.length + 1,
26
+ entry,
27
+ ...(options.recordedAt ? { recordedAt: options.recordedAt } : {}),
28
+ piSessionVersion: options.piSessionVersion ?? SUPPORTED_PI_SESSION_VERSION
29
+ });
30
+ written.push(record);
31
+ seen.add(key);
32
+ }
33
+ this.runs.set(runId, records.concat(written));
34
+ this.seen.set(runId, seen);
35
+ return written;
36
+ }
37
+ async read(runId, cursor = START, limit) {
38
+ const all = this.runs.get(runId) ?? [];
39
+ const after = all.filter((record) => record.seq > cursor.afterSeq);
40
+ const records = typeof limit === 'number' ? after.slice(0, limit) : after;
41
+ assertOrdered(records);
42
+ return { records, cursor: cursorAfter(records, cursor) };
43
+ }
44
+ /** Test/debug helper: every record of a run, ignoring cursors. */
45
+ snapshot(runId) {
46
+ return (this.runs.get(runId) ?? []).slice();
47
+ }
48
+ runIds() {
49
+ return Array.from(this.runs.keys());
50
+ }
51
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `@agentic-kit/run-log/file-store` — the node-only JSONL store.
3
+ *
4
+ * A separate entry point because the package's main entry is imported by
5
+ * browsers, Electron renderers and Next client components; a `node:fs` import
6
+ * there breaks those bundles. Same split, same reason, as `12factor-env/dotenv`.
7
+ *
8
+ * The file holds one wrapped record per line, so a run is recoverable with
9
+ * `tail -f` and a partially-written last line is detectable rather than silently
10
+ * dropped. This is the store a local run uses before (or without) a database,
11
+ * and the one tests use when they want the log to survive a process restart.
12
+ */
13
+ import type { PiSessionEntry } from './pi-entry';
14
+ import { type SessionProjectionOptions } from './projectors/session';
15
+ import { type RunEventRecord } from './record';
16
+ import { type AppendOptions, type RunLogCursor, type RunLogPage, type RunLogStore } from './store';
17
+ export interface FileRunLogStoreOptions {
18
+ /** Absolute path of the log file. Parent directories are created. */
19
+ path: string;
20
+ }
21
+ export declare class FileRunLogStore implements RunLogStore {
22
+ private readonly path;
23
+ constructor(options: FileRunLogStoreOptions);
24
+ private load;
25
+ append(runId: string, entries: readonly PiSessionEntry[], options?: AppendOptions): Promise<RunEventRecord[]>;
26
+ read(runId: string, cursor?: RunLogCursor, limit?: number): Promise<RunLogPage>;
27
+ }
28
+ /**
29
+ * Write the run's pi session file so `SessionManager.open` can resume it. This
30
+ * is the cloud→local (and local→local restart) resume path: project, write,
31
+ * hand the path to pi.
32
+ */
33
+ export declare function writeSessionFile(path: string, records: readonly RunEventRecord[], options?: SessionProjectionOptions): string;
package/file-store.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /**
3
+ * `@agentic-kit/run-log/file-store` — the node-only JSONL store.
4
+ *
5
+ * A separate entry point because the package's main entry is imported by
6
+ * browsers, Electron renderers and Next client components; a `node:fs` import
7
+ * there breaks those bundles. Same split, same reason, as `12factor-env/dotenv`.
8
+ *
9
+ * The file holds one wrapped record per line, so a run is recoverable with
10
+ * `tail -f` and a partially-written last line is detectable rather than silently
11
+ * dropped. This is the store a local run uses before (or without) a database,
12
+ * and the one tests use when they want the log to survive a process restart.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.FileRunLogStore = void 0;
16
+ exports.writeSessionFile = writeSessionFile;
17
+ const node_fs_1 = require("node:fs");
18
+ const node_path_1 = require("node:path");
19
+ const session_1 = require("./projectors/session");
20
+ const record_1 = require("./record");
21
+ const store_1 = require("./store");
22
+ class FileRunLogStore {
23
+ path;
24
+ constructor(options) {
25
+ this.path = options.path;
26
+ }
27
+ load() {
28
+ if (!(0, node_fs_1.existsSync)(this.path))
29
+ return [];
30
+ const contents = (0, node_fs_1.readFileSync)(this.path, 'utf8');
31
+ const records = [];
32
+ const lines = contents.split('\n');
33
+ for (let i = 0; i < lines.length; i += 1) {
34
+ const line = lines[i].trim();
35
+ if (line.length === 0)
36
+ continue;
37
+ let parsed;
38
+ try {
39
+ parsed = JSON.parse(line);
40
+ }
41
+ catch (error) {
42
+ throw new Error(`run log ${this.path} line ${String(i + 1)} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
43
+ }
44
+ records.push((0, record_1.assertRunEventRecord)(parsed));
45
+ }
46
+ return records;
47
+ }
48
+ async append(runId, entries, options = {}) {
49
+ const existing = this.load().filter((record) => record.runId === runId);
50
+ const seen = new Set(existing.map((record) => (0, record_1.idempotencyKey)(runId, record.entry)));
51
+ const written = [];
52
+ for (const entry of entries) {
53
+ const key = (0, record_1.idempotencyKey)(runId, entry);
54
+ if (seen.has(key))
55
+ continue;
56
+ written.push((0, record_1.wrapEntry)({
57
+ runId,
58
+ seq: existing.length + written.length + 1,
59
+ entry,
60
+ ...(options.recordedAt ? { recordedAt: options.recordedAt } : {}),
61
+ piSessionVersion: options.piSessionVersion ?? record_1.SUPPORTED_PI_SESSION_VERSION
62
+ }));
63
+ seen.add(key);
64
+ }
65
+ if (written.length === 0)
66
+ return written;
67
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(this.path), { recursive: true });
68
+ if (!(0, node_fs_1.existsSync)(this.path))
69
+ (0, node_fs_1.writeFileSync)(this.path, '', { mode: 0o600 });
70
+ (0, node_fs_1.appendFileSync)(this.path, written.map((record) => JSON.stringify(record)).join('\n') + '\n');
71
+ return written;
72
+ }
73
+ async read(runId, cursor = store_1.START, limit) {
74
+ const after = this.load().filter((record) => record.runId === runId && record.seq > cursor.afterSeq);
75
+ const records = typeof limit === 'number' ? after.slice(0, limit) : after;
76
+ return { records, cursor: (0, store_1.cursorAfter)(records, cursor) };
77
+ }
78
+ }
79
+ exports.FileRunLogStore = FileRunLogStore;
80
+ /**
81
+ * Write the run's pi session file so `SessionManager.open` can resume it. This
82
+ * is the cloud→local (and local→local restart) resume path: project, write,
83
+ * hand the path to pi.
84
+ */
85
+ function writeSessionFile(path, records, options = {}) {
86
+ const projection = (0, session_1.projectSession)(records, options);
87
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(path), { recursive: true });
88
+ (0, node_fs_1.writeFileSync)(path, projection.jsonl, { mode: 0o600 });
89
+ return path;
90
+ }
package/follow.d.ts ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Following a run log.
3
+ *
4
+ * Every surface — a desktop chat pane, a web execution view, a CLI tail, the
5
+ * resume path — is the same reader: hold a cursor, ask for what came after it.
6
+ * That is what makes local and cloud runs indistinguishable to a UI, so this is
7
+ * the only reader loop in the system.
8
+ *
9
+ * A push wakeup (LISTEN/NOTIFY, IPC, websocket) is an optimisation, not a
10
+ * requirement: `waitForChange` short-circuits the delay when it resolves, and
11
+ * without one the loop degrades to polling at `pollIntervalMs`.
12
+ */
13
+ import type { RunEventRecord } from './record';
14
+ import { type RunLogCursor, type RunLogReadStore } from './store';
15
+ export interface FollowOptions {
16
+ cursor?: RunLogCursor;
17
+ /** Polling delay when no wakeup arrives. */
18
+ pollIntervalMs?: number;
19
+ /** Records per read. */
20
+ limit?: number;
21
+ /** Resolves when the run may have new records; races the poll delay. */
22
+ waitForChange?: (signal?: AbortSignal) => Promise<void>;
23
+ /** Stop following once this returns true for the batch just yielded. */
24
+ isTerminal?: (records: readonly RunEventRecord[]) => boolean;
25
+ signal?: AbortSignal;
26
+ /** Injectable for tests; defaults to `setTimeout`. */
27
+ sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
28
+ }
29
+ /**
30
+ * Yield every batch of new records until the run reaches a terminal state or
31
+ * the caller aborts. Batches are yielded as read, so a caller can project
32
+ * incrementally rather than re-projecting the whole run per frame.
33
+ */
34
+ export declare function follow(store: RunLogReadStore, runId: string, options?: FollowOptions): AsyncGenerator<RunEventRecord[], void, void>;
35
+ /** Read a run to its current end in one pass. */
36
+ export declare function readAll(store: RunLogReadStore, runId: string, cursor?: RunLogCursor, pageLimit?: number): Promise<RunEventRecord[]>;
package/follow.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Following a run log.
4
+ *
5
+ * Every surface — a desktop chat pane, a web execution view, a CLI tail, the
6
+ * resume path — is the same reader: hold a cursor, ask for what came after it.
7
+ * That is what makes local and cloud runs indistinguishable to a UI, so this is
8
+ * the only reader loop in the system.
9
+ *
10
+ * A push wakeup (LISTEN/NOTIFY, IPC, websocket) is an optimisation, not a
11
+ * requirement: `waitForChange` short-circuits the delay when it resolves, and
12
+ * without one the loop degrades to polling at `pollIntervalMs`.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.follow = follow;
16
+ exports.readAll = readAll;
17
+ const store_1 = require("./store");
18
+ const defaultSleep = (ms, signal) => new Promise((resolve) => {
19
+ const timer = setTimeout(resolve, ms);
20
+ signal?.addEventListener('abort', () => {
21
+ clearTimeout(timer);
22
+ resolve();
23
+ }, { once: true });
24
+ });
25
+ /**
26
+ * Yield every batch of new records until the run reaches a terminal state or
27
+ * the caller aborts. Batches are yielded as read, so a caller can project
28
+ * incrementally rather than re-projecting the whole run per frame.
29
+ */
30
+ async function* follow(store, runId, options = {}) {
31
+ const pollIntervalMs = options.pollIntervalMs ?? 500;
32
+ const sleep = options.sleep ?? defaultSleep;
33
+ let cursor = options.cursor ?? store_1.START;
34
+ while (!options.signal?.aborted) {
35
+ const page = await store.read(runId, cursor, options.limit);
36
+ if (page.records.length > 0) {
37
+ cursor = (0, store_1.cursorAfter)(page.records, cursor);
38
+ yield page.records;
39
+ if (options.isTerminal?.(page.records))
40
+ return;
41
+ // Drain before waiting: a burst of tool output should not be paced by the
42
+ // poll interval.
43
+ continue;
44
+ }
45
+ if (options.waitForChange) {
46
+ await Promise.race([
47
+ options.waitForChange(options.signal),
48
+ sleep(pollIntervalMs, options.signal)
49
+ ]);
50
+ }
51
+ else {
52
+ await sleep(pollIntervalMs, options.signal);
53
+ }
54
+ }
55
+ }
56
+ /** Read a run to its current end in one pass. */
57
+ async function readAll(store, runId, cursor = store_1.START, pageLimit = 500) {
58
+ const records = [];
59
+ let position = cursor;
60
+ for (;;) {
61
+ const page = await store.read(runId, position, pageLimit);
62
+ if (page.records.length === 0)
63
+ return records;
64
+ records.push(...page.records);
65
+ position = (0, store_1.cursorAfter)(page.records, position);
66
+ if (page.records.length < pageLimit)
67
+ return records;
68
+ }
69
+ }
package/index.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `@agentic-kit/run-log` — the append-only run log: one ordered record of what
3
+ * an agent run did, wherever it ran.
4
+ *
5
+ * Browser-safe on purpose: renderers import the projectors, so nothing here may
6
+ * reach for a node builtin. The filesystem store lives behind
7
+ * `@agentic-kit/run-log/file-store`.
8
+ */
9
+ export { follow, type FollowOptions, readAll } from './follow';
10
+ export { assertPiSessionEntry, contentText, isAssistantMessage, isPiBranchSummaryEntry, isPiCompactionEntry, isPiMessageEntry, isPiSessionHeader, isToolResultMessage, type PiAssistantMessage, type PiBashExecutionMessage, type PiBranchSummaryEntry, type PiCompactionEntry, type PiContent, type PiCustomMessage, type PiEntryBase, type PiImageContent, type PiMessage, type PiMessageEntry, type PiOtherEntry, type PiSessionEntry, type PiSessionHeader, type PiSummaryMessage, type PiTextContent, type PiThinkingContent, type PiToolCallContent, type PiToolResultMessage, type PiUsage, type PiUsageCost, type PiUserMessage, toolCalls } from './pi-entry';
11
+ export { type BashPart, type Conversation, type ConversationPart, type CustomPart, projectParts, type SummaryPart, type TextPart, type ThinkingPart, type ToolPart, type ToolStatus, type UnknownPart } from './projectors/parts';
12
+ export { parseSessionJsonl, projectSession, type SessionProjection, type SessionProjectionOptions } from './projectors/session';
13
+ export { APPROVAL_REQUEST_TYPE, APPROVAL_RESOLUTION_TYPE, type ApprovalRequestInput, approvalRequestMessage, type ApprovalResolutionInput, approvalResolutionMessage, type ApprovalState, projectToolState, type ToolCallState, type ToolCallStatus, type ToolStateProjection } from './projectors/tool-state';
14
+ export { modelKey, type ModelUsage, projectUsage, type RunUsage, type UsageTotals } from './projectors/usage';
15
+ export { assertOrdered, assertRunEventRecord, idempotencyKey, RUN_LOG_WRAPPER_VERSION, type RunEventRecord, SUPPORTED_PI_SESSION_VERSION, wrapEntry, type WrapEntryOptions } from './record';
16
+ export { type AppendOptions, cursorAfter, MemoryRunLogStore, type RunLogAppendStore, type RunLogCursor, type RunLogPage, type RunLogReadStore, type RunLogStore, START } from './store';
package/index.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /**
3
+ * `@agentic-kit/run-log` — the append-only run log: one ordered record of what
4
+ * an agent run did, wherever it ran.
5
+ *
6
+ * Browser-safe on purpose: renderers import the projectors, so nothing here may
7
+ * reach for a node builtin. The filesystem store lives behind
8
+ * `@agentic-kit/run-log/file-store`.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.START = exports.MemoryRunLogStore = exports.cursorAfter = exports.wrapEntry = exports.SUPPORTED_PI_SESSION_VERSION = exports.RUN_LOG_WRAPPER_VERSION = exports.idempotencyKey = exports.assertRunEventRecord = exports.assertOrdered = exports.projectUsage = exports.modelKey = exports.projectToolState = exports.approvalResolutionMessage = exports.approvalRequestMessage = exports.APPROVAL_RESOLUTION_TYPE = exports.APPROVAL_REQUEST_TYPE = exports.projectSession = exports.parseSessionJsonl = exports.projectParts = exports.toolCalls = exports.isToolResultMessage = exports.isPiSessionHeader = exports.isPiMessageEntry = exports.isPiCompactionEntry = exports.isPiBranchSummaryEntry = exports.isAssistantMessage = exports.contentText = exports.assertPiSessionEntry = exports.readAll = exports.follow = void 0;
12
+ var follow_1 = require("./follow");
13
+ Object.defineProperty(exports, "follow", { enumerable: true, get: function () { return follow_1.follow; } });
14
+ Object.defineProperty(exports, "readAll", { enumerable: true, get: function () { return follow_1.readAll; } });
15
+ var pi_entry_1 = require("./pi-entry");
16
+ Object.defineProperty(exports, "assertPiSessionEntry", { enumerable: true, get: function () { return pi_entry_1.assertPiSessionEntry; } });
17
+ Object.defineProperty(exports, "contentText", { enumerable: true, get: function () { return pi_entry_1.contentText; } });
18
+ Object.defineProperty(exports, "isAssistantMessage", { enumerable: true, get: function () { return pi_entry_1.isAssistantMessage; } });
19
+ Object.defineProperty(exports, "isPiBranchSummaryEntry", { enumerable: true, get: function () { return pi_entry_1.isPiBranchSummaryEntry; } });
20
+ Object.defineProperty(exports, "isPiCompactionEntry", { enumerable: true, get: function () { return pi_entry_1.isPiCompactionEntry; } });
21
+ Object.defineProperty(exports, "isPiMessageEntry", { enumerable: true, get: function () { return pi_entry_1.isPiMessageEntry; } });
22
+ Object.defineProperty(exports, "isPiSessionHeader", { enumerable: true, get: function () { return pi_entry_1.isPiSessionHeader; } });
23
+ Object.defineProperty(exports, "isToolResultMessage", { enumerable: true, get: function () { return pi_entry_1.isToolResultMessage; } });
24
+ Object.defineProperty(exports, "toolCalls", { enumerable: true, get: function () { return pi_entry_1.toolCalls; } });
25
+ var parts_1 = require("./projectors/parts");
26
+ Object.defineProperty(exports, "projectParts", { enumerable: true, get: function () { return parts_1.projectParts; } });
27
+ var session_1 = require("./projectors/session");
28
+ Object.defineProperty(exports, "parseSessionJsonl", { enumerable: true, get: function () { return session_1.parseSessionJsonl; } });
29
+ Object.defineProperty(exports, "projectSession", { enumerable: true, get: function () { return session_1.projectSession; } });
30
+ var tool_state_1 = require("./projectors/tool-state");
31
+ Object.defineProperty(exports, "APPROVAL_REQUEST_TYPE", { enumerable: true, get: function () { return tool_state_1.APPROVAL_REQUEST_TYPE; } });
32
+ Object.defineProperty(exports, "APPROVAL_RESOLUTION_TYPE", { enumerable: true, get: function () { return tool_state_1.APPROVAL_RESOLUTION_TYPE; } });
33
+ Object.defineProperty(exports, "approvalRequestMessage", { enumerable: true, get: function () { return tool_state_1.approvalRequestMessage; } });
34
+ Object.defineProperty(exports, "approvalResolutionMessage", { enumerable: true, get: function () { return tool_state_1.approvalResolutionMessage; } });
35
+ Object.defineProperty(exports, "projectToolState", { enumerable: true, get: function () { return tool_state_1.projectToolState; } });
36
+ var usage_1 = require("./projectors/usage");
37
+ Object.defineProperty(exports, "modelKey", { enumerable: true, get: function () { return usage_1.modelKey; } });
38
+ Object.defineProperty(exports, "projectUsage", { enumerable: true, get: function () { return usage_1.projectUsage; } });
39
+ var record_1 = require("./record");
40
+ Object.defineProperty(exports, "assertOrdered", { enumerable: true, get: function () { return record_1.assertOrdered; } });
41
+ Object.defineProperty(exports, "assertRunEventRecord", { enumerable: true, get: function () { return record_1.assertRunEventRecord; } });
42
+ Object.defineProperty(exports, "idempotencyKey", { enumerable: true, get: function () { return record_1.idempotencyKey; } });
43
+ Object.defineProperty(exports, "RUN_LOG_WRAPPER_VERSION", { enumerable: true, get: function () { return record_1.RUN_LOG_WRAPPER_VERSION; } });
44
+ Object.defineProperty(exports, "SUPPORTED_PI_SESSION_VERSION", { enumerable: true, get: function () { return record_1.SUPPORTED_PI_SESSION_VERSION; } });
45
+ Object.defineProperty(exports, "wrapEntry", { enumerable: true, get: function () { return record_1.wrapEntry; } });
46
+ var store_1 = require("./store");
47
+ Object.defineProperty(exports, "cursorAfter", { enumerable: true, get: function () { return store_1.cursorAfter; } });
48
+ Object.defineProperty(exports, "MemoryRunLogStore", { enumerable: true, get: function () { return store_1.MemoryRunLogStore; } });
49
+ Object.defineProperty(exports, "START", { enumerable: true, get: function () { return store_1.START; } });
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@agentic-kit/run-log",
3
+ "version": "0.2.0",
4
+ "author": "Constructive <developers@constructive.io>",
5
+ "description": "The append-only agent run log — pi session entries stored verbatim under a run/seq wrapper, with projections for transcript, usage, tool state and resumable sessions",
6
+ "main": "index.js",
7
+ "module": "esm/index.js",
8
+ "types": "index.d.ts",
9
+ "homepage": "https://github.com/constructive-io/constructive",
10
+ "license": "SEE LICENSE IN LICENSE",
11
+ "publishConfig": {
12
+ "access": "public",
13
+ "directory": "dist"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/constructive-io/constructive"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/constructive-io/constructive/issues"
21
+ },
22
+ "scripts": {
23
+ "clean": "makage clean",
24
+ "prepack": "npm run build",
25
+ "build": "makage build",
26
+ "build:dev": "makage build --dev",
27
+ "lint": "eslint . --fix",
28
+ "test": "jest",
29
+ "test:watch": "jest --watch"
30
+ },
31
+ "keywords": [
32
+ "agentic-kit",
33
+ "pi",
34
+ "coding-agent",
35
+ "run-log",
36
+ "constructive"
37
+ ],
38
+ "gitHead": "d4bf3a37545daad7246505a96ae8a4b87f44d53c"
39
+ }