@nanobpm/agentic 0.1.0 → 0.4.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.
Files changed (117) hide show
  1. package/README.md +1 -0
  2. package/dist/demand/model.d.ts +7 -4
  3. package/dist/demand/model.js +22 -4
  4. package/dist/demand/taskdef.d.ts +13 -1
  5. package/dist/demand/taskdef.js +20 -2
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/protocol/conformance/frames.js +32 -4
  9. package/dist/protocol/index.d.ts +1 -1
  10. package/dist/protocol/payloads.d.ts +44 -0
  11. package/dist/protocol/payloads.js +61 -7
  12. package/dist/session/acp/client.d.ts +109 -0
  13. package/dist/session/acp/client.js +254 -0
  14. package/dist/session/acp/index.d.ts +27 -0
  15. package/dist/session/acp/index.js +27 -0
  16. package/dist/session/acp/jsonrpc.d.ts +25 -0
  17. package/dist/session/acp/jsonrpc.js +148 -0
  18. package/dist/session/acp/normalize.d.ts +48 -0
  19. package/dist/session/acp/normalize.js +162 -0
  20. package/dist/session/acp/protocol.d.ts +94 -0
  21. package/dist/session/acp/protocol.js +136 -0
  22. package/dist/session/acp/spawn.d.ts +36 -0
  23. package/dist/session/acp/spawn.js +68 -0
  24. package/dist/session/acp/transport.d.ts +62 -0
  25. package/dist/session/acp/transport.js +126 -0
  26. package/dist/session/adapter.d.ts +135 -0
  27. package/dist/session/adapter.js +24 -0
  28. package/dist/session/backend.d.ts +43 -0
  29. package/dist/session/backend.js +95 -0
  30. package/dist/session/events.d.ts +152 -0
  31. package/dist/session/events.js +192 -0
  32. package/dist/session/index.d.ts +31 -0
  33. package/dist/session/index.js +5 -0
  34. package/dist/session/log.d.ts +107 -0
  35. package/dist/session/log.js +351 -0
  36. package/dist/session/normalizer/claude.d.ts +23 -0
  37. package/dist/session/normalizer/claude.js +138 -0
  38. package/dist/session/normalizer/copilot.d.ts +27 -0
  39. package/dist/session/normalizer/copilot.js +105 -0
  40. package/dist/session/normalizer/deepseek.d.ts +11 -0
  41. package/dist/session/normalizer/deepseek.js +68 -0
  42. package/dist/session/normalizer/index.d.ts +36 -0
  43. package/dist/session/normalizer/index.js +29 -0
  44. package/dist/session/normalizer/kimi.d.ts +10 -0
  45. package/dist/session/normalizer/kimi.js +80 -0
  46. package/dist/session/normalizer/link.d.ts +36 -0
  47. package/dist/session/normalizer/link.js +56 -0
  48. package/dist/session/normalizer/pi.d.ts +13 -0
  49. package/dist/session/normalizer/pi.js +61 -0
  50. package/dist/session/normalizer/qwen.d.ts +11 -0
  51. package/dist/session/normalizer/qwen.js +65 -0
  52. package/dist/session/normalizer/record.d.ts +21 -0
  53. package/dist/session/normalizer/record.js +87 -0
  54. package/dist/session/normalizer/types.d.ts +139 -0
  55. package/dist/session/normalizer/types.js +31 -0
  56. package/dist/session/schema.d.ts +38 -0
  57. package/dist/session/schema.js +74 -0
  58. package/package.json +17 -1
  59. package/src/demand/model.test.ts +82 -4
  60. package/src/demand/model.ts +30 -9
  61. package/src/demand/taskdef.test.ts +51 -6
  62. package/src/demand/taskdef.ts +31 -2
  63. package/src/index.ts +1 -0
  64. package/src/protocol/conformance/frames.ts +32 -4
  65. package/src/protocol/index.ts +4 -0
  66. package/src/protocol/payloads.test.ts +31 -1
  67. package/src/protocol/payloads.ts +110 -7
  68. package/src/session/acp/client.test.ts +222 -0
  69. package/src/session/acp/client.ts +356 -0
  70. package/src/session/acp/fake-agent.ts +71 -0
  71. package/src/session/acp/index.ts +68 -0
  72. package/src/session/acp/integration.test.ts +37 -0
  73. package/src/session/acp/jsonrpc.test.ts +75 -0
  74. package/src/session/acp/jsonrpc.ts +171 -0
  75. package/src/session/acp/normalize.test.ts +150 -0
  76. package/src/session/acp/normalize.ts +204 -0
  77. package/src/session/acp/protocol.ts +178 -0
  78. package/src/session/acp/spawn.test.ts +45 -0
  79. package/src/session/acp/spawn.ts +91 -0
  80. package/src/session/acp/transport.test.ts +82 -0
  81. package/src/session/acp/transport.ts +155 -0
  82. package/src/session/adapter.ts +159 -0
  83. package/src/session/backend.test.ts +198 -0
  84. package/src/session/backend.ts +128 -0
  85. package/src/session/events.test.ts +168 -0
  86. package/src/session/events.ts +347 -0
  87. package/src/session/index.ts +67 -0
  88. package/src/session/log.test.ts +215 -0
  89. package/src/session/log.ts +525 -0
  90. package/src/session/normalizer/backend-integration.test.ts +103 -0
  91. package/src/session/normalizer/claude.test.ts +68 -0
  92. package/src/session/normalizer/claude.ts +136 -0
  93. package/src/session/normalizer/copilot.test.ts +59 -0
  94. package/src/session/normalizer/copilot.ts +133 -0
  95. package/src/session/normalizer/deepseek.ts +80 -0
  96. package/src/session/normalizer/index.ts +61 -0
  97. package/src/session/normalizer/kimi.ts +82 -0
  98. package/src/session/normalizer/link.test.ts +24 -0
  99. package/src/session/normalizer/link.ts +81 -0
  100. package/src/session/normalizer/pi.ts +75 -0
  101. package/src/session/normalizer/probe.test.ts +49 -0
  102. package/src/session/normalizer/qwen.test.ts +20 -0
  103. package/src/session/normalizer/qwen.ts +77 -0
  104. package/src/session/normalizer/record.test.ts +68 -0
  105. package/src/session/normalizer/record.ts +88 -0
  106. package/src/session/normalizer/resume.test.ts +25 -0
  107. package/src/session/normalizer/types.ts +152 -0
  108. package/src/session/normalizer/vectors.test.ts +180 -0
  109. package/src/session/schema.test.ts +84 -0
  110. package/src/session/schema.ts +78 -0
  111. package/src/session/test-db.ts +56 -0
  112. package/dist/blackboard/test-db.d.ts +0 -5
  113. package/dist/blackboard/test-db.js +0 -42
  114. package/dist/presence/test-db.d.ts +0 -5
  115. package/dist/presence/test-db.js +0 -42
  116. package/dist/transcript/test-db.d.ts +0 -5
  117. package/dist/transcript/test-db.js +0 -41
