@morlay/session-rdb 0.0.19 → 0.0.21-alpha.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 (70) hide show
  1. package/README.md +59 -31
  2. package/dist/artifact.d.mts +25 -65
  3. package/dist/artifact.mjs +3 -3
  4. package/dist/{schema-DPcuEh_a.d.mts → backend-DpdtxYpz.d.mts} +360 -107
  5. package/dist/branch-5JzX9rUq.mjs +390 -0
  6. package/dist/deletion.d.mts +7 -0
  7. package/dist/deletion.mjs +2 -0
  8. package/dist/dist-vIVO6bA-.mjs +1524 -0
  9. package/dist/import.d.mts +4 -4
  10. package/dist/import.mjs +214 -1
  11. package/dist/index.d.mts +2 -3
  12. package/dist/index.mjs +4 -1630
  13. package/dist/{log-DO69NQnn.mjs → log-CnYct2Dv.mjs} +37 -82
  14. package/dist/{sqlite-DYExtbLo.mjs → sqlite-fpvm5Dzs.mjs} +205 -75
  15. package/dist/src-CWTWV7vx.mjs +1904 -0
  16. package/dist/storage.d.mts +14 -5
  17. package/dist/storage.mjs +2 -2
  18. package/dist/testing.d.mts +2 -26
  19. package/dist/testing.mjs +10504 -9614
  20. package/drizzle/postgres/20260918120000_v3_event_usage/migration.sql +14 -0
  21. package/drizzle/postgres/20260918120000_v3_event_usage/snapshot.json +1309 -0
  22. package/drizzle/sqlite/20260918120000_v3_event_usage/migration.sql +14 -0
  23. package/drizzle/sqlite/20260918120000_v3_event_usage/snapshot.json +1031 -0
  24. package/package.json +29 -30
  25. package/src/adapters/to-postgres.ts +1 -3
  26. package/src/adapters/to-sqlite.ts +0 -2
  27. package/src/adapters/types.ts +0 -3
  28. package/src/artifact.ts +0 -2
  29. package/src/backend.ts +31 -2
  30. package/src/branch.ts +223 -135
  31. package/src/deletion.ts +87 -0
  32. package/src/drizzle/postgres-v2.ts +0 -1
  33. package/src/drizzle/postgres-v3.ts +0 -1
  34. package/src/drizzle/sqlite-v2.ts +0 -1
  35. package/src/drizzle/sqlite-v3.ts +0 -1
  36. package/src/entities/v2/session-events.ts +0 -1
  37. package/src/entities/v3/event-usage.ts +25 -0
  38. package/src/entities/v3/events.ts +1 -3
  39. package/src/entities/v3/index.ts +4 -0
  40. package/src/entities/v3/session-events.ts +1 -2
  41. package/src/entities/v3/session-projcache-rows.ts +0 -8
  42. package/src/entities/v3/sessions.ts +3 -3
  43. package/src/entities/v3/storage-units.ts +0 -1
  44. package/src/entities/v3/workspace-sessions.ts +0 -5
  45. package/src/entities/v3/workspace-state.ts +0 -6
  46. package/src/entities/v3/workspaces.ts +0 -5
  47. package/src/export.ts +103 -0
  48. package/src/gc.ts +76 -0
  49. package/src/import-storages.ts +4 -37
  50. package/src/import.ts +54 -31
  51. package/src/index.ts +150 -114
  52. package/src/legacy.ts +4 -42
  53. package/src/log.ts +63 -106
  54. package/src/postgres.ts +249 -22
  55. package/src/schema.ts +6 -6
  56. package/src/session-query.ts +0 -4
  57. package/src/sqlite.ts +231 -55
  58. package/src/storage-takeover/index.ts +2 -28
  59. package/src/storage-takeover/projection-cache.ts +30 -134
  60. package/src/storage-takeover/repository.ts +20 -59
  61. package/src/storage-takeover/storage-backend.ts +3 -33
  62. package/src/storage-takeover/types.ts +14 -56
  63. package/src/storage.ts +0 -2
  64. package/src/testing/contract.ts +19 -50
  65. package/src/testing/coordinator-contract.ts +10 -25
  66. package/src/testing.ts +2 -2
  67. package/src/usage.ts +191 -0
  68. package/dist/import-Bc2QQa5G.mjs +0 -473
  69. package/dist/index-CCcK9tia.d.mts +0 -270
  70. package/dist/magic-string.es-BgJoa-3K.mjs +0 -1017
