@morlay/session-rdb 0.0.14 → 0.0.16-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 (65) hide show
  1. package/README.md +11 -13
  2. package/dist/artifact.d.mts +6 -16
  3. package/dist/artifact.mjs +3 -3
  4. package/dist/{import-B-tf5vQn.mjs → import-CKrzjXVB.mjs} +73 -83
  5. package/dist/import.d.mts +2 -3
  6. package/dist/import.mjs +2 -2
  7. package/dist/index-CgGDHQSK.d.mts +225 -0
  8. package/dist/index.d.mts +3 -3
  9. package/dist/index.mjs +694 -169
  10. package/dist/log-DTJsxMud.mjs +314 -0
  11. package/dist/{schema-CFXZURX7.d.mts → schema-COK7-wRV.d.mts} +3 -15
  12. package/dist/sqlite-DCy4VTD8.mjs +698 -0
  13. package/dist/storage.d.mts +2 -7
  14. package/dist/storage.mjs +2 -3
  15. package/dist/testing.d.mts +30 -1
  16. package/dist/testing.mjs +676 -1991
  17. package/drizzle/postgres/20260908072805_v2_initial/migration.sql +58 -0
  18. package/drizzle/postgres/20260908072805_v2_initial/snapshot.json +686 -0
  19. package/drizzle/postgres/20260908072806_v3_drop_original_seq/migration.sql +1 -0
  20. package/drizzle/postgres/20260908072806_v3_drop_original_seq/snapshot.json +673 -0
  21. package/drizzle/sqlite/20260908072751_v2_initial/migration.sql +53 -0
  22. package/drizzle/sqlite/20260908072751_v2_initial/snapshot.json +492 -0
  23. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/migration.sql +6 -0
  24. package/drizzle/sqlite/20260908072752_v3_drop_original_seq/snapshot.json +513 -0
  25. package/package.json +17 -12
  26. package/src/adapters/index.ts +10 -2
  27. package/src/adapters/to-postgres.ts +19 -15
  28. package/src/adapters/to-sqlite.ts +20 -14
  29. package/src/{entities → adapters}/types.ts +7 -8
  30. package/src/backend.ts +0 -7
  31. package/src/branch.ts +29 -110
  32. package/src/drizzle/postgres-v2.ts +11 -0
  33. package/src/drizzle/postgres-v3.ts +11 -0
  34. package/src/drizzle/sqlite-v2.ts +10 -0
  35. package/src/drizzle/sqlite-v3.ts +11 -0
  36. package/src/entities/index.ts +2 -30
  37. package/src/entities/v2/index.ts +20 -0
  38. package/src/entities/v2/session-events.ts +11 -0
  39. package/src/entities/v3/events.ts +27 -0
  40. package/src/entities/v3/index.ts +27 -0
  41. package/src/entities/v3/persistence-state.ts +10 -0
  42. package/src/entities/v3/schema-meta.ts +9 -0
  43. package/src/entities/v3/session-events.ts +26 -0
  44. package/src/entities/v3/sessions.ts +20 -0
  45. package/src/import.ts +65 -57
  46. package/src/index.ts +868 -223
  47. package/src/invariant.ts +0 -2
  48. package/src/legacy.ts +67 -0
  49. package/src/log.ts +41 -81
  50. package/src/postgres.ts +75 -93
  51. package/src/schema.ts +3 -14
  52. package/src/sqlite.ts +59 -46
  53. package/src/testing/contract.ts +460 -375
  54. package/src/testing/coordinator-contract.ts +108 -1374
  55. package/src/testing.ts +1 -6
  56. package/dist/index-uUvn6gYp.d.mts +0 -111
  57. package/dist/schema-BfPVmr1X.mjs +0 -875
  58. package/dist/sqlite-BUWnS0so.mjs +0 -356
  59. package/src/adapters/ddl.ts +0 -77
  60. package/src/entities/events.ts +0 -27
  61. package/src/entities/persistence-state.ts +0 -10
  62. package/src/entities/schema-meta.ts +0 -9
  63. package/src/entities/session-events.ts +0 -29
  64. package/src/entities/sessions.ts +0 -20
  65. package/src/migrate.ts +0 -137