@@ -0,0 +1,192 @@
1
+ /**
2
+ * The canonical `SessionEvent` model — ADR 0062, slice 1 (the shared contract).
3
+ *
4
+ * This is **Nano's own** agent-session event model: the single schema every
5
+ * harness dialect (ACP, stream-json, a native normalizer, …) normalizes *into*.
6
+ * We never adopt an external harness schema as ours — those are ingestion
7
+ * details owned by the later slices; this union is the stable interface they all
8
+ * target.
9
+ *
10
+ * ## The causal chain
11
+ *
12
+ * A session is an append-only log of events. Two orthogonal orderings make the
13
+ * log both replayable and mergeable:
14
+ *
15
+ * - a **monotonic, gap-free `offset`** assigned by the authoritative log on
16
+ * append (see {@link AppendedSessionEvent}); it is the resume coordinate —
17
+ * `restore` hands back everything up to a checkpoint offset.
18
+ * - a **causal `parentId`** the producer stamps: the id of the event this one
19
+ * logically follows (`null` for the first event of a session). Offset gives a
20
+ * total order for replay; `parentId` records the *causal* edge, which survives
21
+ * a compaction that rewrites offsets.
22
+ *
23
+ * The producer owns identity (`id`) and causality (`parentId`); the log owns
24
+ * ordering (`offset`) and fencing (`incarnation`). Keeping those responsibilities
25
+ * split is what lets a resumed incarnation continue the same causal chain at a
26
+ * fresh offset without the producer knowing the log's internal cursor.
27
+ */
28
+ /** The set of valid event types, for a runtime membership check at the DB boundary. */
29
+ export const SESSION_EVENT_TYPES = [
30
+ "system",
31
+ "user",
32
+ "assistant",
33
+ "reasoning",
34
+ "tool-call",
35
+ "tool-result",
36
+ "compaction",
37
+ "usage",
38
+ "turn-start",
39
+ "turn-end",
40
+ ];
41
+ /** Raised when a value read back from storage is not a well-formed session event. */
42
+ export class SessionEventShapeError extends Error {
43
+ constructor(message) {
44
+ super(message);
45
+ this.name = "SessionEventShapeError";
46
+ }
47
+ }
48
+ function isRecord(value) {
49
+ return typeof value === "object" && value !== null && !Array.isArray(value);
50
+ }
51
+ function reqString(obj, field) {
52
+ const v = obj[field];
53
+ if (typeof v !== "string") {
54
+ throw new SessionEventShapeError(`session event field "${field}" must be a string, got ${typeof v}`);
55
+ }
56
+ return v;
57
+ }
58
+ function optString(obj, field) {
59
+ const v = obj[field];
60
+ if (v === undefined)
61
+ return undefined;
62
+ if (typeof v !== "string") {
63
+ throw new SessionEventShapeError(`session event field "${field}" must be a string when present, got ${typeof v}`);
64
+ }
65
+ return v;
66
+ }
67
+ function reqNonNegInt(obj, field) {
68
+ const v = obj[field];
69
+ if (typeof v !== "number" || !Number.isSafeInteger(v) || v < 0) {
70
+ throw new SessionEventShapeError(`session event field "${field}" must be a non-negative safe integer, got ${String(v)}`);
71
+ }
72
+ return v;
73
+ }
74
+ function reqBool(obj, field) {
75
+ const v = obj[field];
76
+ if (typeof v !== "boolean") {
77
+ throw new SessionEventShapeError(`session event field "${field}" must be a boolean, got ${typeof v}`);
78
+ }
79
+ return v;
80
+ }
81
+ function parentId(obj) {
82
+ const v = obj.parentId;
83
+ if (v === null)
84
+ return null;
85
+ if (typeof v === "string")
86
+ return v;
87
+ throw new SessionEventShapeError(`session event "parentId" must be a string or null, got ${typeof v}`);
88
+ }
89
+ /**
90
+ * Coerce a required opaque payload (a tool-call `args` / tool-result `result`) to
91
+ * a JSON-serialisable value. These fields are documented as opaque *JSON-
92
+ * serialisable* values, but a dialect can legitimately omit them (e.g. a tool
93
+ * call with no arguments surfaces as `obj.arguments ?? obj.args === undefined`).
94
+ * `undefined` is not JSON-serialisable — `JSON.stringify` drops the key — so an
95
+ * un-normalised `undefined` would persist an event that no longer round-trips to
96
+ * the same shape on replay. We normalise the absence to the canonical JSON "no
97
+ * value" (`null`) here, at the single boundary every dialect flows through, so
98
+ * they all get the same replay-stable guarantee (derivation over duplication).
99
+ */
100
+ function opaquePayload(value) {
101
+ return value === undefined ? null : value;
102
+ }
103
+ /**
104
+ * Parse and validate an untyped value (e.g. `JSON.parse` of a stored row) into a
105
+ * {@link SessionEvent}, reconstructing the exact union member for its `type`.
106
+ * Throws {@link SessionEventShapeError} on any malformed field. This is the
107
+ * single trusted boundary between untyped storage and the typed union — it never
108
+ * uses an `as`-cast to fabricate a shape (see AGENTS.md), it *builds* one field
109
+ * by field, so a corrupt row fails loudly instead of masquerading as valid.
110
+ */
111
+ export function parseSessionEvent(value) {
112
+ if (!isRecord(value)) {
113
+ throw new SessionEventShapeError(`session event must be an object, got ${typeof value}`);
114
+ }
115
+ const id = reqString(value, "id");
116
+ const parent = parentId(value);
117
+ const type = value.type;
118
+ switch (type) {
119
+ case "system":
120
+ return { type, id, parentId: parent, text: reqString(value, "text") };
121
+ case "user":
122
+ return { type, id, parentId: parent, text: reqString(value, "text") };
123
+ case "assistant":
124
+ return { type, id, parentId: parent, text: reqString(value, "text") };
125
+ case "reasoning": {
126
+ const event = { type, id, parentId: parent };
127
+ const text = optString(value, "text");
128
+ const cont = optString(value, "providerContinuation");
129
+ return {
130
+ ...event,
131
+ ...(text !== undefined ? { text } : {}),
132
+ ...(cont !== undefined ? { providerContinuation: cont } : {}),
133
+ };
134
+ }
135
+ case "tool-call":
136
+ return {
137
+ type,
138
+ id,
139
+ parentId: parent,
140
+ callId: reqString(value, "callId"),
141
+ name: reqString(value, "name"),
142
+ args: opaquePayload(value.args),
143
+ };
144
+ case "tool-result":
145
+ return {
146
+ type,
147
+ id,
148
+ parentId: parent,
149
+ callId: reqString(value, "callId"),
150
+ ok: reqBool(value, "ok"),
151
+ result: opaquePayload(value.result),
152
+ };
153
+ case "compaction": {
154
+ const reason = value.reason;
155
+ if (reason !== "compaction" && reason !== "truncation") {
156
+ throw new SessionEventShapeError(`compaction "reason" must be "compaction" or "truncation", got ${String(reason)}`);
157
+ }
158
+ const summary = optString(value, "summary");
159
+ const replacesFrom = reqNonNegInt(value, "replacesFrom");
160
+ const replacesTo = reqNonNegInt(value, "replacesTo");
161
+ if (replacesTo < replacesFrom) {
162
+ throw new SessionEventShapeError(`compaction "replacesTo" (${replacesTo}) must be >= "replacesFrom" (${replacesFrom})`);
163
+ }
164
+ return {
165
+ type,
166
+ id,
167
+ parentId: parent,
168
+ reason,
169
+ replacesFrom,
170
+ replacesTo,
171
+ ...(summary !== undefined ? { summary } : {}),
172
+ };
173
+ }
174
+ case "usage": {
175
+ const model = optString(value, "model");
176
+ return {
177
+ type,
178
+ id,
179
+ parentId: parent,
180
+ inputTokens: reqNonNegInt(value, "inputTokens"),
181
+ outputTokens: reqNonNegInt(value, "outputTokens"),
182
+ ...(model !== undefined ? { model } : {}),
183
+ };
184
+ }
185
+ case "turn-start":
186
+ return { type, id, parentId: parent, turn: reqNonNegInt(value, "turn") };
187
+ case "turn-end":
188
+ return { type, id, parentId: parent, turn: reqNonNegInt(value, "turn") };
189
+ default:
190
+ throw new SessionEventShapeError(`unknown session event type: ${JSON.stringify(type)}`);
191
+ }
192
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `@nanobpm/agentic/session` — the canonical agent-session contract (ADR 0062,
3
+ * slice 1). The foundation the two ingestion backends (ACP, normalisers) and the
4
+ * nano-workforce world-restore all code against in parallel.
5
+ *
6
+ * Exports, in the order a consumer meets them:
7
+ * - the canonical {@link SessionEvent} union every harness dialect normalises
8
+ * into, plus {@link parseSessionEvent} (the untyped-storage boundary);
9
+ * - the three-method {@link SessionAdapter} interface (emit/checkpoint/restore)
10
+ * with its {@link ActivationKey}, {@link SessionCheckpoint} and
11
+ * {@link SessionSeed} types;
12
+ * - the {@link SessionLog} port and its two backends — the in-memory reference
13
+ * ({@link InMemorySessionLog}, the stub) and the durable, authoritative
14
+ * {@link SqliteSessionLog} that promotes the ADR 0056 §12 relay ring + fence;
15
+ * - {@link SessionBackend} (the one adapter implementation) and the
16
+ * {@link openInMemorySession} / {@link openSqliteSession} factories.
17
+ *
18
+ * The new DB schema ships as the forward-only migration
19
+ * `db/migrations/005_agentic_session.sql`, mirrored by {@link SESSION_SCHEMA_SQL}
20
+ * and kept in lockstep by a drift-guard test. Nothing here rides the Camunda-8
21
+ * engine — the log is app-tier (ADR 0056 boundary preserved).
22
+ */
23
+ export type { AppendedSessionEvent, AssistantMessageEvent, CompactionEvent, ReasoningEvent, SessionEvent, SessionEventEnvelope, SessionEventType, SystemMessageEvent, ToolCallEvent, ToolResultEvent, TurnEndEvent, TurnStartEvent, UsageEvent, UserMessageEvent, } from "./events.ts";
24
+ export { parseSessionEvent, SESSION_EVENT_TYPES, SessionEventShapeError } from "./events.ts";
25
+ export type { ActivationKey, EffectEntry, EffectLedger, SessionAdapter, SessionCheckpoint, SessionSeed, } from "./adapter.ts";
26
+ export { activationKeyString, StaleIncarnationError } from "./adapter.ts";
27
+ export type { Clock, SessionLog, SqliteDb } from "./log.ts";
28
+ export { InMemorySessionLog, SessionLogCorruptionError, SqliteSessionLog, systemClock, } from "./log.ts";
29
+ export type { SessionBackendOptions } from "./backend.ts";
30
+ export { openInMemorySession, openSqliteSession, SessionBackend } from "./backend.ts";
31
+ export { SESSION_CHECKPOINT_TABLE, SESSION_EVENT_TABLE, SESSION_LOG_TABLE, SESSION_SCHEMA_SQL, } from "./schema.ts";
@@ -0,0 +1,5 @@
1
+ export { parseSessionEvent, SESSION_EVENT_TYPES, SessionEventShapeError } from "./events.js";
2
+ export { activationKeyString, StaleIncarnationError } from "./adapter.js";
3
+ export { InMemorySessionLog, SessionLogCorruptionError, SqliteSessionLog, systemClock, } from "./log.js";
4
+ export { openInMemorySession, openSqliteSession, SessionBackend } from "./backend.js";
5
+ export { SESSION_CHECKPOINT_TABLE, SESSION_EVENT_TABLE, SESSION_LOG_TABLE, SESSION_SCHEMA_SQL, } from "./schema.js";
@@ -0,0 +1,107 @@
1
+ import { type ActivationKey, type SessionCheckpoint } from "./adapter.ts";
2
+ import { type AppendedSessionEvent, type SessionEvent } from "./events.ts";
3
+ /**
4
+ * The authoritative-log port the {@link SessionBackend} adapter writes through.
5
+ * Two backends implement it: {@link InMemorySessionLog} (the reference/stub) and
6
+ * {@link SqliteSessionLog} (durable, over the app DataLayer). All writes are
7
+ * fenced by `incarnation`; a stale writer throws {@link StaleIncarnationError}.
8
+ */
9
+ export interface SessionLog {
10
+ /**
11
+ * Take (or renew) the lease for `key` at `incarnation`, advancing the fence
12
+ * high-water mark. Throws {@link StaleIncarnationError} if a newer incarnation
13
+ * already owns the activation. Called once when an adapter is constructed so a
14
+ * re-lease fences prior incarnations immediately, before any write.
15
+ */
16
+ lease(key: ActivationKey, incarnation: number): void;
17
+ /** The current (highest leased) incarnation for `key`, or `undefined`. */
18
+ currentIncarnation(key: ActivationKey): number | undefined;
19
+ /** The offset the next appended event will occupy (also the event count). */
20
+ nextOffset(key: ActivationKey): number;
21
+ /**
22
+ * Append `event` at `offset` under `incarnation`, returning it stamped as an
23
+ * {@link AppendedSessionEvent}. Fenced. `offset` must be `<= nextOffset`: at
24
+ * `nextOffset` it extends the log; below it (a resume writing back into the log
25
+ * after `restore`) it first drops the now-superseded uncommitted tail
26
+ * `[offset, nextOffset)` — **and every checkpoint pinned above `offset`**, which
27
+ * would otherwise dangle past the rewritten head and mis-seed a later `restore`
28
+ * (a gap `RangeError` on the next `emit`) — and then writes: an idempotent
29
+ * re-key that keeps the authoritative log gap-free. An `offset > nextOffset` is
30
+ * a gap and throws.
31
+ */
32
+ append(key: ActivationKey, incarnation: number, offset: number, event: SessionEvent): AppendedSessionEvent;
33
+ /** Persist a checkpoint (fenced by `incarnation`). Returns it unchanged. */
34
+ putCheckpoint(key: ActivationKey, incarnation: number, checkpoint: SessionCheckpoint): SessionCheckpoint;
35
+ /** The checkpoint with the highest offset (newest), or `undefined`. */
36
+ latestCheckpoint(key: ActivationKey): SessionCheckpoint | undefined;
37
+ /** A specific checkpoint by id, or `undefined`. */
38
+ getCheckpoint(key: ActivationKey, id: string): SessionCheckpoint | undefined;
39
+ /** The events with `from <= offset < to`, in offset order. `to` defaults to the head. */
40
+ replay(key: ActivationKey, from: number, to?: number): AppendedSessionEvent[];
41
+ }
42
+ /**
43
+ * The in-memory reference backend (the stub slices 2–5 code against and the tests
44
+ * exercise). Reuses the relay {@link IncarnationFence} verbatim and keeps each
45
+ * activation's full event array — the authoritative, non-evicting analogue of the
46
+ * relay ring's resume window.
47
+ */
48
+ export declare class InMemorySessionLog implements SessionLog {
49
+ #private;
50
+ lease(key: ActivationKey, incarnation: number): void;
51
+ currentIncarnation(key: ActivationKey): number | undefined;
52
+ nextOffset(key: ActivationKey): number;
53
+ append(key: ActivationKey, incarnation: number, offset: number, event: SessionEvent): AppendedSessionEvent;
54
+ putCheckpoint(key: ActivationKey, incarnation: number, checkpoint: SessionCheckpoint): SessionCheckpoint;
55
+ latestCheckpoint(key: ActivationKey): SessionCheckpoint | undefined;
56
+ getCheckpoint(key: ActivationKey, id: string): SessionCheckpoint | undefined;
57
+ replay(key: ActivationKey, from: number, to?: number): AppendedSessionEvent[];
58
+ }
59
+ /**
60
+ * The minimal synchronous SQLite handle the durable log needs — structurally the
61
+ * same surface the Urban runtime's DataLayer exposes (`host.openSqlite`), and
62
+ * identical to the presence/transcript stores' `SqliteDb`. Kept local so the log
63
+ * depends on a shape, not on the runtime package.
64
+ */
65
+ export interface SqliteDb {
66
+ exec(sql: string): void;
67
+ run(sql: string, params?: unknown[]): {
68
+ changes: number;
69
+ lastInsertRowid: number | bigint;
70
+ };
71
+ all<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
72
+ }
73
+ /** A monotonic wall clock, injectable for deterministic tests. */
74
+ export interface Clock {
75
+ now(): number;
76
+ }
77
+ /** The default clock: `Date.now()`. */
78
+ export declare const systemClock: Clock;
79
+ /**
80
+ * The durable authoritative log over the app DataLayer/SQLite. The fence
81
+ * high-water lives in the activation row's `incarnation` column, so fencing
82
+ * survives a process restart — the durable counterpart of the in-memory
83
+ * {@link IncarnationFence}.
84
+ */
85
+ export declare class SqliteSessionLog implements SessionLog {
86
+ #private;
87
+ constructor(db: SqliteDb, options?: {
88
+ clock?: Clock;
89
+ });
90
+ /** Apply the canonical DDL (idempotent). Identical to the boot migration (drift-guarded). */
91
+ ensureSchema(): void;
92
+ lease(key: ActivationKey, incarnation: number): void;
93
+ currentIncarnation(key: ActivationKey): number | undefined;
94
+ nextOffset(key: ActivationKey): number;
95
+ append(key: ActivationKey, incarnation: number, offset: number, event: SessionEvent): AppendedSessionEvent;
96
+ putCheckpoint(key: ActivationKey, incarnation: number, checkpoint: SessionCheckpoint): SessionCheckpoint;
97
+ latestCheckpoint(key: ActivationKey): SessionCheckpoint | undefined;
98
+ getCheckpoint(key: ActivationKey, id: string): SessionCheckpoint | undefined;
99
+ replay(key: ActivationKey, from: number, to?: number): AppendedSessionEvent[];
100
+ }
101
+ /**
102
+ * Raised when a row read back from the durable session log holds a value outside
103
+ * its domain (e.g. a corrupt effect-ledger JSON). Fail fast rather than coercing.
104
+ */
105
+ export declare class SessionLogCorruptionError extends Error {
106
+ constructor(message: string);
107
+ }