@morlay/session-rdb 0.1.9 → 0.1.10-alpha.2

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 (143) hide show
  1. package/README.md +24 -3
  2. package/dist/artifact.d.mts +118 -3
  3. package/dist/artifact.mjs +5 -3
  4. package/dist/{log-C0q5svm7.d.mts → backend-BKtJ5sO5.d.mts} +189 -291
  5. package/dist/backend-rdb-BDCntVDy.mjs +1341 -0
  6. package/dist/branch-CG1PUlO6.mjs +833 -0
  7. package/dist/deletion-SSX7IqU8.mjs +35 -0
  8. package/dist/deletion.d.mts +1 -3
  9. package/dist/deletion.mjs +2 -2
  10. package/dist/export-CfJQjQfr.mjs +123 -0
  11. package/dist/export.d.mts +1 -3
  12. package/dist/export.mjs +32 -57
  13. package/dist/import.d.mts +1 -3
  14. package/dist/import.mjs +32 -78
  15. package/dist/index-CUD2ZpTA.d.mts +71 -0
  16. package/dist/index.d.mts +20 -2
  17. package/dist/index.mjs +1562 -5
  18. package/dist/open-YoyD_kah.mjs +561 -0
  19. package/dist/organize.d.mts +9 -0
  20. package/dist/organize.mjs +30 -0
  21. package/dist/route-DpfY0zq-.mjs +114 -0
  22. package/dist/storage.d.mts +41 -50
  23. package/dist/storage.mjs +3 -1
  24. package/dist/testing.d.mts +9 -5
  25. package/dist/testing.mjs +27 -8
  26. package/dist/usage-row-BQQM-_t6.mjs +36 -0
  27. package/dist/usage.d.mts +1 -1
  28. package/dist/usage.mjs +8 -42
  29. package/dist/write-guard-CYrY58GM.mjs +174 -0
  30. package/package.json +32 -36
  31. package/src/artifact.ts +4 -1
  32. package/src/backend-rdb.ts +331 -0
  33. package/src/backend.ts +32 -15
  34. package/src/{branch.ts → branch/index.ts} +125 -112
  35. package/src/branch/port.ts +62 -0
  36. package/src/branch/semantics.ts +69 -0
  37. package/src/db/open.ts +180 -0
  38. package/src/db/stats.ts +449 -0
  39. package/src/deletion-error.ts +17 -0
  40. package/src/deletion.ts +19 -72
  41. package/src/entities/index.ts +16 -1
  42. package/src/entities/v3/event-usage.ts +3 -3
  43. package/src/entities/v3/events.ts +3 -3
  44. package/src/entities/v3/index.ts +4 -16
  45. package/src/entities/v3/persistence-state.ts +3 -3
  46. package/src/entities/v3/schema-meta.ts +3 -3
  47. package/src/entities/v3/session-counts.ts +3 -3
  48. package/src/entities/v3/session-events.ts +3 -3
  49. package/src/entities/v3/session-projcache-rows.ts +3 -3
  50. package/src/entities/v3/session-usage.ts +3 -3
  51. package/src/entities/v3/sessions.ts +3 -3
  52. package/src/entities/v3/storage-records.ts +17 -0
  53. package/src/entities/v3/storage-units.ts +3 -3
  54. package/src/{schema.ts → event-shape.ts} +0 -46
  55. package/src/export.ts +32 -78
  56. package/src/handles.ts +349 -0
  57. package/src/http/route.ts +178 -0
  58. package/src/import-storages.ts +5 -2
  59. package/src/import.ts +63 -125
  60. package/src/index.ts +15 -1630
  61. package/src/legacy.ts +3 -1
  62. package/src/live-routing.ts +205 -0
  63. package/src/log/export.ts +84 -0
  64. package/src/{log.ts → log/repair.ts} +1 -272
  65. package/src/log/rows.ts +107 -0
  66. package/src/log/usage-row.ts +64 -0
  67. package/src/migrations.ts +196 -0
  68. package/src/organize.ts +38 -0
  69. package/src/read-path.ts +190 -0
  70. package/src/routes.ts +2 -1
  71. package/src/rows.ts +25 -77
  72. package/src/session-ops.ts +444 -0
  73. package/src/session-query.ts +17 -4
  74. package/src/session-store.ts +675 -0
  75. package/src/stats-fold.ts +44 -0
  76. package/src/storage-takeover/index.ts +2 -5
  77. package/src/storage-takeover/legacy-domain-migration.ts +118 -0
  78. package/src/storage-takeover/projection-cache.ts +139 -77
  79. package/src/storage-takeover/read-model.ts +189 -0
  80. package/src/storage-takeover/repository.ts +238 -425
  81. package/src/storage-takeover/storage-backend.ts +47 -149
  82. package/src/storage-takeover/types.ts +45 -14
  83. package/src/storage-takeover/workspace-documents.ts +65 -0
  84. package/src/storage.ts +4 -2
  85. package/src/testing.ts +21 -1
  86. package/src/usage.ts +11 -65
  87. package/src/version.ts +13 -0
  88. package/src/write-path.ts +286 -0
  89. package/dist/branch-DbFW3rJX.mjs +0 -391
  90. package/dist/deletion-ODZFcbZm.mjs +0 -2218
  91. package/dist/gc.d.mts +0 -6
  92. package/dist/gc.mjs +0 -49
  93. package/dist/log-DYxdjJ-l.mjs +0 -562
  94. package/dist/routes-DGBlBE_I.mjs +0 -10
  95. package/dist/sqlite-DjOnMRh2.mjs +0 -1777
  96. package/drizzle/postgres/20260908072805_v2_initial/migration.sql +0 -58
  97. package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +0 -686
  98. package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +0 -1
  99. package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +0 -673
  100. package/drizzle/postgres/20260910120001_v3_storage_tables/migration.sql +0 -65
  101. package/drizzle/postgres/20260910120001_v3_storage_tables/snapshot.json +0 -1183
  102. package/drizzle/postgres/20260910130001_v3_session_title_backfill/migration.sql +0 -10
  103. package/drizzle/postgres/20260910130001_v3_session_title_backfill/snapshot.json +0 -1183
  104. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +0 -14
  105. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +0 -1309
  106. package/drizzle/postgres/20260921075900_v3_agent_preset/migration.sql +0 -1
  107. package/drizzle/postgres/20260922090001_v3_pinned_seq/migration.sql +0 -2
  108. package/drizzle/postgres/20260922093001_v3_last_event_at/migration.sql +0 -10
  109. package/drizzle/postgres/20260923120000_v3_usage_materialized/migration.sql +0 -48
  110. package/drizzle/postgres/20261008103001_v3_schedule_tasks/migration.sql +0 -11
  111. package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +0 -53
  112. package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +0 -492
  113. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +0 -6
  114. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +0 -513
  115. package/drizzle/sqlite/20260910120000_v3_storage_tables/migration.sql +0 -66
  116. package/drizzle/sqlite/20260910120000_v3_storage_tables/snapshot.json +0 -905
  117. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/migration.sql +0 -13
  118. package/drizzle/sqlite/20260910130000_v3_session_title_backfill/snapshot.json +0 -905
  119. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +0 -14
  120. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +0 -1031
  121. package/drizzle/sqlite/20260921075855_v3_agent_preset/migration.sql +0 -7
  122. package/drizzle/sqlite/20260921075855_v3_agent_preset/snapshot.json +0 -1041
  123. package/drizzle/sqlite/20260922090000_v3_pinned_seq/migration.sql +0 -4
  124. package/drizzle/sqlite/20260922093000_v3_last_event_at/migration.sql +0 -13
  125. package/drizzle/sqlite/20260923120000_v3_usage_materialized/migration.sql +0 -48
  126. package/drizzle/sqlite/20261008103000_v3_schedule_tasks/migration.sql +0 -14
  127. package/src/adapters/index.ts +0 -12
  128. package/src/adapters/to-postgres.ts +0 -93
  129. package/src/adapters/to-sqlite.ts +0 -83
  130. package/src/adapters/types.ts +0 -44
  131. package/src/drizzle/postgres-v2.ts +0 -10
  132. package/src/drizzle/postgres-v3.ts +0 -18
  133. package/src/drizzle/sqlite-v2.ts +0 -9
  134. package/src/drizzle/sqlite-v3.ts +0 -18
  135. package/src/entities/v2/index.ts +0 -20
  136. package/src/entities/v2/session-events.ts +0 -10
  137. package/src/entities/v3/schedule-tasks.ts +0 -16
  138. package/src/entities/v3/workspace-sessions.ts +0 -19
  139. package/src/entities/v3/workspace-state.ts +0 -12
  140. package/src/entities/v3/workspaces.ts +0 -14
  141. package/src/gc.ts +0 -77
  142. package/src/postgres.ts +0 -1015
  143. package/src/sqlite.ts +0 -1086