@@ -1,875 +0,0 @@
1
- import { SessionSeq, encodeSeqRanges, packChunkRuns } from "@deepseek-ai/dsh-session";
2
- import { sql } from "drizzle-orm";
3
- import { check, index, integer, sqliteTable, text, unique } from "drizzle-orm/sqlite-core";
4
- import { bigint, check as check$1, index as index$1, integer as integer$1, pgSchema, pgTable, serial, text as text$1, unique as unique$1 } from "drizzle-orm/pg-core";
5
- //#region src/log.ts
6
- function rowToMeta(row) {
7
- if (!Number.isSafeInteger(row.fCreatedAt) || row.fCreatedAt < 0) throw new Error("stored session createdAt must be a non-negative safe integer");
8
- return {
9
- version: row.fVersion,
10
- id: row.fSessionId,
11
- createdAt: row.fCreatedAt,
12
- ...row.fCwd !== null ? { cwd: row.fCwd } : {},
13
- ...row.fParentSession !== null ? { parentSession: row.fParentSession } : {},
14
- isSeeded: row.fSeedLength !== null,
15
- ...row.fOrigin !== null ? { origin: row.fOrigin } : {},
16
- ...row.fDelegationDepth === null ? {} : { delegationDepth: row.fDelegationDepth }
17
- };
18
- }
19
- function sessionInsertRow(storage, incarnation) {
20
- const meta = storage.meta;
21
- return {
22
- fSessionId: meta.id,
23
- fHeadEventId: "",
24
- fHeadSequence: -1,
25
- fVersion: meta.version,
26
- fCreatedAt: meta.createdAt,
27
- fCwd: meta.cwd ?? null,
28
- fParentSession: meta.parentSession ?? null,
29
- fSeedLength: meta.isSeeded ? storage.inheritedEventCount : null,
30
- fOrigin: meta.origin ?? null,
31
- fDelegationDepth: meta.delegationDepth ?? null,
32
- fIncarnation: incarnation,
33
- fRevision: 0
34
- };
35
- }
36
- function sessionConflictRow(storage) {
37
- const meta = storage.meta;
38
- return {
39
- fVersion: meta.version,
40
- fCreatedAt: meta.createdAt,
41
- fCwd: meta.cwd ?? null,
42
- fParentSession: meta.parentSession ?? null,
43
- fSeedLength: meta.isSeeded ? storage.inheritedEventCount : null,
44
- fOrigin: meta.origin ?? null,
45
- fDelegationDepth: meta.delegationDepth ?? null
46
- };
47
- }
48
- function remapSurfaceOp(op, remap) {
49
- if (op === "append") return op;
50
- return {
51
- op: "replace",
52
- start: SessionSeq(remap(op.start)),
53
- end: SessionSeq(remap(op.end))
54
- };
55
- }
56
- function remapShadowedRange(range, remap) {
57
- return {
58
- start: remap(range.start),
59
- end: remap(range.end)
60
- };
61
- }
62
- function remapShadowedSeqs(seqs, remap) {
63
- return seqs.map(remap);
64
- }
65
- function rowToEvent(row, seqMap) {
66
- const remap = (seq) => seqMap.get(seq) ?? seq;
67
- const surfaceOp = row.fSurfaceOp !== null ? remapSurfaceOp(JSON.parse(row.fSurfaceOp), remap) : void 0;
68
- const data = JSON.parse(row.fData);
69
- if (row.fType === "compaction/summary" || row.fType === "compaction/prune") {
70
- const metering = data;
71
- if (metering.shadowedRange !== void 0) metering.shadowedRange = remapShadowedRange(metering.shadowedRange, remap);
72
- if (metering.shadowedSeqs !== void 0) metering.shadowedSeqs = remapShadowedSeqs(metering.shadowedSeqs, remap);
73
- }
74
- return {
75
- type: row.fType,
76
- seq: row.fSequence,
77
- time: row.fCreatedAt,
78
- data,
79
- ...surfaceOp === void 0 ? {} : { surfaceOp }
80
- };
81
- }
82
- function buildSeqMap(rows) {
83
- const map = /* @__PURE__ */ new Map();
84
- for (const row of rows) if (!map.has(row.fOriginalSeq)) map.set(row.fOriginalSeq, row.fSequence);
85
- return map;
86
- }
87
- const SURFACE_EVENT_TYPES = /* @__PURE__ */ new Set([
88
- "user/message",
89
- "assistant/message",
90
- "tool/result"
91
- ]);
92
- const METERING_EVENT_TYPES = /* @__PURE__ */ new Set(["compaction/summary", "compaction/prune"]);
93
- /**
94
- * 读取时重计算 replace 的 sourceEventSeqs(sourceEventSeqs 不落库)。
95
- *
96
- * 优先采用紧邻 metering 事件(compaction/summary | compaction/prune)的
97
- * shadowedSeqs:它是压缩事务落库的**权威被遮蔽节点列表**(range 只是首尾
98
- * 边界对,压缩竞态下可能漏掉并发落地的节点——range 数值扫描会漏掉这些
99
- * 节点,使上游 assertProvenance 报 missing)。shadowedSeqs 已由 rowToEvent
100
- * 重映射到稠密坐标,与 replace 的 surfaceOp range 同空间。
101
- *
102
- * 无紧邻 metering 事件时回退到 range 数值扫描(历史数据 / 非压缩 replace,
103
- * 如 tool-result pruner 的旧样式),保证既有行为不变。
104
- */
105
- function recomputeReplaceProvenance(events) {
106
- for (let i = 0; i < events.length; i++) {
107
- const raw = events[i];
108
- const op = raw.surfaceOp;
109
- if (typeof op !== "object" || op === null || op.op !== "replace") continue;
110
- const { start, end } = op;
111
- const metering = i > 0 ? events[i - 1] : void 0;
112
- const meteringData = metering !== void 0 && METERING_EVENT_TYPES.has(metering.type) ? metering.data : void 0;
113
- if (meteringData?.shadowedSeqs !== void 0) {
114
- raw.sourceEventSeqs = meteringData.shadowedSeqs;
115
- continue;
116
- }
117
- const refs = [];
118
- for (const candidate of events) if (candidate.seq >= start && candidate.seq <= end && SURFACE_EVENT_TYPES.has(candidate.type)) refs.push(candidate.seq);
119
- raw.sourceEventSeqs = refs;
120
- }
121
- }
122
- function isEventSeqLike(value) {
123
- return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && !Object.is(value, -0);
124
- }
125
- function isDeepEqualJson(a, b) {
126
- if (a === b) return true;
127
- if (Array.isArray(a) || Array.isArray(b)) {
128
- if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
129
- return a.every((item, i) => isDeepEqualJson(item, b[i]));
130
- }
131
- if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
132
- const aKeys = Object.keys(a);
133
- const bRecord = b;
134
- if (aKeys.length !== Object.keys(bRecord).length) return false;
135
- return aKeys.every((key) => Object.hasOwn(bRecord, key) && isDeepEqualJson(a[key], bRecord[key]));
136
- }
137
- function toolResultRewriteContentOnly(original, replacement) {
138
- const originalData = original.data;
139
- const replacementData = replacement.data;
140
- const originalMessage = originalData["message"];
141
- const replacementMessage = replacementData["message"];
142
- const originalContent = Array.isArray(originalMessage?.content) ? originalMessage.content : void 0;
143
- const replacementContent = Array.isArray(replacementMessage?.content) ? replacementMessage.content : void 0;
144
- if (originalContent === void 0 || replacementContent === void 0) return false;
145
- return isDeepEqualJson({
146
- ...originalData,
147
- message: {
148
- ...originalMessage,
149
- content: [{
150
- ...originalContent[0],
151
- content: null
152
- }]
153
- }
154
- }, {
155
- ...replacementData,
156
- message: {
157
- ...replacementMessage,
158
- content: [{
159
- ...replacementContent[0],
160
- content: null
161
- }]
162
- }
163
- });
164
- }
165
- function findSurfaceRepairs(events) {
166
- const nodes = [];
167
- const degradeToAppend = /* @__PURE__ */ new Set();
168
- const addAppendMarker = /* @__PURE__ */ new Set();
169
- const clearSurfaceOp = /* @__PURE__ */ new Set();
170
- for (const event of events) {
171
- const op = event.surfaceOp;
172
- if (op === void 0) {
173
- if (SURFACE_EVENT_TYPES.has(event.type)) {
174
- addAppendMarker.add(event.seq);
175
- nodes.push(event.seq);
176
- }
177
- continue;
178
- }
179
- if (op === "append") {
180
- if (SURFACE_EVENT_TYPES.has(event.type)) nodes.push(event.seq);
181
- else clearSurfaceOp.add(event.seq);
182
- continue;
183
- }
184
- if (!SURFACE_EVENT_TYPES.has(event.type)) {
185
- clearSurfaceOp.add(event.seq);
186
- continue;
187
- }
188
- const replace = typeof op === "object" && op !== null && !Array.isArray(op) ? op : void 0;
189
- const start = replace?.["start"];
190
- const end = replace?.["end"];
191
- const shapeOk = replace !== void 0 && replace["op"] === "replace" && isEventSeqLike(start) && isEventSeqLike(end);
192
- const startIdx = shapeOk ? nodes.indexOf(start) : -1;
193
- const endIdx = shapeOk ? nodes.indexOf(end) : -1;
194
- const rangeOk = shapeOk && startIdx !== -1 && endIdx !== -1 && startIdx <= endIdx;
195
- let rewriteOk = true;
196
- if (rangeOk && event.type === "tool/result") {
197
- const shadowed = nodes.slice(startIdx, endIdx + 1);
198
- if (shadowed.length !== 1) rewriteOk = false;
199
- else {
200
- const original = events[shadowed[0]];
201
- rewriteOk = original?.type === "tool/result" && toolResultRewriteContentOnly(original, event);
202
- }
203
- }
204
- if (!rangeOk || !rewriteOk) {
205
- degradeToAppend.add(event.seq);
206
- nodes.push(event.seq);
207
- continue;
208
- }
209
- nodes.splice(startIdx, endIdx - startIdx + 1, event.seq);
210
- }
211
- return {
212
- degradeToAppend,
213
- addAppendMarker,
214
- clearSurfaceOp
215
- };
216
- }
217
- function repairSurfaceOps(events) {
218
- const repairs = findSurfaceRepairs(events);
219
- if (repairs.degradeToAppend.size === 0 && repairs.addAppendMarker.size === 0 && repairs.clearSurfaceOp.size === 0) return;
220
- for (const event of events) {
221
- const raw = event;
222
- if (repairs.degradeToAppend.has(event.seq)) raw.surfaceOp = "append";
223
- else if (repairs.addAppendMarker.has(event.seq)) raw.surfaceOp = "append";
224
- else if (repairs.clearSurfaceOp.has(event.seq)) delete raw.surfaceOp;
225
- }
226
- }
227
- /**
228
- * 定位无法从空状态增量重放的 agent/inbox/spliced 事件(孤儿操作)。
229
- *
230
- * 上游 Inbox 每次构造都从会话起点重放全部 inbox splice,失败即拒绝整个
231
- * 会话(resume / 编辑重放不可用)。rewind 截断历史轮次后若残留 splice 引用
232
- * 已被截断的排队消息(插入被删、消费保留,或反之),重放时越界或重复——
233
- * 无法独立重放。
234
- */
235
- function orphanInboxSpliceSeqs(events) {
236
- const inbox = {
237
- "next-turn": [],
238
- "next-step": []
239
- };
240
- const orphan = /* @__PURE__ */ new Set();
241
- for (const raw of events) {
242
- const event = raw;
243
- if (event.type !== "agent/inbox/spliced") continue;
244
- const { target, start, removedCount, inserted } = event.data;
245
- const list = typeof target === "string" ? inbox[target] : void 0;
246
- if (list === void 0) {
247
- orphan.add(event.seq);
248
- continue;
249
- }
250
- const removed = removedCount ?? 0;
251
- const parsedInserted = (inserted ?? []).map((m) => ({ id: typeof m.id === "string" ? m.id : "" }));
252
- if (!Number.isSafeInteger(start) || start < 0 || start > list.length || !Number.isSafeInteger(removed) || removed < 0 || start + removed > list.length) {
253
- orphan.add(event.seq);
254
- continue;
255
- }
256
- const candidate = [
257
- ...list.slice(0, start),
258
- ...parsedInserted,
259
- ...list.slice(start + removed)
260
- ];
261
- const other = (target === "next-turn" ? inbox["next-step"] : inbox["next-turn"]) ?? [];
262
- const seen = /* @__PURE__ */ new Set();
263
- let dup = false;
264
- for (const m of [...candidate, ...other]) {
265
- if (m.id === "") continue;
266
- if (seen.has(m.id)) {
267
- dup = true;
268
- break;
269
- }
270
- seen.add(m.id);
271
- }
272
- if (dup) {
273
- orphan.add(event.seq);
274
- continue;
275
- }
276
- list.splice(start, removed, ...parsedInserted);
277
- }
278
- return orphan;
279
- }
280
- /** 内存修复:把孤儿 inbox splice 改写为 no-op(调用方负责持久化)。 */
281
- function repairOrphanInboxSplices(events) {
282
- const orphan = orphanInboxSpliceSeqs(events);
283
- if (orphan.size === 0) return;
284
- for (const event of events) {
285
- if (!orphan.has(event.seq)) continue;
286
- const target = event.data.target;
287
- event.data = {
288
- ...typeof target === "string" ? { target } : { target: "next-turn" },
289
- start: 0,
290
- removedCount: 0,
291
- inserted: []
292
- };
293
- }
294
- }
295
- function scanRows(rows, base = 0, seqMap = /* @__PURE__ */ new Map()) {
296
- const parsed = rows.map((row) => {
297
- try {
298
- return {
299
- ok: true,
300
- event: rowToEvent(row, seqMap)
301
- };
302
- } catch {
303
- return { ok: false };
304
- }
305
- });
306
- let lastTurnEnd = -1;
307
- for (let i = parsed.length - 1; i >= 0; i--) if (parsed[i]?.ok && rows[i]?.fType === "turn/end") {
308
- lastTurnEnd = i;
309
- break;
310
- }
311
- const preserved = [];
312
- for (let i = 0; i < rows.length; i++) {
313
- const p = parsed[i];
314
- if (!p?.ok || p.event === void 0) {
315
- if (i <= lastTurnEnd) throw new Error(`corrupt session log: unparsable committed event at seq ${rows[i]?.fSequence}`);
316
- break;
317
- }
318
- if (p.event.seq !== base + i) {
319
- if (i <= lastTurnEnd) throw new Error(`corrupt session log: seq gap in committed region (expected ${base + i}, got ${p.event.seq})`);
320
- break;
321
- }
322
- preserved.push(p.event);
323
- }
324
- return preserved.length < rows.length ? {
325
- preserved,
326
- tornFrom: base + preserved.length
327
- } : { preserved };
328
- }
329
- function toStorageRecord(record) {
330
- const withSeqs = record;
331
- if (withSeqs.sourceEventSeqs === void 0) return record;
332
- return {
333
- ...record,
334
- sourceEventSeqs: encodeSeqRanges(withSeqs.sourceEventSeqs)
335
- };
336
- }
337
- function toJsonlArtifact(meta, inheritedEventCount, events) {
338
- const header = {
339
- type: "session",
340
- version: meta.version,
341
- id: meta.id,
342
- createdAt: meta.createdAt,
343
- ...meta.cwd === void 0 ? {} : { cwd: meta.cwd },
344
- ...meta.parentSession === void 0 ? {} : { parentSession: meta.parentSession },
345
- ...meta.isSeeded ? { seedLength: inheritedEventCount } : {},
346
- ...meta.origin === void 0 ? {} : { origin: meta.origin },
347
- delegationDepth: meta.delegationDepth ?? 0,
348
- ...meta.agentPreset === void 0 ? {} : { agentPreset: meta.agentPreset }
349
- };
350
- const lines = [JSON.stringify(header)];
351
- for (const record of packChunkRuns(events)) lines.push(JSON.stringify(toStorageRecord(record)));
352
- return lines.join("\n");
353
- }
354
- //#endregion
355
- //#region src/entities/types.ts
356
- function toProperty(name) {
357
- return name.replace(/_([a-z])/g, (_match, char) => char.toUpperCase());
358
- }
359
- //#endregion
360
- //#region src/adapters/to-sqlite.ts
361
- function buildColumn$1(c, tables) {
362
- let col;
363
- switch (c.type) {
364
- case "text":
365
- col = text(c.name);
366
- break;
367
- case "serial":
368
- col = integer(c.name).primaryKey({ autoIncrement: true });
369
- break;
370
- case "integer":
371
- case "bigint": {
372
- const built = integer(c.name);
373
- col = c.primaryKey ? built.primaryKey() : built;
374
- break;
375
- }
376
- }
377
- if (c.notNull) col = col.notNull();
378
- if (c.default !== void 0) col = col.default(c.default);
379
- if (c.unique) col = col.unique();
380
- if (c.references) {
381
- const { table, column, onDelete } = c.references;
382
- col = col.references(() => tables[table][toProperty(column)], { onDelete });
383
- }
384
- return col;
385
- }
386
- function toSqliteSchema(defs) {
387
- const tables = {};
388
- for (const def of defs) {
389
- const columns = {};
390
- for (const c of def.columns) columns[toProperty(c.name)] = buildColumn$1(c, tables);
391
- const extra = (self) => [
392
- ...(def.checks ?? []).map((c) => check(c.name, sql.raw(c.expression))),
393
- ...(def.uniques ?? []).map((u) => unique(u.name).on(...u.columns.map((name) => self[toProperty(name)]))),
394
- ...(def.indexes ?? []).map((i) => index(i.name).on(...i.columns.map((name) => self[toProperty(name)])))
395
- ];
396
- tables[def.name] = sqliteTable(def.name, columns, extra);
397
- }
398
- return tables;
399
- }
400
- //#endregion
401
- //#region src/adapters/to-postgres.ts
402
- function buildColumn(c, tables) {
403
- let col;
404
- switch (c.type) {
405
- case "text":
406
- col = text$1(c.name);
407
- break;
408
- case "serial":
409
- col = serial(c.name).primaryKey();
410
- break;
411
- case "integer": {
412
- const built = integer$1(c.name);
413
- col = c.primaryKey ? built.primaryKey() : built;
414
- break;
415
- }
416
- case "bigint": {
417
- const built = bigint(c.name, { mode: "number" });
418
- col = c.primaryKey ? built.primaryKey() : built;
419
- break;
420
- }
421
- }
422
- if (c.notNull) col = col.notNull();
423
- if (c.default !== void 0) col = col.default(c.default);
424
- if (c.unique) col = col.unique();
425
- if (c.references) {
426
- const { table, column, onDelete } = c.references;
427
- col = col.references(() => tables[table][toProperty(column)], { onDelete });
428
- }
429
- return col;
430
- }
431
- function toPostgresSchema(defs, schemaName = "public") {
432
- const tables = {};
433
- const table = schemaName === "public" ? pgTable : pgSchema(schemaName).table;
434
- for (const def of defs) {
435
- const columns = {};
436
- for (const c of def.columns) columns[toProperty(c.name)] = buildColumn(c, tables);
437
- const extra = (self) => [
438
- ...(def.checks ?? []).map((c) => check$1(c.name, sql.raw(c.expression))),
439
- ...(def.uniques ?? []).map((u) => unique$1(u.name).on(...u.columns.map((name) => self[toProperty(name)]))),
440
- ...(def.indexes ?? []).map((i) => index$1(i.name).on(...i.columns.map((name) => self[toProperty(name)])))
441
- ];
442
- tables[def.name] = table(def.name, columns, extra);
443
- }
444
- return tables;
445
- }
446
- //#endregion
447
- //#region src/entities/persistence-state.ts
448
- const persistenceState = {
449
- name: "t_persistence_state",
450
- columns: [{
451
- name: "f_singleton",
452
- type: "integer",
453
- primaryKey: true
454
- }, {
455
- name: "f_store_id",
456
- type: "text",
457
- notNull: true
458
- }],
459
- checks: [{
460
- name: "ck_persistence_state_singleton",
461
- expression: "f_singleton = 1"
462
- }]
463
- };
464
- //#endregion
465
- //#region src/entities/schema-meta.ts
466
- const schemaMeta = {
467
- name: "t_schema_meta",
468
- columns: [{
469
- name: "f_key",
470
- type: "text",
471
- primaryKey: true
472
- }, {
473
- name: "f_value",
474
- type: "text",
475
- notNull: true
476
- }]
477
- };
478
- //#endregion
479
- //#region src/entities/sessions.ts
480
- const sessions = {
481
- name: "t_sessions",
482
- columns: [
483
- {
484
- name: "f_id",
485
- type: "serial",
486
- primaryKey: true
487
- },
488
- {
489
- name: "f_session_id",
490
- type: "text",
491
- notNull: true,
492
- unique: true
493
- },
494
- {
495
- name: "f_head_event_id",
496
- type: "text",
497
- notNull: true,
498
- default: ""
499
- },
500
- {
501
- name: "f_head_sequence",
502
- type: "integer",
503
- notNull: true,
504
- default: -1
505
- },
506
- {
507
- name: "f_version",
508
- type: "integer",
509
- notNull: true
510
- },
511
- {
512
- name: "f_created_at",
513
- type: "bigint",
514
- notNull: true
515
- },
516
- {
517
- name: "f_cwd",
518
- type: "text"
519
- },
520
- {
521
- name: "f_parent_session",
522
- type: "text"
523
- },
524
- {
525
- name: "f_seed_length",
526
- type: "integer"
527
- },
528
- {
529
- name: "f_origin",
530
- type: "text"
531
- },
532
- {
533
- name: "f_delegation_depth",
534
- type: "integer"
535
- },
536
- {
537
- name: "f_incarnation",
538
- type: "text",
539
- notNull: true
540
- },
541
- {
542
- name: "f_revision",
543
- type: "integer",
544
- notNull: true
545
- }
546
- ]
547
- };
548
- //#endregion
549
- //#region src/entities/events.ts
550
- const events = {
551
- name: "t_events",
552
- columns: [
553
- {
554
- name: "f_id",
555
- type: "serial",
556
- primaryKey: true
557
- },
558
- {
559
- name: "f_event_id",
560
- type: "text",
561
- notNull: true,
562
- unique: true
563
- },
564
- {
565
- name: "f_parent_id",
566
- type: "text",
567
- notNull: true,
568
- default: ""
569
- },
570
- {
571
- name: "f_type",
572
- type: "text",
573
- notNull: true,
574
- default: ""
575
- },
576
- {
577
- name: "f_kind",
578
- type: "text",
579
- notNull: true,
580
- default: ""
581
- },
582
- {
583
- name: "f_role",
584
- type: "text",
585
- notNull: true,
586
- default: ""
587
- },
588
- {
589
- name: "f_name",
590
- type: "text",
591
- notNull: true,
592
- default: ""
593
- },
594
- {
595
- name: "f_action_id",
596
- type: "text",
597
- notNull: true,
598
- default: ""
599
- },
600
- {
601
- name: "f_encoding",
602
- type: "text",
603
- notNull: true,
604
- default: ""
605
- },
606
- {
607
- name: "f_data",
608
- type: "text",
609
- notNull: true
610
- },
611
- {
612
- name: "f_created_at",
613
- type: "bigint",
614
- notNull: true,
615
- default: 0
616
- }
617
- ],
618
- indexes: [
619
- {
620
- name: "idx_events_kind",
621
- columns: ["f_kind"]
622
- },
623
- {
624
- name: "idx_events_role",
625
- columns: ["f_role"]
626
- },
627
- {
628
- name: "idx_events_name",
629
- columns: ["f_name"]
630
- },
631
- {
632
- name: "idx_events_action_id",
633
- columns: ["f_action_id"]
634
- }
635
- ]
636
- };
637
- //#endregion
638
- //#region src/entities/session-events.ts
639
- const sessionEvents = {
640
- name: "t_session_events",
641
- columns: [
642
- {
643
- name: "f_id",
644
- type: "serial",
645
- primaryKey: true
646
- },
647
- {
648
- name: "f_session_id",
649
- type: "text",
650
- notNull: true,
651
- references: {
652
- table: "t_sessions",
653
- column: "f_session_id",
654
- onDelete: "cascade"
655
- }
656
- },
657
- {
658
- name: "f_event_id",
659
- type: "text",
660
- notNull: true,
661
- references: {
662
- table: "t_events",
663
- column: "f_event_id",
664
- onDelete: "cascade"
665
- }
666
- },
667
- {
668
- name: "f_sequence",
669
- type: "integer",
670
- notNull: true
671
- },
672
- {
673
- name: "f_original_seq",
674
- type: "integer",
675
- notNull: true
676
- },
677
- {
678
- name: "f_surface_op",
679
- type: "text"
680
- }
681
- ],
682
- uniques: [{
683
- name: "uq_session_events_session_sequence",
684
- columns: ["f_session_id", "f_sequence"]
685
- }],
686
- indexes: [{
687
- name: "idx_session_events_event_id",
688
- columns: ["f_event_id"]
689
- }]
690
- };
691
- //#endregion
692
- //#region src/entities/index.ts
693
- const sqliteTableDefs = [
694
- persistenceState,
695
- sessions,
696
- events,
697
- sessionEvents
698
- ];
699
- const postgresTableDefs = [
700
- persistenceState,
701
- schemaMeta,
702
- sessions,
703
- events,
704
- sessionEvents
705
- ];
706
- //#endregion
707
- //#region src/schema.ts
708
- const SCHEMA_VERSION = 2;
709
- const SESSION_PERSISTENCE_SQLITE_APPLICATION_ID = 1146308688;
710
- const EPHEMERAL_EVENT_TYPES = ["assistant/chunk"];
711
- const EVENT_ENCODING = "json";
712
- const sqliteTables = toSqliteSchema(sqliteTableDefs);
713
- const tPersistenceState = sqliteTables["t_persistence_state"];
714
- const tSessions = sqliteTables["t_sessions"];
715
- const tEvents = sqliteTables["t_events"];
716
- const tSessionEvents = sqliteTables["t_session_events"];
717
- const DEFAULT_BUSY_TIMEOUT_MS = 5e3;
718
- function isEphemeralType(type) {
719
- return EPHEMERAL_EVENT_TYPES.includes(type);
720
- }
721
- function isPersistedEvent(event) {
722
- return !isEphemeralType(event.type) && event.ignorable !== true;
723
- }
724
- function eventKind(event) {
725
- switch (event.type) {
726
- case "user/message": return "message";
727
- case "assistant/message":
728
- if ((event.data.message?.content)?.some((block) => block?.type === "reasoning")) return "thinking";
729
- return "message";
730
- case "turn/start":
731
- case "turn/end":
732
- case "step/start":
733
- case "step/end":
734
- case "session/end-seed": return "turn";
735
- case "tool/call":
736
- case "tool/result":
737
- case "tool/code-dispatch-start":
738
- case "tool/code-dispatch": return "tool";
739
- case "request/header":
740
- case "request/context": return "request";
741
- case "model/selection":
742
- case "permission/preset":
743
- case "approval/policy":
744
- case "sandbox/mode":
745
- case "plan/mode":
746
- case "agent-preset/selected": return "config";
747
- case "approval/asked":
748
- case "approval/decided":
749
- case "command/run":
750
- case "command/done":
751
- case "hook/invoked":
752
- case "hook/result":
753
- case "feedback/record": return "audit";
754
- case "session/title":
755
- case "session/title-llm-request":
756
- case "session-log-deepseek/delivery-accepted": return "lifecycle";
757
- case "agent/inbox/spliced": return "inbox";
758
- case "compaction/start":
759
- case "compaction/end":
760
- case "compaction/summary":
761
- case "compaction/prune": return "compaction";
762
- case "llm/retry":
763
- case "llm/retry-started": return "llm";
764
- case "subagent/descriptor":
765
- case "subagent/model-selection-policy": return "subagent";
766
- case "team/member":
767
- case "team/task":
768
- case "team/message/queued":
769
- case "team/message/delivered": return "team";
770
- case "tool-workflow/run-start":
771
- case "tool-workflow/run-end":
772
- case "tool-workflow/agent-start":
773
- case "tool-workflow/agent-end": return "workflow";
774
- case "goal/change": return "goal";
775
- case "schedule/change": return "schedule";
776
- case "todo/write": return "todo";
777
- case "web/deepseek-search-llm-request": return "web";
778
- default: return "";
779
- }
780
- }
781
- function eventDimensions(event) {
782
- const kind = eventKind(event);
783
- const type = event.type;
784
- const data = event.data;
785
- switch (type) {
786
- case "user/message": return {
787
- kind,
788
- role: "user",
789
- name: "",
790
- actionId: ""
791
- };
792
- case "assistant/message": return {
793
- kind,
794
- role: "assistant",
795
- name: "",
796
- actionId: ""
797
- };
798
- case "tool/result": return {
799
- kind,
800
- role: "tool",
801
- name: "",
802
- actionId: data["message"]?.content?.[0]?.toolCallId ?? ""
803
- };
804
- case "tool/call": return {
805
- kind,
806
- role: "",
807
- name: typeof data["name"] === "string" ? data["name"] : "",
808
- actionId: typeof data["callId"] === "string" ? data["callId"] : ""
809
- };
810
- case "tool/code-dispatch-start":
811
- case "tool/code-dispatch": return {
812
- kind,
813
- role: "",
814
- name: "",
815
- actionId: typeof data["subCallId"] === "string" ? data["subCallId"] : ""
816
- };
817
- case "command/run":
818
- case "command/done": return {
819
- kind,
820
- role: "",
821
- name: type === "command/run" && typeof data["name"] === "string" ? data["name"] : "",
822
- actionId: typeof data["commandId"] === "string" ? data["commandId"] : ""
823
- };
824
- case "approval/asked":
825
- case "approval/decided": return {
826
- kind,
827
- role: "",
828
- name: "",
829
- actionId: typeof data["id"] === "string" ? data["id"] : ""
830
- };
831
- case "hook/invoked":
832
- case "hook/result": return {
833
- kind,
834
- role: "",
835
- name: "",
836
- actionId: typeof data["handlerId"] === "string" ? data["handlerId"] : ""
837
- };
838
- case "llm/retry":
839
- case "llm/retry-started": return {
840
- kind,
841
- role: "",
842
- name: "",
843
- actionId: typeof data["retryId"] === "string" ? data["retryId"] : ""
844
- };
845
- case "tool-workflow/run-start":
846
- case "tool-workflow/run-end":
847
- case "tool-workflow/agent-start":
848
- case "tool-workflow/agent-end": return {
849
- kind,
850
- role: "",
851
- name: "",
852
- actionId: typeof data["runId"] === "string" ? data["runId"] : ""
853
- };
854
- case "todo/write": return {
855
- kind,
856
- role: "",
857
- name: "todos",
858
- actionId: ""
859
- };
860
- case "subagent/descriptor": return {
861
- kind,
862
- role: "",
863
- name: typeof data["label"] === "string" ? data["label"] : "",
864
- actionId: ""
865
- };
866
- default: return {
867
- kind,
868
- role: "",
869
- name: "",
870
- actionId: ""
871
- };
872
- }
873
- }
874
- //#endregion
875
- export { sessionInsertRow as A, remapSurfaceOp as C, rowToMeta as D, rowToEvent as E, scanRows as O, remapShadowedSeqs as S, repairSurfaceOps as T, buildSeqMap as _, SESSION_PERSISTENCE_SQLITE_APPLICATION_ID as a, recomputeReplaceProvenance as b, isEphemeralType as c, tPersistenceState as d, tSessionEvents as f, toPostgresSchema as g, sqliteTableDefs as h, SCHEMA_VERSION as i, toJsonlArtifact as j, sessionConflictRow as k, isPersistedEvent as l, postgresTableDefs as m, EPHEMERAL_EVENT_TYPES as n, eventDimensions as o, tSessions as p, EVENT_ENCODING as r, eventKind as s, DEFAULT_BUSY_TIMEOUT_MS as t, tEvents as u, findSurfaceRepairs as v, repairOrphanInboxSplices as w, remapShadowedRange as x, orphanInboxSpliceSeqs as y };