@@ -0,0 +1,390 @@
1
+ import { c as repairRequestHeaders, d as rowToMeta, f as scanRows } from "./log-CnYct2Dv.mjs";
2
+ import { randomUUID } from "node:crypto";
3
+ import { SESSION_FORMAT_VERSION, SessionLogOffset } from "@deepseek-ai/dsh-session";
4
+ import { sessionFormatCatalog } from "@deepseek-ai/dsh-session-format-catalog";
5
+ import { SessionBranch, SessionBranchError, balanceRewindPrefix, buildTimeline, rewindKeepLength } from "@morlay/session-branch";
6
+ //#region src/legacy.ts
7
+ function physicalHeader(row) {
8
+ const common = {
9
+ type: "session",
10
+ version: row.fVersion,
11
+ id: row.fSessionId,
12
+ createdAt: row.fCreatedAt,
13
+ ...row.fCwd !== null ? { cwd: row.fCwd } : {},
14
+ ...row.fParentSession !== null ? { parentSession: row.fParentSession } : {},
15
+ ...row.fOrigin !== null ? { origin: row.fOrigin } : {},
16
+ delegationDepth: row.fDelegationDepth ?? 0
17
+ };
18
+ return row.fVersion < 2 ? {
19
+ ...common,
20
+ ...row.fSeedLength !== null ? { seedLength: row.fSeedLength } : {}
21
+ } : {
22
+ ...common,
23
+ isSeeded: row.fSeedLength !== null
24
+ };
25
+ }
26
+ function physicalEvent(row) {
27
+ const stored = JSON.parse(row.fData);
28
+ const full = typeof stored === "object" && stored !== null && !Array.isArray(stored) && typeof stored["type"] === "string" && "data" in stored;
29
+ return {
30
+ type: row.fType,
31
+ seq: row.fSequence,
32
+ time: row.fCreatedAt,
33
+ data: full ? stored["data"] : stored,
34
+ ...row.fSurfaceOp !== null ? { surfaceOp: JSON.parse(row.fSurfaceOp) } : {}
35
+ };
36
+ }
37
+ function convertLegacyRows(row, eventRows) {
38
+ const restore = sessionFormatCatalog.createRestore(physicalHeader(row), {
39
+ recovery: "strict",
40
+ validation: "transformed"
41
+ });
42
+ for (const eventRow of eventRows) restore.decodeRow(physicalEvent(eventRow));
43
+ const artifact = restore.finish();
44
+ return {
45
+ meta: artifact.header,
46
+ inheritedEventCount: artifact.inheritedEventCount,
47
+ events: artifact.events
48
+ };
49
+ }
50
+ function isLegacyVersion(version) {
51
+ return version < SESSION_FORMAT_VERSION;
52
+ }
53
+ function adoptLegacyRows(row, eventRows) {
54
+ const { preserved, tornFrom } = scanRows(eventRows, 0);
55
+ repairRequestHeaders(preserved);
56
+ return {
57
+ meta: {
58
+ ...rowToMeta(row),
59
+ version: SESSION_FORMAT_VERSION
60
+ },
61
+ inheritedEventCount: Math.min(row.fSeedLength ?? 0, preserved.length),
62
+ events: preserved,
63
+ ...tornFrom !== void 0 ? { tornFrom } : {}
64
+ };
65
+ }
66
+ //#endregion
67
+ //#region src/branch.ts
68
+ function assertRewindBoundary(id, toBoundary, boundaryType, head) {
69
+ if (toBoundary === -1) return;
70
+ if (toBoundary > head) throw new SessionBranchError(`rewind boundary ${toBoundary} is beyond the stored head ${head}`, "INVALID_BOUNDARY");
71
+ if (boundaryType === void 0) throw new SessionBranchError(`rewind boundary ${toBoundary} does not exist in session "${id}"`, "INVALID_BOUNDARY");
72
+ if (boundaryType !== "turn/end" && boundaryType !== "user/message") throw new SessionBranchError(`rewind boundary ${toBoundary} is not a turn/end or user/message (${boundaryType})`, "INVALID_BOUNDARY");
73
+ }
74
+ function locateTurnEnd(events, atSeq, mode = "after") {
75
+ const ends = events.filter((event) => event.type === "turn/end").map((event) => event.seq);
76
+ if (atSeq === void 0) {
77
+ const last = ends.at(-1);
78
+ if (last === void 0) throw new SessionBranchError("session has no closed turn", "OPEN_TURN");
79
+ return last;
80
+ }
81
+ if (mode === "before") {
82
+ let boundary = -1;
83
+ for (const seq of ends) if (seq < atSeq) boundary = seq;
84
+ else break;
85
+ return boundary;
86
+ }
87
+ const firstAfter = ends.find((seq) => seq >= atSeq);
88
+ if (firstAfter !== void 0) return firstAfter;
89
+ const lastStart = [...events].reverse().find((event) => event.type === "turn/start");
90
+ if (lastStart !== void 0 && lastStart.seq <= atSeq) throw new SessionBranchError(`anchor ${atSeq} lies inside an open turn`, "OPEN_TURN");
91
+ const last = ends.at(-1);
92
+ if (last === void 0) throw new SessionBranchError("session has no closed turn", "OPEN_TURN");
93
+ return last;
94
+ }
95
+ function renumber(events, offset) {
96
+ return events.map((event, index) => ({
97
+ ...event,
98
+ seq: offset + index
99
+ }));
100
+ }
101
+ function mintSessionId() {
102
+ return `session-${randomUUID()}`;
103
+ }
104
+ function resetSurfaceManager(surfaceManager) {
105
+ const state = surfaceManager._state;
106
+ state.nodes = [];
107
+ state.replaceGeneration = 0;
108
+ state.contentGeneration = 0;
109
+ state.projectedMessages = /* @__PURE__ */ new Map();
110
+ surfaceManager._lastProcessedSeq = surfaceManager.baseSeq - 1;
111
+ surfaceManager._pendingPlan = void 0;
112
+ }
113
+ function truncateLiveSession(session, newLength) {
114
+ const s = session;
115
+ s.log.length = newLength;
116
+ s.eventsSnapshot = void 0;
117
+ s.headerFold = void 0;
118
+ s.headerFoldSeq = 0;
119
+ s.contextFold = void 0;
120
+ s.contextFoldSeq = 0;
121
+ s.derived = [];
122
+ s.derivedNodes = 0;
123
+ s.derivedGeneration = 0;
124
+ resetSurfaceManager(s.surfaceManager);
125
+ }
126
+ function replaceLiveSessionLog(session, events) {
127
+ const s = session;
128
+ s.log.length = 0;
129
+ s.log.push(...events);
130
+ s.eventsSnapshot = void 0;
131
+ s.headerFold = void 0;
132
+ s.headerFoldSeq = 0;
133
+ s.contextFold = void 0;
134
+ s.contextFoldSeq = 0;
135
+ s.derived = [];
136
+ s.derivedNodes = 0;
137
+ s.derivedGeneration = 0;
138
+ resetSurfaceManager(s.surfaceManager);
139
+ }
140
+ var SessionBranchRdbProvider = class {
141
+ persistence;
142
+ live;
143
+ name = "session-rdb";
144
+ constructor(persistence, live = {
145
+ getSession: () => void 0,
146
+ getAgent: () => void 0,
147
+ flush: async () => true
148
+ }) {
149
+ this.persistence = persistence;
150
+ this.live = live;
151
+ }
152
+ async readBranchPrefix(id, atSeq, mode = "after", signal) {
153
+ const { events } = await this.readRawEvents(id, signal);
154
+ const boundary = locateTurnEnd(events, atSeq, mode);
155
+ return {
156
+ seq: boundary,
157
+ events: events.slice(0, boundary + 1)
158
+ };
159
+ }
160
+ async readRawEvents(id, signal) {
161
+ const stored = await this.persistence.readLog(id, {}, signal);
162
+ if (stored === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
163
+ return {
164
+ meta: stored.meta,
165
+ events: stored.events
166
+ };
167
+ }
168
+ async forkFrom(sourceId, options = {}, signal) {
169
+ signal?.throwIfAborted();
170
+ const { atSeq, anchorMode = "after", seedSuffix = [], childSessionId, meta = {} } = options;
171
+ const source = await this.persistence.readLog(sourceId, {}, signal);
172
+ if (source === void 0) throw new SessionBranchError(`session "${sourceId}" not found`, "SESSION_NOT_FOUND");
173
+ const boundary = locateTurnEnd(source.events, atSeq, anchorMode);
174
+ const prefix = balanceRewindPrefix(source.events.slice(0, boundary + 1));
175
+ 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`);
176
+ const childId = childSessionId ?? mintSessionId();
177
+ const childMeta = {
178
+ version: SESSION_FORMAT_VERSION,
179
+ id: childId,
180
+ createdAt: meta.createdAt ?? Date.now(),
181
+ ...meta.cwd !== void 0 ? { cwd: meta.cwd } : source.meta.cwd !== void 0 ? { cwd: source.meta.cwd } : {},
182
+ parentSession: sourceId,
183
+ isSeeded: true,
184
+ ...meta.agentPreset !== void 0 ? { agentPreset: meta.agentPreset } : source.meta.agentPreset !== void 0 ? { agentPreset: source.meta.agentPreset } : {},
185
+ ...meta.origin !== void 0 ? { origin: meta.origin } : {},
186
+ ...meta.delegationDepth !== void 0 ? { delegationDepth: meta.delegationDepth } : {}
187
+ };
188
+ const seed = [...renumber(prefix, 0), ...renumber(seedSuffix, prefix.length)];
189
+ const internals = this.persistence.internals();
190
+ const sourceRows = await internals.backend.getEventRows(sourceId);
191
+ const sourceEventIds = new Map(sourceRows.map((row) => [row.fSequence, row.fEventId]));
192
+ const reuse = /* @__PURE__ */ new Map();
193
+ for (const event of prefix) {
194
+ const eventId = sourceEventIds.get(event.seq);
195
+ if (eventId !== void 0) reuse.set(event.seq, eventId);
196
+ }
197
+ internals.registerReuseEventIds(childId, reuse);
198
+ const handle = await this.persistence.create(childMeta, { inheritedEventCount: SessionLogOffset(prefix.length) });
199
+ try {
200
+ if (seed.length > 0) await handle.append(seed);
201
+ } finally {
202
+ await handle.close();
203
+ }
204
+ return childId;
205
+ }
206
+ async rewind(id, toBoundary, signal) {
207
+ signal?.throwIfAborted();
208
+ if (!Number.isSafeInteger(toBoundary) || toBoundary < -1) throw new SessionBranchError(`rewind boundary must be a non-negative safe integer, got ${toBoundary}`, "INVALID_BOUNDARY");
209
+ const live = this.live.getSession(id);
210
+ if (live !== void 0) await this.live.flush(live);
211
+ const internals = this.persistence.internals();
212
+ const row = await internals.backend.getSession(id);
213
+ if (row === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
214
+ const meta = rowToMeta(row);
215
+ let rawKeepLength;
216
+ let kept;
217
+ if (isLegacyVersion(row.fVersion)) {
218
+ const log = await this.persistence.readLog(id, {}, signal);
219
+ if (log === void 0) throw new SessionBranchError(`session "${id}" not found`, "SESSION_NOT_FOUND");
220
+ const boundaryType = log.events[toBoundary]?.type;
221
+ assertRewindBoundary(id, toBoundary, boundaryType, log.events.length - 1);
222
+ rawKeepLength = toBoundary === -1 ? 0 : boundaryType === "turn/end" ? toBoundary + 1 : toBoundary;
223
+ kept = balanceRewindPrefix(log.events.slice(0, rawKeepLength));
224
+ } else {
225
+ const boundaryType = toBoundary === -1 ? void 0 : await internals.backend.getEventTypeAt(id, toBoundary);
226
+ assertRewindBoundary(id, toBoundary, boundaryType, row.fHeadSequence);
227
+ rawKeepLength = toBoundary === -1 ? 0 : boundaryType === "turn/end" ? toBoundary + 1 : toBoundary;
228
+ }
229
+ const keepLength = kept === void 0 ? await this.rewindKeepLength(id, rawKeepLength, internals.backend) : kept.length;
230
+ 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`);
231
+ const denseBoundary = keepLength - 1;
232
+ const newSeedLength = await internals.backend.transaction(async (tx) => {
233
+ signal?.throwIfAborted();
234
+ const head = await tx.getHead(id);
235
+ if (denseBoundary > head.fHeadSequence) throw new SessionBranchError(`rewind boundary ${toBoundary} is beyond the stored head ${head.fHeadSequence}`, "INVALID_BOUNDARY");
236
+ if (denseBoundary < head.fHeadSequence) {
237
+ await tx.deleteBridgeTail(id, denseBoundary + 1);
238
+ const prev = denseBoundary === -1 ? void 0 : await tx.getPrevBridge(id, denseBoundary);
239
+ if (prev === void 0) await tx.updateHead(id, "", -1);
240
+ else await tx.updateHead(id, prev.fEventId, prev.fSequence);
241
+ }
242
+ const storedSeedLength = await tx.getSeedLength(id);
243
+ let shrunk = storedSeedLength;
244
+ if (storedSeedLength !== null && storedSeedLength > denseBoundary + 1) {
245
+ await tx.updateSeedLength(id, denseBoundary + 1);
246
+ shrunk = denseBoundary + 1;
247
+ }
248
+ await tx.refreshTitle(id);
249
+ await tx.bumpRevision(id);
250
+ return shrunk;
251
+ });
252
+ internals.writeGuard.confirmHead(id, denseBoundary);
253
+ if (live !== void 0) {
254
+ truncateLiveSession(live, keepLength);
255
+ this.live.resetProjections?.(live);
256
+ this.live.resetTokenMeter?.(live);
257
+ const agent = this.live.getAgent(id);
258
+ if (agent !== void 0) {
259
+ agent.requestHeaderLogged = false;
260
+ const lastTurn = live.snapshotEvents().findLast((e) => e.type === "turn/start")?.data.turn ?? 0;
261
+ const phase = agent.phase;
262
+ if (phase !== void 0) phase.lastTurn = lastTurn;
263
+ }
264
+ const handle = this.persistence.tracker.writerOf(id);
265
+ if (handle !== void 0) handle.resetAfterRewind(keepLength, newSeedLength === null ? void 0 : newSeedLength);
266
+ agent?.inbox?.clear();
267
+ await this.live.flush(live);
268
+ await this.refreshProjectionCache(live);
269
+ } else await this.refreshProjectionCache({
270
+ id,
271
+ header: meta,
272
+ inheritedEventCount: SessionLogOffset(newSeedLength ?? row.fSeedLength ?? 0),
273
+ headSeq: keepLength - 1,
274
+ snapshotEvents: () => []
275
+ });
276
+ return {
277
+ header: rowToMeta(row),
278
+ revision: await internals.readStoredRevision(id)
279
+ };
280
+ }
281
+ async rewindKeepLength(id, rawKeepLength, backend) {
282
+ if (rawKeepLength === 0) return 0;
283
+ let limit = 64;
284
+ for (;;) {
285
+ const types = [...await backend.getEventTypesBefore(id, rawKeepLength, limit)].reverse().map((row) => row.fType);
286
+ const windowStart = rawKeepLength - types.length;
287
+ if (types.includes("turn/end") || windowStart === 0 || types.length >= rawKeepLength) return rewindKeepLength(types, rawKeepLength);
288
+ limit *= 4;
289
+ }
290
+ }
291
+ async refreshProjectionCache(session) {
292
+ if (this.live.refreshProjectionCache === void 0) return;
293
+ try {
294
+ await this.live.refreshProjectionCache(session);
295
+ } catch {}
296
+ }
297
+ };
298
+ var SessionBranchRdb = class extends SessionBranch {
299
+ static inject = ["sessionPersistence", "sessions"];
300
+ warned = /* @__PURE__ */ new Set();
301
+ constructor(ctx) {
302
+ super(ctx);
303
+ }
304
+ resetLiveDerivedState(session) {
305
+ this.resetProjectionCells(session);
306
+ this.resetTokenMeterFold(session);
307
+ }
308
+ warnOnce(key, message) {
309
+ if (this.warned.has(key)) return;
310
+ this.warned.add(key);
311
+ this.ctx.logger.warn(message);
312
+ }
313
+ resetProjectionCells(session) {
314
+ const registrations = this.ctx.get("sessionProjections")?.registrations;
315
+ if (!(registrations instanceof Map)) {
316
+ 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`);
317
+ return;
318
+ }
319
+ for (const registration of registrations.values()) {
320
+ const cells = registration?.cells;
321
+ if (!(cells instanceof WeakMap)) {
322
+ 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`);
323
+ continue;
324
+ }
325
+ cells.delete(session);
326
+ }
327
+ }
328
+ resetTokenMeterFold(session) {
329
+ const meter = this.ctx.get("tokenMeter");
330
+ if (meter === void 0) {
331
+ 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"`);
332
+ return;
333
+ }
334
+ const states = meter.states;
335
+ if (!(states instanceof WeakMap)) {
336
+ 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"`);
337
+ return;
338
+ }
339
+ states.delete(session);
340
+ }
341
+ provider = new SessionBranchRdbProvider(this.ctx.sessionPersistence, {
342
+ getSession: (id) => this.ctx.sessions.get(id),
343
+ getAgent: (id) => {
344
+ return this.ctx.get("agents")?.get(id);
345
+ },
346
+ flush: (session) => this.ctx.sessions.flush(session),
347
+ warn: (message) => {
348
+ this.ctx.logger.warn(message);
349
+ },
350
+ resetProjections: (session) => this.resetProjectionCells(session),
351
+ resetTokenMeter: (session) => this.resetTokenMeterFold(session),
352
+ refreshProjectionCache: async (session) => {
353
+ const cache = this.ctx.get("sessionProjectionCache");
354
+ if (cache === void 0) return;
355
+ try {
356
+ if (session.headSeq !== void 0 && cache.truncateTo !== void 0) {
357
+ await cache.truncateTo(session.header, session.inheritedEventCount, session.headSeq);
358
+ return;
359
+ }
360
+ await cache.write(session);
361
+ } catch (error) {
362
+ this.ctx.logger.warn(`session-rdb: projection cache refresh after rewind for "${session.id}" failed (cache stays stale): ${String(error)}`);
363
+ }
364
+ }
365
+ });
366
+ readBranchPrefix(id, atSeq, mode, signal) {
367
+ return this.provider.readBranchPrefix(id, atSeq, mode, signal);
368
+ }
369
+ readRawEvents(id, signal) {
370
+ return this.provider.readRawEvents(id, signal);
371
+ }
372
+ forkFrom(sourceId, options, signal) {
373
+ return this.provider.forkFrom(sourceId, options, signal);
374
+ }
375
+ rewind(id, toBoundary, signal) {
376
+ return this.provider.rewind(id, toBoundary, signal);
377
+ }
378
+ async timeline(sessionId, signal) {
379
+ const persistence = this.ctx.sessionPersistence;
380
+ const snapshots = await persistence.listSnapshots(signal);
381
+ const readOwnEvents = async (id, fromSeq, s) => {
382
+ const live = this.ctx.sessions.get(id);
383
+ if (live !== void 0) return live.snapshotEvents().slice(fromSeq);
384
+ return (await persistence.internals().readFrom(id, fromSeq, s)).events;
385
+ };
386
+ return buildTimeline(snapshots, readOwnEvents, sessionId, signal);
387
+ }
388
+ };
389
+ //#endregion
390
+ export { truncateLiveSession as a, isLegacyVersion as c, replaceLiveSessionLog as i, SessionBranchRdbProvider as n, adoptLegacyRows as o, locateTurnEnd as r, convertLegacyRows as s, SessionBranchRdb as t };
@@ -0,0 +1,7 @@
1
+ import { u as SessionPersistenceRdb } from "./backend-DpdtxYpz.mjs";
2
+ import { Context } from "@deepseek-ai/cordis";
3
+ //#region src/deletion.d.ts
4
+ declare const SESSION_DELETE_PATH = "/api/session.delete";
5
+ declare function registerSessionDeletion(ctx: Context, persistence: SessionPersistenceRdb): void;
6
+ //#endregion
7
+ export { SESSION_DELETE_PATH, registerSessionDeletion };
@@ -0,0 +1,2 @@
1
+ import { i as registerSessionDeletion, r as SESSION_DELETE_PATH } from "./src-CWTWV7vx.mjs";
2
+ export { SESSION_DELETE_PATH, registerSessionDeletion };