@earendil-works/pi-session-backend-sqlite-node 0.84.4 → 0.85.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 (106) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +26 -15
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +9 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/sqlite/index.d.ts +3 -4
  7. package/dist/sqlite/index.d.ts.map +1 -1
  8. package/dist/sqlite/index.js +2 -3
  9. package/dist/sqlite/index.js.map +1 -1
  10. package/dist/sqlite/migrations/001_initial.sql +88 -89
  11. package/dist/sqlite/migrations.d.ts +1 -7
  12. package/dist/sqlite/migrations.d.ts.map +1 -1
  13. package/dist/sqlite/migrations.js +3 -35
  14. package/dist/sqlite/migrations.js.map +1 -1
  15. package/dist/sqlite/repo.d.ts +38 -38
  16. package/dist/sqlite/repo.d.ts.map +1 -1
  17. package/dist/sqlite/repo.js +353 -695
  18. package/dist/sqlite/repo.js.map +1 -1
  19. package/dist/sqlite/session/branch-entries.d.ts +6 -0
  20. package/dist/sqlite/session/branch-entries.d.ts.map +1 -0
  21. package/dist/sqlite/session/branch-entries.js +213 -0
  22. package/dist/sqlite/session/branch-entries.js.map +1 -0
  23. package/dist/sqlite/session/entries.d.ts +24 -0
  24. package/dist/sqlite/session/entries.d.ts.map +1 -0
  25. package/dist/sqlite/session/entries.js +126 -0
  26. package/dist/sqlite/session/entries.js.map +1 -0
  27. package/dist/sqlite/session/session-row.d.ts +23 -0
  28. package/dist/sqlite/session/session-row.d.ts.map +1 -0
  29. package/dist/sqlite/session/session-row.js +69 -0
  30. package/dist/sqlite/session/session-row.js.map +1 -0
  31. package/dist/sqlite/session/session-sequences.d.ts +4 -0
  32. package/dist/sqlite/session/session-sequences.d.ts.map +1 -0
  33. package/dist/sqlite/session/session-sequences.js +13 -0
  34. package/dist/sqlite/session/session-sequences.js.map +1 -0
  35. package/dist/sqlite/session/session-stats.d.ts +6 -0
  36. package/dist/sqlite/session/session-stats.d.ts.map +1 -0
  37. package/dist/sqlite/session/session-stats.js +39 -0
  38. package/dist/sqlite/session/session-stats.js.map +1 -0
  39. package/dist/sqlite/session/usage-ledger.d.ts +20 -0
  40. package/dist/sqlite/session/usage-ledger.d.ts.map +1 -0
  41. package/dist/sqlite/session/usage-ledger.js +50 -0
  42. package/dist/sqlite/session/usage-ledger.js.map +1 -0
  43. package/dist/sqlite/session/values.d.ts +23 -0
  44. package/dist/sqlite/session/values.d.ts.map +1 -0
  45. package/dist/sqlite/session/values.js +91 -0
  46. package/dist/sqlite/session/values.js.map +1 -0
  47. package/dist/sqlite/session.d.ts +42 -0
  48. package/dist/sqlite/session.d.ts.map +1 -0
  49. package/dist/sqlite/session.js +163 -0
  50. package/dist/sqlite/session.js.map +1 -0
  51. package/dist/sqlite/storage.d.ts +38 -0
  52. package/dist/sqlite/storage.d.ts.map +1 -0
  53. package/dist/sqlite/storage.js +161 -0
  54. package/dist/sqlite/storage.js.map +1 -0
  55. package/dist/sqlite/types.d.ts +6 -22
  56. package/dist/sqlite/types.d.ts.map +1 -1
  57. package/dist/sqlite/types.js.map +1 -1
  58. package/package.json +5 -4
  59. package/dist/sqlite/branch-cache.d.ts +0 -6
  60. package/dist/sqlite/branch-cache.d.ts.map +0 -1
  61. package/dist/sqlite/branch-cache.js +0 -70
  62. package/dist/sqlite/branch-cache.js.map +0 -1
  63. package/dist/sqlite/search-backend.d.ts +0 -14
  64. package/dist/sqlite/search-backend.d.ts.map +0 -1
  65. package/dist/sqlite/search-backend.js +0 -153
  66. package/dist/sqlite/search-backend.js.map +0 -1
  67. package/dist/sqlite/storage/branch-entries.d.ts +0 -41
  68. package/dist/sqlite/storage/branch-entries.d.ts.map +0 -1
  69. package/dist/sqlite/storage/branch-entries.js +0 -112
  70. package/dist/sqlite/storage/branch-entries.js.map +0 -1
  71. package/dist/sqlite/storage/branch-tips.d.ts +0 -7
  72. package/dist/sqlite/storage/branch-tips.d.ts.map +0 -1
  73. package/dist/sqlite/storage/branch-tips.js +0 -22
  74. package/dist/sqlite/storage/branch-tips.js.map +0 -1
  75. package/dist/sqlite/storage/entries.d.ts +0 -34
  76. package/dist/sqlite/storage/entries.d.ts.map +0 -1
  77. package/dist/sqlite/storage/entries.js +0 -37
  78. package/dist/sqlite/storage/entries.js.map +0 -1
  79. package/dist/sqlite/storage/facts.d.ts +0 -20
  80. package/dist/sqlite/storage/facts.d.ts.map +0 -1
  81. package/dist/sqlite/storage/facts.js +0 -38
  82. package/dist/sqlite/storage/facts.js.map +0 -1
  83. package/dist/sqlite/storage/lanes.d.ts +0 -35
  84. package/dist/sqlite/storage/lanes.d.ts.map +0 -1
  85. package/dist/sqlite/storage/lanes.js +0 -95
  86. package/dist/sqlite/storage/lanes.js.map +0 -1
  87. package/dist/sqlite/storage/records.d.ts +0 -38
  88. package/dist/sqlite/storage/records.d.ts.map +0 -1
  89. package/dist/sqlite/storage/records.js +0 -49
  90. package/dist/sqlite/storage/records.js.map +0 -1
  91. package/dist/sqlite/storage/session-sequences.d.ts +0 -7
  92. package/dist/sqlite/storage/session-sequences.d.ts.map +0 -1
  93. package/dist/sqlite/storage/session-sequences.js +0 -22
  94. package/dist/sqlite/storage/session-sequences.js.map +0 -1
  95. package/dist/sqlite/storage/session-stats.d.ts +0 -17
  96. package/dist/sqlite/storage/session-stats.d.ts.map +0 -1
  97. package/dist/sqlite/storage/session-stats.js +0 -40
  98. package/dist/sqlite/storage/session-stats.js.map +0 -1
  99. package/dist/sqlite/storage/sessions.d.ts +0 -26
  100. package/dist/sqlite/storage/sessions.d.ts.map +0 -1
  101. package/dist/sqlite/storage/sessions.js +0 -99
  102. package/dist/sqlite/storage/sessions.js.map +0 -1
  103. package/dist/sqlite/storage/writer-leases.d.ts +0 -15
  104. package/dist/sqlite/storage/writer-leases.d.ts.map +0 -1
  105. package/dist/sqlite/storage/writer-leases.js +0 -31
  106. package/dist/sqlite/storage/writer-leases.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/sqlite/repo.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FileError, Result } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype BranchBounds,\n\ttype Entry,\n\ttype EntryQuery,\n\ttype ForkOptions,\n\ttype LaneRecord,\n\ttype LogItem,\n\ttype LogOptions,\n\ttype NewRecord,\n\ttype OperationStartedRecord,\n\ttype ProvisionedEntry,\n\ttype RecordQuery,\n\tSession,\n\tSessionError,\n\ttype SessionRepo as SessionRepository,\n\ttype SessionStats,\n\ttype SessionStorage,\n} from \"@earendil-works/pi-agent-core\";\nimport { uuidv7 } from \"@earendil-works/pi-ai\";\nimport { appendEntryToBranchCache, buildCachedBranch, deleteBranchCache, rebuildBranchCache } from \"./branch-cache.ts\";\nimport { applyMigrations } from \"./migrations.ts\";\nimport { sql } from \"./sql.ts\";\nimport { type CachedBranchEntryRow, queryCachedBranchRows, readCachedBranch } from \"./storage/branch-entries.ts\";\nimport { readBranchTipIds } from \"./storage/branch-tips.ts\";\nimport {\n\tdeleteEntryRows,\n\ttype EntryRow,\n\tentryPayload,\n\tidExistsInEntries,\n\tinsertEntryRow,\n\treadEntryRow,\n\treadEntryRows,\n} from \"./storage/entries.ts\";\nimport { appendFact, deleteFactRows, readFactRows, readLatestFact, readLatestLabelFacts } from \"./storage/facts.ts\";\nimport {\n\tcreateInitialLane,\n\tdeleteLaneRows,\n\tfinishLaneOperation,\n\tcreateLane as insertLane,\n\treadLane,\n\treadLaneHead,\n\treadLaneMoveRows,\n\treadLanes,\n\tsetLaneLeaf,\n\tstartLaneOperation,\n\tmoveLane as updateLane,\n} from \"./storage/lanes.ts\";\nimport {\n\tappendRecordRow,\n\tdeleteRecordRows,\n\tidExistsInRecords,\n\treadOpenOperationRows,\n\treadRecordRows,\n} from \"./storage/records.ts\";\nimport {\n\tadvanceSequence,\n\tcreateSequence,\n\tdeleteSequence,\n\tgetNextSequence,\n\tsetNextSequence,\n} from \"./storage/session-sequences.ts\";\nimport {\n\taddUsageToStats,\n\tcreateStats,\n\tdeleteStats,\n\tincrementMessageCount,\n\treadStats,\n} from \"./storage/session-stats.ts\";\nimport {\n\tdecodeSessionMetadata,\n\tdeleteSessionRow,\n\tinsertSessionRow,\n\treadSessionRow,\n\treadSessionRows,\n\ttype SessionRow,\n\tsessionExists,\n} from \"./storage/sessions.ts\";\nimport {\n\tacquireWriterLease,\n\tdeleteWriterLease,\n\treleaseWriterLease,\n\trenewWriterLease,\n\ttype WriterLease,\n} from \"./storage/writer-leases.ts\";\nimport type {\n\tSqliteDatabase,\n\tSqliteDatabaseFactory,\n\tSqliteSessionCreateOptions,\n\tSqliteSessionListOptions,\n\tSqliteSessionMetadata,\n\tSqliteSessionRepositoryEnv,\n} from \"./types.ts\";\n\nexport interface SqliteWriterLeaseOptions {\n\t/** Time without a successful heartbeat before another writer may take over. Default: 30 seconds. */\n\tttlMs?: number;\n\t/** Idle heartbeat cadence. Default: 10 seconds. Must be less than ttlMs. */\n\theartbeatIntervalMs?: number;\n}\n\nexport interface SqliteSessionRepositoryOptions {\n\tenv: SqliteSessionRepositoryEnv;\n\tsqlite: SqliteDatabaseFactory;\n\tdatabasePath: string;\n\twriterLease?: SqliteWriterLeaseOptions;\n}\n\ninterface ResolvedWriterLeaseOptions {\n\tttlMs: number;\n\theartbeatIntervalMs: number;\n}\n\nfunction resolveWriterLeaseOptions(options: SqliteWriterLeaseOptions | undefined): ResolvedWriterLeaseOptions {\n\tconst ttlMs = options?.ttlMs ?? 30_000;\n\tconst heartbeatIntervalMs = options?.heartbeatIntervalMs ?? 10_000;\n\tif (!Number.isSafeInteger(ttlMs) || ttlMs <= 0) throw new RangeError(\"writerLease.ttlMs must be positive\");\n\tif (!Number.isSafeInteger(heartbeatIntervalMs) || heartbeatIntervalMs <= 0 || heartbeatIntervalMs >= ttlMs) {\n\t\tthrow new RangeError(\"writerLease.heartbeatIntervalMs must be positive and less than ttlMs\");\n\t}\n\treturn { ttlMs, heartbeatIntervalMs };\n}\n\nfunction activeWriterError(sessionId: string): SessionError {\n\treturn new SessionError(\"storage\", `SQLite session ${sessionId} already has an active writer`);\n}\n\nfunction lostWriterError(sessionId: string): SessionError {\n\treturn new SessionError(\"storage\", `SQLite session ${sessionId} writer lease was lost`);\n}\n\nfunction claimWriterLease(db: SqliteDatabase, sessionId: string, options: ResolvedWriterLeaseOptions): WriterLease {\n\tconst now = Date.now();\n\tconst lease = acquireWriterLease(db, sessionId, uuidv7(), now, now + options.ttlMs);\n\tif (!lease) throw activeWriterError(sessionId);\n\treturn lease;\n}\n\nclass SerialOperationQueue {\n\tprivate tail: Promise<void> = Promise.resolve();\n\n\tenqueue<T>(operation: () => Promise<T> | T): Promise<T> {\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn result;\n\t}\n\n\tasync drain(): Promise<void> {\n\t\tawait this.tail;\n\t}\n}\n\nfunction resultOrThrow<T>(result: Result<T, FileError>, message: string): T {\n\tif (!result.ok) {\n\t\tconst code = result.error.code === \"not_found\" ? \"not_found\" : \"storage\";\n\t\tthrow new SessionError(code, `${message}: ${result.error.message}`, result.error);\n\t}\n\treturn result.value;\n}\n\nfunction getParentPath(path: string): string {\n\tconst normalized = path.replace(/[\\\\/]+$/, \"\");\n\tconst lastSlash = Math.max(normalized.lastIndexOf(\"/\"), normalized.lastIndexOf(\"\\\\\"));\n\tif (lastSlash < 0) return \".\";\n\tif (lastSlash === 0) return normalized.slice(0, 1);\n\treturn normalized.slice(0, lastSlash);\n}\n\nfunction configureSqliteDatabase(db: SqliteDatabase): void {\n\tsql`PRAGMA journal_mode=WAL`.exec(db);\n\tsql`PRAGMA synchronous=FULL`.exec(db);\n\tsql`PRAGMA busy_timeout=5000`.exec(db);\n}\n\nfunction entryRowFromCached(row: CachedBranchEntryRow): EntryRow {\n\treturn { ...row, seq: row.entry_seq, type: row.type as Entry[\"type\"] };\n}\n\nfunction readObjectPayload(row: EntryRow): Record<string, unknown> {\n\tconst payload = JSON.parse(row.payload) as unknown;\n\tif (typeof payload !== \"object\" || payload === null || Array.isArray(payload)) {\n\t\tthrow new Error(\"Payload is not an object\");\n\t}\n\treturn payload as Record<string, unknown>;\n}\n\nfunction decodeEntry(row: EntryRow): Entry {\n\ttry {\n\t\tconst payload = readObjectPayload(row);\n\t\tconst base = { id: row.id, seq: row.seq, parentId: row.parent_id, timestamp: row.timestamp };\n\t\tswitch (row.type) {\n\t\t\tcase \"message\":\n\t\t\t\tif (typeof payload.message !== \"object\" || payload.message === null) throw new Error(\"Missing message\");\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: \"message\",\n\t\t\t\t\tmessage: payload.message as Extract<Entry, { type: \"message\" }>[\"message\"],\n\t\t\t\t\t...(payload.terminate === true ? { terminate: true as const } : {}),\n\t\t\t\t};\n\t\t\tcase \"model_change\":\n\t\t\t\tif (typeof payload.provider !== \"string\" || typeof payload.modelId !== \"string\") {\n\t\t\t\t\tthrow new Error(\"Invalid model_change payload\");\n\t\t\t\t}\n\t\t\t\treturn { ...base, type: \"model_change\", provider: payload.provider, modelId: payload.modelId };\n\t\t\tcase \"thinking_level_change\":\n\t\t\t\tif (typeof payload.thinkingLevel !== \"string\") throw new Error(\"Invalid thinking_level_change payload\");\n\t\t\t\treturn { ...base, type: \"thinking_level_change\", thinkingLevel: payload.thinkingLevel };\n\t\t\tcase \"active_tools_change\":\n\t\t\t\tif (!Array.isArray(payload.activeToolNames)) throw new Error(\"Invalid active_tools_change payload\");\n\t\t\t\tif (payload.activeToolNames.some((value) => typeof value !== \"string\")) {\n\t\t\t\t\tthrow new Error(\"Invalid active_tools_change payload\");\n\t\t\t\t}\n\t\t\t\treturn { ...base, type: \"active_tools_change\", activeToolNames: payload.activeToolNames };\n\t\t\tcase \"compaction\":\n\t\t\t\tif (\n\t\t\t\t\ttypeof payload.summary !== \"string\" ||\n\t\t\t\t\t!Array.isArray(payload.retainedTail) ||\n\t\t\t\t\ttypeof payload.tokensBefore !== \"number\"\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\"Invalid compaction payload\");\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: \"compaction\",\n\t\t\t\t\tsummary: payload.summary,\n\t\t\t\t\tretainedTail: payload.retainedTail as Extract<Entry, { type: \"compaction\" }>[\"retainedTail\"],\n\t\t\t\t\ttokensBefore: payload.tokensBefore,\n\t\t\t\t\t...(Object.hasOwn(payload, \"details\") ? { details: payload.details } : {}),\n\t\t\t\t\t...(Object.hasOwn(payload, \"usage\")\n\t\t\t\t\t\t? { usage: payload.usage as Extract<Entry, { type: \"compaction\" }>[\"usage\"] }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\tcase \"branch_summary\":\n\t\t\t\tif (typeof payload.fromId !== \"string\" || typeof payload.summary !== \"string\") {\n\t\t\t\t\tthrow new Error(\"Invalid branch_summary payload\");\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: \"branch_summary\",\n\t\t\t\t\tfromId: payload.fromId,\n\t\t\t\t\tsummary: payload.summary,\n\t\t\t\t\t...(Object.hasOwn(payload, \"details\") ? { details: payload.details } : {}),\n\t\t\t\t\t...(Object.hasOwn(payload, \"usage\")\n\t\t\t\t\t\t? { usage: payload.usage as Extract<Entry, { type: \"branch_summary\" }>[\"usage\"] }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\tcase \"custom\":\n\t\t\t\tif (typeof payload.customType !== \"string\") throw new Error(\"Invalid custom payload\");\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttype: \"custom\",\n\t\t\t\t\tcustomType: payload.customType,\n\t\t\t\t\t...(Object.hasOwn(payload, \"data\") ? { data: payload.data } : {}),\n\t\t\t\t};\n\t\t}\n\t} catch (error) {\n\t\tthrow new SessionError(\n\t\t\t\"invalid_entry\",\n\t\t\t`Invalid SQLite session entry ${row.id}: failed to decode entry ${row.id}`,\n\t\t\terror instanceof Error ? error : undefined,\n\t\t);\n\t}\n}\n\nfunction recordRunId(record: NewRecord): string | undefined {\n\treturn record.type === \"operation_started\" ? record.id : \"runId\" in record ? record.runId : undefined;\n}\n\nfunction recordOpKind(record: NewRecord): string | undefined {\n\treturn record.type === \"operation_started\" ? record.intent.kind : undefined;\n}\n\nfunction decodeRecord(row: { seq: number; timestamp: number; payload: string }): LaneRecord {\n\ttry {\n\t\treturn {\n\t\t\t...(JSON.parse(row.payload) as object),\n\t\t\tseq: row.seq,\n\t\t\ttimestamp: row.timestamp,\n\t\t} as LaneRecord;\n\t} catch (error) {\n\t\tthrow new SessionError(\n\t\t\t\"storage\",\n\t\t\t`Invalid SQLite session record at sequence ${row.seq}: failed to decode payload`,\n\t\t\terror instanceof Error ? error : undefined,\n\t\t);\n\t}\n}\n\nfunction validateCachedBranchRows(rows: readonly CachedBranchEntryRow[], query: BranchBounds & EntryQuery): void {\n\tif (rows.length === 0 || query.type !== undefined || query.customType !== undefined) return;\n\tconst path = [...rows].sort((left, right) => left.entry_seq - right.entry_seq);\n\tconst shouldIncludeRoot =\n\t\tquery.stopAtId === undefined &&\n\t\tquery.stopAtType === undefined &&\n\t\tquery.cursor === undefined &&\n\t\t(query.order === \"oldestFirst\" || query.limit === undefined);\n\tif (shouldIncludeRoot && path[0]?.parent_id !== null) {\n\t\tthrow new SessionError(\"invalid_entry\", `Entry ${path[0]?.parent_id} not found`);\n\t}\n\tfor (let index = 1; index < path.length; index++) {\n\t\tconst previous = path[index - 1]!;\n\t\tconst current = path[index]!;\n\t\tif (current.parent_id !== previous.id) {\n\t\t\tthrow new SessionError(\"invalid_entry\", `Entry ${current.parent_id} not found`);\n\t\t}\n\t}\n}\n\nfunction matchesEntryQuery(entry: Entry, query: EntryQuery): boolean {\n\treturn (\n\t\t(query.type === undefined || entry.type === query.type) &&\n\t\t(query.customType === undefined || (entry.type === \"custom\" && entry.customType === query.customType)) &&\n\t\t(query.cursor === undefined ||\n\t\t\t(query.order === \"oldestFirst\" ? entry.seq > query.cursor.afterSeq : entry.seq < query.cursor.afterSeq))\n\t);\n}\n\nfunction assertUnusedId(db: SqliteDatabase, sessionId: string, id: string): void {\n\tif (idExistsInEntries(db, sessionId, id) || idExistsInRecords(db, sessionId, id)) {\n\t\tthrow new SessionError(\"already_exists\", `ID already exists: ${id}`);\n\t}\n}\n\nfunction requireSessionRow(db: SqliteDatabase, sessionId: string): SessionRow {\n\tconst row = readSessionRow(db, sessionId);\n\tif (!row) throw new SessionError(\"not_found\", `Session not found: ${sessionId}`);\n\treturn row;\n}\n\nclass SqliteSessionStorage implements SessionStorage<SqliteSessionMetadata> {\n\tprivate readonly db: SqliteDatabase;\n\tprivate readonly metadata: SqliteSessionMetadata;\n\tprivate readonly lease: WriterLease;\n\tprivate readonly leaseOptions: ResolvedWriterLeaseOptions;\n\tprivate readonly onRelease: () => void;\n\tprivate readonly operations = new SerialOperationQueue();\n\tprivate heartbeatTimer: ReturnType<typeof setTimeout> | undefined;\n\tprivate leaseError: SessionError | undefined;\n\tprivate closing = false;\n\tprivate releasePromise: Promise<void> | undefined;\n\n\tconstructor(\n\t\tdb: SqliteDatabase,\n\t\tmetadata: SqliteSessionMetadata,\n\t\tlease: WriterLease,\n\t\tleaseOptions: ResolvedWriterLeaseOptions,\n\t\tonRelease: () => void,\n\t) {\n\t\tthis.db = db;\n\t\tthis.metadata = metadata;\n\t\tthis.lease = lease;\n\t\tthis.leaseOptions = leaseOptions;\n\t\tthis.onRelease = onRelease;\n\t\tthis.scheduleHeartbeat();\n\t}\n\n\tasync release(): Promise<void> {\n\t\tthis.releasePromise ??= this.finishRelease();\n\t\tawait this.releasePromise;\n\t}\n\n\tprivate async finishRelease(): Promise<void> {\n\t\tthis.closing = true;\n\t\tif (this.heartbeatTimer !== undefined) clearTimeout(this.heartbeatTimer);\n\t\ttry {\n\t\t\tawait this.operations.enqueue(() =>\n\t\t\t\tthis.db.transaction(() => releaseWriterLease(this.db, this.metadata.id, this.lease)),\n\t\t\t);\n\t\t} finally {\n\t\t\tthis.onRelease();\n\t\t}\n\t}\n\n\tprivate enqueueWrite<T>(operation: () => T): Promise<T> {\n\t\tif (this.closing)\n\t\t\treturn Promise.reject(new SessionError(\"storage\", `SQLite session ${this.metadata.id} is closed`));\n\t\treturn this.operations.enqueue(() => {\n\t\t\tif (this.leaseError) throw this.leaseError;\n\t\t\treturn this.db.transaction(() => {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tif (!renewWriterLease(this.db, this.metadata.id, this.lease, now, now + this.leaseOptions.ttlMs)) {\n\t\t\t\t\tthis.leaseError = lostWriterError(this.metadata.id);\n\t\t\t\t\tif (this.heartbeatTimer !== undefined) clearTimeout(this.heartbeatTimer);\n\t\t\t\t\tthrow this.leaseError;\n\t\t\t\t}\n\t\t\t\treturn operation();\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate scheduleHeartbeat(): void {\n\t\tif (this.closing || this.leaseError) return;\n\t\tthis.heartbeatTimer = setTimeout(async () => {\n\t\t\tthis.heartbeatTimer = undefined;\n\t\t\ttry {\n\t\t\t\tawait this.operations.enqueue(() => {\n\t\t\t\t\tif (this.closing || this.leaseError) return;\n\t\t\t\t\tthis.db.transaction(() => {\n\t\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\t\tif (!renewWriterLease(this.db, this.metadata.id, this.lease, now, now + this.leaseOptions.ttlMs)) {\n\t\t\t\t\t\t\tthis.leaseError = lostWriterError(this.metadata.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} catch {\n\t\t\t\t// A transient heartbeat failure is retried. Every write still verifies ownership transactionally.\n\t\t\t} finally {\n\t\t\t\tthis.scheduleHeartbeat();\n\t\t\t}\n\t\t}, this.leaseOptions.heartbeatIntervalMs);\n\t\tthis.heartbeatTimer.unref();\n\t}\n\n\tasync getMetadata(): Promise<SqliteSessionMetadata> {\n\t\treturn decodeSessionMetadata(requireSessionRow(this.db, this.metadata.id), this.metadata.path);\n\t}\n\n\tisForSession(sessionId: string): boolean {\n\t\treturn this.metadata.id === sessionId;\n\t}\n\n\tasync getLanes(): Promise<{ lane: string; leafId: string | null }[]> {\n\t\treturn readLanes(this.db, this.metadata.id).map((row) => ({ lane: row.lane, leafId: row.leaf_id }));\n\t}\n\n\tasync createLane(lane: string, at: string | null): Promise<void> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tif (readLane(this.db, this.metadata.id, lane)) {\n\t\t\t\tthrow new SessionError(\"already_exists\", `Lane already exists: ${lane}`);\n\t\t\t}\n\t\t\tif (at !== null && !readEntryRow(this.db, this.metadata.id, at)) {\n\t\t\t\tthrow new SessionError(\"not_found\", `Entry not found: ${at}`);\n\t\t\t}\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tinsertLane(this.db, this.metadata.id, seq, lane, at);\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t});\n\t}\n\n\tasync moveLane(lane: string, to: string | null): Promise<void> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tif (!readLane(this.db, this.metadata.id, lane))\n\t\t\t\tthrow new SessionError(\"invalid_lane\", `Lane not found: ${lane}`);\n\t\t\tif (to !== null && !readEntryRow(this.db, this.metadata.id, to)) {\n\t\t\t\tthrow new SessionError(\"not_found\", `Entry not found: ${to}`);\n\t\t\t}\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tupdateLane(this.db, this.metadata.id, seq, lane, to);\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t});\n\t}\n\n\tasync appendEntry<TEntry extends Entry>(entry: ProvisionedEntry<TEntry>, lane: string): Promise<TEntry> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tconst parentId = readLaneHead(this.db, this.metadata.id, lane).leafId;\n\t\t\tassertUnusedId(this.db, this.metadata.id, entry.id);\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tconst committed = { ...entry, parentId, seq, timestamp: Date.now() } as Entry;\n\t\t\tinsertEntryRow(this.db, this.metadata.id, {\n\t\t\t\tseq,\n\t\t\t\tid: committed.id,\n\t\t\t\tparentId: committed.parentId,\n\t\t\t\ttype: committed.type,\n\t\t\t\ttimestamp: committed.timestamp,\n\t\t\t\tpayload: JSON.stringify(entryPayload(committed)),\n\t\t\t});\n\t\t\tsetLaneLeaf(this.db, this.metadata.id, lane, committed.id);\n\t\t\tappendEntryToBranchCache(\n\t\t\t\tthis.db,\n\t\t\t\tthis.metadata.id,\n\t\t\t\tcommitted.id,\n\t\t\t\tseq,\n\t\t\t\tcommitted.type,\n\t\t\t\tcommitted.type === \"custom\" ? committed.customType : null,\n\t\t\t\tcommitted.parentId,\n\t\t\t);\n\t\t\tif (committed.type === \"message\") incrementMessageCount(this.db, this.metadata.id);\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t\treturn structuredClone(committed as TEntry);\n\t\t});\n\t}\n\n\tasync appendRecord<TRecord extends LaneRecord>(record: NewRecord<TRecord>): Promise<TRecord>;\n\tasync appendRecord(record: NewRecord): Promise<LaneRecord> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tif (!readLane(this.db, this.metadata.id, record.lane)) {\n\t\t\t\tthrow new SessionError(\"invalid_lane\", `Lane not found: ${record.lane}`);\n\t\t\t}\n\t\t\tassertUnusedId(this.db, this.metadata.id, record.id);\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tconst committed: LaneRecord = { ...record, seq, timestamp: Date.now() };\n\t\t\tif (record.type === \"operation_started\") {\n\t\t\t\tstartLaneOperation(this.db, this.metadata.id, record.lane, record.id);\n\t\t\t}\n\t\t\tappendRecordRow(this.db, this.metadata.id, {\n\t\t\t\tseq,\n\t\t\t\tid: record.id,\n\t\t\t\tlane: record.lane,\n\t\t\t\trunId: recordRunId(record),\n\t\t\t\ttype: record.type,\n\t\t\t\topKind: recordOpKind(record),\n\t\t\t\ttimestamp: committed.timestamp,\n\t\t\t\tpayload: JSON.stringify(record),\n\t\t\t});\n\t\t\tif (record.type === \"operation_finished\") {\n\t\t\t\tfinishLaneOperation(this.db, this.metadata.id, record.lane, record.runId);\n\t\t\t}\n\t\t\tif (record.type === \"usage\") addUsageToStats(this.db, this.metadata.id, record.usage);\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t\treturn structuredClone(committed);\n\t\t});\n\t}\n\n\tasync getEntry(id: string): Promise<Entry | undefined> {\n\t\tconst row = readEntryRow(this.db, this.metadata.id, id);\n\t\treturn row ? decodeEntry(row) : undefined;\n\t}\n\n\tasync findEntries(query: EntryQuery = {}): Promise<Entry[]> {\n\t\tconst sqlType = query.type ?? (query.customType === undefined ? undefined : \"custom\");\n\t\tconst sqlLimit = query.customType === undefined ? query.limit : undefined;\n\t\tconst rows = readEntryRows(this.db, this.metadata.id, {\n\t\t\tcursor: query.cursor,\n\t\t\tlimit: sqlLimit,\n\t\t\torder: query.order,\n\t\t\ttype: sqlType,\n\t\t});\n\t\tconst entries = rows.map(decodeEntry).filter((entry) => matchesEntryQuery(entry, query));\n\t\treturn query.limit === undefined ? entries : entries.slice(0, query.limit);\n\t}\n\n\tasync findEntriesOnBranch(query: EntryQuery & BranchBounds & { start: string }): Promise<Entry[]> {\n\t\tconst cached = readCachedBranch(this.db, this.metadata.id, query.start);\n\t\tif (!cached) {\n\t\t\tif (!readEntryRow(this.db, this.metadata.id, query.start))\n\t\t\t\tthrow new SessionError(\"not_found\", `Entry not found: ${query.start}`);\n\t\t\tthrow new SessionError(\"invalid_entry\", `Branch cache missing entry ${query.start}`);\n\t\t}\n\t\tconst rows = queryCachedBranchRows(this.db, this.metadata.id, cached, query);\n\t\tvalidateCachedBranchRows(rows, query);\n\t\tconst entries = rows\n\t\t\t.map(entryRowFromCached)\n\t\t\t.map(decodeEntry)\n\t\t\t.filter((entry) => matchesEntryQuery(entry, query));\n\t\treturn query.limit === undefined ? entries : entries.slice(0, query.limit);\n\t}\n\n\tasync findRecords(query: RecordQuery = {}): Promise<LaneRecord[]> {\n\t\tconst rows = readRecordRows(this.db, this.metadata.id, query);\n\t\treturn rows.map(decodeRecord);\n\t}\n\n\tasync findOpenOperations(lane: string, options?: { limit?: number }): Promise<OperationStartedRecord[]> {\n\t\tconst rows = readOpenOperationRows(this.db, this.metadata.id, lane, options);\n\n\t\treturn rows.map((row) => {\n\t\t\tconst record = decodeRecord(row);\n\t\t\tif (record.type !== \"operation_started\") {\n\t\t\t\tthrow new SessionError(\"storage\", \"Expected operation_started record\");\n\t\t\t}\n\t\t\treturn record;\n\t\t});\n\t}\n\n\tasync getLog(options: LogOptions = {}): Promise<LogItem[]> {\n\t\tconst afterSeq = options.afterSeq ?? 0;\n\t\tconst limit = options.limit;\n\t\tconst entryRows = readEntryRows(this.db, this.metadata.id, { afterSeq, order: \"oldestFirst\", limit });\n\t\tconst recordRows = readRecordRows(this.db, this.metadata.id, { afterSeq, order: \"oldestFirst\", limit });\n\t\tconst laneRows = readLaneMoveRows(this.db, this.metadata.id, { afterSeq, limit });\n\t\tconst factRows = readFactRows(this.db, this.metadata.id, { afterSeq, limit });\n\n\t\tconst logRows: { seq: number; decode: () => LogItem }[] = [\n\t\t\t...entryRows.map((row) => ({\n\t\t\t\tseq: row.seq,\n\t\t\t\tdecode: () => ({ kind: \"entry\" as const, seq: row.seq, entry: decodeEntry(row) }),\n\t\t\t})),\n\t\t\t...recordRows.map((row) => ({\n\t\t\t\tseq: row.seq,\n\t\t\t\tdecode: () => ({ kind: \"record\" as const, seq: row.seq, record: decodeRecord(row) }),\n\t\t\t})),\n\t\t\t...laneRows.map((row) => ({\n\t\t\t\tseq: row.seq,\n\t\t\t\tdecode: () => ({ kind: \"lane\" as const, seq: row.seq, lane: row.lane, leafId: row.leaf_id }),\n\t\t\t})),\n\t\t\t...factRows.map((row) => ({\n\t\t\t\tseq: row.seq,\n\t\t\t\tdecode: () => {\n\t\t\t\t\tif (row.kind === \"name\")\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tkind: \"fact\" as const,\n\t\t\t\t\t\t\tseq: row.seq,\n\t\t\t\t\t\t\tfact: \"name\" as const,\n\t\t\t\t\t\t\tname: row.value === null ? undefined : (JSON.parse(row.value) as string),\n\t\t\t\t\t\t};\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: \"fact\" as const,\n\t\t\t\t\t\tseq: row.seq,\n\t\t\t\t\t\tfact: \"label\" as const,\n\t\t\t\t\t\ttargetId: row.key ?? \"\",\n\t\t\t\t\t\tlabel: row.value === null ? undefined : (JSON.parse(row.value) as string),\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t})),\n\t\t].sort((left, right) => left.seq - right.seq);\n\t\tconst selectedRows = options.limit === undefined ? logRows : logRows.slice(0, options.limit);\n\t\treturn selectedRows.map((row) => row.decode());\n\t}\n\n\tasync getName(): Promise<string | undefined> {\n\t\tconst row = readLatestFact(this.db, this.metadata.id, \"name\", null);\n\t\treturn row?.value === undefined || row.value === null ? undefined : (JSON.parse(row.value) as string);\n\t}\n\n\tasync setName(name: string | undefined): Promise<void> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tappendFact(this.db, this.metadata.id, seq, \"name\", null, name === undefined ? null : JSON.stringify(name));\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t});\n\t}\n\n\tasync getLabel(id: string): Promise<string | undefined> {\n\t\tconst row = readLatestFact(this.db, this.metadata.id, \"label\", id);\n\t\treturn row?.value === undefined || row.value === null ? undefined : (JSON.parse(row.value) as string);\n\t}\n\n\tasync setLabel(id: string, label: string | undefined): Promise<void> {\n\t\treturn this.enqueueWrite(() => {\n\t\t\tif (!readEntryRow(this.db, this.metadata.id, id)) {\n\t\t\t\tthrow new SessionError(\"not_found\", `Entry not found: ${id}`);\n\t\t\t}\n\t\t\tconst seq = getNextSequence(this.db, this.metadata.id);\n\t\t\tappendFact(this.db, this.metadata.id, seq, \"label\", id, label === undefined ? null : JSON.stringify(label));\n\t\t\tadvanceSequence(this.db, this.metadata.id, seq);\n\t\t});\n\t}\n\n\tasync getStats(): Promise<SessionStats> {\n\t\treturn readStats(this.db, this.metadata.id);\n\t}\n}\n\nfunction claimStorage(\n\tdb: SqliteDatabase,\n\tmetadata: SqliteSessionMetadata,\n\tleaseOptions: ResolvedWriterLeaseOptions,\n\tonRelease: () => void,\n): SqliteSessionStorage {\n\trequireSessionRow(db, metadata.id);\n\tconst claimed = db.transaction(() => {\n\t\tconst lease = claimWriterLease(db, metadata.id, leaseOptions);\n\t\tconst row = requireSessionRow(db, metadata.id);\n\t\treadLanes(db, metadata.id);\n\t\treturn { lease, row };\n\t});\n\treturn new SqliteSessionStorage(\n\t\tdb,\n\t\tdecodeSessionMetadata(claimed.row, metadata.path),\n\t\tclaimed.lease,\n\t\tleaseOptions,\n\t\tonRelease,\n\t);\n}\n\nexport class SqliteSessionRepository\n\timplements\n\t\tSessionRepository<SqliteSessionMetadata, SqliteSessionCreateOptions, SqliteSessionListOptions>,\n\t\tAsyncDisposable\n{\n\tprivate databasePath: string | undefined;\n\tprivate database: SqliteDatabase | undefined;\n\tprivate databasePromise: Promise<SqliteDatabase> | undefined;\n\tprivate readonly operations = new SerialOperationQueue();\n\tprivate readonly activeStorages = new Set<SqliteSessionStorage>();\n\tprivate readonly options: SqliteSessionRepositoryOptions;\n\tprivate readonly leaseOptions: ResolvedWriterLeaseOptions;\n\n\tconstructor(options: SqliteSessionRepositoryOptions) {\n\t\tthis.options = options;\n\t\tthis.leaseOptions = resolveWriterLeaseOptions(options.writerLease);\n\t}\n\n\tprivate async releaseStoragesForSession(sessionId: string): Promise<void> {\n\t\tfor (const storage of [...this.activeStorages]) {\n\t\t\tif (storage.isForSession(sessionId)) await storage.release();\n\t\t}\n\t}\n\n\tprivate sessionFromLease(\n\t\tdb: SqliteDatabase,\n\t\tmetadata: SqliteSessionMetadata,\n\t\tlease: WriterLease,\n\t): Session<SqliteSessionMetadata> {\n\t\tlet storage: SqliteSessionStorage;\n\t\tstorage = new SqliteSessionStorage(db, metadata, lease, this.leaseOptions, () => {\n\t\t\tthis.activeStorages.delete(storage);\n\t\t});\n\t\tthis.activeStorages.add(storage);\n\t\treturn new Session(storage);\n\t}\n\n\tprivate claimSession(db: SqliteDatabase, metadata: SqliteSessionMetadata): Session<SqliteSessionMetadata> {\n\t\tconst active = [...this.activeStorages].find((storage) => storage.isForSession(metadata.id));\n\t\tif (active) {\n\t\t\treadLanes(db, metadata.id);\n\t\t\treturn new Session(active);\n\t\t}\n\t\tlet storage: SqliteSessionStorage;\n\t\tstorage = claimStorage(db, metadata, this.leaseOptions, () => {\n\t\t\tthis.activeStorages.delete(storage);\n\t\t});\n\t\tthis.activeStorages.add(storage);\n\t\treturn new Session(storage);\n\t}\n\n\tasync create(options: SqliteSessionCreateOptions): Promise<Session<SqliteSessionMetadata>> {\n\t\treturn this.operations.enqueue(async () => {\n\t\t\tconst db = await this.getDatabase();\n\t\t\tconst path = await this.getDatabasePath();\n\t\t\tconst id = options.id ?? uuidv7();\n\t\t\tif (sessionExists(db, id)) throw new SessionError(\"already_exists\", `Session already exists: ${id}`);\n\t\t\tconst createdAt = Date.now();\n\t\t\tconst lease = db.transaction(() => {\n\t\t\t\tinsertSessionRow(db, {\n\t\t\t\t\tid,\n\t\t\t\t\tcreatedAt,\n\t\t\t\t\tcwd: options.cwd,\n\t\t\t\t\tparentSessionId: options.parentSessionId,\n\t\t\t\t\tmetadata: options.metadata,\n\t\t\t\t});\n\t\t\t\tcreateSequence(db, id);\n\t\t\t\tcreateStats(db, id);\n\t\t\t\tcreateInitialLane(db, id);\n\t\t\t\treturn claimWriterLease(db, id, this.leaseOptions);\n\t\t\t});\n\t\t\tconst row = requireSessionRow(db, id);\n\t\t\treturn this.sessionFromLease(db, decodeSessionMetadata(row, path), lease);\n\t\t});\n\t}\n\n\tasync open(metadata: SqliteSessionMetadata): Promise<Session<SqliteSessionMetadata>> {\n\t\treturn this.operations.enqueue(async () => this.claimSession(await this.getDatabase(), metadata));\n\t}\n\n\t/** Rebuilds this session's private branch-read cache from canonical entry parent links. */\n\tasync repairBranchCache(metadata: SqliteSessionMetadata): Promise<void> {\n\t\treturn this.operations.enqueue(async () => {\n\t\t\tawait this.releaseStoragesForSession(metadata.id);\n\t\t\tconst db = await this.getDatabase();\n\t\t\tdb.transaction(() => {\n\t\t\t\tconst lease = claimWriterLease(db, metadata.id, this.leaseOptions);\n\t\t\t\trequireSessionRow(db, metadata.id);\n\t\t\t\trebuildBranchCache(db, metadata.id);\n\t\t\t\treleaseWriterLease(db, metadata.id, lease);\n\t\t\t});\n\t\t});\n\t}\n\n\t/** Reads the session catalog without acquiring or renewing per-session writer leases. */\n\tasync list(options: SqliteSessionListOptions = {}): Promise<SqliteSessionMetadata[]> {\n\t\treturn this.operations.enqueue(async () => {\n\t\t\tconst path = await this.getDatabasePath();\n\t\t\tif (!resultOrThrow(await this.options.env.exists(path), `Failed to check database ${path}`)) return [];\n\t\t\tconst db = await this.getDatabase();\n\t\t\tconst rows = readSessionRows(db, options);\n\t\t\treturn rows.map((row) => decodeSessionMetadata(row, path));\n\t\t});\n\t}\n\n\tasync delete(metadata: SqliteSessionMetadata): Promise<void> {\n\t\treturn this.operations.enqueue(async () => {\n\t\t\tawait this.releaseStoragesForSession(metadata.id);\n\t\t\tconst db = await this.getDatabase();\n\t\t\tdb.transaction(() => {\n\t\t\t\tif (!sessionExists(db, metadata.id)) {\n\t\t\t\t\tdeleteWriterLease(db, metadata.id);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tclaimWriterLease(db, metadata.id, this.leaseOptions);\n\t\t\t\tdeleteBranchCache(db, metadata.id);\n\t\t\t\tdeleteFactRows(db, metadata.id);\n\t\t\t\tdeleteLaneRows(db, metadata.id);\n\t\t\t\tdeleteRecordRows(db, metadata.id);\n\t\t\t\tdeleteEntryRows(db, metadata.id);\n\t\t\t\tdeleteWriterLease(db, metadata.id);\n\t\t\t\tdeleteStats(db, metadata.id);\n\t\t\t\tdeleteSequence(db, metadata.id);\n\t\t\t\tdeleteSessionRow(db, metadata.id);\n\t\t\t});\n\t\t});\n\t}\n\n\tasync fork(\n\t\tsource: SqliteSessionMetadata,\n\t\toptions: ForkOptions & SqliteSessionCreateOptions,\n\t): Promise<Session<SqliteSessionMetadata>> {\n\t\treturn this.operations.enqueue(async () => {\n\t\t\tconst db = await this.getDatabase();\n\t\t\tconst path = await this.getDatabasePath();\n\t\t\tconst sourceMetadata = decodeSessionMetadata(requireSessionRow(db, source.id), path);\n\t\t\tconst id = options.id ?? uuidv7();\n\t\t\tif (sessionExists(db, id)) throw new SessionError(\"already_exists\", `Session already exists: ${id}`);\n\n\t\t\tconst entries: EntryRow[] = [];\n\t\t\tconst lanes: { lane: string; leafId: string | null }[] = [];\n\t\t\tconst branchTips: string[] = [];\n\t\t\tlet branchForkTargetId: string | null = null;\n\n\t\t\tif (options.scope === \"tree\") {\n\t\t\t\tentries.push(...readEntryRows(db, source.id, { order: \"oldestFirst\" }));\n\t\t\t\tlanes.push(...readLanes(db, source.id).map((row) => ({ lane: row.lane, leafId: row.leaf_id })));\n\t\t\t\tbranchTips.push(...readBranchTipIds(db, source.id));\n\t\t\t} else {\n\t\t\t\tconst main = readLane(db, source.id, \"main\");\n\t\t\t\tif (!main) throw new SessionError(\"invalid_lane\", \"Lane not found: main\");\n\t\t\t\tconst selectedEntryId = options.entryId ?? main.leaf_id;\n\t\t\t\tif (selectedEntryId !== null) {\n\t\t\t\t\tconst target = readEntryRow(db, source.id, selectedEntryId);\n\t\t\t\t\tif (!target || target.type !== \"message\") {\n\t\t\t\t\t\tthrow new SessionError(\n\t\t\t\t\t\t\t\"invalid_fork_target\",\n\t\t\t\t\t\t\t`Fork target is not a message entry: ${selectedEntryId}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst position = options.position ?? (options.entryId === undefined ? \"at\" : \"before\");\n\t\t\t\t\tbranchForkTargetId = position === \"at\" ? target.id : target.parent_id;\n\t\t\t\t}\n\t\t\t\tlanes.push({ lane: \"main\", leafId: branchForkTargetId });\n\t\t\t\tif (branchForkTargetId !== null) {\n\t\t\t\t\tconst cached = readCachedBranch(db, source.id, branchForkTargetId);\n\t\t\t\t\tif (!cached) {\n\t\t\t\t\t\tthrow new SessionError(\n\t\t\t\t\t\t\t\"invalid_fork_target\",\n\t\t\t\t\t\t\t`Fork target is not on a cached branch: ${branchForkTargetId}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst rows = queryCachedBranchRows(db, source.id, cached, { order: \"oldestFirst\" });\n\t\t\t\t\tentries.push(...rows.map(entryRowFromCached));\n\t\t\t\t\tbranchTips.push(branchForkTargetId);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst copiedIds = new Set(entries.map((entry) => entry.id));\n\t\t\tconst latestName = readLatestFact(db, source.id, \"name\", null);\n\t\t\tconst latestLabels = readLatestLabelFacts(db, source.id);\n\t\t\tconst labelsToCopy = latestLabels.filter(\n\t\t\t\t(row) => options.scope === \"tree\" || (row.key !== null && copiedIds.has(row.key)),\n\t\t\t);\n\t\t\tconst createdAt = Date.now();\n\t\t\tconst metadata = options.metadata ?? sourceMetadata.metadata;\n\t\t\tlet lease: WriterLease;\n\n\t\t\ttry {\n\t\t\t\tlease = db.transaction(() => {\n\t\t\t\t\tinsertSessionRow(db, {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tcreatedAt,\n\t\t\t\t\t\tcwd: options.cwd,\n\t\t\t\t\t\tparentSessionId: options.parentSessionId ?? source.id,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t});\n\t\t\t\t\tcreateSequence(db, id);\n\t\t\t\t\tcreateStats(db, id, entries.filter((entry) => entry.type === \"message\").length);\n\n\t\t\t\t\tlet nextSeq = 1;\n\t\t\t\t\tconst allocateSeq = () => nextSeq++;\n\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\tinsertEntryRow(db, id, {\n\t\t\t\t\t\t\tseq: allocateSeq(),\n\t\t\t\t\t\t\tid: entry.id,\n\t\t\t\t\t\t\tparentId: entry.parent_id,\n\t\t\t\t\t\t\ttype: entry.type,\n\t\t\t\t\t\t\ttimestamp: entry.timestamp,\n\t\t\t\t\t\t\tpayload: entry.payload,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (options.scope === \"tree\") {\n\t\t\t\t\t\tfor (const lane of lanes) insertLane(db, id, allocateSeq(), lane.lane, lane.leafId);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcreateInitialLane(db, id, \"main\", branchForkTargetId);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (latestName?.value !== undefined && latestName.value !== null) {\n\t\t\t\t\t\tappendFact(db, id, allocateSeq(), \"name\", null, latestName.value);\n\t\t\t\t\t}\n\t\t\t\t\tfor (const label of labelsToCopy) appendFact(db, id, allocateSeq(), \"label\", label.key, label.value);\n\n\t\t\t\t\tsetNextSequence(db, id, nextSeq);\n\t\t\t\t\tfor (const tip of branchTips) buildCachedBranch(db, id, tip);\n\t\t\t\t\treturn claimWriterLease(db, id, this.leaseOptions);\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof SessionError) throw error;\n\t\t\t\tthrow new SessionError(\n\t\t\t\t\t\"storage\",\n\t\t\t\t\t`Failed to fork SQLite session ${id}`,\n\t\t\t\t\terror instanceof Error ? error : undefined,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst row = requireSessionRow(db, id);\n\t\t\treturn this.sessionFromLease(db, decodeSessionMetadata(row, path), lease);\n\t\t});\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.operations.drain();\n\t\tfor (const storage of [...this.activeStorages]) await storage.release();\n\t\tif (this.database) this.database.close();\n\t\tthis.database = undefined;\n\t\tthis.databasePromise = undefined;\n\t}\n\n\tasync [Symbol.asyncDispose](): Promise<void> {\n\t\tawait this.close();\n\t}\n\n\tprivate async getDatabasePath(): Promise<string> {\n\t\tthis.databasePath ??= resultOrThrow(\n\t\t\tawait this.options.env.absolutePath(this.options.databasePath),\n\t\t\t`Failed to resolve SQLite sessions database ${this.options.databasePath}`,\n\t\t);\n\t\treturn this.databasePath;\n\t}\n\n\tprivate async getDatabase(): Promise<SqliteDatabase> {\n\t\tif (!this.databasePromise) this.databasePromise = this.openDatabase();\n\t\tthis.database = await this.databasePromise;\n\t\treturn this.database;\n\t}\n\n\tprivate async openDatabase(): Promise<SqliteDatabase> {\n\t\tconst path = await this.getDatabasePath();\n\t\tresultOrThrow(\n\t\t\tawait this.options.env.createDir(getParentPath(path), { recursive: true }),\n\t\t\t`Failed to create SQLite sessions directory ${path}`,\n\t\t);\n\t\tconst db = await this.options.sqlite.open(path);\n\t\ttry {\n\t\t\tconfigureSqliteDatabase(db);\n\t\t\tawait applyMigrations(db);\n\t\t\treturn db;\n\t\t} catch (error) {\n\t\t\tdb.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"repo.js","sourceRoot":"","sources":["../../src/sqlite/repo.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, open as openFile, readdir, realpath, rm } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport type { Context, Entry, ForkOptions, SessionCreateOptions, StoredValue } from \"@earendil-works/pi-agent-core\";\nimport { branchTip, createForkSnapshot, StorageBackedSession } from \"@earendil-works/pi-agent-core\";\nimport { uuidv7 } from \"@earendil-works/pi-ai\";\nimport { applyInitialSchema } from \"./migrations.ts\";\nimport { appendEntryToBranchIndex, scanBranchEntries } from \"./session/branch-entries.ts\";\nimport { decodeEntryRow, type EntryRow, EntryRowWriter } from \"./session/entries.ts\";\nimport {\n\tdeleteSessionRows,\n\thasSessionRow,\n\tinsertSessionRow,\n\tmetadataFromSessionRow,\n\treadAllSessionRows,\n\treadSessionRow,\n\ttype SqliteSessionMetadata,\n} from \"./session/session-row.ts\";\nimport { readAllScalarValueRows, setScalarValueRow } from \"./session/values.ts\";\nimport { SqliteOpenSession } from \"./session.ts\";\nimport { sql } from \"./sql.ts\";\nimport { SqliteStorage, type SqliteStorageSnapshot } from \"./storage.ts\";\nimport type { SqliteDatabase, SqliteDatabaseFactory } from \"./types.ts\";\n\nexport const SQLITE_STORAGE_VERSION = 1;\nexport const SQLITE_SESSION_EXTENSION = \".sqlite\";\n\nconst FIRST_AVAILABLE_COMMIT_SEQ = 1;\nconst SAFE_SESSION_FILE_ID = /^[A-Za-z0-9_-]+$/;\n\nexport type SqliteSessionCreateOptions = SessionCreateOptions;\n\nexport interface SqliteSessionRepoOptions {\n\tdirectory: string;\n\t/** Optional single container path. Defaults to one encoded `${id}.sqlite` file per session under directory. */\n\tdatabasePath?: string;\n\tdatabaseFactory: SqliteDatabaseFactory;\n\tnow?: () => number;\n}\n\nfunction sessionFileName(id: string): string {\n\tif (SAFE_SESSION_FILE_ID.test(id)) return `${id}${SQLITE_SESSION_EXTENSION}`;\n\tconst encoded = Buffer.from(id, \"utf16le\").toString(\"base64url\");\n\treturn `~${encoded}${SQLITE_SESSION_EXTENSION}`;\n}\n\nfunction sessionPath(directory: string, id: string): string {\n\treturn join(directory, sessionFileName(id));\n}\n\nfunction storageIdentity(path: string, sessionId: string): string {\n\treturn JSON.stringify([path, sessionId]);\n}\n\nfunction isErrorWithCode(error: unknown, code: string): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === code;\n}\n\nasync function removeSessionFiles(path: string, options: { force: boolean }): Promise<void> {\n\tawait rm(path, { force: options.force });\n\tawait rm(`${path}-wal`, { force: true });\n\tawait rm(`${path}-shm`, { force: true });\n}\n\nfunction configureWritableConnection(db: SqliteDatabase): void {\n\tdb.exec(\"PRAGMA journal_mode = WAL; PRAGMA busy_timeout = 5000;\");\n}\n\nfunction configureReadOnlyConnection(db: SqliteDatabase): void {\n\tdb.exec(\"PRAGMA busy_timeout = 5000;\");\n}\n\ninterface ForkSnapshot {\n\tentries: Entry[];\n\tscalarValues: StoredValue<unknown>[];\n\tmessageCount: number;\n\tnextSeq: number;\n}\n\nfunction readSourceEntries(db: SqliteDatabase, sessionId: string): Entry[] {\n\treturn sql`SELECT id, parent_id, seq, type, custom_type, timestamp, payload\n\t\tFROM entries WHERE session_id = ${sessionId} ORDER BY seq ASC`\n\t\t.all<EntryRow>(db)\n\t\t.map(decodeEntryRow);\n}\n\nfunction buildForkSnapshot(source: SqliteStorageSnapshot, options: ForkOptions): ForkSnapshot {\n\tconst snapshot = createForkSnapshot(\n\t\t{\n\t\t\tentries: source.entries,\n\t\t\tscalarValues: source.scalarValues,\n\t\t\tentriesComplete: source.entriesComplete,\n\t\t},\n\t\toptions,\n\t);\n\tconst entries = [...snapshot.entries.values()].sort((left, right) => left.seq - right.seq);\n\treturn {\n\t\tentries,\n\t\tscalarValues: snapshot.scalarValues,\n\t\tmessageCount: entries.filter((entry) => entry.type === \"message\").length,\n\t\tnextSeq: snapshot.nextSeq,\n\t};\n}\n\n// TODO(WP08): Remove this snapshot path when SQLite forks use streaming staging.\nfunction readForkSourceEntries(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tscalarValues: readonly StoredValue<unknown>[],\n\toptions: ForkOptions,\n): Entry[] {\n\tif (options.scope === \"tree\") return readSourceEntries(db, sessionId);\n\tconst sourceAddress = branchTip(options.branch);\n\tconst sourceTip = scalarValues.find(\n\t\t(stored) => stored.address.namespace === sourceAddress.namespace && stored.address.key === sourceAddress.key,\n\t) as StoredValue<string | null> | undefined;\n\tif (sourceTip === undefined) throw new Error(`Unknown source branch: ${options.branch}`);\n\treturn sourceTip.value === null\n\t\t? []\n\t\t: scanBranchEntries(db, sessionId, { start: sourceTip.value, order: \"oldestFirst\" });\n}\n\nfunction createSqliteForkSnapshot(\n\tsourceDb: SqliteDatabase,\n\tsource: SqliteSessionMetadata,\n\toptions: ForkOptions,\n): ForkSnapshot {\n\tsourceDb.exec(\"BEGIN\");\n\tlet committed = false;\n\ttry {\n\t\tmetadataFromSessionRow(source.path, readSessionRow(sourceDb, source.id), SQLITE_STORAGE_VERSION);\n\t\tconst scalarValues = readAllScalarValueRows(sourceDb, source.id);\n\t\tconst snapshot = buildForkSnapshot(\n\t\t\t{\n\t\t\t\tentries: readForkSourceEntries(sourceDb, source.id, scalarValues, options),\n\t\t\t\tscalarValues,\n\t\t\t\tentriesComplete: options.scope === \"tree\",\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t\tsourceDb.exec(\"COMMIT\");\n\t\tcommitted = true;\n\t\treturn snapshot;\n\t} catch (error) {\n\t\tif (!committed) sourceDb.exec(\"ROLLBACK\");\n\t\tthrow error;\n\t}\n}\n\nfunction insertForkValue(db: SqliteDatabase, sessionId: string, stored: StoredValue<unknown>): void {\n\tsetScalarValueRow(db, sessionId, stored.address.namespace, stored.address.key, stored.seq, stored.value);\n}\n\nfunction updateForkSessionStats(db: SqliteDatabase, sessionId: string, messageCount: number): void {\n\tsql`UPDATE sessions SET message_count = ${messageCount} WHERE id = ${sessionId}`.run(db);\n}\n\nexport class SqliteSessionRepo {\n\tprivate readonly directory: string;\n\tprivate readonly databasePath: string | undefined;\n\tprivate readonly databaseFactory: SqliteDatabaseFactory;\n\tprivate readonly now: () => number;\n\tprivate readonly pendingIds = new Set<string>();\n\tprivate readonly openStorages = new Map<string, SqliteStorage>();\n\tprivate readonly openSessions = new Set<SqliteOpenSession>();\n\tprivate closed = false;\n\tprivate closePromise: Promise<void> | undefined;\n\n\tconstructor(options: SqliteSessionRepoOptions) {\n\t\tthis.directory = options.directory;\n\t\tthis.databasePath = options.databasePath;\n\t\tthis.databaseFactory = options.databaseFactory;\n\t\tthis.now = options.now ?? Date.now;\n\t}\n\n\tasync create(options: SqliteSessionCreateOptions | undefined, _context: Context): Promise<SqliteOpenSession> {\n\t\tthis.assertOpen();\n\t\toptions ??= {};\n\t\tconst createdAt = this.now();\n\t\tconst id = options.id ?? uuidv7(createdAt);\n\t\tthis.reserveId(id);\n\t\tconst path = this.pathForSession(id);\n\t\tlet db: SqliteDatabase | undefined;\n\t\tlet reservedFile = false;\n\t\tlet initialized = false;\n\t\tlet session: SqliteOpenSession | undefined;\n\t\ttry {\n\t\t\tawait mkdir(dirname(path), { recursive: true });\n\t\t\tif (!this.usesSharedDatabase()) {\n\t\t\t\tconst file = await openFile(path, \"wx\");\n\t\t\t\tawait file.close();\n\t\t\t\treservedFile = true;\n\t\t\t}\n\t\t\tconst activeDb = await this.databaseFactory.open(path);\n\t\t\tdb = activeDb;\n\t\t\tconfigureWritableConnection(activeDb);\n\t\t\tawait applyInitialSchema(activeDb);\n\t\t\tconst canonicalPath = await realpath(path);\n\t\t\tconst metadata: SqliteSessionMetadata = {\n\t\t\t\tid,\n\t\t\t\tcreatedAt,\n\t\t\t\tstorageVersion: SQLITE_STORAGE_VERSION,\n\t\t\t\t...(options.parentSessionId === undefined ? {} : { parentSessionId: options.parentSessionId }),\n\t\t\t\tpath: canonicalPath,\n\t\t\t};\n\t\t\tactiveDb.transaction(() => {\n\t\t\t\tif (hasSessionRow(activeDb, id)) throw new Error(`SQLite session already exists: ${id}`);\n\t\t\t\tinsertSessionRow(activeDb, metadata, SQLITE_STORAGE_VERSION, FIRST_AVAILABLE_COMMIT_SEQ);\n\t\t\t});\n\t\t\tinitialized = true;\n\t\t\tsession = this.openStorageBackedSession(metadata, activeDb);\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\tif (reservedFile && !initialized) await removeSessionFiles(path, { force: true });\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tif (session === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tdb?.close();\n\t\t\t\t} finally {\n\t\t\t\t\tthis.pendingIds.delete(id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync open(metadata: SqliteSessionMetadata, _context: Context): Promise<SqliteOpenSession> {\n\t\tthis.assertOpen();\n\t\tthis.reserveId(metadata.id);\n\t\tlet db: SqliteDatabase | undefined;\n\t\tlet session: SqliteOpenSession | undefined;\n\t\ttry {\n\t\t\tconst path = await this.repositoryPathForMetadata(metadata);\n\t\t\tconst activeDb = await this.databaseFactory.openExisting(path);\n\t\t\tdb = activeDb;\n\t\t\tconfigureWritableConnection(activeDb);\n\t\t\tconst stored = metadataFromSessionRow(path, readSessionRow(activeDb, metadata.id), SQLITE_STORAGE_VERSION);\n\t\t\tsession = this.openStorageBackedSession(stored, activeDb);\n\t\t\treturn session;\n\t\t} finally {\n\t\t\tif (session === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tdb?.close();\n\t\t\t\t} finally {\n\t\t\t\t\tthis.pendingIds.delete(metadata.id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tasync list(_options: undefined, _context: Context): Promise<SqliteSessionMetadata[]> {\n\t\tthis.assertOpen();\n\t\tlet paths: string[];\n\t\tif (this.usesSharedDatabase()) {\n\t\t\tpaths = [this.databasePath!];\n\t\t} else {\n\t\t\tlet names: string[];\n\t\t\ttry {\n\t\t\t\tnames = await readdir(this.directory);\n\t\t\t} catch (error) {\n\t\t\t\tif (isErrorWithCode(error, \"ENOENT\")) return [];\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tpaths = names\n\t\t\t\t.filter((name) => name.endsWith(SQLITE_SESSION_EXTENSION))\n\t\t\t\t.map((name) => join(this.directory, name));\n\t\t}\n\t\tconst sessions: SqliteSessionMetadata[] = [];\n\t\tfor (const path of paths) {\n\t\t\tlet db: SqliteDatabase | undefined;\n\t\t\ttry {\n\t\t\t\tconst canonicalPath = await realpath(path);\n\t\t\t\tdb = await this.databaseFactory.openReadOnly(canonicalPath);\n\t\t\t\tconfigureReadOnlyConnection(db);\n\t\t\t\tfor (const row of readAllSessionRows(db)) {\n\t\t\t\t\tsessions.push(metadataFromSessionRow(canonicalPath, row, SQLITE_STORAGE_VERSION));\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Discovery is best-effort: corrupt files, incompatible versions, and\n\t\t\t\t// unrelated *.sqlite files are reported when explicitly opened.\n\t\t\t} finally {\n\t\t\t\tdb?.close();\n\t\t\t}\n\t\t}\n\t\treturn sessions.sort((left, right) => right.createdAt - left.createdAt);\n\t}\n\n\tasync delete(metadata: SqliteSessionMetadata, _context: Context): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.reserveId(metadata.id);\n\t\ttry {\n\t\t\tconst path = await this.repositoryPathForMetadata(metadata);\n\t\t\tconst db = await this.databaseFactory.openExisting(path);\n\t\t\ttry {\n\t\t\t\tconfigureWritableConnection(db);\n\t\t\t\tif (this.usesSharedDatabase()) {\n\t\t\t\t\tdb.transaction(() => {\n\t\t\t\t\t\tmetadataFromSessionRow(path, readSessionRow(db, metadata.id), SQLITE_STORAGE_VERSION);\n\t\t\t\t\t\tdeleteSessionRows(db, metadata.id);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tmetadataFromSessionRow(path, readSessionRow(db, metadata.id), SQLITE_STORAGE_VERSION);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tdb.close();\n\t\t\t}\n\t\t\tif (!this.usesSharedDatabase()) await removeSessionFiles(path, { force: false });\n\t\t} finally {\n\t\t\tthis.pendingIds.delete(metadata.id);\n\t\t}\n\t}\n\n\tasync fork(source: SqliteSessionMetadata, options: ForkOptions, context: Context): Promise<SqliteOpenSession> {\n\t\tthis.assertOpen();\n\t\tconst createdAt = this.now();\n\t\tconst id = options.id ?? uuidv7(createdAt);\n\t\tthis.reserveId(id);\n\t\tconst sourceStorage = this.openStorages.get(storageIdentity(source.path, source.id));\n\t\tconst activeSourceSnapshot = sourceStorage?.snapshot(options, context);\n\t\tvoid activeSourceSnapshot?.catch(() => undefined);\n\t\tconst path = this.pathForSession(id);\n\t\tlet db: SqliteDatabase | undefined;\n\t\tlet reservedFile = false;\n\t\tlet initialized = false;\n\t\tlet session: SqliteOpenSession | undefined;\n\t\ttry {\n\t\t\tawait mkdir(dirname(path), { recursive: true });\n\t\t\tif (!this.usesSharedDatabase()) {\n\t\t\t\tconst file = await openFile(path, \"wx\");\n\t\t\t\tawait file.close();\n\t\t\t\treservedFile = true;\n\t\t\t}\n\n\t\t\tconst snapshot =\n\t\t\t\tactiveSourceSnapshot === undefined\n\t\t\t\t\t? await this.createForkSnapshotFromExternalSource(source, options)\n\t\t\t\t\t: buildForkSnapshot(await activeSourceSnapshot, options);\n\n\t\t\tconst activeDb = await this.databaseFactory.open(path);\n\t\t\tdb = activeDb;\n\t\t\tconfigureWritableConnection(activeDb);\n\t\t\tawait applyInitialSchema(activeDb);\n\t\t\tconst canonicalPath = await realpath(path);\n\t\t\tconst metadata: SqliteSessionMetadata = {\n\t\t\t\tid,\n\t\t\t\tcreatedAt,\n\t\t\t\tstorageVersion: SQLITE_STORAGE_VERSION,\n\t\t\t\tparentSessionId: source.id,\n\t\t\t\tpath: canonicalPath,\n\t\t\t};\n\t\t\tactiveDb.transaction(() => {\n\t\t\t\tif (hasSessionRow(activeDb, id)) throw new Error(`SQLite session already exists: ${id}`);\n\t\t\t\tinsertSessionRow(activeDb, metadata, SQLITE_STORAGE_VERSION, snapshot.nextSeq);\n\t\t\t\tconst entryWriter = new EntryRowWriter(activeDb, id);\n\t\t\t\tfor (const entry of snapshot.entries) {\n\t\t\t\t\tentryWriter.insert(entry);\n\t\t\t\t\tappendEntryToBranchIndex(activeDb, id, entry);\n\t\t\t\t}\n\t\t\t\tfor (const stored of snapshot.scalarValues) insertForkValue(activeDb, id, stored);\n\t\t\t\tupdateForkSessionStats(activeDb, id, snapshot.messageCount);\n\t\t\t});\n\t\t\tinitialized = true;\n\t\t\tsession = this.openStorageBackedSession(metadata, activeDb);\n\t\t\treturn session;\n\t\t} catch (error) {\n\t\t\tif (reservedFile && !initialized) await removeSessionFiles(path, { force: true });\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tif (session === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tdb?.close();\n\t\t\t\t} finally {\n\t\t\t\t\tthis.pendingIds.delete(id);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tclose(context: Context): Promise<void> {\n\t\tif (this.closePromise !== undefined) return this.closePromise;\n\t\tthis.closed = true;\n\t\tthis.closePromise = this.closeOpenSessions(context);\n\t\treturn this.closePromise;\n\t}\n\n\tprivate async createForkSnapshotFromExternalSource(\n\t\tsource: SqliteSessionMetadata,\n\t\toptions: ForkOptions,\n\t): Promise<ForkSnapshot> {\n\t\tconst path = await realpath(source.path);\n\t\tconst sourceDb = await this.databaseFactory.openReadOnly(path);\n\t\ttry {\n\t\t\tconfigureReadOnlyConnection(sourceDb);\n\t\t\treturn createSqliteForkSnapshot(sourceDb, { ...source, path }, options);\n\t\t} finally {\n\t\t\tsourceDb.close();\n\t\t}\n\t}\n\n\tprivate async closeOpenSessions(context: Context): Promise<void> {\n\t\tconst results = await Promise.allSettled([...this.openSessions].map((session) => session.close(context)));\n\t\tconst errors = results.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to close SQLite Sessions\");\n\t}\n\n\tprivate openStorageBackedSession(metadata: SqliteSessionMetadata, db: SqliteDatabase): SqliteOpenSession {\n\t\tconst key = storageIdentity(metadata.path, metadata.id);\n\t\tconst storage = new SqliteStorage(db, { sessionId: metadata.id, now: this.now });\n\t\tthis.openStorages.set(key, storage);\n\t\tconst session = new StorageBackedSession(metadata, storage);\n\t\tconst openSession = new SqliteOpenSession(session, {\n\t\t\tonClose: () => {\n\t\t\t\ttry {\n\t\t\t\t\tdb.close();\n\t\t\t\t} finally {\n\t\t\t\t\tif (this.openStorages.get(key) === storage) this.openStorages.delete(key);\n\t\t\t\t\tthis.openSessions.delete(openSession);\n\t\t\t\t\tthis.pendingIds.delete(metadata.id);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tthis.openSessions.add(openSession);\n\t\treturn openSession;\n\t}\n\n\tprivate async repositoryPathForMetadata(metadata: SqliteSessionMetadata): Promise<string> {\n\t\tconst [expected, actual] = await Promise.all([\n\t\t\trealpath(this.pathForSession(metadata.id)),\n\t\t\trealpath(metadata.path),\n\t\t]);\n\t\tif (expected !== actual) {\n\t\t\tthrow new Error(`SQLite session metadata path is outside this repository: ${metadata.path}`);\n\t\t}\n\t\treturn actual;\n\t}\n\n\tprivate reserveId(id: string): void {\n\t\tif (this.pendingIds.has(id)) throw new Error(`Session is already open: ${id}`);\n\t\tthis.pendingIds.add(id);\n\t}\n\n\tprivate pathForSession(id: string): string {\n\t\treturn this.databasePath ?? sessionPath(this.directory, id);\n\t}\n\n\tprivate usesSharedDatabase(): boolean {\n\t\treturn this.databasePath !== undefined;\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) throw new Error(\"SqliteSessionRepo is closed\");\n\t}\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { Entry, EntryStructure, StorageBranchScan } from "@earendil-works/pi-agent-core";