@@ -0,0 +1,833 @@
1
+ import { a as rowToMeta, i as rowToEvent, t as scanRows } from "./export-CfJQjQfr.mjs";
2
+ import { SESSION_FORMAT_VERSION, SessionLogOffset, SessionSeq } from "@deepseek-ai/dsh-session";
3
+ import { createSessionFormatCatalogWithChildren } from "@deepseek-ai/dsh-session-format-catalog";
4
+ import { randomUUID } from "node:crypto";
5
+ import { SessionBranch, SessionBranchError, balanceRewindPrefix, rewindKeepLength } from "@morlay/session-branch";
6
+ // src/log/repair.ts
7
+ const SURFACE_EVENT_TYPES = /* @__PURE__ */ new Set([
8
+ "system/message",
9
+ "developer/message",
10
+ "user/message",
11
+ "assistant/message",
12
+ "tool/result"
13
+ ]);
14
+ const METERING_EVENT_TYPES = /* @__PURE__ */ new Set(["compaction/summary", "compaction/prune"]);
15
+ function surfaceSeqIndex(events) {
16
+ const seqs = [];
17
+ for (const event of events) if (SURFACE_EVENT_TYPES.has(event.type)) seqs.push(event.seq);
18
+ return seqs;
19
+ }
20
+ function surfaceSeqsInRange(seqs, startSeq, endSeq) {
21
+ let low = 0;
22
+ let high = seqs.length;
23
+ while (low < high) {
24
+ const mid = low + high >> 1;
25
+ if (seqs[mid] < startSeq) low = mid + 1;
26
+ else high = mid;
27
+ }
28
+ const from = low;
29
+ high = seqs.length;
30
+ while (low < high) {
31
+ const mid = low + high >> 1;
32
+ if (seqs[mid] <= endSeq) low = mid + 1;
33
+ else high = mid;
34
+ }
35
+ return seqs.slice(from, low);
36
+ }
37
+ function recomputeReplaceProvenance(events) {
38
+ const seqs = surfaceSeqIndex(events);
39
+ for (let i = 0; i < events.length; i++) {
40
+ const raw = events[i];
41
+ const op = raw.surfaceOp;
42
+ if (typeof op !== "object" || op === null || op.op !== "replace") continue;
43
+ const { startSeq, endSeq } = op;
44
+ const metering = i > 0 ? events[i - 1] : void 0;
45
+ const meteringData = metering !== void 0 && METERING_EVENT_TYPES.has(metering.type) ? metering.data : void 0;
46
+ if (meteringData?.shadowedSeqs !== void 0) {
47
+ raw.sourceEventSeqs = meteringData.shadowedSeqs;
48
+ continue;
49
+ }
50
+ raw.sourceEventSeqs = surfaceSeqsInRange(seqs, startSeq, endSeq);
51
+ }
52
+ }
53
+ function isEventSeqLike(value) {
54
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && !Object.is(value, -0);
55
+ }
56
+ function isDeepEqualJson(a, b) {
57
+ if (a === b) return true;
58
+ if (Array.isArray(a) || Array.isArray(b)) {
59
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
60
+ return a.every((item, i) => isDeepEqualJson(item, b[i]));
61
+ }
62
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
63
+ const aKeys = Object.keys(a);
64
+ const bRecord = b;
65
+ if (aKeys.length !== Object.keys(bRecord).length) return false;
66
+ return aKeys.every((key) => Object.hasOwn(bRecord, key) && isDeepEqualJson(a[key], bRecord[key]));
67
+ }
68
+ function toolResultRewriteContentOnly(original, replacement) {
69
+ const originalData = original.data;
70
+ const replacementData = replacement.data;
71
+ const originalMessage = originalData["message"];
72
+ const replacementMessage = replacementData["message"];
73
+ if (!Array.isArray(originalMessage?.content) || !Array.isArray(replacementMessage?.content)) return false;
74
+ const rest = (data, message) => ({
75
+ ...data,
76
+ message: {
77
+ ...message,
78
+ content: null
79
+ }
80
+ });
81
+ return isDeepEqualJson(rest(originalData, originalMessage), rest(replacementData, replacementMessage));
82
+ }
83
+ function findSurfaceRepairs(events) {
84
+ const nodes = [];
85
+ const degradeToAppend = /* @__PURE__ */ new Set();
86
+ const addAppendMarker = /* @__PURE__ */ new Set();
87
+ const clearSurfaceOp = /* @__PURE__ */ new Set();
88
+ const clampEnd = /* @__PURE__ */ new Map();
89
+ for (let index = 0; index < events.length; index++) {
90
+ const event = events[index];
91
+ const op = event.surfaceOp;
92
+ if (op === void 0) {
93
+ if (SURFACE_EVENT_TYPES.has(event.type)) {
94
+ addAppendMarker.add(event.seq);
95
+ nodes.push(event.seq);
96
+ }
97
+ continue;
98
+ }
99
+ if (op === "append") {
100
+ if (SURFACE_EVENT_TYPES.has(event.type)) nodes.push(event.seq);
101
+ else clearSurfaceOp.add(event.seq);
102
+ continue;
103
+ }
104
+ if (!SURFACE_EVENT_TYPES.has(event.type)) {
105
+ clearSurfaceOp.add(event.seq);
106
+ continue;
107
+ }
108
+ const replace = typeof op === "object" && op !== null && !Array.isArray(op) ? op : void 0;
109
+ const start = replace?.["startSeq"];
110
+ const end = replace?.["endSeq"];
111
+ const shapeOk = replace !== void 0 && replace["op"] === "replace" && isEventSeqLike(start) && isEventSeqLike(end);
112
+ const startIdx = shapeOk ? nodes.indexOf(start) : -1;
113
+ let endIdx = shapeOk ? nodes.indexOf(end) : -1;
114
+ let clamped;
115
+ if (shapeOk && startIdx !== -1 && endIdx === -1) {
116
+ clamped = clampReplaceEnd(events, index, nodes, startIdx);
117
+ if (clamped !== void 0) endIdx = nodes.indexOf(clamped);
118
+ }
119
+ const rangeOk = shapeOk && startIdx !== -1 && endIdx !== -1 && startIdx <= endIdx;
120
+ const provenanceOk = event.type !== "assistant/message";
121
+ let rewriteOk = true;
122
+ if (rangeOk && event.type === "tool/result") {
123
+ const shadowed = nodes.slice(startIdx, endIdx + 1);
124
+ if (shadowed.length !== 1) rewriteOk = false;
125
+ else {
126
+ const original = events[shadowed[0]];
127
+ rewriteOk = original?.type === "tool/result" && toolResultRewriteContentOnly(original, event);
128
+ }
129
+ }
130
+ if (!rangeOk || !rewriteOk || !provenanceOk) {
131
+ degradeToAppend.add(event.seq);
132
+ nodes.push(event.seq);
133
+ continue;
134
+ }
135
+ if (clamped !== void 0) clampEnd.set(event.seq, clamped);
136
+ nodes.splice(startIdx, endIdx - startIdx + 1, event.seq);
137
+ }
138
+ return {
139
+ degradeToAppend,
140
+ addAppendMarker,
141
+ clearSurfaceOp,
142
+ clampEnd
143
+ };
144
+ }
145
+ function clampReplaceEnd(events, index, nodes, startIdx) {
146
+ const metering = index > 0 ? events[index - 1] : void 0;
147
+ if (metering === void 0 || !METERING_EVENT_TYPES.has(metering.type)) return void 0;
148
+ const shadowedSeqs = metering.data.shadowedSeqs;
149
+ if (!Array.isArray(shadowedSeqs) || shadowedSeqs.length === 0) return void 0;
150
+ return nodes[Math.min(startIdx + shadowedSeqs.length - 1, nodes.length - 1)];
151
+ }
152
+ function repairSurfaceOps(events) {
153
+ const repairs = findSurfaceRepairs(events);
154
+ if (repairs.degradeToAppend.size === 0 && repairs.addAppendMarker.size === 0 && repairs.clearSurfaceOp.size === 0 && repairs.clampEnd.size === 0) return;
155
+ for (const event of events) {
156
+ const raw = event;
157
+ const clamped = repairs.clampEnd.get(event.seq);
158
+ if (repairs.degradeToAppend.has(event.seq)) raw.surfaceOp = "append";
159
+ else if (clamped !== void 0) {
160
+ const op = raw.surfaceOp;
161
+ raw.surfaceOp = {
162
+ op: "replace",
163
+ startSeq: SessionSeq(op.startSeq),
164
+ endSeq: SessionSeq(clamped)
165
+ };
166
+ } else if (repairs.addAppendMarker.has(event.seq)) raw.surfaceOp = "append";
167
+ else if (repairs.clearSurfaceOp.has(event.seq)) delete raw.surfaceOp;
168
+ }
169
+ }
170
+ function repairAssistantSettlement(events) {
171
+ for (const event of events) {
172
+ if (event.type !== "assistant/message" && event.type !== "assistant/attempt") continue;
173
+ const data = event.data;
174
+ if (!Array.isArray(data["stream"])) data["stream"] = [];
175
+ }
176
+ }
177
+ function repairRequestHeaders(events) {
178
+ for (const event of events) {
179
+ if (event.type !== "request/header") continue;
180
+ const header = event.data["header"];
181
+ if (typeof header !== "object" || header === null || Array.isArray(header)) continue;
182
+ const record = header;
183
+ delete record["system"];
184
+ if (Array.isArray(record["tools"]) && record["tools"].length === 0) delete record["tools"];
185
+ const defaults = record["adapterDefaults"];
186
+ if (typeof defaults === "object" && defaults !== null && !Array.isArray(defaults) && Object.keys(defaults).length === 0) delete record["adapterDefaults"];
187
+ }
188
+ }
189
+ function syncMeteringRanges(events) {
190
+ const seqs = surfaceSeqIndex(events);
191
+ for (let i = 1; i < events.length; i++) {
192
+ const metering = events[i - 1];
193
+ if (!METERING_EVENT_TYPES.has(metering.type)) continue;
194
+ const op = events[i].surfaceOp;
195
+ if (typeof op !== "object" || op === null || op.op !== "replace") continue;
196
+ const { startSeq, endSeq } = op;
197
+ const data = metering.data;
198
+ if (data.shadowedRange?.start === startSeq && data.shadowedRange.end === endSeq) continue;
199
+ data.shadowedRange = {
200
+ start: startSeq,
201
+ end: endSeq
202
+ };
203
+ data.shadowedSeqs = surfaceSeqsInRange(seqs, startSeq, endSeq);
204
+ }
205
+ }
206
+ const PTC_EVENT_RENAMES = {
207
+ "tool/code-dispatch-start": "tool/ptc-dispatch-start",
208
+ "tool/code-dispatch": "tool/ptc-dispatch"
209
+ };
210
+ function renamePtcMessageSource(message) {
211
+ if (typeof message !== "object" || message === null || Array.isArray(message)) return message;
212
+ const record = message;
213
+ const source = record["source"];
214
+ if (typeof source !== "object" || source === null || Array.isArray(source)) return message;
215
+ const sourceRecord = source;
216
+ if (sourceRecord["kind"] !== "plugin" || sourceRecord["plugin"] !== "tools-code-mode") return message;
217
+ return {
218
+ ...record,
219
+ source: {
220
+ ...sourceRecord,
221
+ plugin: "tools-ptc"
222
+ }
223
+ };
224
+ }
225
+ function renameLegacyPtcEvents(events) {
226
+ for (let index = 0; index < events.length; index++) {
227
+ const event = events[index];
228
+ const renamedType = PTC_EVENT_RENAMES[event.type];
229
+ if (renamedType !== void 0) {
230
+ events[index] = {
231
+ ...event,
232
+ type: renamedType
233
+ };
234
+ continue;
235
+ }
236
+ if (event.type === "agent-preset/selected") {
237
+ const data = event.data;
238
+ if (data["agentPreset"] === "code") events[index] = {
239
+ ...event,
240
+ data: {
241
+ ...data,
242
+ agentPreset: "ptc"
243
+ }
244
+ };
245
+ continue;
246
+ }
247
+ if (event.type === "user/message") {
248
+ const renamed = renamePtcMessageSource(event.data);
249
+ if (renamed !== event.data) events[index] = {
250
+ ...event,
251
+ data: renamed
252
+ };
253
+ continue;
254
+ }
255
+ if (event.type === "agent/inbox/spliced" || event.type === "session/title-llm-request") {
256
+ const data = event.data;
257
+ const key = event.type === "agent/inbox/spliced" ? "inserted" : "messages";
258
+ const list = data[key];
259
+ if (!Array.isArray(list)) continue;
260
+ const renamed = list.map(renamePtcMessageSource);
261
+ if (renamed.some((message, position) => message !== list[position])) events[index] = {
262
+ ...event,
263
+ data: {
264
+ ...data,
265
+ [key]: renamed
266
+ }
267
+ };
268
+ }
269
+ }
270
+ }
271
+ function normalizeToCurrentShape(events) {
272
+ for (const event of events) {
273
+ const type = event.type;
274
+ if (OWN_EVENT_TYPES.has(type)) {
275
+ event.ignorable = true;
276
+ continue;
277
+ }
278
+ if (type === "system/message") {
279
+ const message = event.data["message"];
280
+ liftSystemMessageSource(message);
281
+ continue;
282
+ }
283
+ if (type === "tool/result") {
284
+ const message = event.data["message"];
285
+ liftToolResultMessage(message);
286
+ }
287
+ }
288
+ }
289
+ function liftSystemMessageSource(message) {
290
+ if (typeof message !== "object" || message === null) return;
291
+ const record = message;
292
+ const source = record["source"];
293
+ if (typeof source !== "object" || source === null) return;
294
+ if (source["kind"] !== "plugin") return;
295
+ record["source"] = { kind: "system-prompt" };
296
+ }
297
+ function liftToolResultMessage(message) {
298
+ if (typeof message !== "object" || message === null) return;
299
+ const record = message;
300
+ if (record["role"] === "tool" && typeof record["toolCallId"] === "string") return;
301
+ const source = record["source"];
302
+ const block = Array.isArray(record["content"]) ? record["content"][0] : void 0;
303
+ if (typeof block !== "object" || block === null) return;
304
+ const lifted = block;
305
+ const callId = lifted["toolCallId"] ?? source?.["callId"];
306
+ if (typeof callId !== "string") return;
307
+ record["role"] = "tool";
308
+ record["toolCallId"] = callId;
309
+ record["content"] = Array.isArray(lifted["content"]) ? lifted["content"] : [];
310
+ if (typeof lifted["isError"] === "boolean") record["isError"] = lifted["isError"];
311
+ record["source"] = {
312
+ kind: "tool",
313
+ callId
314
+ };
315
+ }
316
+ function sealOwnEvents(events) {
317
+ for (const event of events) if (OWN_EVENT_TYPES.has(event.type)) event.ignorable = true;
318
+ }
319
+ const OWN_EVENT_TYPES = /* @__PURE__ */ new Set(["session-branch/version", "session-mode/selected"]);
320
+ function needsShapeAdoption(events) {
321
+ for (const event of events) {
322
+ const type = event.type;
323
+ if (OWN_EVENT_TYPES.has(type)) return true;
324
+ if (type === "system/message") {
325
+ if ((event.data["message"]?.["source"])?.["kind"] === "plugin") return true;
326
+ continue;
327
+ }
328
+ if (type === "tool/result") {
329
+ const message = event.data["message"];
330
+ if (message !== void 0 && message["role"] !== "tool") return true;
331
+ }
332
+ }
333
+ return false;
334
+ }
335
+ function repairReadView(events) {
336
+ repairAssistantSettlement(events);
337
+ repairRequestHeaders(events);
338
+ renameLegacyPtcEvents(events);
339
+ repairSurfaceOps(events);
340
+ syncMeteringRanges(events);
341
+ recomputeReplaceProvenance(events);
342
+ repairOrphanInboxSplices(events);
343
+ }
344
+ function orphanInboxSpliceSeqs(events) {
345
+ const inbox = {
346
+ "next-turn": [],
347
+ "next-step": []
348
+ };
349
+ const orphan = /* @__PURE__ */ new Set();
350
+ for (const raw of events) {
351
+ const event = raw;
352
+ if (event.type !== "agent/inbox/spliced") continue;
353
+ const { target, start, removedCount, inserted } = event.data;
354
+ const list = typeof target === "string" ? inbox[target] : void 0;
355
+ if (list === void 0) {
356
+ orphan.add(event.seq);
357
+ continue;
358
+ }
359
+ const removed = removedCount ?? 0;
360
+ const parsedInserted = (inserted ?? []).map((m) => ({ id: typeof m.id === "string" ? m.id : "" }));
361
+ if (!Number.isSafeInteger(start) || start < 0 || start > list.length || !Number.isSafeInteger(removed) || removed < 0 || start + removed > list.length) {
362
+ orphan.add(event.seq);
363
+ continue;
364
+ }
365
+ const candidate = [
366
+ ...list.slice(0, start),
367
+ ...parsedInserted,
368
+ ...list.slice(start + removed)
369
+ ];
370
+ const other = (target === "next-turn" ? inbox["next-step"] : inbox["next-turn"]) ?? [];
371
+ const seen = /* @__PURE__ */ new Set();
372
+ let dup = false;
373
+ for (const m of [...candidate, ...other]) {
374
+ if (m.id === "") continue;
375
+ if (seen.has(m.id)) {
376
+ dup = true;
377
+ break;
378
+ }
379
+ seen.add(m.id);
380
+ }
381
+ if (dup) {
382
+ orphan.add(event.seq);
383
+ continue;
384
+ }
385
+ list.splice(start, removed, ...parsedInserted);
386
+ }
387
+ return orphan;
388
+ }
389
+ function repairOrphanInboxSplices(events) {
390
+ const orphan = orphanInboxSpliceSeqs(events);
391
+ if (orphan.size === 0) return;
392
+ for (const event of events) {
393
+ if (!orphan.has(event.seq)) continue;
394
+ const target = event.data.target;
395
+ event.data = {
396
+ ...typeof target === "string" ? { target } : { target: "next-turn" },
397
+ start: 0,
398
+ removedCount: 0,
399
+ inserted: []
400
+ };
401
+ }
402
+ }
403
+ // src/legacy.ts
404
+ function physicalHeader(row) {
405
+ const common = {
406
+ type: "session",
407
+ version: row.fVersion,
408
+ id: row.fSessionId,
409
+ createdAt: row.fCreatedAt,
410
+ ...row.fCwd !== null ? { cwd: row.fCwd } : {},
411
+ ...row.fParentSession !== null ? { parentSession: row.fParentSession } : {},
412
+ ...row.fOrigin !== null ? { origin: row.fOrigin } : {},
413
+ delegationDepth: row.fDelegationDepth ?? 0,
414
+ ...row.fAgentPreset !== null ? { agentPreset: row.fAgentPreset } : {}
415
+ };
416
+ return row.fVersion < 2 ? {
417
+ ...common,
418
+ ...row.fSeedLength !== null ? { seedLength: row.fSeedLength } : {}
419
+ } : {
420
+ ...common,
421
+ isSeeded: row.fSeedLength !== null
422
+ };
423
+ }
424
+ function physicalEvent(row) {
425
+ const stored = JSON.parse(row.fData);
426
+ const full = typeof stored === "object" && stored !== null && !Array.isArray(stored) && typeof stored["type"] === "string" && "data" in stored;
427
+ return {
428
+ type: row.fType,
429
+ seq: row.fSequence,
430
+ time: row.fCreatedAt,
431
+ data: full ? stored["data"] : stored,
432
+ ...row.fSurfaceOp !== null ? { surfaceOp: JSON.parse(row.fSurfaceOp) } : {}
433
+ };
434
+ }
435
+ const restoreCatalog = createSessionFormatCatalogWithChildren([]);
436
+ function convertLegacyRows(row, eventRows) {
437
+ const restore = restoreCatalog.createRestore(physicalHeader(row), {
438
+ recovery: "strict",
439
+ validation: "transformed"
440
+ });
441
+ for (const eventRow of eventRows) restore.decodeRow(physicalEvent(eventRow));
442
+ const artifact = restore.finish();
443
+ return {
444
+ meta: artifact.header,
445
+ inheritedEventCount: artifact.inheritedEventCount,
446
+ events: artifact.events
447
+ };
448
+ }
449
+ function isLegacyVersion(version) {
450
+ return version < SESSION_FORMAT_VERSION;
451
+ }
452
+ function adoptLegacyRows(row, eventRows) {
453
+ const { preserved, tornFrom } = scanRows(eventRows, 0);
454
+ repairRequestHeaders(preserved);
455
+ normalizeToCurrentShape(preserved);
456
+ return {
457
+ meta: {
458
+ ...rowToMeta(row),
459
+ version: SESSION_FORMAT_VERSION
460
+ },
461
+ inheritedEventCount: Math.min(row.fSeedLength ?? 0, preserved.length),
462
+ events: preserved,
463
+ ...tornFrom !== void 0 ? { tornFrom } : {}
464
+ };
465
+ }
466
+ // src/branch/semantics.ts
467
+ function assertRewindBoundary(id, toBoundary, boundaryType, head) {
468
+ if (toBoundary === -1) return;
469
+ if (toBoundary > head) throw new SessionBranchError(`rewind boundary ${toBoundary} is beyond the stored head ${head}`, "INVALID_BOUNDARY");
470
+ if (boundaryType === void 0) throw new SessionBranchError(`rewind boundary ${toBoundary} does not exist in session "${id}"`, "INVALID_BOUNDARY");
471
+ if (boundaryType !== "turn/end" && boundaryType !== "user/message") throw new SessionBranchError(`rewind boundary ${toBoundary} is not a turn/end or user/message (${boundaryType})`, "INVALID_BOUNDARY");
472
+ }
473
+ function locateTurnEnd(events, atSeq, mode = "after") {
474
+ const ends = events.filter((event) => event.type === "turn/end").map((event) => event.seq);
475
+ if (atSeq === void 0) {
476
+ const last = ends.at(-1);
477
+ if (last === void 0) throw new SessionBranchError("session has no closed turn", "OPEN_TURN");
478
+ return last;
479
+ }
480
+ if (mode === "before") {
481
+ let boundary = -1;
482
+ for (const seq of ends) if (seq < atSeq) boundary = seq;
483
+ else break;
484
+ return boundary;
485
+ }
486
+ const firstAfter = ends.find((seq) => seq >= atSeq);
487
+ if (firstAfter !== void 0) return firstAfter;
488
+ const lastStart = [...events].reverse().find((event) => event.type === "turn/start");
489
+ if (lastStart !== void 0 && lastStart.seq <= atSeq) throw new SessionBranchError(`anchor ${atSeq} lies inside an open turn`, "OPEN_TURN");
490
+ const last = ends.at(-1);
491
+ if (last === void 0) throw new SessionBranchError("session has no closed turn", "OPEN_TURN");
492
+ return last;
493
+ }
494
+ function renumber(events, offset) {
495
+ return events.map((event, index) => ({
496
+ ...event,
497
+ seq: offset + index
498
+ }));
499
+ }
500
+ function mintSessionId() {
501
+ return `session-${randomUUID()}`;
502
+ }
503
+ // src/branch/index.ts
504
+ function resetSurfaceManager(surfaceManager) {
505
+ const state = surfaceManager._state;
506
+ state.nodes = [];
507
+ state.replaceGeneration = 0;
508
+ state.contentGeneration = 0;
509
+ state.projectedMessages = /* @__PURE__ */ new Map();
510
+ surfaceManager._lastProcessedSeq = surfaceManager.baseSeq - 1;
511
+ surfaceManager._pendingPlan = void 0;
512
+ }
513
+ /**
514
+ * 会话**当前内存 log** 的快照(复制一份)。用于"需要完整序列"的操作(首次落库的 seed、rewind / fork 的历史),
515
+ * 不走已弃用的同步历史读 `snapshotEvents()`——那三个读口上游已声明「新调用禁止」,而这里要的是当前内存里
516
+ * 那份完整日志,不是按需分页的历史。
517
+ * @param session - 会话。
518
+ * @returns 事件副本(调用方可以自由遍历)。
519
+ */
520
+ function liveEventsOf(session) {
521
+ return [...session.log];
522
+ }
523
+ /** @returns 截断后日志里最后一个 `turn/start` 的 turn 号(没有则 0)。 */
524
+ function truncateLiveSession(session, newLength) {
525
+ const s = session;
526
+ const lastTurn = s.log.slice(0, newLength).findLast((event) => event.type === "turn/start")?.data.turn ?? 0;
527
+ s.log.length = newLength;
528
+ s.eventsSnapshot = void 0;
529
+ s.headerFold = void 0;
530
+ s.headerFoldSeq = 0;
531
+ s.contextFold = void 0;
532
+ s.contextFoldSeq = 0;
533
+ s.derived = [];
534
+ s.derivedNodes = 0;
535
+ s.derivedGeneration = 0;
536
+ resetSurfaceManager(s.surfaceManager);
537
+ return lastTurn;
538
+ }
539
+ function replaceLiveSessionLog(session, events) {
540
+ const s = session;
541
+ s.log.length = 0;
542
+ s.log.push(...events);
543
+ s.eventsSnapshot = void 0;
544
+ s.headerFold = void 0;
545
+ s.headerFoldSeq = 0;
546
+ s.contextFold = void 0;
547
+ s.contextFoldSeq = 0;
548
+ s.derived = [];
549
+ s.derivedNodes = 0;
550
+ s.derivedGeneration = 0;
551
+ resetSurfaceManager(s.surfaceManager);
552
+ }
553
+ var SessionBranchRdbProvider = class {
554
+ port;
555
+ live;
556
+ name = "session-rdb";
557
+ constructor(port, live = {
558
+ getSession: () => void 0,
559
+ getAgent: () => void 0,
560
+ flush: async () => true
561
+ }) {
562
+ this.port = port;
563
+ this.live = live;
564
+ }
565
+ async readBranchPrefix(id, atSeq, mode = "after", signal) {
566
+ const { events } = await this.readRawEvents(id, signal);
567
+ const boundary = locateTurnEnd(events, atSeq, mode);
568
+ return {
569
+ seq: boundary,
570
+ events: events.slice(0, boundary + 1)
571
+ };
572
+ }
573
+ async readRawEvents(id, signal) {
574
+ const stored = await this.port.readLog(id, {}, signal);
575
+ if (stored === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
576
+ return {
577
+ meta: stored.meta,
578
+ events: stored.events
579
+ };
580
+ }
581
+ async forkFrom(sourceId, options = {}, signal) {
582
+ signal?.throwIfAborted();
583
+ const { atSeq, anchorMode = "after", seedSuffix = [], childSessionId, meta = {} } = options;
584
+ const source = await this.port.readLog(sourceId, {}, signal);
585
+ if (source === void 0) throw new SessionBranchError(`session "${sourceId}" not found`, "SESSION_NOT_FOUND");
586
+ const boundary = locateTurnEnd(source.events, atSeq, anchorMode);
587
+ const prefix = balanceRewindPrefix(source.events.slice(0, boundary + 1));
588
+ if (prefix.length <= boundary) this.live.warn?.(`session-rdb: fork "${sourceId}" dropped ${boundary + 1 - prefix.length} trailing event(s) from seq ${prefix.length} to keep the seed's step pairs balanced`);
589
+ const childId = childSessionId ?? mintSessionId();
590
+ const childMeta = {
591
+ version: SESSION_FORMAT_VERSION,
592
+ id: childId,
593
+ createdAt: meta.createdAt ?? Date.now(),
594
+ ...meta.cwd !== void 0 ? { cwd: meta.cwd } : source.meta.cwd !== void 0 ? { cwd: source.meta.cwd } : {},
595
+ parentSession: sourceId,
596
+ isSeeded: true,
597
+ ...meta.agentPreset !== void 0 ? { agentPreset: meta.agentPreset } : source.meta.agentPreset !== void 0 ? { agentPreset: source.meta.agentPreset } : {},
598
+ ...meta.origin !== void 0 ? { origin: meta.origin } : {},
599
+ ...meta.delegationDepth !== void 0 ? { delegationDepth: meta.delegationDepth } : {}
600
+ };
601
+ const seed = [...renumber(prefix, 0), ...renumber(seedSuffix, prefix.length)];
602
+ await this.port.ready;
603
+ const reusable = !source.migrated && source.events.length === source.storedCount;
604
+ const reuse = /* @__PURE__ */ new Map();
605
+ if (reusable) {
606
+ const sourceRows = await this.port.eventRows(sourceId);
607
+ const sourceEventIds = new Map(sourceRows.map((row) => [row.fSequence, row.fEventId]));
608
+ for (const event of prefix) {
609
+ const eventId = sourceEventIds.get(event.seq);
610
+ if (eventId !== void 0) reuse.set(event.seq, eventId);
611
+ }
612
+ } else if (prefix.length > 0) this.live.warn?.(`session-rdb: fork "${sourceId}" copies event rows instead of reusing them — its read view comes from a migration, so stored seqs need not line up`);
613
+ this.port.registerReuseEventIds(childId, reuse);
614
+ try {
615
+ const handle = await this.port.create(childMeta, { inheritedEventCount: SessionLogOffset(prefix.length) });
616
+ try {
617
+ if (seed.length > 0) await handle.append(seed);
618
+ } finally {
619
+ await handle.close();
620
+ }
621
+ } catch (error) {
622
+ this.port.dropReuseEventIds(childId);
623
+ throw error;
624
+ }
625
+ return childId;
626
+ }
627
+ async rewind(id, toBoundary, signal) {
628
+ signal?.throwIfAborted();
629
+ if (!Number.isSafeInteger(toBoundary) || toBoundary < -1) throw new SessionBranchError(`rewind boundary must be a non-negative safe integer, got ${toBoundary}`, "INVALID_BOUNDARY");
630
+ const live = this.live.getSession(id);
631
+ if (live !== void 0) await this.live.flush(live);
632
+ await this.port.ready;
633
+ const row = await this.port.sessionRow(id);
634
+ if (row === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
635
+ const meta = rowToMeta(row);
636
+ let rawKeepLength;
637
+ let kept;
638
+ if (isLegacyVersion(row.fVersion)) {
639
+ const log = await this.port.readLog(id, {}, signal);
640
+ if (log === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
641
+ const boundaryType = log.events[toBoundary]?.type;
642
+ assertRewindBoundary(id, toBoundary, boundaryType, log.events.length - 1);
643
+ rawKeepLength = toBoundary === -1 ? 0 : boundaryType === "turn/end" ? toBoundary + 1 : toBoundary;
644
+ kept = balanceRewindPrefix(log.events.slice(0, rawKeepLength));
645
+ } else {
646
+ const boundaryType = toBoundary === -1 ? void 0 : await this.port.eventTypeAt(id, toBoundary);
647
+ assertRewindBoundary(id, toBoundary, boundaryType, row.fHeadSequence);
648
+ rawKeepLength = toBoundary === -1 ? 0 : boundaryType === "turn/end" ? toBoundary + 1 : toBoundary;
649
+ }
650
+ const keepLength = kept === void 0 ? await this.rewindKeepLength(id, rawKeepLength) : kept.length;
651
+ if (keepLength < rawKeepLength) this.live.warn?.(`session-rdb: rewind "${id}" dropped ${rawKeepLength - keepLength} trailing event(s) from seq ${keepLength} to keep the retained prefix's step pairs balanced`);
652
+ const denseBoundary = keepLength - 1;
653
+ const newSeedLength = await this.port.transaction(async (tx) => {
654
+ signal?.throwIfAborted();
655
+ const head = await tx.getHead(id);
656
+ if (denseBoundary > head.fHeadSequence) throw new SessionBranchError(`rewind boundary ${toBoundary} is beyond the stored head ${head.fHeadSequence}`, "INVALID_BOUNDARY");
657
+ let nextHead;
658
+ if (denseBoundary < head.fHeadSequence) {
659
+ await tx.deleteBridgeTail(id, denseBoundary + 1);
660
+ const prev = denseBoundary === -1 ? void 0 : await tx.getPrevBridge(id, denseBoundary);
661
+ nextHead = prev === void 0 ? {
662
+ fEventId: "",
663
+ fSequence: -1
664
+ } : {
665
+ fEventId: prev.fEventId,
666
+ fSequence: prev.fSequence
667
+ };
668
+ }
669
+ const storedSeedLength = await tx.getSeedLength(id);
670
+ let shrunk = storedSeedLength;
671
+ if (storedSeedLength !== null && storedSeedLength > denseBoundary + 1) {
672
+ await tx.updateSeedLength(id, denseBoundary + 1);
673
+ shrunk = denseBoundary + 1;
674
+ }
675
+ await tx.refreshTitle(id);
676
+ if (nextHead === void 0) await tx.bumpRevision(id);
677
+ else await tx.updateHeadAndRevision(id, nextHead.fEventId, nextHead.fSequence);
678
+ return shrunk;
679
+ });
680
+ this.port.confirmHead(id, denseBoundary);
681
+ if (live !== void 0) {
682
+ const liveLength = live.log.length;
683
+ let lastTurn;
684
+ if (liveLength < keepLength) {
685
+ const prefix = kept ?? (await this.port.eventRows(id)).map(rowToEvent).filter((event) => event.seq <= denseBoundary);
686
+ replaceLiveSessionLog(live, prefix);
687
+ lastTurn = prefix.findLast((event) => event.type === "turn/start")?.data.turn ?? 0;
688
+ } else lastTurn = truncateLiveSession(live, keepLength);
689
+ this.live.resetProjections?.(live);
690
+ this.live.resetTokenMeter?.(live);
691
+ const agent = this.live.getAgent(id);
692
+ if (agent !== void 0) {
693
+ agent.requestHeaderLogged = false;
694
+ const phase = agent.phase;
695
+ if (phase !== void 0) phase.lastTurn = lastTurn;
696
+ }
697
+ this.port.resetWriterAfterRewind(id, keepLength, newSeedLength === null ? void 0 : newSeedLength);
698
+ agent?.inbox?.clear();
699
+ try {
700
+ await this.live.flush(live);
701
+ } catch (error) {
702
+ this.live.warn?.(`session-rdb: flush after rewind for "${id}" failed (the stored log is already truncated; live buffers may lag): ${describeError(error)}`);
703
+ }
704
+ await this.refreshProjectionCache({
705
+ id: live.id,
706
+ header: live.header,
707
+ inheritedEventCount: live.inheritedEventCount,
708
+ headSeq: keepLength - 1,
709
+ snapshotEvents: () => live.snapshotEvents()
710
+ });
711
+ } else await this.refreshProjectionCache({
712
+ id,
713
+ header: meta,
714
+ inheritedEventCount: SessionLogOffset(newSeedLength ?? row.fSeedLength ?? 0),
715
+ headSeq: keepLength - 1,
716
+ snapshotEvents: () => []
717
+ });
718
+ return {
719
+ header: rowToMeta(row),
720
+ revision: await this.port.readStoredRevision(id)
721
+ };
722
+ }
723
+ async rewindKeepLength(id, rawKeepLength) {
724
+ if (rawKeepLength === 0) return 0;
725
+ let limit = 64;
726
+ for (;;) {
727
+ const types = [...await this.port.eventTypesBefore(id, rawKeepLength, limit)].reverse().map((row) => row.fType);
728
+ const windowStart = rawKeepLength - types.length;
729
+ if (types.includes("turn/end") || windowStart === 0 || types.length >= rawKeepLength) return rewindKeepLength(types, rawKeepLength);
730
+ limit *= 4;
731
+ }
732
+ }
733
+ async refreshProjectionCache(session) {
734
+ if (this.live.refreshProjectionCache === void 0) return;
735
+ try {
736
+ await this.live.refreshProjectionCache(session);
737
+ } catch {}
738
+ }
739
+ };
740
+ var SessionBranchRdb = class extends SessionBranch {
741
+ static inject = ["sessionPersistence", "sessions"];
742
+ warned = /* @__PURE__ */ new Set();
743
+ constructor(ctx) {
744
+ super(ctx);
745
+ }
746
+ resetLiveDerivedState(session) {
747
+ this.resetProjectionCells(session);
748
+ this.resetTokenMeterFold(session);
749
+ }
750
+ warnOnce(key, message) {
751
+ if (this.warned.has(key)) return;
752
+ this.warned.add(key);
753
+ this.ctx.logger.warn(message);
754
+ }
755
+ resetProjectionCells(session) {
756
+ const registrations = this.ctx.get("sessionProjections")?.registrations;
757
+ if (!(registrations instanceof Map)) {
758
+ this.warnOnce("sessionProjections.registrations", `session-rdb: ctx.sessionProjections.registrations is not a Map (upstream field shape changed); rewind leaves the projection cell caches of "${session.id}" stale, so replayed events can be skipped`);
759
+ return;
760
+ }
761
+ for (const registration of registrations.values()) {
762
+ const cells = registration?.cells;
763
+ if (!(cells instanceof WeakMap)) {
764
+ this.warnOnce("sessionProjections.cells", `session-rdb: ctx.sessionProjections registration cells are not a WeakMap (upstream field shape changed); rewind leaves the projection cell caches of "${session.id}" stale, so replayed events can be skipped`);
765
+ continue;
766
+ }
767
+ cells.delete(session);
768
+ }
769
+ }
770
+ resetTokenMeterFold(session) {
771
+ const meter = this.ctx.get("tokenMeter");
772
+ if (meter === void 0) {
773
+ this.warnOnce("tokenMeter", `session-rdb: ctx.tokenMeter is not mounted; after rewind the token-meter fold watermark of "${session.id}" may stay stale, so compaction can report "step/end ... has no matching step/start event"`);
774
+ return;
775
+ }
776
+ const states = meter.states;
777
+ if (!(states instanceof WeakMap)) {
778
+ this.warnOnce("tokenMeter.states", `session-rdb: ctx.tokenMeter.states is not a WeakMap (upstream field shape changed); after rewind the token-meter fold watermark of "${session.id}" may stay stale, so compaction can report "step/end ... has no matching step/start event"`);
779
+ return;
780
+ }
781
+ states.delete(session);
782
+ }
783
+ provider = new SessionBranchRdbProvider(this.ctx.sessionPersistence.branchPort(), {
784
+ getSession: (id) => this.ctx.sessions.get(id),
785
+ getAgent: (id) => {
786
+ return this.ctx.get("agents")?.get(id);
787
+ },
788
+ flush: (session) => this.ctx.sessions.flush(session),
789
+ warn: (message) => {
790
+ this.ctx.logger.warn(message);
791
+ },
792
+ resetProjections: (session) => this.resetProjectionCells(session),
793
+ resetTokenMeter: (session) => this.resetTokenMeterFold(session),
794
+ refreshProjectionCache: async (session) => {
795
+ const cache = this.ctx.get("sessionProjectionCache");
796
+ if (cache === void 0) return;
797
+ if (session.snapshotEvents().length === 0 && session.headSeq !== void 0 && cache.truncateTo !== void 0) {
798
+ try {
799
+ await cache.truncateTo(session.header, session.inheritedEventCount, session.headSeq);
800
+ } catch (error) {
801
+ this.ctx.logger.warn(`session-rdb: projection cache truncate after rewind for "${session.id}" failed: ${describeError(error)}`);
802
+ }
803
+ return;
804
+ }
805
+ try {
806
+ await cache.write(session);
807
+ } catch (error) {
808
+ if (session.headSeq !== void 0 && cache.truncateTo !== void 0) try {
809
+ await cache.truncateTo(session.header, session.inheritedEventCount, session.headSeq);
810
+ } catch (fallbackError) {
811
+ this.ctx.logger.warn(`session-rdb: projection cache truncate fallback after rewind for "${session.id}" failed: ${describeError(fallbackError)}`);
812
+ }
813
+ this.ctx.logger.warn(`session-rdb: projection cache rebuild after rewind for "${session.id}" failed (fell back to truncating the cache at the new head): ${describeError(error)}\n${error instanceof Error ? error.stack ?? "" : ""}`);
814
+ }
815
+ }
816
+ });
817
+ readBranchPrefix(id, atSeq, mode, signal) {
818
+ return this.provider.readBranchPrefix(id, atSeq, mode, signal);
819
+ }
820
+ readRawEvents(id, signal) {
821
+ return this.provider.readRawEvents(id, signal);
822
+ }
823
+ forkFrom(sourceId, options, signal) {
824
+ return this.provider.forkFrom(sourceId, options, signal);
825
+ }
826
+ rewind(id, toBoundary, signal) {
827
+ return this.provider.rewind(id, toBoundary, signal);
828
+ }
829
+ };
830
+ function describeError(error) {
831
+ return error instanceof Error ? error.message : "unknown error";
832
+ }
833
+ export { sealOwnEvents as C, repairSurfaceOps as S, renameLegacyPtcEvents as _, truncateLiveSession as a, repairReadView as b, convertLegacyRows as c, OWN_EVENT_TYPES as d, findSurfaceRepairs as f, recomputeReplaceProvenance as g, orphanInboxSpliceSeqs as h, replaceLiveSessionLog as i, isLegacyVersion as l, normalizeToCurrentShape as m, SessionBranchRdbProvider as n, locateTurnEnd as o, needsShapeAdoption as p, liveEventsOf as r, adoptLegacyRows as s, SessionBranchRdb as t, restoreCatalog as u, repairAssistantSettlement as v, syncMeteringRanges as w, repairRequestHeaders as x, repairOrphanInboxSplices as y };