2
+ import type { SqliteDatabase } from "../types.ts";
3
+ export declare function appendEntryToBranchIndex(db: SqliteDatabase, sessionId: string, entry: Entry): void;
4
+ export declare function scanBranchEntries(db: SqliteDatabase, sessionId: string, query: StorageBranchScan): Entry[];
5
+ export declare function scanBranchEntryStructures(db: SqliteDatabase, sessionId: string, query: StorageBranchScan): EntryStructure[];
6
+ //# sourceMappingURL=branch-entries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-entries.d.ts","sourceRoot":"","sources":["../../../src/sqlite/session/branch-entries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAE9F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAmKlD,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAYlG;AAwID,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,KAAK,EAAE,CAE1G;AAED,wBAAgB,yBAAyB,CACxC,EAAE,EAAE,cAAc,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,iBAAiB,GACtB,cAAc,EAAE,CAElB","sourcesContent":["import type { Entry, EntryStructure, StorageBranchScan } from \"@earendil-works/pi-agent-core\";\nimport { joinSqlFragments, type SqlQuery, sql } from \"../sql.ts\";\nimport type { SqliteDatabase } from \"../types.ts\";\nimport { decodeEntryRow, type EntryRow } from \"./entries.ts\";\n\ninterface BranchMembershipRow {\n\tbranch_id: string;\n\tentry_seq: number;\n}\n\ninterface BranchMetaRow {\n\tbranch_id: string;\n\ttip_entry_id: string;\n\ttip_seq: number;\n\tbase_branch_id: string | null;\n\tbase_seq: number | null;\n}\n\ninterface BranchSegment {\n\tbranchId: string;\n\tlowerSeq: number;\n\tupperSeq: number;\n}\n\ninterface StopSeqRow {\n\tstop_seq: number | null;\n}\n\ninterface EntryStructureRow {\n\tid: string;\n\tparent_id: string | null;\n\tseq: number;\n\ttype: Entry[\"type\"];\n\tcustom_type: string | null;\n\ttimestamp: number;\n}\n\ninterface BranchTipRow {\n\tbranch_id: string;\n}\n\ninterface CompactionBoundary {\n\tbranchId: string;\n\tseq: number;\n}\n\ninterface CompactionBoundaryRow {\n\tentry_seq: number | null;\n}\n\nfunction readBranchMembership(db: SqliteDatabase, sessionId: string, entryId: string): BranchMembershipRow {\n\tconst row = sql`SELECT b.branch_id, b.entry_seq\n\t\tFROM branch_entries b\n\t\tJOIN branch_meta m ON m.session_id = b.session_id AND m.branch_id = b.branch_id\n\t\tWHERE b.session_id = ${sessionId}\n\t\t\tAND b.entry_id = ${entryId}\n\t\t\tAND ((m.base_seq IS NULL AND b.entry_seq > 0) OR (m.base_seq IS NOT NULL AND b.entry_seq > m.base_seq))\n\t\t\tAND b.entry_seq <= m.tip_seq\n\t\tORDER BY m.tip_seq DESC, b.branch_id\n\t\tLIMIT 1`.get<BranchMembershipRow>(db);\n\tif (row === undefined) throw new Error(`Branch cache missing entry ${entryId}`);\n\treturn row;\n}\n\nfunction readBranchMeta(db: SqliteDatabase, sessionId: string, branchId: string): BranchMetaRow {\n\tconst row = sql`SELECT branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq\n\t\tFROM branch_meta\n\t\tWHERE session_id = ${sessionId} AND branch_id = ${branchId}`.get<BranchMetaRow>(db);\n\tif (row === undefined) throw new Error(`Branch metadata missing for branch ${branchId}`);\n\treturn row;\n}\n\nfunction insertBranchEntry(db: SqliteDatabase, sessionId: string, branchId: string, entry: Entry): void {\n\tsql`INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)\n\t\tVALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${entry.type})`.run(db);\n}\n\nfunction readBranchTipForParent(db: SqliteDatabase, sessionId: string, parentId: string): BranchTipRow | undefined {\n\treturn sql`SELECT branch_id\n\t\tFROM branch_meta\n\t\tWHERE session_id = ${sessionId} AND tip_entry_id = ${parentId}`.get<BranchTipRow>(db);\n}\n\nfunction createRootBranchForEntry(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tsql`INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)\n\t\tVALUES (${sessionId}, ${entry.id}, ${entry.id}, ${entry.seq}, ${null}, ${null})`.run(db);\n\tinsertBranchEntry(db, sessionId, entry.id, entry);\n}\n\nfunction appendEntryToExistingBranch(db: SqliteDatabase, sessionId: string, branchId: string, entry: Entry): void {\n\tinsertBranchEntry(db, sessionId, branchId, entry);\n\tconst result = sql`UPDATE branch_meta\n\t\tSET tip_entry_id = ${entry.id}, tip_seq = ${entry.seq}\n\t\tWHERE session_id = ${sessionId} AND branch_id = ${branchId}`.run(db);\n\tif (result.changes !== 1) throw new Error(`Expected to update branch ${branchId}, updated ${result.changes}`);\n}\n\nfunction readBranchSegmentsNewestFirst(db: SqliteDatabase, sessionId: string, start: string): BranchSegment[] {\n\tlet { branch_id: branchId, entry_seq: upperSeq } = readBranchMembership(db, sessionId, start);\n\tconst segments: BranchSegment[] = [];\n\twhile (true) {\n\t\tconst meta = readBranchMeta(db, sessionId, branchId);\n\t\tconst lowerSeq = meta.base_seq ?? 0;\n\t\tsegments.push({ branchId, lowerSeq, upperSeq });\n\t\tif (meta.base_branch_id === null) break;\n\t\tif (meta.base_seq === null) throw new Error(`Branch ${branchId} has base branch without base_seq`);\n\t\tbranchId = meta.base_branch_id;\n\t\tupperSeq = meta.base_seq;\n\t}\n\treturn segments;\n}\n\nfunction readNewestCompactionBoundary(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegmentsNewestFirst: readonly BranchSegment[],\n): CompactionBoundary | undefined {\n\tfor (const segment of segmentsNewestFirst) {\n\t\tconst row = sql`SELECT MAX(entry_seq) AS entry_seq\n\t\t\tFROM branch_entries\n\t\t\tWHERE session_id = ${sessionId}\n\t\t\t\tAND branch_id = ${segment.branchId}\n\t\t\t\tAND entry_seq > ${segment.lowerSeq}\n\t\t\t\tAND entry_seq <= ${segment.upperSeq}\n\t\t\t\tAND entry_type = ${\"compaction\"}`.get<CompactionBoundaryRow>(db);\n\t\tif (row?.entry_seq !== null && row?.entry_seq !== undefined)\n\t\t\treturn { branchId: segment.branchId, seq: row.entry_seq };\n\t}\n\treturn undefined;\n}\n\nfunction copyBranchEntriesAfterSeqThroughParent(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\ttargetBranchId: string,\n\tsegmentsNewestFirst: readonly BranchSegment[],\n\tafterSeq: number,\n): void {\n\tfor (const segment of [...segmentsNewestFirst].reverse()) {\n\t\tconst lowerSeq = Math.max(segment.lowerSeq, afterSeq);\n\t\tif (segment.upperSeq <= lowerSeq) continue;\n\t\tsql`INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)\n\t\t\tSELECT ${sessionId}, ${targetBranchId}, entry_id, entry_seq, entry_type\n\t\t\tFROM branch_entries\n\t\t\tWHERE session_id = ${sessionId}\n\t\t\t\tAND branch_id = ${segment.branchId}\n\t\t\t\tAND entry_seq > ${lowerSeq}\n\t\t\t\tAND entry_seq <= ${segment.upperSeq}`.run(db);\n\t}\n}\n\nfunction createDivergentBranchForEntry(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tif (entry.parentId === null) throw new Error(\"Root entries do not create divergent branches\");\n\tconst segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, entry.parentId);\n\tconst compaction = readNewestCompactionBoundary(db, sessionId, segmentsNewestFirst);\n\tconst branchId = entry.id;\n\t// A null base means this segment stores its own root-through-parent prefix.\n\tsql`INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)\n\t\tVALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${compaction?.branchId ?? null}, ${compaction?.seq ?? null})`.run(\n\t\tdb,\n\t);\n\tcopyBranchEntriesAfterSeqThroughParent(db, sessionId, branchId, segmentsNewestFirst, compaction?.seq ?? 0);\n\tinsertBranchEntry(db, sessionId, branchId, entry);\n}\n\nexport function appendEntryToBranchIndex(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tif (entry.parentId === null) {\n\t\tcreateRootBranchForEntry(db, sessionId, entry);\n\t\treturn;\n\t}\n\n\tconst branch = readBranchTipForParent(db, sessionId, entry.parentId);\n\tif (branch === undefined) {\n\t\tcreateDivergentBranchForEntry(db, sessionId, entry);\n\t\treturn;\n\t}\n\tappendEntryToExistingBranch(db, sessionId, branch.branch_id, entry);\n}\n\nfunction stopPredicates(query: StorageBranchScan): SqlQuery[] {\n\tconst predicates: SqlQuery[] = [];\n\tif (query.stopAtType !== undefined) predicates.push(sql`b.entry_type = ${query.stopAtType}`);\n\tif (query.stopAtId !== undefined) predicates.push(sql`b.entry_id = ${query.stopAtId}`);\n\treturn predicates;\n}\n\nfunction readStopSeq(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n): number | undefined {\n\tconst stop = stopPredicates(query);\n\tif (stop.length === 0) return undefined;\n\tconst aggregate = oldestFirst ? sql`MIN(b.entry_seq)` : sql`MAX(b.entry_seq)`;\n\tconst row = sql`SELECT ${aggregate} AS stop_seq\n\t\tFROM branch_entries b\n\t\tWHERE b.session_id = ${sessionId}\n\t\t\tAND b.branch_id = ${segment.branchId}\n\t\t\tAND b.entry_seq > ${segment.lowerSeq}\n\t\t\tAND b.entry_seq <= ${segment.upperSeq}\n\t\t\tAND (${joinSqlFragments(stop, \" OR \")})`.get<StopSeqRow>(db);\n\treturn row?.stop_seq ?? undefined;\n}\n\nfunction branchScanPredicates(\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n): SqlQuery[] {\n\tconst predicates: SqlQuery[] = [\n\t\tsql`b.session_id = ${sessionId}`,\n\t\tsql`b.branch_id = ${segment.branchId}`,\n\t\tsql`b.entry_seq > ${segment.lowerSeq}`,\n\t\tsql`b.entry_seq <= ${segment.upperSeq}`,\n\t\tsql`e.session_id = b.session_id`,\n\t];\n\tif (stopSeq !== undefined)\n\t\tpredicates.push(oldestFirst ? sql`b.entry_seq <= ${stopSeq}` : sql`b.entry_seq >= ${stopSeq}`);\n\tif (query.type !== undefined) predicates.push(sql`b.entry_type = ${query.type}`);\n\tif (query.customType !== undefined) predicates.push(sql`e.custom_type = ${query.customType}`);\n\tif (query.cursor !== undefined) {\n\t\tpredicates.push(oldestFirst ? sql`b.entry_seq > ${query.cursor.seq}` : sql`b.entry_seq < ${query.cursor.seq}`);\n\t}\n\treturn predicates;\n}\n\nfunction limitSql(limit: number | undefined): SqlQuery {\n\treturn limit === undefined ? sql`` : sql`LIMIT ${Math.max(0, limit)}`;\n}\n\nfunction scanEntrySegmentRows(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n\tlimit: number | undefined,\n): EntryRow[] {\n\tconst predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);\n\tconst order = oldestFirst ? sql`ASC` : sql`DESC`;\n\treturn sql`SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp, e.payload\n\t\tFROM branch_entries b\n\t\tCROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id\n\t\tWHERE ${joinSqlFragments(predicates, \" AND \")}\n\t\tORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all<EntryRow>(db);\n}\n\nfunction decodeEntryStructureRow(row: EntryStructureRow): EntryStructure {\n\treturn {\n\t\tid: row.id,\n\t\tparentId: row.parent_id,\n\t\tseq: row.seq,\n\t\ttimestamp: row.timestamp,\n\t\ttype: row.type,\n\t\t...(row.custom_type === null ? {} : { customType: row.custom_type }),\n\t};\n}\n\nfunction scanStructureSegmentRows(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n\tlimit: number | undefined,\n): EntryStructure[] {\n\tconst predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);\n\tconst order = oldestFirst ? sql`ASC` : sql`DESC`;\n\tconst rows = sql`SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp\n\t\tFROM branch_entries b\n\t\tCROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id\n\t\tWHERE ${joinSqlFragments(predicates, \" AND \")}\n\t\tORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all<EntryStructureRow>(db);\n\treturn rows.map(decodeEntryStructureRow);\n}\n\nfunction scanBranchSegments<T>(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tquery: StorageBranchScan,\n\treadSegment: (\n\t\tdb: SqliteDatabase,\n\t\tsessionId: string,\n\t\tsegment: BranchSegment,\n\t\tquery: StorageBranchScan,\n\t\toldestFirst: boolean,\n\t\tstopSeq: number | undefined,\n\t\tlimit: number | undefined,\n\t) => T[],\n): T[] {\n\tconst oldestFirst = query.order === \"oldestFirst\";\n\tconst segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, query.start);\n\tconst segments = oldestFirst ? [...segmentsNewestFirst].reverse() : segmentsNewestFirst;\n\tconst limit = query.limit === undefined ? undefined : Math.max(0, query.limit);\n\tif (limit === 0) return [];\n\n\tconst rows: T[] = [];\n\tfor (const segment of segments) {\n\t\tconst remaining = limit === undefined ? undefined : limit - rows.length;\n\t\tif (remaining !== undefined && remaining <= 0) break;\n\t\tconst stopSeq = readStopSeq(db, sessionId, segment, query, oldestFirst);\n\t\trows.push(...readSegment(db, sessionId, segment, query, oldestFirst, stopSeq, remaining));\n\t\tif (stopSeq !== undefined) break;\n\t}\n\treturn rows;\n}\n\nexport function scanBranchEntries(db: SqliteDatabase, sessionId: string, query: StorageBranchScan): Entry[] {\n\treturn scanBranchSegments(db, sessionId, query, scanEntrySegmentRows).map(decodeEntryRow);\n}\n\nexport function scanBranchEntryStructures(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tquery: StorageBranchScan,\n): EntryStructure[] {\n\treturn scanBranchSegments(db, sessionId, query, scanStructureSegmentRows);\n}\n"]}
@@ -0,0 +1,213 @@
1
+ import { joinSqlFragments, sql } from "../sql.js";
2
+ import { decodeEntryRow } from "./entries.js";
3
+ function readBranchMembership(db, sessionId, entryId) {
4
+ const row = sql `SELECT b.branch_id, b.entry_seq
5
+ FROM branch_entries b
6
+ JOIN branch_meta m ON m.session_id = b.session_id AND m.branch_id = b.branch_id
7
+ WHERE b.session_id = ${sessionId}
8
+ AND b.entry_id = ${entryId}
9
+ AND ((m.base_seq IS NULL AND b.entry_seq > 0) OR (m.base_seq IS NOT NULL AND b.entry_seq > m.base_seq))
10
+ AND b.entry_seq <= m.tip_seq
11
+ ORDER BY m.tip_seq DESC, b.branch_id
12
+ LIMIT 1`.get(db);
13
+ if (row === undefined)
14
+ throw new Error(`Branch cache missing entry ${entryId}`);
15
+ return row;
16
+ }
17
+ function readBranchMeta(db, sessionId, branchId) {
18
+ const row = sql `SELECT branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq
19
+ FROM branch_meta
20
+ WHERE session_id = ${sessionId} AND branch_id = ${branchId}`.get(db);
21
+ if (row === undefined)
22
+ throw new Error(`Branch metadata missing for branch ${branchId}`);
23
+ return row;
24
+ }
25
+ function insertBranchEntry(db, sessionId, branchId, entry) {
26
+ sql `INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)
27
+ VALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${entry.type})`.run(db);
28
+ }
29
+ function readBranchTipForParent(db, sessionId, parentId) {
30
+ return sql `SELECT branch_id
31
+ FROM branch_meta
32
+ WHERE session_id = ${sessionId} AND tip_entry_id = ${parentId}`.get(db);
33
+ }
34
+ function createRootBranchForEntry(db, sessionId, entry) {
35
+ sql `INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)
36
+ VALUES (${sessionId}, ${entry.id}, ${entry.id}, ${entry.seq}, ${null}, ${null})`.run(db);
37
+ insertBranchEntry(db, sessionId, entry.id, entry);
38
+ }
39
+ function appendEntryToExistingBranch(db, sessionId, branchId, entry) {
40
+ insertBranchEntry(db, sessionId, branchId, entry);
41
+ const result = sql `UPDATE branch_meta
42
+ SET tip_entry_id = ${entry.id}, tip_seq = ${entry.seq}
43
+ WHERE session_id = ${sessionId} AND branch_id = ${branchId}`.run(db);
44
+ if (result.changes !== 1)
45
+ throw new Error(`Expected to update branch ${branchId}, updated ${result.changes}`);
46
+ }
47
+ function readBranchSegmentsNewestFirst(db, sessionId, start) {
48
+ let { branch_id: branchId, entry_seq: upperSeq } = readBranchMembership(db, sessionId, start);
49
+ const segments = [];
50
+ while (true) {
51
+ const meta = readBranchMeta(db, sessionId, branchId);
52
+ const lowerSeq = meta.base_seq ?? 0;
53
+ segments.push({ branchId, lowerSeq, upperSeq });
54
+ if (meta.base_branch_id === null)
55
+ break;
56
+ if (meta.base_seq === null)
57
+ throw new Error(`Branch ${branchId} has base branch without base_seq`);
58
+ branchId = meta.base_branch_id;
59
+ upperSeq = meta.base_seq;
60
+ }
61
+ return segments;
62
+ }
63
+ function readNewestCompactionBoundary(db, sessionId, segmentsNewestFirst) {
64
+ for (const segment of segmentsNewestFirst) {
65
+ const row = sql `SELECT MAX(entry_seq) AS entry_seq
66
+ FROM branch_entries
67
+ WHERE session_id = ${sessionId}
68
+ AND branch_id = ${segment.branchId}
69
+ AND entry_seq > ${segment.lowerSeq}
70
+ AND entry_seq <= ${segment.upperSeq}
71
+ AND entry_type = ${"compaction"}`.get(db);
72
+ if (row?.entry_seq !== null && row?.entry_seq !== undefined)
73
+ return { branchId: segment.branchId, seq: row.entry_seq };
74
+ }
75
+ return undefined;
76
+ }
77
+ function copyBranchEntriesAfterSeqThroughParent(db, sessionId, targetBranchId, segmentsNewestFirst, afterSeq) {
78
+ for (const segment of [...segmentsNewestFirst].reverse()) {
79
+ const lowerSeq = Math.max(segment.lowerSeq, afterSeq);
80
+ if (segment.upperSeq <= lowerSeq)
81
+ continue;
82
+ sql `INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)
83
+ SELECT ${sessionId}, ${targetBranchId}, entry_id, entry_seq, entry_type
84
+ FROM branch_entries
85
+ WHERE session_id = ${sessionId}
86
+ AND branch_id = ${segment.branchId}
87
+ AND entry_seq > ${lowerSeq}
88
+ AND entry_seq <= ${segment.upperSeq}`.run(db);
89
+ }
90
+ }
91
+ function createDivergentBranchForEntry(db, sessionId, entry) {
92
+ if (entry.parentId === null)
93
+ throw new Error("Root entries do not create divergent branches");
94
+ const segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, entry.parentId);
95
+ const compaction = readNewestCompactionBoundary(db, sessionId, segmentsNewestFirst);
96
+ const branchId = entry.id;
97
+ // A null base means this segment stores its own root-through-parent prefix.
98
+ sql `INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)
99
+ VALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${compaction?.branchId ?? null}, ${compaction?.seq ?? null})`.run(db);
100
+ copyBranchEntriesAfterSeqThroughParent(db, sessionId, branchId, segmentsNewestFirst, compaction?.seq ?? 0);
101
+ insertBranchEntry(db, sessionId, branchId, entry);
102
+ }
103
+ export function appendEntryToBranchIndex(db, sessionId, entry) {
104
+ if (entry.parentId === null) {
105
+ createRootBranchForEntry(db, sessionId, entry);
106
+ return;
107
+ }
108
+ const branch = readBranchTipForParent(db, sessionId, entry.parentId);
109
+ if (branch === undefined) {
110
+ createDivergentBranchForEntry(db, sessionId, entry);
111
+ return;
112
+ }
113
+ appendEntryToExistingBranch(db, sessionId, branch.branch_id, entry);
114
+ }
115
+ function stopPredicates(query) {
116
+ const predicates = [];
117
+ if (query.stopAtType !== undefined)
118
+ predicates.push(sql `b.entry_type = ${query.stopAtType}`);
119
+ if (query.stopAtId !== undefined)
120
+ predicates.push(sql `b.entry_id = ${query.stopAtId}`);
121
+ return predicates;
122
+ }
123
+ function readStopSeq(db, sessionId, segment, query, oldestFirst) {
124
+ const stop = stopPredicates(query);
125
+ if (stop.length === 0)
126
+ return undefined;
127
+ const aggregate = oldestFirst ? sql `MIN(b.entry_seq)` : sql `MAX(b.entry_seq)`;
128
+ const row = sql `SELECT ${aggregate} AS stop_seq
129
+ FROM branch_entries b
130
+ WHERE b.session_id = ${sessionId}
131
+ AND b.branch_id = ${segment.branchId}
132
+ AND b.entry_seq > ${segment.lowerSeq}
133
+ AND b.entry_seq <= ${segment.upperSeq}
134
+ AND (${joinSqlFragments(stop, " OR ")})`.get(db);
135
+ return row?.stop_seq ?? undefined;
136
+ }
137
+ function branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq) {
138
+ const predicates = [
139
+ sql `b.session_id = ${sessionId}`,
140
+ sql `b.branch_id = ${segment.branchId}`,
141
+ sql `b.entry_seq > ${segment.lowerSeq}`,
142
+ sql `b.entry_seq <= ${segment.upperSeq}`,
143
+ sql `e.session_id = b.session_id`,
144
+ ];
145
+ if (stopSeq !== undefined)
146
+ predicates.push(oldestFirst ? sql `b.entry_seq <= ${stopSeq}` : sql `b.entry_seq >= ${stopSeq}`);
147
+ if (query.type !== undefined)
148
+ predicates.push(sql `b.entry_type = ${query.type}`);
149
+ if (query.customType !== undefined)
150
+ predicates.push(sql `e.custom_type = ${query.customType}`);
151
+ if (query.cursor !== undefined) {
152
+ predicates.push(oldestFirst ? sql `b.entry_seq > ${query.cursor.seq}` : sql `b.entry_seq < ${query.cursor.seq}`);
153
+ }
154
+ return predicates;
155
+ }
156
+ function limitSql(limit) {
157
+ return limit === undefined ? sql `` : sql `LIMIT ${Math.max(0, limit)}`;
158
+ }
159
+ function scanEntrySegmentRows(db, sessionId, segment, query, oldestFirst, stopSeq, limit) {
160
+ const predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);
161
+ const order = oldestFirst ? sql `ASC` : sql `DESC`;
162
+ return sql `SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp, e.payload
163
+ FROM branch_entries b
164
+ CROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id
165
+ WHERE ${joinSqlFragments(predicates, " AND ")}
166
+ ORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all(db);
167
+ }
168
+ function decodeEntryStructureRow(row) {
169
+ return {
170
+ id: row.id,
171
+ parentId: row.parent_id,
172
+ seq: row.seq,
173
+ timestamp: row.timestamp,
174
+ type: row.type,
175
+ ...(row.custom_type === null ? {} : { customType: row.custom_type }),
176
+ };
177
+ }
178
+ function scanStructureSegmentRows(db, sessionId, segment, query, oldestFirst, stopSeq, limit) {
179
+ const predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);
180
+ const order = oldestFirst ? sql `ASC` : sql `DESC`;
181
+ const rows = sql `SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp
182
+ FROM branch_entries b
183
+ CROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id
184
+ WHERE ${joinSqlFragments(predicates, " AND ")}
185
+ ORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all(db);
186
+ return rows.map(decodeEntryStructureRow);
187
+ }
188
+ function scanBranchSegments(db, sessionId, query, readSegment) {
189
+ const oldestFirst = query.order === "oldestFirst";
190
+ const segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, query.start);
191
+ const segments = oldestFirst ? [...segmentsNewestFirst].reverse() : segmentsNewestFirst;
192
+ const limit = query.limit === undefined ? undefined : Math.max(0, query.limit);
193
+ if (limit === 0)
194
+ return [];
195
+ const rows = [];
196
+ for (const segment of segments) {
197
+ const remaining = limit === undefined ? undefined : limit - rows.length;
198
+ if (remaining !== undefined && remaining <= 0)
199
+ break;
200
+ const stopSeq = readStopSeq(db, sessionId, segment, query, oldestFirst);
201
+ rows.push(...readSegment(db, sessionId, segment, query, oldestFirst, stopSeq, remaining));
202
+ if (stopSeq !== undefined)
203
+ break;
204
+ }
205
+ return rows;
206
+ }
207
+ export function scanBranchEntries(db, sessionId, query) {
208
+ return scanBranchSegments(db, sessionId, query, scanEntrySegmentRows).map(decodeEntryRow);
209
+ }
210
+ export function scanBranchEntryStructures(db, sessionId, query) {
211
+ return scanBranchSegments(db, sessionId, query, scanStructureSegmentRows);
212
+ }
213
+ //# sourceMappingURL=branch-entries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-entries.js","sourceRoot":"","sources":["../../../src/sqlite/session/branch-entries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Entry, EntryStructure, StorageBranchScan } from \"@earendil-works/pi-agent-core\";\nimport { joinSqlFragments, type SqlQuery, sql } from \"../sql.ts\";\nimport type { SqliteDatabase } from \"../types.ts\";\nimport { decodeEntryRow, type EntryRow } from \"./entries.ts\";\n\ninterface BranchMembershipRow {\n\tbranch_id: string;\n\tentry_seq: number;\n}\n\ninterface BranchMetaRow {\n\tbranch_id: string;\n\ttip_entry_id: string;\n\ttip_seq: number;\n\tbase_branch_id: string | null;\n\tbase_seq: number | null;\n}\n\ninterface BranchSegment {\n\tbranchId: string;\n\tlowerSeq: number;\n\tupperSeq: number;\n}\n\ninterface StopSeqRow {\n\tstop_seq: number | null;\n}\n\ninterface EntryStructureRow {\n\tid: string;\n\tparent_id: string | null;\n\tseq: number;\n\ttype: Entry[\"type\"];\n\tcustom_type: string | null;\n\ttimestamp: number;\n}\n\ninterface BranchTipRow {\n\tbranch_id: string;\n}\n\ninterface CompactionBoundary {\n\tbranchId: string;\n\tseq: number;\n}\n\ninterface CompactionBoundaryRow {\n\tentry_seq: number | null;\n}\n\nfunction readBranchMembership(db: SqliteDatabase, sessionId: string, entryId: string): BranchMembershipRow {\n\tconst row = sql`SELECT b.branch_id, b.entry_seq\n\t\tFROM branch_entries b\n\t\tJOIN branch_meta m ON m.session_id = b.session_id AND m.branch_id = b.branch_id\n\t\tWHERE b.session_id = ${sessionId}\n\t\t\tAND b.entry_id = ${entryId}\n\t\t\tAND ((m.base_seq IS NULL AND b.entry_seq > 0) OR (m.base_seq IS NOT NULL AND b.entry_seq > m.base_seq))\n\t\t\tAND b.entry_seq <= m.tip_seq\n\t\tORDER BY m.tip_seq DESC, b.branch_id\n\t\tLIMIT 1`.get<BranchMembershipRow>(db);\n\tif (row === undefined) throw new Error(`Branch cache missing entry ${entryId}`);\n\treturn row;\n}\n\nfunction readBranchMeta(db: SqliteDatabase, sessionId: string, branchId: string): BranchMetaRow {\n\tconst row = sql`SELECT branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq\n\t\tFROM branch_meta\n\t\tWHERE session_id = ${sessionId} AND branch_id = ${branchId}`.get<BranchMetaRow>(db);\n\tif (row === undefined) throw new Error(`Branch metadata missing for branch ${branchId}`);\n\treturn row;\n}\n\nfunction insertBranchEntry(db: SqliteDatabase, sessionId: string, branchId: string, entry: Entry): void {\n\tsql`INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)\n\t\tVALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${entry.type})`.run(db);\n}\n\nfunction readBranchTipForParent(db: SqliteDatabase, sessionId: string, parentId: string): BranchTipRow | undefined {\n\treturn sql`SELECT branch_id\n\t\tFROM branch_meta\n\t\tWHERE session_id = ${sessionId} AND tip_entry_id = ${parentId}`.get<BranchTipRow>(db);\n}\n\nfunction createRootBranchForEntry(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tsql`INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)\n\t\tVALUES (${sessionId}, ${entry.id}, ${entry.id}, ${entry.seq}, ${null}, ${null})`.run(db);\n\tinsertBranchEntry(db, sessionId, entry.id, entry);\n}\n\nfunction appendEntryToExistingBranch(db: SqliteDatabase, sessionId: string, branchId: string, entry: Entry): void {\n\tinsertBranchEntry(db, sessionId, branchId, entry);\n\tconst result = sql`UPDATE branch_meta\n\t\tSET tip_entry_id = ${entry.id}, tip_seq = ${entry.seq}\n\t\tWHERE session_id = ${sessionId} AND branch_id = ${branchId}`.run(db);\n\tif (result.changes !== 1) throw new Error(`Expected to update branch ${branchId}, updated ${result.changes}`);\n}\n\nfunction readBranchSegmentsNewestFirst(db: SqliteDatabase, sessionId: string, start: string): BranchSegment[] {\n\tlet { branch_id: branchId, entry_seq: upperSeq } = readBranchMembership(db, sessionId, start);\n\tconst segments: BranchSegment[] = [];\n\twhile (true) {\n\t\tconst meta = readBranchMeta(db, sessionId, branchId);\n\t\tconst lowerSeq = meta.base_seq ?? 0;\n\t\tsegments.push({ branchId, lowerSeq, upperSeq });\n\t\tif (meta.base_branch_id === null) break;\n\t\tif (meta.base_seq === null) throw new Error(`Branch ${branchId} has base branch without base_seq`);\n\t\tbranchId = meta.base_branch_id;\n\t\tupperSeq = meta.base_seq;\n\t}\n\treturn segments;\n}\n\nfunction readNewestCompactionBoundary(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegmentsNewestFirst: readonly BranchSegment[],\n): CompactionBoundary | undefined {\n\tfor (const segment of segmentsNewestFirst) {\n\t\tconst row = sql`SELECT MAX(entry_seq) AS entry_seq\n\t\t\tFROM branch_entries\n\t\t\tWHERE session_id = ${sessionId}\n\t\t\t\tAND branch_id = ${segment.branchId}\n\t\t\t\tAND entry_seq > ${segment.lowerSeq}\n\t\t\t\tAND entry_seq <= ${segment.upperSeq}\n\t\t\t\tAND entry_type = ${\"compaction\"}`.get<CompactionBoundaryRow>(db);\n\t\tif (row?.entry_seq !== null && row?.entry_seq !== undefined)\n\t\t\treturn { branchId: segment.branchId, seq: row.entry_seq };\n\t}\n\treturn undefined;\n}\n\nfunction copyBranchEntriesAfterSeqThroughParent(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\ttargetBranchId: string,\n\tsegmentsNewestFirst: readonly BranchSegment[],\n\tafterSeq: number,\n): void {\n\tfor (const segment of [...segmentsNewestFirst].reverse()) {\n\t\tconst lowerSeq = Math.max(segment.lowerSeq, afterSeq);\n\t\tif (segment.upperSeq <= lowerSeq) continue;\n\t\tsql`INSERT INTO branch_entries (session_id, branch_id, entry_id, entry_seq, entry_type)\n\t\t\tSELECT ${sessionId}, ${targetBranchId}, entry_id, entry_seq, entry_type\n\t\t\tFROM branch_entries\n\t\t\tWHERE session_id = ${sessionId}\n\t\t\t\tAND branch_id = ${segment.branchId}\n\t\t\t\tAND entry_seq > ${lowerSeq}\n\t\t\t\tAND entry_seq <= ${segment.upperSeq}`.run(db);\n\t}\n}\n\nfunction createDivergentBranchForEntry(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tif (entry.parentId === null) throw new Error(\"Root entries do not create divergent branches\");\n\tconst segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, entry.parentId);\n\tconst compaction = readNewestCompactionBoundary(db, sessionId, segmentsNewestFirst);\n\tconst branchId = entry.id;\n\t// A null base means this segment stores its own root-through-parent prefix.\n\tsql`INSERT INTO branch_meta (session_id, branch_id, tip_entry_id, tip_seq, base_branch_id, base_seq)\n\t\tVALUES (${sessionId}, ${branchId}, ${entry.id}, ${entry.seq}, ${compaction?.branchId ?? null}, ${compaction?.seq ?? null})`.run(\n\t\tdb,\n\t);\n\tcopyBranchEntriesAfterSeqThroughParent(db, sessionId, branchId, segmentsNewestFirst, compaction?.seq ?? 0);\n\tinsertBranchEntry(db, sessionId, branchId, entry);\n}\n\nexport function appendEntryToBranchIndex(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tif (entry.parentId === null) {\n\t\tcreateRootBranchForEntry(db, sessionId, entry);\n\t\treturn;\n\t}\n\n\tconst branch = readBranchTipForParent(db, sessionId, entry.parentId);\n\tif (branch === undefined) {\n\t\tcreateDivergentBranchForEntry(db, sessionId, entry);\n\t\treturn;\n\t}\n\tappendEntryToExistingBranch(db, sessionId, branch.branch_id, entry);\n}\n\nfunction stopPredicates(query: StorageBranchScan): SqlQuery[] {\n\tconst predicates: SqlQuery[] = [];\n\tif (query.stopAtType !== undefined) predicates.push(sql`b.entry_type = ${query.stopAtType}`);\n\tif (query.stopAtId !== undefined) predicates.push(sql`b.entry_id = ${query.stopAtId}`);\n\treturn predicates;\n}\n\nfunction readStopSeq(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n): number | undefined {\n\tconst stop = stopPredicates(query);\n\tif (stop.length === 0) return undefined;\n\tconst aggregate = oldestFirst ? sql`MIN(b.entry_seq)` : sql`MAX(b.entry_seq)`;\n\tconst row = sql`SELECT ${aggregate} AS stop_seq\n\t\tFROM branch_entries b\n\t\tWHERE b.session_id = ${sessionId}\n\t\t\tAND b.branch_id = ${segment.branchId}\n\t\t\tAND b.entry_seq > ${segment.lowerSeq}\n\t\t\tAND b.entry_seq <= ${segment.upperSeq}\n\t\t\tAND (${joinSqlFragments(stop, \" OR \")})`.get<StopSeqRow>(db);\n\treturn row?.stop_seq ?? undefined;\n}\n\nfunction branchScanPredicates(\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n): SqlQuery[] {\n\tconst predicates: SqlQuery[] = [\n\t\tsql`b.session_id = ${sessionId}`,\n\t\tsql`b.branch_id = ${segment.branchId}`,\n\t\tsql`b.entry_seq > ${segment.lowerSeq}`,\n\t\tsql`b.entry_seq <= ${segment.upperSeq}`,\n\t\tsql`e.session_id = b.session_id`,\n\t];\n\tif (stopSeq !== undefined)\n\t\tpredicates.push(oldestFirst ? sql`b.entry_seq <= ${stopSeq}` : sql`b.entry_seq >= ${stopSeq}`);\n\tif (query.type !== undefined) predicates.push(sql`b.entry_type = ${query.type}`);\n\tif (query.customType !== undefined) predicates.push(sql`e.custom_type = ${query.customType}`);\n\tif (query.cursor !== undefined) {\n\t\tpredicates.push(oldestFirst ? sql`b.entry_seq > ${query.cursor.seq}` : sql`b.entry_seq < ${query.cursor.seq}`);\n\t}\n\treturn predicates;\n}\n\nfunction limitSql(limit: number | undefined): SqlQuery {\n\treturn limit === undefined ? sql`` : sql`LIMIT ${Math.max(0, limit)}`;\n}\n\nfunction scanEntrySegmentRows(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n\tlimit: number | undefined,\n): EntryRow[] {\n\tconst predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);\n\tconst order = oldestFirst ? sql`ASC` : sql`DESC`;\n\treturn sql`SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp, e.payload\n\t\tFROM branch_entries b\n\t\tCROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id\n\t\tWHERE ${joinSqlFragments(predicates, \" AND \")}\n\t\tORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all<EntryRow>(db);\n}\n\nfunction decodeEntryStructureRow(row: EntryStructureRow): EntryStructure {\n\treturn {\n\t\tid: row.id,\n\t\tparentId: row.parent_id,\n\t\tseq: row.seq,\n\t\ttimestamp: row.timestamp,\n\t\ttype: row.type,\n\t\t...(row.custom_type === null ? {} : { customType: row.custom_type }),\n\t};\n}\n\nfunction scanStructureSegmentRows(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tsegment: BranchSegment,\n\tquery: StorageBranchScan,\n\toldestFirst: boolean,\n\tstopSeq: number | undefined,\n\tlimit: number | undefined,\n): EntryStructure[] {\n\tconst predicates = branchScanPredicates(sessionId, segment, query, oldestFirst, stopSeq);\n\tconst order = oldestFirst ? sql`ASC` : sql`DESC`;\n\tconst rows = sql`SELECT e.id, e.parent_id, e.seq, e.type, e.custom_type, e.timestamp\n\t\tFROM branch_entries b\n\t\tCROSS JOIN entries e ON e.session_id = b.session_id AND e.id = b.entry_id\n\t\tWHERE ${joinSqlFragments(predicates, \" AND \")}\n\t\tORDER BY b.entry_seq ${order} ${limitSql(limit)}`.all<EntryStructureRow>(db);\n\treturn rows.map(decodeEntryStructureRow);\n}\n\nfunction scanBranchSegments<T>(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tquery: StorageBranchScan,\n\treadSegment: (\n\t\tdb: SqliteDatabase,\n\t\tsessionId: string,\n\t\tsegment: BranchSegment,\n\t\tquery: StorageBranchScan,\n\t\toldestFirst: boolean,\n\t\tstopSeq: number | undefined,\n\t\tlimit: number | undefined,\n\t) => T[],\n): T[] {\n\tconst oldestFirst = query.order === \"oldestFirst\";\n\tconst segmentsNewestFirst = readBranchSegmentsNewestFirst(db, sessionId, query.start);\n\tconst segments = oldestFirst ? [...segmentsNewestFirst].reverse() : segmentsNewestFirst;\n\tconst limit = query.limit === undefined ? undefined : Math.max(0, query.limit);\n\tif (limit === 0) return [];\n\n\tconst rows: T[] = [];\n\tfor (const segment of segments) {\n\t\tconst remaining = limit === undefined ? undefined : limit - rows.length;\n\t\tif (remaining !== undefined && remaining <= 0) break;\n\t\tconst stopSeq = readStopSeq(db, sessionId, segment, query, oldestFirst);\n\t\trows.push(...readSegment(db, sessionId, segment, query, oldestFirst, stopSeq, remaining));\n\t\tif (stopSeq !== undefined) break;\n\t}\n\treturn rows;\n}\n\nexport function scanBranchEntries(db: SqliteDatabase, sessionId: string, query: StorageBranchScan): Entry[] {\n\treturn scanBranchSegments(db, sessionId, query, scanEntrySegmentRows).map(decodeEntryRow);\n}\n\nexport function scanBranchEntryStructures(\n\tdb: SqliteDatabase,\n\tsessionId: string,\n\tquery: StorageBranchScan,\n): EntryStructure[] {\n\treturn scanBranchSegments(db, sessionId, query, scanStructureSegmentRows);\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import type { Entry, EntryScan, EntryStructure } from "@earendil-works/pi-agent-core";
2
+ import type { SqliteDatabase } from "../types.ts";
3
+ export interface EntryRow {
4
+ id: string;
5
+ parent_id: string | null;
6
+ seq: number;
7
+ type: Entry["type"];
8
+ custom_type: string | null;
9
+ timestamp: number;
10
+ payload: string;
11
+ }
12
+ export declare class EntryRowWriter {
13
+ private readonly insertStatement;
14
+ private readonly sessionId;
15
+ constructor(db: SqliteDatabase, sessionId: string);
16
+ insert(entry: Entry): void;
17
+ }
18
+ export declare function insertEntryRow(db: SqliteDatabase, sessionId: string, entry: Entry): void;
19
+ export declare function decodeEntryRow(row: EntryRow): Entry;
20
+ export declare function entryStructureFromRow(row: EntryRow): EntryStructure;
21
+ export declare function readEntryRows(db: SqliteDatabase, sessionId: string, ids: readonly string[]): EntryRow[];
22
+ export declare function readAllEntryRows(db: SqliteDatabase, sessionId: string): EntryRow[];
23
+ export declare function scanEntryRows(db: SqliteDatabase, sessionId: string, query: EntryScan): EntryRow[];
24
+ //# sourceMappingURL=entries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../../src/sqlite/session/entries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIX,KAAK,EACL,SAAS,EACT,cAAc,EAEd,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,aAAa,CAAC;AAEnE,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAgED,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAAY,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAGhD;IAED,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAEzB;CACD;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAExF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,KAAK,CAkBnD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,QAAQ,GAAG,cAAc,CASnE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,EAAE,CASvG;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAGlF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,EAAE,CAWjG","sourcesContent":["import type {\n\tBranchSummaryEntry,\n\tCompactionEntry,\n\tCustomEntry,\n\tEntry,\n\tEntryScan,\n\tEntryStructure,\n\tMessageEntry,\n} from \"@earendil-works/pi-agent-core\";\nimport { joinSqlFragments, type SqlQuery, sql } from \"../sql.ts\";\nimport type { SqliteDatabase, SqliteStatement } from \"../types.ts\";\n\nexport interface EntryRow {\n\tid: string;\n\tparent_id: string | null;\n\tseq: number;\n\ttype: Entry[\"type\"];\n\tcustom_type: string | null;\n\ttimestamp: number;\n\tpayload: string;\n}\n\ntype StoredEntryPayload<TEntry extends Entry> = Omit<\n\tTEntry,\n\t\"id\" | \"parentId\" | \"seq\" | \"timestamp\" | \"type\" | \"customType\"\n>;\n\nfunction entryPayload(entry: Entry): StoredEntryPayload<Entry> {\n\tswitch (entry.type) {\n\t\tcase \"message\": {\n\t\t\tconst payload: StoredEntryPayload<MessageEntry> = {\n\t\t\t\tmessage: entry.message,\n\t\t\t\t...(entry.terminate === undefined ? {} : { terminate: entry.terminate }),\n\t\t\t};\n\t\t\treturn payload;\n\t\t}\n\t\tcase \"compaction\": {\n\t\t\tconst payload: StoredEntryPayload<CompactionEntry> = {\n\t\t\t\tsummary: entry.summary,\n\t\t\t\tretainedTail: entry.retainedTail,\n\t\t\t\ttokensBefore: entry.tokensBefore,\n\t\t\t\t...(entry.details === undefined ? {} : { details: entry.details }),\n\t\t\t\t...(entry.usage === undefined ? {} : { usage: entry.usage }),\n\t\t\t\tfromHook: entry.fromHook,\n\t\t\t};\n\t\t\treturn payload;\n\t\t}\n\t\tcase \"branch_summary\": {\n\t\t\tconst payload: StoredEntryPayload<BranchSummaryEntry> = {\n\t\t\t\tfromId: entry.fromId,\n\t\t\t\tsummary: entry.summary,\n\t\t\t\t...(entry.details === undefined ? {} : { details: entry.details }),\n\t\t\t\t...(entry.usage === undefined ? {} : { usage: entry.usage }),\n\t\t\t\tfromHook: entry.fromHook,\n\t\t\t};\n\t\t\treturn payload;\n\t\t}\n\t\tcase \"custom\": {\n\t\t\tconst payload: StoredEntryPayload<CustomEntry> = entry.data === undefined ? {} : { data: entry.data };\n\t\t\treturn payload;\n\t\t}\n\t}\n}\n\nfunction parsePayload<TEntry extends Entry>(row: EntryRow): StoredEntryPayload<TEntry> {\n\treturn JSON.parse(row.payload) as StoredEntryPayload<TEntry>;\n}\n\nconst INSERT_ENTRY_SQL = `INSERT INTO entries (session_id, id, parent_id, seq, type, custom_type, timestamp, payload)\n\tVALUES (?, ?, ?, ?, ?, ?, ?, ?)`;\n\nfunction entryRowParams(sessionId: string, entry: Entry): unknown[] {\n\treturn [\n\t\tsessionId,\n\t\tentry.id,\n\t\tentry.parentId,\n\t\tentry.seq,\n\t\tentry.type,\n\t\tentry.type === \"custom\" ? entry.customType : null,\n\t\tentry.timestamp,\n\t\tJSON.stringify(entryPayload(entry)),\n\t];\n}\n\nexport class EntryRowWriter {\n\tprivate readonly insertStatement: SqliteStatement;\n\tprivate readonly sessionId: string;\n\n\tconstructor(db: SqliteDatabase, sessionId: string) {\n\t\tthis.insertStatement = db.prepare(INSERT_ENTRY_SQL);\n\t\tthis.sessionId = sessionId;\n\t}\n\n\tinsert(entry: Entry): void {\n\t\tthis.insertStatement.run(...entryRowParams(this.sessionId, entry));\n\t}\n}\n\nexport function insertEntryRow(db: SqliteDatabase, sessionId: string, entry: Entry): void {\n\tdb.prepare(INSERT_ENTRY_SQL).run(...entryRowParams(sessionId, entry));\n}\n\nexport function decodeEntryRow(row: EntryRow): Entry {\n\tconst base = {\n\t\tid: row.id,\n\t\tparentId: row.parent_id,\n\t\tseq: row.seq,\n\t\ttimestamp: row.timestamp,\n\t};\n\tswitch (row.type) {\n\t\tcase \"message\":\n\t\t\treturn { ...base, type: \"message\", ...parsePayload<MessageEntry>(row) };\n\t\tcase \"compaction\":\n\t\t\treturn { ...base, type: \"compaction\", ...parsePayload<CompactionEntry>(row) };\n\t\tcase \"branch_summary\":\n\t\t\treturn { ...base, type: \"branch_summary\", ...parsePayload<BranchSummaryEntry>(row) };\n\t\tcase \"custom\":\n\t\t\tif (row.custom_type === null) throw new Error(`Custom entry ${row.id} is missing custom_type`);\n\t\t\treturn { ...base, type: \"custom\", customType: row.custom_type, ...parsePayload<CustomEntry>(row) };\n\t}\n}\n\nexport function entryStructureFromRow(row: EntryRow): EntryStructure {\n\treturn {\n\t\tid: row.id,\n\t\tparentId: row.parent_id,\n\t\tseq: row.seq,\n\t\ttimestamp: row.timestamp,\n\t\ttype: row.type,\n\t\t...(row.custom_type === null ? {} : { customType: row.custom_type }),\n\t};\n}\n\nexport function readEntryRows(db: SqliteDatabase, sessionId: string, ids: readonly string[]): EntryRow[] {\n\tif (ids.length === 0) return [];\n\tconst placeholders = joinSqlFragments(\n\t\tids.map((id) => sql`${id}`),\n\t\t\", \",\n\t);\n\treturn sql`SELECT id, parent_id, seq, type, custom_type, timestamp, payload\n\t\tFROM entries\n\t\tWHERE session_id = ${sessionId} AND id IN (${placeholders})`.all<EntryRow>(db);\n}\n\nexport function readAllEntryRows(db: SqliteDatabase, sessionId: string): EntryRow[] {\n\treturn sql`SELECT id, parent_id, seq, type, custom_type, timestamp, payload\n\t\tFROM entries WHERE session_id = ${sessionId} ORDER BY seq ASC`.all<EntryRow>(db);\n}\n\nexport function scanEntryRows(db: SqliteDatabase, sessionId: string, query: EntryScan): EntryRow[] {\n\tconst filters: SqlQuery[] = [sql`session_id = ${sessionId}`];\n\tif (query.type !== undefined) filters.push(sql`type = ${query.type}`);\n\tif (query.customType !== undefined) filters.push(sql`custom_type = ${query.customType}`);\n\tif (query.fromSeq !== undefined) filters.push(sql`seq >= ${query.fromSeq}`);\n\tif (query.toSeq !== undefined) filters.push(sql`seq <= ${query.toSeq}`);\n\n\tconst order = query.order === \"desc\" ? sql`ORDER BY seq DESC` : sql`ORDER BY seq ASC`;\n\tconst limit = query.limit === undefined ? sql`` : sql`LIMIT ${Math.max(0, query.limit)}`;\n\treturn sql`SELECT id, parent_id, seq, type, custom_type, timestamp, payload\n\t\tFROM entries WHERE ${joinSqlFragments(filters, \" AND \")} ${order} ${limit}`.all<EntryRow>(db);\n}\n"]}