@iworkforces/tracelattice 2.0.7 → 2.1.1

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 (217) hide show
  1. package/README.md +88 -64
  2. package/dist/ServerConfig.d.ts +1 -1
  3. package/dist/ServerConfig.js.map +1 -1
  4. package/dist/cli.js +223 -254
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config/ConfigLoader.d.ts +29 -26
  7. package/dist/config/ConfigLoader.d.ts.map +1 -1
  8. package/dist/config/ConfigLoader.js +40 -36
  9. package/dist/config/ConfigLoader.js.map +1 -1
  10. package/dist/contracts/PersistenceBackend.d.ts +7 -108
  11. package/dist/contracts/PersistenceBackend.d.ts.map +1 -1
  12. package/dist/contracts/PersistenceBackend.js +1 -6
  13. package/dist/contracts/calibrator.d.ts +6 -6
  14. package/dist/contracts/calibrator.d.ts.map +1 -1
  15. package/dist/contracts/ids.d.ts +1 -8
  16. package/dist/contracts/ids.d.ts.map +1 -1
  17. package/dist/contracts/ids.js +2 -3
  18. package/dist/contracts/ids.js.map +1 -1
  19. package/dist/contracts/interfaces.d.ts +4 -6
  20. package/dist/contracts/interfaces.d.ts.map +1 -1
  21. package/dist/contracts/persistence-work.d.ts +2 -3
  22. package/dist/contracts/persistence-work.d.ts.map +1 -1
  23. package/dist/contracts/summary.d.ts +0 -1
  24. package/dist/contracts/summary.d.ts.map +1 -1
  25. package/dist/core/HistoryManager.d.ts +12 -16
  26. package/dist/core/HistoryManager.d.ts.map +1 -1
  27. package/dist/core/HistoryManager.js +19 -40
  28. package/dist/core/HistoryManager.js.map +1 -1
  29. package/dist/core/IHistoryManager.d.ts +22 -30
  30. package/dist/core/IHistoryManager.d.ts.map +1 -1
  31. package/dist/core/InputNormalizer.d.ts +7 -24
  32. package/dist/core/InputNormalizer.d.ts.map +1 -1
  33. package/dist/core/InputNormalizer.js +3 -9
  34. package/dist/core/InputNormalizer.js.map +1 -1
  35. package/dist/core/PersistenceBuffer.d.ts +3 -20
  36. package/dist/core/PersistenceBuffer.d.ts.map +1 -1
  37. package/dist/core/PersistenceBuffer.js +1 -4
  38. package/dist/core/PersistenceBuffer.js.map +1 -1
  39. package/dist/core/PersistenceRestore.d.ts +1 -1
  40. package/dist/core/PersistenceRestore.d.ts.map +1 -1
  41. package/dist/core/PersistenceRestore.js +4 -10
  42. package/dist/core/PersistenceRestore.js.map +1 -1
  43. package/dist/core/PersistenceWriter.d.ts.map +1 -1
  44. package/dist/core/PersistenceWriter.js +3 -12
  45. package/dist/core/PersistenceWriter.js.map +1 -1
  46. package/dist/core/SessionErrors.d.ts +0 -11
  47. package/dist/core/SessionErrors.d.ts.map +1 -1
  48. package/dist/core/SessionErrors.js +1 -14
  49. package/dist/core/SessionErrors.js.map +1 -1
  50. package/dist/core/SessionLock.d.ts +4 -5
  51. package/dist/core/SessionLock.d.ts.map +1 -1
  52. package/dist/core/SessionLock.js +5 -10
  53. package/dist/core/SessionLock.js.map +1 -1
  54. package/dist/core/SessionManager.d.ts +0 -2
  55. package/dist/core/SessionManager.d.ts.map +1 -1
  56. package/dist/core/SessionManager.js +3 -5
  57. package/dist/core/SessionManager.js.map +1 -1
  58. package/dist/core/SessionResetCoordinator.d.ts +10 -7
  59. package/dist/core/SessionResetCoordinator.d.ts.map +1 -1
  60. package/dist/core/SessionResetCoordinator.js +10 -28
  61. package/dist/core/SessionResetCoordinator.js.map +1 -1
  62. package/dist/core/ThoughtEvaluator.d.ts +5 -5
  63. package/dist/core/ThoughtEvaluator.d.ts.map +1 -1
  64. package/dist/core/ThoughtEvaluator.js +4 -40
  65. package/dist/core/ThoughtEvaluator.js.map +1 -1
  66. package/dist/core/ThoughtFormatter.js.map +1 -1
  67. package/dist/core/ThoughtProcessor.d.ts +10 -3
  68. package/dist/core/ThoughtProcessor.d.ts.map +1 -1
  69. package/dist/core/ThoughtProcessor.js +34 -38
  70. package/dist/core/ThoughtProcessor.js.map +1 -1
  71. package/dist/core/VerificationOutcomeAdmission.d.ts.map +1 -1
  72. package/dist/core/VerificationOutcomeAdmission.js +5 -7
  73. package/dist/core/VerificationOutcomeAdmission.js.map +1 -1
  74. package/dist/core/compression/CompressionService.d.ts +2 -1
  75. package/dist/core/compression/CompressionService.d.ts.map +1 -1
  76. package/dist/core/compression/CompressionService.js.map +1 -1
  77. package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -1
  78. package/dist/core/compression/DehydrationPolicy.js.map +1 -1
  79. package/dist/core/compression/InMemorySummaryStore.d.ts +2 -1
  80. package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -1
  81. package/dist/core/compression/InMemorySummaryStore.js.map +1 -1
  82. package/dist/core/evaluator/Calibrator.d.ts +2 -2
  83. package/dist/core/evaluator/Calibrator.d.ts.map +1 -1
  84. package/dist/core/evaluator/Calibrator.js +2 -5
  85. package/dist/core/evaluator/Calibrator.js.map +1 -1
  86. package/dist/core/evaluator/SignalComputer.d.ts +2 -1
  87. package/dist/core/evaluator/SignalComputer.d.ts.map +1 -1
  88. package/dist/core/evaluator/SignalComputer.js.map +1 -1
  89. package/dist/core/evaluator/internals.d.ts +1 -5
  90. package/dist/core/evaluator/internals.d.ts.map +1 -1
  91. package/dist/core/evaluator/internals.js +1 -3
  92. package/dist/core/evaluator/internals.js.map +1 -1
  93. package/dist/core/graph/Edge.d.ts +1 -1
  94. package/dist/core/graph/EdgeEmitter.d.ts +2 -4
  95. package/dist/core/graph/EdgeEmitter.d.ts.map +1 -1
  96. package/dist/core/graph/EdgeEmitter.js +2 -4
  97. package/dist/core/graph/EdgeEmitter.js.map +1 -1
  98. package/dist/core/graph/GraphView.d.ts +13 -1
  99. package/dist/core/graph/GraphView.d.ts.map +1 -1
  100. package/dist/core/graph/GraphView.js +34 -0
  101. package/dist/core/graph/GraphView.js.map +1 -1
  102. package/dist/core/reasoning/OutcomeRecorder.d.ts +0 -1
  103. package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -1
  104. package/dist/core/reasoning/OutcomeRecorder.js.map +1 -1
  105. package/dist/core/reasoning/strategies/SequentialStrategy.d.ts +3 -3
  106. package/dist/core/reasoning/strategies/SequentialStrategy.js.map +1 -1
  107. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts +6 -6
  108. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -1
  109. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +16 -2
  110. package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -1
  111. package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -1
  112. package/dist/core/reasoning/strategies/totScoring.js.map +1 -1
  113. package/dist/core/reasoning.d.ts +1 -3
  114. package/dist/core/reasoning.d.ts.map +1 -1
  115. package/dist/core/thought.d.ts +3 -2
  116. package/dist/core/thought.d.ts.map +1 -1
  117. package/dist/errors.d.ts +4 -20
  118. package/dist/errors.d.ts.map +1 -1
  119. package/dist/errors.js +2 -28
  120. package/dist/errors.js.map +1 -1
  121. package/dist/lib.d.ts +31 -24
  122. package/dist/lib.d.ts.map +1 -1
  123. package/dist/lib.js +55 -10
  124. package/dist/lib.js.map +1 -1
  125. package/dist/logger/NullLogger.d.ts +9 -11
  126. package/dist/logger/NullLogger.d.ts.map +1 -1
  127. package/dist/logger/NullLogger.js.map +1 -1
  128. package/dist/persistence/FilePersistence.d.ts +3 -12
  129. package/dist/persistence/FilePersistence.d.ts.map +1 -1
  130. package/dist/persistence/FilePersistence.js +9 -61
  131. package/dist/persistence/FilePersistence.js.map +1 -1
  132. package/dist/persistence/FileSnapshotV2.d.ts +2 -2
  133. package/dist/persistence/FileSnapshotV2.js +2 -2
  134. package/dist/persistence/FileSnapshotV2.js.map +1 -1
  135. package/dist/persistence/FileWriter.d.ts +1 -0
  136. package/dist/persistence/FileWriter.d.ts.map +1 -1
  137. package/dist/persistence/FileWriter.js +3 -3
  138. package/dist/persistence/FileWriter.js.map +1 -1
  139. package/dist/persistence/MemoryPersistence.d.ts +5 -15
  140. package/dist/persistence/MemoryPersistence.d.ts.map +1 -1
  141. package/dist/persistence/MemoryPersistence.js +6 -40
  142. package/dist/persistence/MemoryPersistence.js.map +1 -1
  143. package/dist/persistence/PersistenceCodec.js +1 -3
  144. package/dist/persistence/PersistenceCodec.js.map +1 -1
  145. package/dist/persistence/PersistenceErrors.d.ts +0 -6
  146. package/dist/persistence/PersistenceErrors.d.ts.map +1 -1
  147. package/dist/persistence/PersistenceErrors.js +1 -9
  148. package/dist/persistence/PersistenceErrors.js.map +1 -1
  149. package/dist/persistence/PersistenceScope.d.ts.map +1 -1
  150. package/dist/persistence/PersistenceScope.js +2 -2
  151. package/dist/persistence/PersistenceScope.js.map +1 -1
  152. package/dist/persistence/SqlitePersistence.d.ts +3 -10
  153. package/dist/persistence/SqlitePersistence.d.ts.map +1 -1
  154. package/dist/persistence/SqlitePersistence.js +2 -26
  155. package/dist/persistence/SqlitePersistence.js.map +1 -1
  156. package/dist/persistence/SqliteSchemaV2.d.ts.map +1 -1
  157. package/dist/persistence/SqliteSchemaV2.js +3 -12
  158. package/dist/persistence/SqliteSchemaV2.js.map +1 -1
  159. package/dist/pool/ConnectionPool.d.ts +3 -12
  160. package/dist/pool/ConnectionPool.d.ts.map +1 -1
  161. package/dist/pool/ConnectionPool.js +5 -8
  162. package/dist/pool/ConnectionPool.js.map +1 -1
  163. package/dist/pool/IConnectionPool.d.ts +3 -9
  164. package/dist/pool/IConnectionPool.d.ts.map +1 -1
  165. package/dist/registry/SkillRegistry.d.ts +1 -7
  166. package/dist/registry/SkillRegistry.d.ts.map +1 -1
  167. package/dist/registry/SkillRegistry.js +0 -15
  168. package/dist/registry/SkillRegistry.js.map +1 -1
  169. package/dist/registry/ToolRegistry.d.ts +1 -9
  170. package/dist/registry/ToolRegistry.d.ts.map +1 -1
  171. package/dist/registry/ToolRegistry.js +0 -21
  172. package/dist/registry/ToolRegistry.js.map +1 -1
  173. package/dist/schema.d.ts +2 -1
  174. package/dist/schema.d.ts.map +1 -1
  175. package/dist/schema.js +3 -3
  176. package/dist/schema.js.map +1 -1
  177. package/dist/transport/BaseTransport.d.ts +0 -9
  178. package/dist/transport/BaseTransport.d.ts.map +1 -1
  179. package/dist/transport/BaseTransport.js +0 -11
  180. package/dist/transport/BaseTransport.js.map +1 -1
  181. package/dist/transport/HttpHelpers.d.ts +4 -1
  182. package/dist/transport/HttpHelpers.d.ts.map +1 -1
  183. package/dist/transport/HttpHelpers.js +61 -11
  184. package/dist/transport/HttpHelpers.js.map +1 -1
  185. package/dist/transport/HttpRequestLifecycle.d.ts +15 -1
  186. package/dist/transport/HttpRequestLifecycle.d.ts.map +1 -1
  187. package/dist/transport/HttpRequestLifecycle.js +66 -4
  188. package/dist/transport/HttpRequestLifecycle.js.map +1 -1
  189. package/dist/transport/HttpTransport.d.ts +2 -0
  190. package/dist/transport/HttpTransport.d.ts.map +1 -1
  191. package/dist/transport/HttpTransport.js +75 -38
  192. package/dist/transport/HttpTransport.js.map +1 -1
  193. package/dist/transport/StreamableHttpTransport.d.ts +5 -29
  194. package/dist/transport/StreamableHttpTransport.d.ts.map +1 -1
  195. package/dist/transport/StreamableHttpTransport.js +74 -116
  196. package/dist/transport/StreamableHttpTransport.js.map +1 -1
  197. package/dist/watchers/SkillWatcher.d.ts.map +1 -1
  198. package/dist/watchers/SkillWatcher.js +1 -1
  199. package/dist/watchers/SkillWatcher.js.map +1 -1
  200. package/package.json +2 -2
  201. package/dist/contracts/PersistenceBackend.js.map +0 -1
  202. package/dist/persistence/FileLegacyImport.d.ts +0 -2
  203. package/dist/persistence/FileLegacyImport.d.ts.map +0 -1
  204. package/dist/persistence/FileLegacyImport.js +0 -183
  205. package/dist/persistence/FileLegacyImport.js.map +0 -1
  206. package/dist/persistence/SessionScopedPersistence.d.ts +0 -4
  207. package/dist/persistence/SessionScopedPersistence.d.ts.map +0 -1
  208. package/dist/persistence/SessionScopedPersistence.js +0 -9
  209. package/dist/persistence/SessionScopedPersistence.js.map +0 -1
  210. package/dist/persistence/SqliteLegacyImport.d.ts +0 -14
  211. package/dist/persistence/SqliteLegacyImport.d.ts.map +0 -1
  212. package/dist/persistence/SqliteLegacyImport.js +0 -136
  213. package/dist/persistence/SqliteLegacyImport.js.map +0 -1
  214. package/dist/persistence/SqliteLegacySchema.d.ts +0 -15
  215. package/dist/persistence/SqliteLegacySchema.d.ts.map +0 -1
  216. package/dist/persistence/SqliteLegacySchema.js +0 -72
  217. package/dist/persistence/SqliteLegacySchema.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/FilePersistence.js","sources":["../../src/persistence/FilePersistence.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile, readdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type {\n\tPersistenceConfig,\n\tSessionScopedPersistenceBackend,\n} from '../contracts/PersistenceBackend.js';\nimport { asSessionId, GLOBAL_SESSION_ID, type BranchId, type SessionId } from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceImportRequiredError } from '../errors.js';\nimport {\n\tEMPTY_FILE_SNAPSHOT_V2,\n\tparseFileSnapshotV2,\n\tserializeFileSnapshotV2,\n\tsessionsInSnapshot,\n} from './FileSnapshotV2.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport { FileWriter, isFileNotFound, type FileWriterOperations } from './FileWriter.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertPersistableThoughts,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\n\ntype FilePersistenceOptions = NonNullable<PersistenceConfig['options']> & {\n\treadonly metrics?: IMetrics;\n\treadonly writerOperations?: FileWriterOperations;\n};\n\nconst SNAPSHOT_NAME = 'snapshot.json';\nconst LEGACY_DIRECTORIES = ['branches', 'edges', 'summaries'] as const;\n\nexport class FilePersistence implements SessionScopedPersistenceBackend {\n\tprivate readonly _dataDir: string;\n\tprivate readonly _maxHistorySize: number;\n\tprivate readonly _persistBranches: boolean;\n\tprivate readonly _metrics: IMetrics | undefined;\n\tprivate readonly _writer: FileWriter;\n\n\tconstructor(options?: FilePersistenceOptions) {\n\t\tconst defaultDataDir = existsSync('.claude/data')\n\t\t\t? '.claude/data'\n\t\t\t: join(homedir(), '.claude/data');\n\t\tthis._dataDir = options?.dataDir ?? defaultDataDir;\n\t\tthis._maxHistorySize = options?.maxHistorySize ?? 10000;\n\t\tthis._persistBranches = options?.persistBranches ?? true;\n\t\tthis._metrics = options?.metrics;\n\t\tthis._writer = new FileWriter(this._dataDir, options?.writerOperations);\n\t}\n\n\tpublic static async create(options?: FilePersistenceOptions): Promise<FilePersistence> {\n\t\tconst persistence = new FilePersistence(options);\n\t\ttry {\n\t\t\tawait persistence._writer.ready();\n\t\t\tawait persistence._writer.run(async (dataDir) => await persistence._loadSnapshot(dataDir));\n\t\t\treturn persistence;\n\t\t} catch (error) {\n\t\t\tawait persistence.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async saveThought(thought: ThoughtData): Promise<void> {\n\t\tassertThoughtScope('saveThought', GLOBAL_SESSION_ID, thought);\n\t\tawait this._saveThought(GLOBAL_SESSION_ID, thought);\n\t}\n\n\tpublic async saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope('saveThoughtForSession', validatedSessionId, thought);\n\t\tawait this._saveThought(validatedSessionId, thought);\n\t}\n\n\tprivate async _saveThought(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tassertPersistableThoughts([thought], `${sessionId}/thoughts`);\n\t\tawait this._mutate('save_thought', (snapshot) => {\n\t\t\tconst current =\n\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [];\n\t\t\tconst prospective = [...current, thought];\n\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t[\n\t\t\t\t\t{ sessionId, thoughts: prospective },\n\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t],\n\t\t\t\t`${sessionId}/thoughts`\n\t\t\t);\n\t\t\tconst retained =\n\t\t\t\tthis._maxHistorySize > 0 ? prospective.slice(-this._maxHistorySize) : prospective;\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tthoughts: [\n\t\t\t\t\t...snapshot.thoughts.filter((record) => record.sessionId !== sessionId),\n\t\t\t\t\t{ sessionId, thoughts: retained },\n\t\t\t\t],\n\t\t\t};\n\t\t});\n\t}\n\n\tpublic async loadHistory(): Promise<ThoughtData[]> {\n\t\treturn await this.loadHistoryForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_history', (snapshot) => [\n\t\t\t...(snapshot.thoughts.find((record) => record.sessionId === validatedSessionId)?.thoughts ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void> {\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, 'global/branches');\n\t\tassertBranchScope('saveBranch', GLOBAL_SESSION_ID, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(GLOBAL_SESSION_ID, validatedBranchId, thoughts);\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(validatedSessionId, validatedBranchId, thoughts);\n\t}\n\n\tprivate async _saveBranch(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tassertPersistableThoughtCollections(\n\t\t\t[{ sessionId, thoughts }],\n\t\t\t`${sessionId}/branches/${branchId}`\n\t\t);\n\t\tif (!this._persistBranches) {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshot = await this._loadSnapshot(dataDir);\n\t\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tthoughts:\n\t\t\t\t\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t\t\t{ sessionId, thoughts },\n\t\t\t\t\t],\n\t\t\t\t\t`${sessionId}/branches/${branchId}`\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this._mutate('save_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: [\n\t\t\t\t...snapshot.branches.filter(\n\t\t\t\t\t(record) => record.sessionId !== sessionId || record.branchId !== branchId\n\t\t\t\t),\n\t\t\t\t{ sessionId, branchId, thoughts: [...thoughts] },\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async deleteBranch(branchId: BranchId): Promise<void> {\n\t\tawait this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tawait this._mutate('delete_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: snapshot.branches.filter(\n\t\t\t\t(record) => record.sessionId !== validatedSessionId || record.branchId !== validatedBranchId\n\t\t\t),\n\t\t}));\n\t}\n\n\tpublic async loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined> {\n\t\treturn await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\treturn await this._read('load_branch', (snapshot) => {\n\t\t\tconst thoughts = snapshot.branches.find(\n\t\t\t\t(record) => record.sessionId === validatedSessionId && record.branchId === validatedBranchId\n\t\t\t)?.thoughts;\n\t\t\treturn thoughts === undefined ? undefined : [...thoughts];\n\t\t});\n\t}\n\n\tpublic async listBranches(): Promise<BranchId[]> {\n\t\treturn await this.listBranchesForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('list_branches', (snapshot) =>\n\t\t\tsnapshot.branches\n\t\t\t\t.filter((record) => record.sessionId === validatedSessionId)\n\t\t\t\t.map((record) => record.branchId)\n\t\t\t\t.sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_sessions', sessionsInSnapshot);\n\t}\n\n\tpublic async clear(): Promise<void> {\n\t\tawait this._mutate('clear', () => EMPTY_FILE_SNAPSHOT_V2);\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tawait this._mutate('clear_session', (snapshot) => ({\n\t\t\tversion: 2,\n\t\t\tthoughts: snapshot.thoughts.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tbranches: snapshot.branches.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tedges: snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tsummaries: snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t}));\n\t}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tawait this._mutate('save_edges', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tedges: [\n\t\t\t\t...snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(edges.length === 0 ? [] : [{ sessionId: validatedSessionId, edges: [...edges] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_edges', (snapshot) => [\n\t\t\t...(snapshot.edges.find((record) => record.sessionId === validatedSessionId)?.edges ?? []),\n\t\t]);\n\t}\n\n\tpublic async listEdgeSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_edge_sessions', (snapshot) =>\n\t\t\tsnapshot.edges.map((record) => record.sessionId).sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tawait this._mutate('save_summaries', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tsummaries: [\n\t\t\t\t...snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(summaries.length === 0\n\t\t\t\t\t? []\n\t\t\t\t\t: [{ sessionId: validatedSessionId, summaries: [...summaries] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_summaries', (snapshot) => [\n\t\t\t...(snapshot.summaries.find((record) => record.sessionId === validatedSessionId)?.summaries ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this._writer.run(async (dataDir) => await this._loadSnapshot(dataDir));\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) return false;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getDataDir(): string {\n\t\treturn this._dataDir;\n\t}\n\n\tpublic async getBranchIds(): Promise<string[]> {\n\t\treturn await this.listBranches();\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this._writer.close();\n\t}\n\n\tprivate async _read<T>(operation: string, select: (snapshot: FileSnapshotV2) => T): Promise<T> {\n\t\treturn await this._measure(\n\t\t\toperation,\n\t\t\tasync () =>\n\t\t\t\tawait this._writer.run(async (dataDir) => select(await this._loadSnapshot(dataDir)))\n\t\t);\n\t}\n\n\tprivate async _mutate(\n\t\toperation: string,\n\t\tmutate: (snapshot: FileSnapshotV2) => FileSnapshotV2\n\t): Promise<void> {\n\t\tawait this._measure(operation, async () => {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\t\t\tconst updated = mutate(await this._loadSnapshot(dataDir));\n\t\t\t\tawait this._writer.publish(snapshotPath, serializeFileSnapshotV2(updated, snapshotPath));\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async _loadSnapshot(dataDir: string): Promise<FileSnapshotV2> {\n\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\ttry {\n\t\t\treturn parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t}\n\t\tconst legacyArtifacts = await this._legacyArtifacts(dataDir);\n\t\tif (legacyArtifacts.length > 0) {\n\t\t\tthrow new PersistenceImportRequiredError(dataDir, legacyArtifacts);\n\t\t}\n\t\treturn EMPTY_FILE_SNAPSHOT_V2;\n\t}\n\n\tprivate async _legacyArtifacts(dataDir: string): Promise<string[]> {\n\t\tconst artifacts: string[] = [];\n\t\ttry {\n\t\t\tawait readFile(join(dataDir, 'history.json'), 'utf-8');\n\t\t\tartifacts.push('history.json');\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t}\n\t\tfor (const directory of LEGACY_DIRECTORIES) {\n\t\t\ttry {\n\t\t\t\tconst files = await readdir(join(dataDir, directory));\n\t\t\t\tartifacts.push(\n\t\t\t\t\t...files.filter((file) => file.endsWith('.json')).map((file) => `${directory}/${file}`)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tif (!isFileNotFound(error)) throw error;\n\t\t\t}\n\t\t}\n\t\treturn artifacts.sort(compareCodePoint);\n\t}\n\n\tprivate async _measure<T>(operation: string, action: () => Promise<T>): Promise<T> {\n\t\tconst startTime = Date.now();\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis._metrics?.histogram('persistence_op_duration_seconds', (Date.now() - startTime) / 1000, {\n\t\t\t\toperation,\n\t\t\t});\n\t\t}\n\t}\n}\n"],"names":["SNAPSHOT_NAME","LEGACY_DIRECTORIES","FilePersistence","options","defaultDataDir","existsSync","join","homedir","FileWriter","persistence","dataDir","error","thought","assertThoughtScope","GLOBAL_SESSION_ID","sessionId","validatedSessionId","asSessionId","assertPersistableThoughts","snapshot","current","record","prospective","assertPersistableThoughtCollections","retained","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","undefined","compareCodePoint","sessionsInSnapshot","EMPTY_FILE_SNAPSHOT_V2","edges","assertEdgeScopes","summaries","assertSummaryScopes","Error","operation","select","mutate","snapshotPath","updated","serializeFileSnapshotV2","parseFileSnapshotV2","readFile","isFileNotFound","legacyArtifacts","PersistenceImportRequiredError","artifacts","directory","files","readdir","file","action","startTime","Date"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/FilePersistence.js","sources":["../../src/persistence/FilePersistence.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { readFile, readdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { IMetrics } from '../contracts/interfaces.js';\nimport type {\n\tPersistenceConfig,\n\tPersistenceBackend,\n} from '../contracts/PersistenceBackend.js';\nimport { asSessionId, type BranchId, type SessionId } from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError } from '../errors.js';\nimport {\n\tEMPTY_FILE_SNAPSHOT_V2,\n\tparseFileSnapshotV2,\n\tserializeFileSnapshotV2,\n\tsessionsInSnapshot,\n} from './FileSnapshotV2.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tFILE_WRITER_LOCK_NAME,\n\tFileWriter,\n\ttype FileWriterOperations,\n} from './FileWriter.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertPersistableThoughts,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\n\ntype FilePersistenceOptions = NonNullable<PersistenceConfig['options']> & {\n\treadonly metrics?: IMetrics;\n\treadonly writerOperations?: FileWriterOperations;\n};\n\nconst SNAPSHOT_NAME = 'snapshot.json';\n\nexport class FilePersistence implements PersistenceBackend {\n\tprivate readonly _dataDir: string;\n\tprivate readonly _maxHistorySize: number;\n\tprivate readonly _persistBranches: boolean;\n\tprivate readonly _metrics: IMetrics | undefined;\n\tprivate readonly _writer: FileWriter;\n\n\tconstructor(options?: FilePersistenceOptions) {\n\t\tconst defaultDataDir = existsSync('.claude/data')\n\t\t\t? '.claude/data'\n\t\t\t: join(homedir(), '.claude/data');\n\t\tthis._dataDir = options?.dataDir ?? defaultDataDir;\n\t\tthis._maxHistorySize = options?.maxHistorySize ?? 10000;\n\t\tthis._persistBranches = options?.persistBranches ?? true;\n\t\tthis._metrics = options?.metrics;\n\t\tthis._writer = new FileWriter(this._dataDir, options?.writerOperations);\n\t}\n\n\tpublic static async create(options?: FilePersistenceOptions): Promise<FilePersistence> {\n\t\tconst persistence = new FilePersistence(options);\n\t\ttry {\n\t\t\tawait persistence._writer.ready();\n\t\t\tawait persistence._writer.run(async (dataDir) => await persistence._loadSnapshot(dataDir));\n\t\t\treturn persistence;\n\t\t} catch (error) {\n\t\t\tawait persistence.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic async saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope('saveThoughtForSession', validatedSessionId, thought);\n\t\tawait this._saveThought(validatedSessionId, thought);\n\t}\n\n\tprivate async _saveThought(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tassertPersistableThoughts([thought], `${sessionId}/thoughts`);\n\t\tawait this._mutate('save_thought', (snapshot) => {\n\t\t\tconst current =\n\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [];\n\t\t\tconst prospective = [...current, thought];\n\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t[\n\t\t\t\t\t{ sessionId, thoughts: prospective },\n\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t],\n\t\t\t\t`${sessionId}/thoughts`\n\t\t\t);\n\t\t\tconst retained =\n\t\t\t\tthis._maxHistorySize > 0 ? prospective.slice(-this._maxHistorySize) : prospective;\n\t\t\treturn {\n\t\t\t\t...snapshot,\n\t\t\t\tthoughts: [\n\t\t\t\t\t...snapshot.thoughts.filter((record) => record.sessionId !== sessionId),\n\t\t\t\t\t{ sessionId, thoughts: retained },\n\t\t\t\t],\n\t\t\t};\n\t\t});\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_history', (snapshot) => [\n\t\t\t...(snapshot.thoughts.find((record) => record.sessionId === validatedSessionId)?.thoughts ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tawait this._saveBranch(validatedSessionId, validatedBranchId, thoughts);\n\t}\n\n\tprivate async _saveBranch(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tassertPersistableThoughtCollections(\n\t\t\t[{ sessionId, thoughts }],\n\t\t\t`${sessionId}/branches/${branchId}`\n\t\t);\n\t\tif (!this._persistBranches) {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshot = await this._loadSnapshot(dataDir);\n\t\t\t\tassertPersistableThoughtCollections(\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsessionId,\n\t\t\t\t\t\t\tthoughts:\n\t\t\t\t\t\t\t\tsnapshot.thoughts.find((record) => record.sessionId === sessionId)?.thoughts ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...snapshot.branches\n\t\t\t\t\t\t\t.filter((record) => record.sessionId === sessionId)\n\t\t\t\t\t\t\t.map((record) => ({ sessionId, thoughts: record.thoughts })),\n\t\t\t\t\t\t{ sessionId, thoughts },\n\t\t\t\t\t],\n\t\t\t\t\t`${sessionId}/branches/${branchId}`\n\t\t\t\t);\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this._mutate('save_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: [\n\t\t\t\t...snapshot.branches.filter(\n\t\t\t\t\t(record) => record.sessionId !== sessionId || record.branchId !== branchId\n\t\t\t\t),\n\t\t\t\t{ sessionId, branchId, thoughts: [...thoughts] },\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tawait this._mutate('delete_branch', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tbranches: snapshot.branches.filter(\n\t\t\t\t(record) => record.sessionId !== validatedSessionId || record.branchId !== validatedBranchId\n\t\t\t),\n\t\t}));\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\treturn await this._read('load_branch', (snapshot) => {\n\t\t\tconst thoughts = snapshot.branches.find(\n\t\t\t\t(record) => record.sessionId === validatedSessionId && record.branchId === validatedBranchId\n\t\t\t)?.thoughts;\n\t\t\treturn thoughts === undefined ? undefined : [...thoughts];\n\t\t});\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('list_branches', (snapshot) =>\n\t\t\tsnapshot.branches\n\t\t\t\t.filter((record) => record.sessionId === validatedSessionId)\n\t\t\t\t.map((record) => record.branchId)\n\t\t\t\t.sort(compareCodePoint)\n\t\t);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\treturn await this._read('list_sessions', sessionsInSnapshot);\n\t}\n\n\tpublic async clearAll(): Promise<void> {\n\t\tawait this._mutate('clear_all', () => EMPTY_FILE_SNAPSHOT_V2);\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tawait this._mutate('clear_session', (snapshot) => ({\n\t\t\tversion: 2,\n\t\t\tthoughts: snapshot.thoughts.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tbranches: snapshot.branches.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tedges: snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\tsummaries: snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t}));\n\t}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tawait this._mutate('save_edges', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tedges: [\n\t\t\t\t...snapshot.edges.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(edges.length === 0 ? [] : [{ sessionId: validatedSessionId, edges: [...edges] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_edges', (snapshot) => [\n\t\t\t...(snapshot.edges.find((record) => record.sessionId === validatedSessionId)?.edges ?? []),\n\t\t]);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tawait this._mutate('save_summaries', (snapshot) => ({\n\t\t\t...snapshot,\n\t\t\tsummaries: [\n\t\t\t\t...snapshot.summaries.filter((record) => record.sessionId !== validatedSessionId),\n\t\t\t\t...(summaries.length === 0\n\t\t\t\t\t? []\n\t\t\t\t\t: [{ sessionId: validatedSessionId, summaries: [...summaries] }]),\n\t\t\t],\n\t\t}));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\treturn await this._read('load_summaries', (snapshot) => [\n\t\t\t...(snapshot.summaries.find((record) => record.sessionId === validatedSessionId)?.summaries ??\n\t\t\t\t[]),\n\t\t]);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this._writer.run(async (dataDir) => await this._loadSnapshot(dataDir));\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) return false;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tpublic getDataDir(): string {\n\t\treturn this._dataDir;\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tawait this._writer.close();\n\t}\n\n\tprivate async _read<T>(operation: string, select: (snapshot: FileSnapshotV2) => T): Promise<T> {\n\t\treturn await this._measure(\n\t\t\toperation,\n\t\t\tasync () =>\n\t\t\t\tawait this._writer.run(async (dataDir) => select(await this._loadSnapshot(dataDir)))\n\t\t);\n\t}\n\n\tprivate async _mutate(\n\t\toperation: string,\n\t\tmutate: (snapshot: FileSnapshotV2) => FileSnapshotV2\n\t): Promise<void> {\n\t\tawait this._measure(operation, async () => {\n\t\t\tawait this._writer.run(async (dataDir) => {\n\t\t\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\t\t\tconst updated = mutate(await this._loadSnapshot(dataDir));\n\t\t\t\tawait this._writer.publish(snapshotPath, serializeFileSnapshotV2(updated, snapshotPath));\n\t\t\t});\n\t\t});\n\t}\n\n\tprivate async _loadSnapshot(dataDir: string): Promise<FileSnapshotV2> {\n\t\tconst snapshotPath = join(dataDir, SNAPSHOT_NAME);\n\t\tconst layoutEntries = (await readdir(dataDir)).filter(\n\t\t\t(entry) => entry !== FILE_WRITER_LOCK_NAME\n\t\t);\n\t\tif (layoutEntries.length === 0) return EMPTY_FILE_SNAPSHOT_V2;\n\t\tif (layoutEntries.length !== 1 || layoutEntries[0] !== SNAPSHOT_NAME) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tdataDir,\n\t\t\t\t'directory does not match File v2 layout'\n\t\t\t);\n\t\t}\n\t\treturn parseFileSnapshotV2(await readFile(snapshotPath, 'utf-8'), snapshotPath);\n\t}\n\n\tprivate async _measure<T>(operation: string, action: () => Promise<T>): Promise<T> {\n\t\tconst startTime = Date.now();\n\t\ttry {\n\t\t\treturn await action();\n\t\t} finally {\n\t\t\tthis._metrics?.histogram('persistence_op_duration_seconds', (Date.now() - startTime) / 1000, {\n\t\t\t\toperation,\n\t\t\t});\n\t\t}\n\t}\n}\n"],"names":["SNAPSHOT_NAME","FilePersistence","options","defaultDataDir","existsSync","join","homedir","FileWriter","persistence","dataDir","error","sessionId","thought","validatedSessionId","asSessionId","assertThoughtScope","assertPersistableThoughts","snapshot","current","record","prospective","assertPersistableThoughtCollections","retained","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","undefined","compareCodePoint","sessionsInSnapshot","EMPTY_FILE_SNAPSHOT_V2","edges","assertEdgeScopes","summaries","assertSummaryScopes","Error","operation","select","mutate","snapshotPath","updated","serializeFileSnapshotV2","layoutEntries","readdir","entry","FILE_WRITER_LOCK_NAME","PersistenceCompatibilityError","parseFileSnapshotV2","readFile","action","startTime","Date"],"mappings":"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"}
@@ -159,7 +159,7 @@ export declare const FileSnapshotV2Schema: v.StrictObjectSchema<{
159
159
  readonly merge_branch_ids: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MaxLengthAction<string, 50, undefined>]>, undefined>, v.DescriptionAction<string[], "Branch IDs being merged into current context">]>, undefined>;
160
160
  readonly meta_observation: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Metacognitive observation about reasoning process">]>, undefined>;
161
161
  readonly reasoning_depth: v.OptionalSchema<v.SchemaWithPipe<readonly [v.PicklistSchema<["shallow", "moderate", "deep"], undefined>, v.DescriptionAction<"shallow" | "moderate" | "deep", "Effort signal: how deep reasoning should go">]>, undefined>;
162
- readonly session_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.DescriptionAction<string, "Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior.">]>, undefined>;
162
+ readonly session_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.NotValueAction<string, "__global__", "Session ID '__global__' is retired; use an explicit named session">, v.DescriptionAction<string, "Required session identifier for state isolation. Thought history, branches, and statistics are scoped to this explicit named session.">]>;
163
163
  readonly reset_state: v.OptionalSchema<v.SchemaWithPipe<readonly [v.BooleanSchema<undefined>, v.DescriptionAction<boolean, "When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.">]>, undefined>;
164
164
  readonly tool_name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.DescriptionAction<string, "Name of the tool being invoked (for tool_call thoughts)">]>, undefined>;
165
165
  readonly tool_arguments: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, v.DescriptionAction<{
@@ -328,7 +328,7 @@ export declare const FileSnapshotV2Schema: v.StrictObjectSchema<{
328
328
  readonly merge_branch_ids: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, undefined>, v.MaxLengthAction<string, 50, undefined>]>, undefined>, v.DescriptionAction<string[], "Branch IDs being merged into current context">]>, undefined>;
329
329
  readonly meta_observation: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.DescriptionAction<string, "Metacognitive observation about reasoning process">]>, undefined>;
330
330
  readonly reasoning_depth: v.OptionalSchema<v.SchemaWithPipe<readonly [v.PicklistSchema<["shallow", "moderate", "deep"], undefined>, v.DescriptionAction<"shallow" | "moderate" | "deep", "Effort signal: how deep reasoning should go">]>, undefined>;
331
- readonly session_id: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.DescriptionAction<string, "Optional session identifier for state isolation. When provided, thought history, branches, and statistics are scoped to this session. Omitting preserves global behavior.">]>, undefined>;
331
+ readonly session_id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "Session ID must contain only letters, numbers, hyphens, and underscores">, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 100, undefined>, v.NotValueAction<string, "__global__", "Session ID '__global__' is retired; use an explicit named session">, v.DescriptionAction<string, "Required session identifier for state isolation. Thought history, branches, and statistics are scoped to this explicit named session.">]>;
332
332
  readonly reset_state: v.OptionalSchema<v.SchemaWithPipe<readonly [v.BooleanSchema<undefined>, v.DescriptionAction<boolean, "When true, clears all state for the target session before processing this thought. The thought is then processed as the first in a fresh session.">]>, undefined>;
333
333
  readonly tool_name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.DescriptionAction<string, "Name of the tool being invoked (for tool_call thoughts)">]>, undefined>;
334
334
  readonly tool_arguments: v.OptionalSchema<v.SchemaWithPipe<readonly [v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, v.DescriptionAction<{
@@ -1,4 +1,4 @@
1
- import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
1
+ import { asSessionId } from "../contracts/ids.js";
2
2
  import { SummarySchema } from "../core/compression/Summary.js";
3
3
  import { PersistenceCompatibilityError, PersistenceCorruptionError } from "../errors.js";
4
4
  import { EdgeSchema, SequentialThinkingSchema } from "../schema.js";
@@ -117,7 +117,7 @@ function sessionsInSnapshot(snapshot) {
117
117
  ].sort(compareCodePoint);
118
118
  }
119
119
  function sessionForThought(thought) {
120
- return thought.session_id ?? GLOBAL_SESSION_ID;
120
+ return asSessionId(thought.session_id);
121
121
  }
122
122
  export { EMPTY_FILE_SNAPSHOT_V2, FileSnapshotV2Schema, parseFileSnapshotV2, serializeFileSnapshotV2, sessionForThought, sessionsInSnapshot };
123
123
 
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/FileSnapshotV2.js","sources":["../../src/persistence/FileSnapshotV2.ts"],"sourcesContent":["import * as v from 'valibot';\nimport type { SessionId } from '../contracts/ids.js';\nimport { asSessionId, GLOBAL_SESSION_ID } from '../contracts/ids.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError, PersistenceCorruptionError } from '../errors.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { parseEdge, parseSummary, parseThoughtData } from './PersistenceCodec.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\nimport { validateFileSnapshotV2 } from './FileSnapshotValidation.js';\n\nconst SessionIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,100}$/));\nconst BranchIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,50}$/));\nconst ThoughtSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst BranchRecordV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tbranchId: BranchIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst EdgeSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tedges: v.array(EdgeSchema),\n});\nconst SummarySessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tsummaries: v.array(SummarySchema),\n});\n\nexport const FileSnapshotV2Schema = v.strictObject({\n\tversion: v.literal(2),\n\tthoughts: v.array(ThoughtSessionV2Schema),\n\tbranches: v.array(BranchRecordV2Schema),\n\tedges: v.array(EdgeSessionV2Schema),\n\tsummaries: v.array(SummarySessionV2Schema),\n});\n\nexport const EMPTY_FILE_SNAPSHOT_V2: FileSnapshotV2 = {\n\tversion: 2,\n\tthoughts: [],\n\tbranches: [],\n\tedges: [],\n\tsummaries: [],\n};\n\nexport function parseFileSnapshotV2(content: string, sourcePath: string): FileSnapshotV2 {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(content);\n\t} catch (error) {\n\t\tthrow new PersistenceCorruptionError(sourcePath, error);\n\t}\n\ttry {\n\t\tconst parsed = v.parse(FileSnapshotV2Schema, raw);\n\t\tconst snapshot: FileSnapshotV2 = {\n\t\t\tversion: 2,\n\t\t\tthoughts: parsed.thoughts.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tbranches: parsed.branches.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tbranchId: parsePersistenceBranchId(record.branchId, sourcePath),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tedges: parsed.edges.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tedges: record.edges.map(parseEdge),\n\t\t\t})),\n\t\t\tsummaries: parsed.summaries.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tsummaries: record.summaries.map((summary) => parseSummary(summary, sourcePath)),\n\t\t\t})),\n\t\t};\n\t\tvalidateFileSnapshotV2(snapshot, sourcePath);\n\t\treturn snapshot;\n\t} catch (error) {\n\t\tif (error instanceof PersistenceCompatibilityError) throw error;\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'document does not match File v2', error);\n\t}\n}\n\nexport function serializeFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): string {\n\tconst canonical: FileSnapshotV2 = {\n\t\tversion: 2,\n\t\tthoughts: [...snapshot.thoughts].sort((left, right) =>\n\t\t\tcompareCodePoint(left.sessionId, right.sessionId)\n\t\t),\n\t\tbranches: [...snapshot.branches].sort(\n\t\t\t(left, right) =>\n\t\t\t\tcompareCodePoint(left.sessionId, right.sessionId) ||\n\t\t\t\tcompareCodePoint(left.branchId, right.branchId)\n\t\t),\n\t\tedges: [...snapshot.edges]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({ ...record, edges: [...record.edges].sort(compareCreatedThenId) })),\n\t\tsummaries: [...snapshot.summaries]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({\n\t\t\t\t...record,\n\t\t\t\tsummaries: [...record.summaries].sort(compareCreatedThenId),\n\t\t\t})),\n\t};\n\tvalidateFileSnapshotV2(canonical, sourcePath);\n\treturn `${JSON.stringify(canonical, null, 2)}\\n`;\n}\n\nexport function sessionsInSnapshot(snapshot: FileSnapshotV2): SessionId[] {\n\tconst sessions = new Set<SessionId>();\n\tfor (const records of [\n\t\tsnapshot.thoughts,\n\t\tsnapshot.branches,\n\t\tsnapshot.edges,\n\t\tsnapshot.summaries,\n\t]) {\n\t\tfor (const record of records) sessions.add(record.sessionId);\n\t}\n\treturn [...sessions].sort(compareCodePoint);\n}\n\nexport function sessionForThought(thought: ThoughtData): SessionId {\n\treturn thought.session_id ?? GLOBAL_SESSION_ID;\n}\n"],"names":["SessionIdStringSchema","v","BranchIdStringSchema","ThoughtSessionV2Schema","SequentialThinkingSchema","BranchRecordV2Schema","EdgeSessionV2Schema","EdgeSchema","SummarySessionV2Schema","SummarySchema","FileSnapshotV2Schema","EMPTY_FILE_SNAPSHOT_V2","parseFileSnapshotV2","content","sourcePath","raw","JSON","error","PersistenceCorruptionError","parsed","snapshot","record","asSessionId","thought","parseThoughtData","parsePersistenceBranchId","parseEdge","summary","parseSummary","validateFileSnapshotV2","PersistenceCompatibilityError","serializeFileSnapshotV2","canonical","left","right","compareCodePoint","compareCreatedThenId","sessionsInSnapshot","sessions","Set","records","sessionForThought","GLOBAL_SESSION_ID"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/FileSnapshotV2.js","sources":["../../src/persistence/FileSnapshotV2.ts"],"sourcesContent":["import * as v from 'valibot';\nimport type { SessionId } from '../contracts/ids.js';\nimport { asSessionId } from '../contracts/ids.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport { PersistenceCompatibilityError, PersistenceCorruptionError } from '../errors.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { parseEdge, parseSummary, parseThoughtData } from './PersistenceCodec.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n} from './PersistenceScope.js';\nimport { validateFileSnapshotV2 } from './FileSnapshotValidation.js';\n\nconst SessionIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,100}$/));\nconst BranchIdStringSchema = v.pipe(v.string(), v.regex(/^[A-Za-z0-9_-]{1,50}$/));\nconst ThoughtSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst BranchRecordV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tbranchId: BranchIdStringSchema,\n\tthoughts: v.array(SequentialThinkingSchema),\n});\nconst EdgeSessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tedges: v.array(EdgeSchema),\n});\nconst SummarySessionV2Schema = v.strictObject({\n\tsessionId: SessionIdStringSchema,\n\tsummaries: v.array(SummarySchema),\n});\n\nexport const FileSnapshotV2Schema = v.strictObject({\n\tversion: v.literal(2),\n\tthoughts: v.array(ThoughtSessionV2Schema),\n\tbranches: v.array(BranchRecordV2Schema),\n\tedges: v.array(EdgeSessionV2Schema),\n\tsummaries: v.array(SummarySessionV2Schema),\n});\n\nexport const EMPTY_FILE_SNAPSHOT_V2: FileSnapshotV2 = {\n\tversion: 2,\n\tthoughts: [],\n\tbranches: [],\n\tedges: [],\n\tsummaries: [],\n};\n\nexport function parseFileSnapshotV2(content: string, sourcePath: string): FileSnapshotV2 {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(content);\n\t} catch (error) {\n\t\tthrow new PersistenceCorruptionError(sourcePath, error);\n\t}\n\ttry {\n\t\tconst parsed = v.parse(FileSnapshotV2Schema, raw);\n\t\tconst snapshot: FileSnapshotV2 = {\n\t\t\tversion: 2,\n\t\t\tthoughts: parsed.thoughts.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tbranches: parsed.branches.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tbranchId: parsePersistenceBranchId(record.branchId, sourcePath),\n\t\t\t\tthoughts: record.thoughts.map((thought) => parseThoughtData(thought, sourcePath)),\n\t\t\t})),\n\t\t\tedges: parsed.edges.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tedges: record.edges.map(parseEdge),\n\t\t\t})),\n\t\t\tsummaries: parsed.summaries.map((record) => ({\n\t\t\t\tsessionId: asSessionId(record.sessionId),\n\t\t\t\tsummaries: record.summaries.map((summary) => parseSummary(summary, sourcePath)),\n\t\t\t})),\n\t\t};\n\t\tvalidateFileSnapshotV2(snapshot, sourcePath);\n\t\treturn snapshot;\n\t} catch (error) {\n\t\tif (error instanceof PersistenceCompatibilityError) throw error;\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'document does not match File v2', error);\n\t}\n}\n\nexport function serializeFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): string {\n\tconst canonical: FileSnapshotV2 = {\n\t\tversion: 2,\n\t\tthoughts: [...snapshot.thoughts].sort((left, right) =>\n\t\t\tcompareCodePoint(left.sessionId, right.sessionId)\n\t\t),\n\t\tbranches: [...snapshot.branches].sort(\n\t\t\t(left, right) =>\n\t\t\t\tcompareCodePoint(left.sessionId, right.sessionId) ||\n\t\t\t\tcompareCodePoint(left.branchId, right.branchId)\n\t\t),\n\t\tedges: [...snapshot.edges]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({ ...record, edges: [...record.edges].sort(compareCreatedThenId) })),\n\t\tsummaries: [...snapshot.summaries]\n\t\t\t.sort((left, right) => compareCodePoint(left.sessionId, right.sessionId))\n\t\t\t.map((record) => ({\n\t\t\t\t...record,\n\t\t\t\tsummaries: [...record.summaries].sort(compareCreatedThenId),\n\t\t\t})),\n\t};\n\tvalidateFileSnapshotV2(canonical, sourcePath);\n\treturn `${JSON.stringify(canonical, null, 2)}\\n`;\n}\n\nexport function sessionsInSnapshot(snapshot: FileSnapshotV2): SessionId[] {\n\tconst sessions = new Set<SessionId>();\n\tfor (const records of [\n\t\tsnapshot.thoughts,\n\t\tsnapshot.branches,\n\t\tsnapshot.edges,\n\t\tsnapshot.summaries,\n\t]) {\n\t\tfor (const record of records) sessions.add(record.sessionId);\n\t}\n\treturn [...sessions].sort(compareCodePoint);\n}\n\nexport function sessionForThought(thought: ThoughtData): SessionId {\n\treturn asSessionId(thought.session_id);\n}\n"],"names":["SessionIdStringSchema","v","BranchIdStringSchema","ThoughtSessionV2Schema","SequentialThinkingSchema","BranchRecordV2Schema","EdgeSessionV2Schema","EdgeSchema","SummarySessionV2Schema","SummarySchema","FileSnapshotV2Schema","EMPTY_FILE_SNAPSHOT_V2","parseFileSnapshotV2","content","sourcePath","raw","JSON","error","PersistenceCorruptionError","parsed","snapshot","record","asSessionId","thought","parseThoughtData","parsePersistenceBranchId","parseEdge","summary","parseSummary","validateFileSnapshotV2","PersistenceCompatibilityError","serializeFileSnapshotV2","canonical","left","right","compareCodePoint","compareCreatedThenId","sessionsInSnapshot","sessions","Set","records","sessionForThought"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export declare const FILE_WRITER_LOCK_NAME = ".tracelattice-writer.lock";
1
2
  export interface FileWriterOperations {
2
3
  readonly mkdir: (path: string) => Promise<void>;
3
4
  readonly mkdirExclusive: (path: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"FileWriter.d.ts","sourceRoot":"","sources":["../../src/persistence/FileWriter.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,eAAO,MAAM,wBAAwB,EAAE,oBAYtC,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAkBD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,oBAA+C;IAK3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBjE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,OAAO,CAAC,aAAa;YAKP,iBAAiB;YA2BjB,yBAAyB;YAuBzB,iBAAiB;CAwB/B"}
1
+ {"version":3,"file":"FileWriter.d.ts","sourceRoot":"","sources":["../../src/persistence/FileWriter.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED,eAAO,MAAM,wBAAwB,EAAE,oBAYtC,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEtD;AAkBD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,iBAAiB,CAA0C;IACnE,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,MAAM,CAAuB;gBAEzB,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,oBAA+C;IAK3E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBjE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB7B,OAAO,CAAC,aAAa;YAKP,iBAAiB;YA2BjB,yBAAyB;YAuBzB,iBAAiB;CAwB/B"}
@@ -2,7 +2,7 @@ import { mkdir, realpath, rename, rmdir, unlink, writeFile } from "node:fs/promi
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { PersistenceClosedError, PersistenceOwnershipError, PersistencePublicationError } from "../errors.js";
5
- const WRITER_LOCK_NAME = '.tracelattice-writer.lock';
5
+ const FILE_WRITER_LOCK_NAME = '.tracelattice-writer.lock';
6
6
  const nodeFileWriterOperations = {
7
7
  mkdir: async (path)=>{
8
8
  await mkdir(path, {
@@ -95,7 +95,7 @@ class FileWriter {
95
95
  async _acquireOwnership() {
96
96
  await this._operations.mkdir(this._configuredDataDir);
97
97
  const canonicalDataDir = await this._operations.realpath(this._configuredDataDir);
98
- const lockPath = join(canonicalDataDir, WRITER_LOCK_NAME);
98
+ const lockPath = join(canonicalDataDir, FILE_WRITER_LOCK_NAME);
99
99
  const markerName = `${process.pid}-${randomUUID()}.owner`;
100
100
  const markerPath = join(lockPath, markerName);
101
101
  try {
@@ -150,6 +150,6 @@ class FileWriter {
150
150
  }
151
151
  }
152
152
  }
153
- export { FileWriter, isFileNotFound, nodeFileWriterOperations };
153
+ export { FILE_WRITER_LOCK_NAME, FileWriter, isFileNotFound, nodeFileWriterOperations };
154
154
 
155
155
  //# sourceMappingURL=FileWriter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/FileWriter.js","sources":["../../src/persistence/FileWriter.ts"],"sourcesContent":["import { mkdir, realpath, rename, rmdir, unlink, writeFile } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { basename, dirname, join } from 'node:path';\nimport {\n\tPersistenceClosedError,\n\tPersistenceOwnershipError,\n\tPersistencePublicationError,\n} from '../errors.js';\n\nconst WRITER_LOCK_NAME = '.tracelattice-writer.lock';\n\nexport interface FileWriterOperations {\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly mkdirExclusive: (path: string) => Promise<void>;\n\treadonly realpath: (path: string) => Promise<string>;\n\treadonly rename: (source: string, destination: string) => Promise<void>;\n\treadonly rmdir: (path: string) => Promise<void>;\n\treadonly unlink: (path: string) => Promise<void>;\n\treadonly writeExclusiveUtf8: (path: string, content: string) => Promise<void>;\n}\n\nexport const nodeFileWriterOperations: FileWriterOperations = {\n\tmkdir: async (path) => {\n\t\tawait mkdir(path, { recursive: true });\n\t},\n\tmkdirExclusive: async (path) => await mkdir(path),\n\trealpath: async (path) => await realpath(path),\n\trename: async (source, destination) => await rename(source, destination),\n\trmdir: async (path) => await rmdir(path),\n\tunlink: async (path) => await unlink(path),\n\twriteExclusiveUtf8: async (path, content) => {\n\t\tawait writeFile(path, content, { encoding: 'utf-8', flag: 'wx' });\n\t},\n};\n\nexport function isFileNotFound(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction isFileAlreadyPresent(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'EEXIST';\n}\n\nfunction isDirectoryNotEmpty(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'ENOTEMPTY';\n}\n\ntype DirectoryOwnership = {\n\treadonly canonicalDataDir: string;\n\treadonly lockPath: string;\n\treadonly markerPath: string;\n};\n\ntype WriterState = 'open' | 'closing' | 'closed';\n\nexport class FileWriter {\n\tprivate readonly _configuredDataDir: string;\n\tprivate readonly _operations: FileWriterOperations;\n\tprivate _ownershipPromise: Promise<DirectoryOwnership> | undefined;\n\tprivate _ownership: DirectoryOwnership | undefined;\n\tprivate _tail: Promise<void> = Promise.resolve();\n\tprivate _closePromise: Promise<void> | undefined;\n\tprivate _state: WriterState = 'open';\n\n\tconstructor(dataDir: string, operations: FileWriterOperations = nodeFileWriterOperations) {\n\t\tthis._configuredDataDir = dataDir;\n\t\tthis._operations = operations;\n\t}\n\n\tpublic async ready(): Promise<void> {\n\t\tif (this._state !== 'open') {\n\t\t\tthrow new PersistenceClosedError(this._configuredDataDir);\n\t\t}\n\t\tawait this._getOwnership();\n\t}\n\n\tpublic run<T>(operation: (canonicalDataDir: string) => Promise<T>): Promise<T> {\n\t\tif (this._state !== 'open') {\n\t\t\treturn Promise.reject(new PersistenceClosedError(this._configuredDataDir));\n\t\t}\n\n\t\tconst queued = this._tail.then(async () => {\n\t\t\tconst ownership = await this._getOwnership();\n\t\t\treturn await operation(ownership.canonicalDataDir);\n\t\t});\n\t\tthis._tail = queued.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined\n\t\t);\n\t\treturn queued;\n\t}\n\n\tpublic async publish(targetPath: string, content: string): Promise<void> {\n\t\tconst temporaryPath = join(\n\t\t\tdirname(targetPath),\n\t\t\t`.${basename(targetPath)}.${process.pid}.${randomUUID()}.tmp`\n\t\t);\n\t\tlet stage: 'temporary-write' | 'atomic-replacement' = 'temporary-write';\n\n\t\ttry {\n\t\t\tawait this._operations.writeExclusiveUtf8(temporaryPath, content);\n\t\t\tstage = 'atomic-replacement';\n\t\t\tawait this._operations.rename(temporaryPath, targetPath);\n\t\t} catch (error) {\n\t\t\tconst publicationError = new PersistencePublicationError(targetPath, stage, error);\n\t\t\ttry {\n\t\t\t\tawait this._operations.unlink(temporaryPath);\n\t\t\t} catch (cleanupError) {\n\t\t\t\tif (!isFileNotFound(cleanupError)) {\n\t\t\t\t\tthrow new PersistencePublicationError(\n\t\t\t\t\t\ttargetPath,\n\t\t\t\t\t\t'cleanup',\n\t\t\t\t\t\tnew AggregateError([publicationError, cleanupError])\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow publicationError;\n\t\t}\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tif (this._closePromise) {\n\t\t\treturn this._closePromise;\n\t\t}\n\n\t\tthis._state = 'closing';\n\t\tthis._closePromise = (async () => {\n\t\t\ttry {\n\t\t\t\tawait this._tail;\n\t\t\t\tawait this._releaseOwnership();\n\t\t\t} finally {\n\t\t\t\tthis._state = 'closed';\n\t\t\t}\n\t\t})();\n\t\treturn this._closePromise;\n\t}\n\n\tprivate _getOwnership(): Promise<DirectoryOwnership> {\n\t\tthis._ownershipPromise ??= this._acquireOwnership();\n\t\treturn this._ownershipPromise;\n\t}\n\n\tprivate async _acquireOwnership(): Promise<DirectoryOwnership> {\n\t\tawait this._operations.mkdir(this._configuredDataDir);\n\t\tconst canonicalDataDir = await this._operations.realpath(this._configuredDataDir);\n\t\tconst lockPath = join(canonicalDataDir, WRITER_LOCK_NAME);\n\t\tconst markerName = `${process.pid}-${randomUUID()}.owner`;\n\t\tconst markerPath = join(lockPath, markerName);\n\n\t\ttry {\n\t\t\tawait this._operations.mkdirExclusive(lockPath);\n\t\t} catch (error) {\n\t\t\tif (isFileAlreadyPresent(error)) {\n\t\t\t\tthrow new PersistenceOwnershipError(canonicalDataDir, lockPath, error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.writeExclusiveUtf8(markerPath, `${process.pid}\\n`);\n\t\t} catch (error) {\n\t\t\tawait this._cleanupFailedAcquisition(lockPath, markerPath, error);\n\t\t}\n\n\t\tconst ownership = { canonicalDataDir, lockPath, markerPath } satisfies DirectoryOwnership;\n\t\tthis._ownership = ownership;\n\t\treturn ownership;\n\t}\n\n\tprivate async _cleanupFailedAcquisition(\n\t\tlockPath: string,\n\t\tmarkerPath: string,\n\t\tacquisitionError: unknown\n\t): Promise<never> {\n\t\tconst failures: unknown[] = [acquisitionError];\n\t\ttry {\n\t\t\tawait this._operations.unlink(markerPath);\n\t\t} catch (unlinkError) {\n\t\t\tif (!isFileNotFound(unlinkError)) {\n\t\t\t\tfailures.push(unlinkError);\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tawait this._operations.rmdir(lockPath);\n\t\t} catch (removeDirectoryError) {\n\t\t\tif (!isFileNotFound(removeDirectoryError) && !isDirectoryNotEmpty(removeDirectoryError)) {\n\t\t\t\tfailures.push(removeDirectoryError);\n\t\t\t}\n\t\t}\n\t\tthrow new PersistencePublicationError(lockPath, 'cleanup', new AggregateError(failures));\n\t}\n\n\tprivate async _releaseOwnership(): Promise<void> {\n\t\tconst ownership = this._ownership;\n\t\tthis._ownership = undefined;\n\t\tif (!ownership) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.unlink(ownership.markerPath);\n\t\t} catch (error) {\n\t\t\tif (isFileNotFound(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new PersistencePublicationError(ownership.markerPath, 'cleanup', error);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.rmdir(ownership.lockPath);\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error) && !isDirectoryNotEmpty(error)) {\n\t\t\t\tthrow new PersistencePublicationError(ownership.lockPath, 'cleanup', error);\n\t\t\t}\n\t\t}\n\t}\n}\n"],"names":["WRITER_LOCK_NAME","nodeFileWriterOperations","path","mkdir","realpath","source","destination","rename","rmdir","unlink","content","writeFile","isFileNotFound","error","Error","isFileAlreadyPresent","isDirectoryNotEmpty","FileWriter","Promise","dataDir","operations","PersistenceClosedError","operation","queued","ownership","undefined","targetPath","temporaryPath","join","dirname","basename","process","randomUUID","stage","publicationError","PersistencePublicationError","cleanupError","AggregateError","canonicalDataDir","lockPath","markerName","markerPath","PersistenceOwnershipError","acquisitionError","failures","unlinkError","removeDirectoryError"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/FileWriter.js","sources":["../../src/persistence/FileWriter.ts"],"sourcesContent":["import { mkdir, realpath, rename, rmdir, unlink, writeFile } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { basename, dirname, join } from 'node:path';\nimport {\n\tPersistenceClosedError,\n\tPersistenceOwnershipError,\n\tPersistencePublicationError,\n} from '../errors.js';\n\nexport const FILE_WRITER_LOCK_NAME = '.tracelattice-writer.lock';\n\nexport interface FileWriterOperations {\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly mkdirExclusive: (path: string) => Promise<void>;\n\treadonly realpath: (path: string) => Promise<string>;\n\treadonly rename: (source: string, destination: string) => Promise<void>;\n\treadonly rmdir: (path: string) => Promise<void>;\n\treadonly unlink: (path: string) => Promise<void>;\n\treadonly writeExclusiveUtf8: (path: string, content: string) => Promise<void>;\n}\n\nexport const nodeFileWriterOperations: FileWriterOperations = {\n\tmkdir: async (path) => {\n\t\tawait mkdir(path, { recursive: true });\n\t},\n\tmkdirExclusive: async (path) => await mkdir(path),\n\trealpath: async (path) => await realpath(path),\n\trename: async (source, destination) => await rename(source, destination),\n\trmdir: async (path) => await rmdir(path),\n\tunlink: async (path) => await unlink(path),\n\twriteExclusiveUtf8: async (path, content) => {\n\t\tawait writeFile(path, content, { encoding: 'utf-8', flag: 'wx' });\n\t},\n};\n\nexport function isFileNotFound(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n\nfunction isFileAlreadyPresent(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'EEXIST';\n}\n\nfunction isDirectoryNotEmpty(error: unknown): boolean {\n\treturn error instanceof Error && 'code' in error && error.code === 'ENOTEMPTY';\n}\n\ntype DirectoryOwnership = {\n\treadonly canonicalDataDir: string;\n\treadonly lockPath: string;\n\treadonly markerPath: string;\n};\n\ntype WriterState = 'open' | 'closing' | 'closed';\n\nexport class FileWriter {\n\tprivate readonly _configuredDataDir: string;\n\tprivate readonly _operations: FileWriterOperations;\n\tprivate _ownershipPromise: Promise<DirectoryOwnership> | undefined;\n\tprivate _ownership: DirectoryOwnership | undefined;\n\tprivate _tail: Promise<void> = Promise.resolve();\n\tprivate _closePromise: Promise<void> | undefined;\n\tprivate _state: WriterState = 'open';\n\n\tconstructor(dataDir: string, operations: FileWriterOperations = nodeFileWriterOperations) {\n\t\tthis._configuredDataDir = dataDir;\n\t\tthis._operations = operations;\n\t}\n\n\tpublic async ready(): Promise<void> {\n\t\tif (this._state !== 'open') {\n\t\t\tthrow new PersistenceClosedError(this._configuredDataDir);\n\t\t}\n\t\tawait this._getOwnership();\n\t}\n\n\tpublic run<T>(operation: (canonicalDataDir: string) => Promise<T>): Promise<T> {\n\t\tif (this._state !== 'open') {\n\t\t\treturn Promise.reject(new PersistenceClosedError(this._configuredDataDir));\n\t\t}\n\n\t\tconst queued = this._tail.then(async () => {\n\t\t\tconst ownership = await this._getOwnership();\n\t\t\treturn await operation(ownership.canonicalDataDir);\n\t\t});\n\t\tthis._tail = queued.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined\n\t\t);\n\t\treturn queued;\n\t}\n\n\tpublic async publish(targetPath: string, content: string): Promise<void> {\n\t\tconst temporaryPath = join(\n\t\t\tdirname(targetPath),\n\t\t\t`.${basename(targetPath)}.${process.pid}.${randomUUID()}.tmp`\n\t\t);\n\t\tlet stage: 'temporary-write' | 'atomic-replacement' = 'temporary-write';\n\n\t\ttry {\n\t\t\tawait this._operations.writeExclusiveUtf8(temporaryPath, content);\n\t\t\tstage = 'atomic-replacement';\n\t\t\tawait this._operations.rename(temporaryPath, targetPath);\n\t\t} catch (error) {\n\t\t\tconst publicationError = new PersistencePublicationError(targetPath, stage, error);\n\t\t\ttry {\n\t\t\t\tawait this._operations.unlink(temporaryPath);\n\t\t\t} catch (cleanupError) {\n\t\t\t\tif (!isFileNotFound(cleanupError)) {\n\t\t\t\t\tthrow new PersistencePublicationError(\n\t\t\t\t\t\ttargetPath,\n\t\t\t\t\t\t'cleanup',\n\t\t\t\t\t\tnew AggregateError([publicationError, cleanupError])\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow publicationError;\n\t\t}\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tif (this._closePromise) {\n\t\t\treturn this._closePromise;\n\t\t}\n\n\t\tthis._state = 'closing';\n\t\tthis._closePromise = (async () => {\n\t\t\ttry {\n\t\t\t\tawait this._tail;\n\t\t\t\tawait this._releaseOwnership();\n\t\t\t} finally {\n\t\t\t\tthis._state = 'closed';\n\t\t\t}\n\t\t})();\n\t\treturn this._closePromise;\n\t}\n\n\tprivate _getOwnership(): Promise<DirectoryOwnership> {\n\t\tthis._ownershipPromise ??= this._acquireOwnership();\n\t\treturn this._ownershipPromise;\n\t}\n\n\tprivate async _acquireOwnership(): Promise<DirectoryOwnership> {\n\t\tawait this._operations.mkdir(this._configuredDataDir);\n\t\tconst canonicalDataDir = await this._operations.realpath(this._configuredDataDir);\n\t\tconst lockPath = join(canonicalDataDir, FILE_WRITER_LOCK_NAME);\n\t\tconst markerName = `${process.pid}-${randomUUID()}.owner`;\n\t\tconst markerPath = join(lockPath, markerName);\n\n\t\ttry {\n\t\t\tawait this._operations.mkdirExclusive(lockPath);\n\t\t} catch (error) {\n\t\t\tif (isFileAlreadyPresent(error)) {\n\t\t\t\tthrow new PersistenceOwnershipError(canonicalDataDir, lockPath, error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.writeExclusiveUtf8(markerPath, `${process.pid}\\n`);\n\t\t} catch (error) {\n\t\t\tawait this._cleanupFailedAcquisition(lockPath, markerPath, error);\n\t\t}\n\n\t\tconst ownership = { canonicalDataDir, lockPath, markerPath } satisfies DirectoryOwnership;\n\t\tthis._ownership = ownership;\n\t\treturn ownership;\n\t}\n\n\tprivate async _cleanupFailedAcquisition(\n\t\tlockPath: string,\n\t\tmarkerPath: string,\n\t\tacquisitionError: unknown\n\t): Promise<never> {\n\t\tconst failures: unknown[] = [acquisitionError];\n\t\ttry {\n\t\t\tawait this._operations.unlink(markerPath);\n\t\t} catch (unlinkError) {\n\t\t\tif (!isFileNotFound(unlinkError)) {\n\t\t\t\tfailures.push(unlinkError);\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tawait this._operations.rmdir(lockPath);\n\t\t} catch (removeDirectoryError) {\n\t\t\tif (!isFileNotFound(removeDirectoryError) && !isDirectoryNotEmpty(removeDirectoryError)) {\n\t\t\t\tfailures.push(removeDirectoryError);\n\t\t\t}\n\t\t}\n\t\tthrow new PersistencePublicationError(lockPath, 'cleanup', new AggregateError(failures));\n\t}\n\n\tprivate async _releaseOwnership(): Promise<void> {\n\t\tconst ownership = this._ownership;\n\t\tthis._ownership = undefined;\n\t\tif (!ownership) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.unlink(ownership.markerPath);\n\t\t} catch (error) {\n\t\t\tif (isFileNotFound(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new PersistencePublicationError(ownership.markerPath, 'cleanup', error);\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._operations.rmdir(ownership.lockPath);\n\t\t} catch (error) {\n\t\t\tif (!isFileNotFound(error) && !isDirectoryNotEmpty(error)) {\n\t\t\t\tthrow new PersistencePublicationError(ownership.lockPath, 'cleanup', error);\n\t\t\t}\n\t\t}\n\t}\n}\n"],"names":["FILE_WRITER_LOCK_NAME","nodeFileWriterOperations","path","mkdir","realpath","source","destination","rename","rmdir","unlink","content","writeFile","isFileNotFound","error","Error","isFileAlreadyPresent","isDirectoryNotEmpty","FileWriter","Promise","dataDir","operations","PersistenceClosedError","operation","queued","ownership","undefined","targetPath","temporaryPath","join","dirname","basename","process","randomUUID","stage","publicationError","PersistencePublicationError","cleanupError","AggregateError","canonicalDataDir","lockPath","markerName","markerPath","PersistenceOwnershipError","acquisitionError","failures","unlinkError","removeDirectoryError"],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import type { ThoughtData } from '../core/thought.js';
2
2
  import type { Edge } from '../core/graph/Edge.js';
3
3
  import type { Summary } from '../core/compression/Summary.js';
4
- import type { SessionScopedPersistenceBackend } from '../contracts/PersistenceBackend.js';
4
+ import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';
5
5
  import { type BranchId, type SessionId } from '../contracts/ids.js';
6
6
  export interface MemoryPersistenceOptions {
7
7
  maxSize?: number;
8
8
  maxHistorySize?: number;
9
9
  persistBranches?: boolean;
10
10
  }
11
- export declare class MemoryPersistence implements SessionScopedPersistenceBackend {
11
+ export declare class MemoryPersistence implements PersistenceBackend {
12
12
  private readonly _histories;
13
13
  private readonly _branches;
14
14
  private readonly _edges;
@@ -16,30 +16,20 @@ export declare class MemoryPersistence implements SessionScopedPersistenceBacken
16
16
  private readonly _maxSize;
17
17
  private readonly _persistBranches;
18
18
  constructor(options?: MemoryPersistenceOptions);
19
- saveThought(thought: ThoughtData): Promise<void>;
20
- saveThoughtForSession(sessionId: SessionId, thought: ThoughtData, operation?: 'saveThought' | 'saveThoughtForSession'): Promise<void>;
21
- loadHistory(): Promise<ThoughtData[]>;
19
+ saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void>;
22
20
  loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]>;
23
- saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void>;
24
- saveBranchForSession(sessionId: SessionId, branchId: BranchId, thoughts: readonly ThoughtData[], operation?: 'saveBranch' | 'saveBranchForSession'): Promise<void>;
25
- deleteBranch(branchId: BranchId): Promise<void>;
21
+ saveBranchForSession(sessionId: SessionId, branchId: BranchId, thoughts: readonly ThoughtData[]): Promise<void>;
26
22
  deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void>;
27
- loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined>;
28
23
  loadBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<ThoughtData[] | undefined>;
29
- listBranches(): Promise<BranchId[]>;
30
24
  listBranchesForSession(sessionId: SessionId): Promise<BranchId[]>;
31
25
  listSessions(): Promise<SessionId[]>;
32
26
  healthy(): Promise<boolean>;
33
- clear(): Promise<void>;
27
+ clearAll(): Promise<void>;
34
28
  clearSession(sessionId: SessionId): Promise<void>;
35
29
  close(): Promise<void>;
36
30
  saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void>;
37
31
  loadEdges(sessionId: SessionId): Promise<Edge[]>;
38
- listEdgeSessions(): Promise<SessionId[]>;
39
32
  saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void>;
40
33
  loadSummaries(sessionId: SessionId): Promise<Summary[]>;
41
- getHistorySize(): number;
42
- getBranchCount(): number;
43
- getBranchIds(): BranchId[];
44
34
  }
45
35
  //# sourceMappingURL=MemoryPersistence.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MemoryPersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/MemoryPersistence.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MemoryPersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/MemoryPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,EAAe,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAcjF,MAAM,WAAW,wBAAwB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,qBAAa,iBAAkB,YAAW,kBAAkB;IAC3D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAClE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsD;IAChF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;gBAE/B,OAAO,GAAE,wBAA6B;IAMrC,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBhF,qBAAqB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAInE,oBAAoB,CAChC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,SAAS,WAAW,EAAE,GAC9B,OAAO,CAAC,IAAI,CAAC;IAuBH,sBAAsB,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/E,oBAAoB,CAChC,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GAChB,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC;IAQxB,sBAAsB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAKjE,YAAY,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAQpC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAOzB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAEtB,SAAS,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtE,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAIhD,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQjF,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;CAIpE"}
@@ -1,4 +1,4 @@
1
- import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
1
+ import { asSessionId } from "../contracts/ids.js";
2
2
  import { assertBranchScope, assertEdgeScopes, assertPersistableThoughtCollections, assertSummaryScopes, assertThoughtScope, assertUniqueRecordIds, compareCodePoint, compareCreatedThenId, parsePersistenceBranchId } from "./PersistenceScope.js";
3
3
  class MemoryPersistence {
4
4
  _histories = new Map();
@@ -12,12 +12,9 @@ class MemoryPersistence {
12
12
  this._maxSize = void 0 !== configuredSize && configuredSize > 0 ? configuredSize : void 0;
13
13
  this._persistBranches = options.persistBranches ?? true;
14
14
  }
15
- async saveThought(thought) {
16
- await this.saveThoughtForSession(GLOBAL_SESSION_ID, thought, 'saveThought');
17
- }
18
- async saveThoughtForSession(sessionId, thought, operation = 'saveThoughtForSession') {
15
+ async saveThoughtForSession(sessionId, thought) {
19
16
  const validatedSessionId = asSessionId(sessionId);
20
- assertThoughtScope(operation, validatedSessionId, thought);
17
+ assertThoughtScope('saveThoughtForSession', validatedSessionId, thought);
21
18
  const history = [
22
19
  ...this._histories.get(validatedSessionId) ?? [],
23
20
  thought
@@ -35,21 +32,15 @@ class MemoryPersistence {
35
32
  assertPersistableThoughtCollections(collections, `${validatedSessionId}/thoughts`);
36
33
  this._histories.set(validatedSessionId, void 0 === this._maxSize ? history : history.slice(-this._maxSize));
37
34
  }
38
- async loadHistory() {
39
- return await this.loadHistoryForSession(GLOBAL_SESSION_ID);
40
- }
41
35
  async loadHistoryForSession(sessionId) {
42
36
  return [
43
37
  ...this._histories.get(asSessionId(sessionId)) ?? []
44
38
  ];
45
39
  }
46
- async saveBranch(branchId, thoughts) {
47
- await this.saveBranchForSession(GLOBAL_SESSION_ID, branchId, thoughts, 'saveBranch');
48
- }
49
- async saveBranchForSession(sessionId, branchId, thoughts, operation = 'saveBranchForSession') {
40
+ async saveBranchForSession(sessionId, branchId, thoughts) {
50
41
  const validatedSessionId = asSessionId(sessionId);
51
42
  const validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);
52
- assertBranchScope(operation, validatedSessionId, validatedBranchId, thoughts);
43
+ assertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);
53
44
  const branches = new Map(this._branches.get(validatedSessionId) ?? []);
54
45
  branches.set(validatedBranchId, [
55
46
  ...thoughts
@@ -68,9 +59,6 @@ class MemoryPersistence {
68
59
  if (!this._persistBranches) return;
69
60
  this._branches.set(validatedSessionId, branches);
70
61
  }
71
- async deleteBranch(branchId) {
72
- await this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);
73
- }
74
62
  async deleteBranchForSession(sessionId, branchId) {
75
63
  if (!this._persistBranches) return;
76
64
  const validatedSessionId = asSessionId(sessionId);
@@ -80,9 +68,6 @@ class MemoryPersistence {
80
68
  branches.delete(validatedBranchId);
81
69
  if (0 === branches.size) this._branches.delete(validatedSessionId);
82
70
  }
83
- async loadBranch(branchId) {
84
- return await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);
85
- }
86
71
  async loadBranchForSession(sessionId, branchId) {
87
72
  if (!this._persistBranches) return;
88
73
  const validatedSessionId = asSessionId(sessionId);
@@ -92,9 +77,6 @@ class MemoryPersistence {
92
77
  ...branch
93
78
  ];
94
79
  }
95
- async listBranches() {
96
- return await this.listBranchesForSession(GLOBAL_SESSION_ID);
97
- }
98
80
  async listBranchesForSession(sessionId) {
99
81
  if (!this._persistBranches) return [];
100
82
  return [
@@ -116,7 +98,7 @@ class MemoryPersistence {
116
98
  async healthy() {
117
99
  return true;
118
100
  }
119
- async clear() {
101
+ async clearAll() {
120
102
  this._histories.clear();
121
103
  this._branches.clear();
122
104
  this._edges.clear();
@@ -144,11 +126,6 @@ class MemoryPersistence {
144
126
  ...this._edges.get(asSessionId(sessionId)) ?? []
145
127
  ].sort(compareCreatedThenId);
146
128
  }
147
- async listEdgeSessions() {
148
- return [
149
- ...this._edges.keys()
150
- ].sort(compareCodePoint);
151
- }
152
129
  async saveSummaries(sessionId, summaries) {
153
130
  const validatedSessionId = asSessionId(sessionId);
154
131
  assertSummaryScopes(validatedSessionId, summaries);
@@ -163,17 +140,6 @@ class MemoryPersistence {
163
140
  ...this._summaries.get(asSessionId(sessionId)) ?? []
164
141
  ].sort(compareCreatedThenId);
165
142
  }
166
- getHistorySize() {
167
- return this._histories.get(GLOBAL_SESSION_ID)?.length ?? 0;
168
- }
169
- getBranchCount() {
170
- return this._branches.get(GLOBAL_SESSION_ID)?.size ?? 0;
171
- }
172
- getBranchIds() {
173
- return [
174
- ...this._branches.get(GLOBAL_SESSION_ID)?.keys() ?? []
175
- ].sort(compareCodePoint);
176
- }
177
143
  }
178
144
  export { MemoryPersistence };
179
145
 
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/MemoryPersistence.js","sources":["../../src/persistence/MemoryPersistence.ts"],"sourcesContent":["import type { ThoughtData } from '../core/thought.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { SessionScopedPersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport { asSessionId, GLOBAL_SESSION_ID, type BranchId, type SessionId } from '../contracts/ids.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tassertUniqueRecordIds,\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n\ttype PersistedThoughtCollection,\n} from './PersistenceScope.js';\n\nexport interface MemoryPersistenceOptions {\n\tmaxSize?: number;\n\tmaxHistorySize?: number;\n\tpersistBranches?: boolean;\n}\n\nexport class MemoryPersistence implements SessionScopedPersistenceBackend {\n\tprivate readonly _histories = new Map<SessionId, ThoughtData[]>();\n\tprivate readonly _branches = new Map<SessionId, Map<BranchId, ThoughtData[]>>();\n\tprivate readonly _edges = new Map<SessionId, Edge[]>();\n\tprivate readonly _summaries = new Map<SessionId, Summary[]>();\n\tprivate readonly _maxSize: number | undefined;\n\tprivate readonly _persistBranches: boolean;\n\n\tconstructor(options: MemoryPersistenceOptions = {}) {\n\t\tconst configuredSize = options.maxHistorySize ?? options.maxSize;\n\t\tthis._maxSize = configuredSize !== undefined && configuredSize > 0 ? configuredSize : undefined;\n\t\tthis._persistBranches = options.persistBranches ?? true;\n\t}\n\n\tpublic async saveThought(thought: ThoughtData): Promise<void> {\n\t\tawait this.saveThoughtForSession(GLOBAL_SESSION_ID, thought, 'saveThought');\n\t}\n\n\tpublic async saveThoughtForSession(\n\t\tsessionId: SessionId,\n\t\tthought: ThoughtData,\n\t\toperation: 'saveThought' | 'saveThoughtForSession' = 'saveThoughtForSession'\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope(operation, validatedSessionId, thought);\n\t\tconst history = [...(this._histories.get(validatedSessionId) ?? []), thought];\n\t\tconst collections: PersistedThoughtCollection[] = [\n\t\t\t{ sessionId: validatedSessionId, thoughts: history },\n\t\t];\n\t\tfor (const branch of this._branches.get(validatedSessionId)?.values() ?? []) {\n\t\t\tcollections.push({ sessionId: validatedSessionId, thoughts: branch });\n\t\t}\n\t\tassertPersistableThoughtCollections(collections, `${validatedSessionId}/thoughts`);\n\t\tthis._histories.set(\n\t\t\tvalidatedSessionId,\n\t\t\tthis._maxSize === undefined ? history : history.slice(-this._maxSize)\n\t\t);\n\t}\n\n\tpublic async loadHistory(): Promise<ThoughtData[]> {\n\t\treturn await this.loadHistoryForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\treturn [...(this._histories.get(asSessionId(sessionId)) ?? [])];\n\t}\n\n\tpublic async saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void> {\n\t\tawait this.saveBranchForSession(GLOBAL_SESSION_ID, branchId, thoughts, 'saveBranch');\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[],\n\t\toperation: 'saveBranch' | 'saveBranchForSession' = 'saveBranchForSession'\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope(operation, validatedSessionId, validatedBranchId, thoughts);\n\t\tconst branches = new Map(this._branches.get(validatedSessionId) ?? []);\n\t\tbranches.set(validatedBranchId, [...thoughts]);\n\t\tconst collections: PersistedThoughtCollection[] = [\n\t\t\t{\n\t\t\t\tsessionId: validatedSessionId,\n\t\t\t\tthoughts: this._histories.get(validatedSessionId) ?? [],\n\t\t\t},\n\t\t];\n\t\tfor (const branch of branches.values()) {\n\t\t\tcollections.push({ sessionId: validatedSessionId, thoughts: branch });\n\t\t}\n\t\tassertPersistableThoughtCollections(\n\t\t\tcollections,\n\t\t\t`${validatedSessionId}/branches/${validatedBranchId}`\n\t\t);\n\t\tif (!this._persistBranches) return;\n\t\tthis._branches.set(validatedSessionId, branches);\n\t}\n\n\tpublic async deleteBranch(branchId: BranchId): Promise<void> {\n\t\tawait this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tconst branches = this._branches.get(validatedSessionId);\n\t\tif (branches === undefined) return;\n\t\tbranches.delete(validatedBranchId);\n\t\tif (branches.size === 0) this._branches.delete(validatedSessionId);\n\t}\n\n\tpublic async loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined> {\n\t\treturn await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tconst branch = this._branches.get(validatedSessionId)?.get(validatedBranchId);\n\t\treturn branch === undefined ? undefined : [...branch];\n\t}\n\n\tpublic async listBranches(): Promise<BranchId[]> {\n\t\treturn await this.listBranchesForSession(GLOBAL_SESSION_ID);\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\treturn [...(this._branches.get(asSessionId(sessionId))?.keys() ?? [])].sort(compareCodePoint);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\tconst sessions = new Set<SessionId>();\n\t\tfor (const namespace of [this._histories, this._branches, this._edges, this._summaries]) {\n\t\t\tfor (const sessionId of namespace.keys()) sessions.add(sessionId);\n\t\t}\n\t\treturn [...sessions].sort(compareCodePoint);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\treturn true;\n\t}\n\n\tpublic async clear(): Promise<void> {\n\t\tthis._histories.clear();\n\t\tthis._branches.clear();\n\t\tthis._edges.clear();\n\t\tthis._summaries.clear();\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tthis._histories.delete(validatedSessionId);\n\t\tthis._branches.delete(validatedSessionId);\n\t\tthis._edges.delete(validatedSessionId);\n\t\tthis._summaries.delete(validatedSessionId);\n\t}\n\n\tpublic async close(): Promise<void> {}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tassertUniqueRecordIds(edges, `${validatedSessionId}/edges`, 'edge');\n\t\tif (edges.length === 0) this._edges.delete(validatedSessionId);\n\t\telse this._edges.set(validatedSessionId, [...edges].sort(compareCreatedThenId));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\treturn [...(this._edges.get(asSessionId(sessionId)) ?? [])].sort(compareCreatedThenId);\n\t}\n\n\tpublic async listEdgeSessions(): Promise<SessionId[]> {\n\t\treturn [...this._edges.keys()].sort(compareCodePoint);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tassertUniqueRecordIds(summaries, `${validatedSessionId}/summaries`, 'summary');\n\t\tif (summaries.length === 0) this._summaries.delete(validatedSessionId);\n\t\telse this._summaries.set(validatedSessionId, [...summaries].sort(compareCreatedThenId));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\treturn [...(this._summaries.get(asSessionId(sessionId)) ?? [])].sort(compareCreatedThenId);\n\t}\n\n\tpublic getHistorySize(): number {\n\t\treturn this._histories.get(GLOBAL_SESSION_ID)?.length ?? 0;\n\t}\n\n\tpublic getBranchCount(): number {\n\t\treturn this._branches.get(GLOBAL_SESSION_ID)?.size ?? 0;\n\t}\n\n\tpublic getBranchIds(): BranchId[] {\n\t\treturn [...(this._branches.get(GLOBAL_SESSION_ID)?.keys() ?? [])].sort(compareCodePoint);\n\t}\n}\n"],"names":["MemoryPersistence","Map","options","configuredSize","undefined","thought","GLOBAL_SESSION_ID","sessionId","operation","validatedSessionId","asSessionId","assertThoughtScope","history","collections","branch","assertPersistableThoughtCollections","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","branches","compareCodePoint","sessions","Set","namespace","edges","assertEdgeScopes","assertUniqueRecordIds","compareCreatedThenId","summaries","assertSummaryScopes"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/MemoryPersistence.js","sources":["../../src/persistence/MemoryPersistence.ts"],"sourcesContent":["import type { ThoughtData } from '../core/thought.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport type { PersistenceBackend } from '../contracts/PersistenceBackend.js';\nimport { asSessionId, type BranchId, type SessionId } from '../contracts/ids.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tassertUniqueRecordIds,\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\tparsePersistenceBranchId,\n\ttype PersistedThoughtCollection,\n} from './PersistenceScope.js';\n\nexport interface MemoryPersistenceOptions {\n\tmaxSize?: number;\n\tmaxHistorySize?: number;\n\tpersistBranches?: boolean;\n}\n\nexport class MemoryPersistence implements PersistenceBackend {\n\tprivate readonly _histories = new Map<SessionId, ThoughtData[]>();\n\tprivate readonly _branches = new Map<SessionId, Map<BranchId, ThoughtData[]>>();\n\tprivate readonly _edges = new Map<SessionId, Edge[]>();\n\tprivate readonly _summaries = new Map<SessionId, Summary[]>();\n\tprivate readonly _maxSize: number | undefined;\n\tprivate readonly _persistBranches: boolean;\n\n\tconstructor(options: MemoryPersistenceOptions = {}) {\n\t\tconst configuredSize = options.maxHistorySize ?? options.maxSize;\n\t\tthis._maxSize = configuredSize !== undefined && configuredSize > 0 ? configuredSize : undefined;\n\t\tthis._persistBranches = options.persistBranches ?? true;\n\t}\n\n\tpublic async saveThoughtForSession(sessionId: SessionId, thought: ThoughtData): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertThoughtScope('saveThoughtForSession', validatedSessionId, thought);\n\t\tconst history = [...(this._histories.get(validatedSessionId) ?? []), thought];\n\t\tconst collections: PersistedThoughtCollection[] = [\n\t\t\t{ sessionId: validatedSessionId, thoughts: history },\n\t\t];\n\t\tfor (const branch of this._branches.get(validatedSessionId)?.values() ?? []) {\n\t\t\tcollections.push({ sessionId: validatedSessionId, thoughts: branch });\n\t\t}\n\t\tassertPersistableThoughtCollections(collections, `${validatedSessionId}/thoughts`);\n\t\tthis._histories.set(\n\t\t\tvalidatedSessionId,\n\t\t\tthis._maxSize === undefined ? history : history.slice(-this._maxSize)\n\t\t);\n\t}\n\n\tpublic async loadHistoryForSession(sessionId: SessionId): Promise<ThoughtData[]> {\n\t\treturn [...(this._histories.get(asSessionId(sessionId)) ?? [])];\n\t}\n\n\tpublic async saveBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tconst branches = new Map(this._branches.get(validatedSessionId) ?? []);\n\t\tbranches.set(validatedBranchId, [...thoughts]);\n\t\tconst collections: PersistedThoughtCollection[] = [\n\t\t\t{\n\t\t\t\tsessionId: validatedSessionId,\n\t\t\t\tthoughts: this._histories.get(validatedSessionId) ?? [],\n\t\t\t},\n\t\t];\n\t\tfor (const branch of branches.values()) {\n\t\t\tcollections.push({ sessionId: validatedSessionId, thoughts: branch });\n\t\t}\n\t\tassertPersistableThoughtCollections(\n\t\t\tcollections,\n\t\t\t`${validatedSessionId}/branches/${validatedBranchId}`\n\t\t);\n\t\tif (!this._persistBranches) return;\n\t\tthis._branches.set(validatedSessionId, branches);\n\t}\n\n\tpublic async deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void> {\n\t\tif (!this._persistBranches) return;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tconst branches = this._branches.get(validatedSessionId);\n\t\tif (branches === undefined) return;\n\t\tbranches.delete(validatedBranchId);\n\t\tif (branches.size === 0) this._branches.delete(validatedSessionId);\n\t}\n\n\tpublic async loadBranchForSession(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId\n\t): Promise<ThoughtData[] | undefined> {\n\t\tif (!this._persistBranches) return undefined;\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);\n\t\tconst branch = this._branches.get(validatedSessionId)?.get(validatedBranchId);\n\t\treturn branch === undefined ? undefined : [...branch];\n\t}\n\n\tpublic async listBranchesForSession(sessionId: SessionId): Promise<BranchId[]> {\n\t\tif (!this._persistBranches) return [];\n\t\treturn [...(this._branches.get(asSessionId(sessionId))?.keys() ?? [])].sort(compareCodePoint);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\tconst sessions = new Set<SessionId>();\n\t\tfor (const namespace of [this._histories, this._branches, this._edges, this._summaries]) {\n\t\t\tfor (const sessionId of namespace.keys()) sessions.add(sessionId);\n\t\t}\n\t\treturn [...sessions].sort(compareCodePoint);\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\treturn true;\n\t}\n\n\tpublic async clearAll(): Promise<void> {\n\t\tthis._histories.clear();\n\t\tthis._branches.clear();\n\t\tthis._edges.clear();\n\t\tthis._summaries.clear();\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tthis._histories.delete(validatedSessionId);\n\t\tthis._branches.delete(validatedSessionId);\n\t\tthis._edges.delete(validatedSessionId);\n\t\tthis._summaries.delete(validatedSessionId);\n\t}\n\n\tpublic async close(): Promise<void> {}\n\n\tpublic async saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertEdgeScopes(validatedSessionId, edges);\n\t\tassertUniqueRecordIds(edges, `${validatedSessionId}/edges`, 'edge');\n\t\tif (edges.length === 0) this._edges.delete(validatedSessionId);\n\t\telse this._edges.set(validatedSessionId, [...edges].sort(compareCreatedThenId));\n\t}\n\n\tpublic async loadEdges(sessionId: SessionId): Promise<Edge[]> {\n\t\treturn [...(this._edges.get(asSessionId(sessionId)) ?? [])].sort(compareCreatedThenId);\n\t}\n\n\tpublic async saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\tassertSummaryScopes(validatedSessionId, summaries);\n\t\tassertUniqueRecordIds(summaries, `${validatedSessionId}/summaries`, 'summary');\n\t\tif (summaries.length === 0) this._summaries.delete(validatedSessionId);\n\t\telse this._summaries.set(validatedSessionId, [...summaries].sort(compareCreatedThenId));\n\t}\n\n\tpublic async loadSummaries(sessionId: SessionId): Promise<Summary[]> {\n\t\treturn [...(this._summaries.get(asSessionId(sessionId)) ?? [])].sort(compareCreatedThenId);\n\t}\n\n}\n"],"names":["MemoryPersistence","Map","options","configuredSize","undefined","sessionId","thought","validatedSessionId","asSessionId","assertThoughtScope","history","collections","branch","assertPersistableThoughtCollections","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","branches","compareCodePoint","sessions","Set","namespace","edges","assertEdgeScopes","assertUniqueRecordIds","compareCreatedThenId","summaries","assertSummaryScopes"],"mappings":"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"}
@@ -43,9 +43,7 @@ function parseThoughtData(raw, sourcePath) {
43
43
  ...void 0 === id ? {} : {
44
44
  id: asThoughtId(id)
45
45
  },
46
- ...void 0 === session_id ? {} : {
47
- session_id: asSessionId(session_id)
48
- },
46
+ session_id: asSessionId(session_id),
49
47
  ...void 0 === branch_id ? {} : {
50
48
  branch_id: parsePersistenceBranchId(branch_id, sourcePath)
51
49
  },
@@ -1 +1 @@
1
- {"version":3,"file":"persistence/PersistenceCodec.js","sources":["../../src/persistence/PersistenceCodec.ts"],"sourcesContent":["import * as v from 'valibot';\nimport {\n\tasBranchId,\n\tasEdgeId,\n\tasSessionId,\n\tasSuspensionToken,\n\tasThoughtId,\n} from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport type { StepRecommendation } from '../core/step.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { PersistenceCompatibilityError } from '../errors.js';\nimport { parsePersistenceBranchId } from './PersistenceScope.js';\n\ntype PersistedToolRecommendation = {\n\treadonly tool_name: string;\n\treadonly confidence?: number;\n\treadonly rationale?: string;\n\treadonly priority?: number;\n\treadonly suggested_inputs?: Record<string, string | number | boolean | null>;\n\treadonly alternatives?: string[];\n};\n\ntype PersistedSkillRecommendation = {\n\treadonly skill_name: string;\n\treadonly confidence?: number;\n\treadonly rationale?: string;\n\treadonly priority?: number;\n\treadonly alternatives?: string[];\n\treadonly allowed_tools?: string[];\n\treadonly user_invocable?: boolean;\n};\n\ntype PersistedStepRecommendation = {\n\treadonly step_description?: string;\n\treadonly recommended_tools: readonly PersistedToolRecommendation[];\n\treadonly recommended_skills?: readonly PersistedSkillRecommendation[];\n\treadonly expected_outcome?: string;\n\treadonly next_step_conditions?: string[];\n};\n\nfunction parseToolRecommendation(recommendation: PersistedToolRecommendation, sourcePath: string) {\n\tif (\n\t\trecommendation.confidence === undefined ||\n\t\trecommendation.rationale === undefined ||\n\t\trecommendation.priority === undefined\n\t) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'tool recommendation defaults are absent');\n\t}\n\treturn {\n\t\t...recommendation,\n\t\tconfidence: recommendation.confidence,\n\t\trationale: recommendation.rationale,\n\t\tpriority: recommendation.priority,\n\t};\n}\n\nfunction parseSkillRecommendation(\n\trecommendation: PersistedSkillRecommendation,\n\tsourcePath: string\n) {\n\tif (\n\t\trecommendation.confidence === undefined ||\n\t\trecommendation.rationale === undefined ||\n\t\trecommendation.priority === undefined\n\t) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'skill recommendation defaults are absent');\n\t}\n\treturn {\n\t\t...recommendation,\n\t\tconfidence: recommendation.confidence,\n\t\trationale: recommendation.rationale,\n\t\tpriority: recommendation.priority,\n\t};\n}\n\nfunction parseStepRecommendation(\n\tstep: PersistedStepRecommendation,\n\tsourcePath: string\n): StepRecommendation {\n\tif (step.step_description === undefined || step.expected_outcome === undefined) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'step recommendation defaults are absent');\n\t}\n\tconst { recommended_tools, recommended_skills, ...fields } = step;\n\treturn {\n\t\t...fields,\n\t\tstep_description: step.step_description,\n\t\texpected_outcome: step.expected_outcome,\n\t\trecommended_tools: recommended_tools.map((tool) => parseToolRecommendation(tool, sourcePath)),\n\t\t...(recommended_skills === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\trecommended_skills: recommended_skills.map((skill) =>\n\t\t\t\t\t\tparseSkillRecommendation(skill, sourcePath)\n\t\t\t\t\t),\n\t\t\t\t}),\n\t};\n}\n\nexport function parseThoughtData(raw: unknown, sourcePath: string): ThoughtData {\n\tconst parsed = v.parse(SequentialThinkingSchema, raw);\n\tconst {\n\t\tid,\n\t\tsession_id,\n\t\tbranch_id,\n\t\tmerge_branch_ids,\n\t\tcontinuation_token,\n\t\tcurrent_step,\n\t\tprevious_steps,\n\t\t...thought\n\t} = parsed;\n\treturn {\n\t\t...thought,\n\t\t...(id === undefined ? {} : { id: asThoughtId(id) }),\n\t\t...(session_id === undefined ? {} : { session_id: asSessionId(session_id) }),\n\t\t...(branch_id === undefined\n\t\t\t? {}\n\t\t\t: { branch_id: parsePersistenceBranchId(branch_id, sourcePath) }),\n\t\t...(merge_branch_ids === undefined\n\t\t\t? {}\n\t\t\t: { merge_branch_ids: merge_branch_ids.map(asBranchId) }),\n\t\t...(continuation_token === undefined\n\t\t\t? {}\n\t\t\t: { continuation_token: asSuspensionToken(continuation_token) }),\n\t\t...(current_step === undefined\n\t\t\t? {}\n\t\t\t: { current_step: parseStepRecommendation(current_step, sourcePath) }),\n\t\t...(previous_steps === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tprevious_steps: previous_steps.map((step) => parseStepRecommendation(step, sourcePath)),\n\t\t\t\t}),\n\t};\n}\n\nexport function parseEdge(raw: unknown): Edge {\n\tconst parsed = v.parse(EdgeSchema, raw);\n\treturn {\n\t\t...parsed,\n\t\tid: asEdgeId(parsed.id),\n\t\tfrom: asThoughtId(parsed.from),\n\t\tto: asThoughtId(parsed.to),\n\t\tsessionId: asSessionId(parsed.sessionId),\n\t};\n}\n\nexport function parseSummary(raw: unknown, sourcePath: string): Summary {\n\tconst parsed = v.parse(SummarySchema, raw);\n\tconst { branchId, sessionId, rootThoughtId, coveredIds, coveredRange, ...summary } = parsed;\n\tconst [rangeStart, rangeEnd] = coveredRange;\n\tif (rangeStart === undefined || rangeEnd === undefined) {\n\t\tthrow new PersistenceCompatibilityError(\n\t\t\tsourcePath,\n\t\t\t'summary coveredRange must contain two values'\n\t\t);\n\t}\n\treturn {\n\t\t...summary,\n\t\tsessionId: asSessionId(sessionId),\n\t\t...(branchId === undefined ? {} : { branchId: parsePersistenceBranchId(branchId, sourcePath) }),\n\t\trootThoughtId: asThoughtId(rootThoughtId),\n\t\tcoveredIds: coveredIds.map(asThoughtId),\n\t\tcoveredRange: [rangeStart, rangeEnd],\n\t};\n}\n"],"names":["parseToolRecommendation","recommendation","sourcePath","undefined","PersistenceCompatibilityError","parseSkillRecommendation","parseStepRecommendation","step","recommended_tools","recommended_skills","fields","tool","skill","parseThoughtData","raw","parsed","v","SequentialThinkingSchema","id","session_id","branch_id","merge_branch_ids","continuation_token","current_step","previous_steps","thought","asThoughtId","asSessionId","parsePersistenceBranchId","asBranchId","asSuspensionToken","parseEdge","EdgeSchema","asEdgeId","parseSummary","SummarySchema","branchId","sessionId","rootThoughtId","coveredIds","coveredRange","summary","rangeStart","rangeEnd"],"mappings":"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"}
1
+ {"version":3,"file":"persistence/PersistenceCodec.js","sources":["../../src/persistence/PersistenceCodec.ts"],"sourcesContent":["import * as v from 'valibot';\nimport {\n\tasBranchId,\n\tasEdgeId,\n\tasSessionId,\n\tasSuspensionToken,\n\tasThoughtId,\n} from '../contracts/ids.js';\nimport type { Summary } from '../core/compression/Summary.js';\nimport { SummarySchema } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type { ThoughtData } from '../core/thought.js';\nimport type { StepRecommendation } from '../core/step.js';\nimport { EdgeSchema, SequentialThinkingSchema } from '../schema.js';\nimport { PersistenceCompatibilityError } from '../errors.js';\nimport { parsePersistenceBranchId } from './PersistenceScope.js';\n\ntype PersistedToolRecommendation = {\n\treadonly tool_name: string;\n\treadonly confidence?: number;\n\treadonly rationale?: string;\n\treadonly priority?: number;\n\treadonly suggested_inputs?: Record<string, string | number | boolean | null>;\n\treadonly alternatives?: string[];\n};\n\ntype PersistedSkillRecommendation = {\n\treadonly skill_name: string;\n\treadonly confidence?: number;\n\treadonly rationale?: string;\n\treadonly priority?: number;\n\treadonly alternatives?: string[];\n\treadonly allowed_tools?: string[];\n\treadonly user_invocable?: boolean;\n};\n\ntype PersistedStepRecommendation = {\n\treadonly step_description?: string;\n\treadonly recommended_tools: readonly PersistedToolRecommendation[];\n\treadonly recommended_skills?: readonly PersistedSkillRecommendation[];\n\treadonly expected_outcome?: string;\n\treadonly next_step_conditions?: string[];\n};\n\nfunction parseToolRecommendation(recommendation: PersistedToolRecommendation, sourcePath: string) {\n\tif (\n\t\trecommendation.confidence === undefined ||\n\t\trecommendation.rationale === undefined ||\n\t\trecommendation.priority === undefined\n\t) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'tool recommendation defaults are absent');\n\t}\n\treturn {\n\t\t...recommendation,\n\t\tconfidence: recommendation.confidence,\n\t\trationale: recommendation.rationale,\n\t\tpriority: recommendation.priority,\n\t};\n}\n\nfunction parseSkillRecommendation(\n\trecommendation: PersistedSkillRecommendation,\n\tsourcePath: string\n) {\n\tif (\n\t\trecommendation.confidence === undefined ||\n\t\trecommendation.rationale === undefined ||\n\t\trecommendation.priority === undefined\n\t) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'skill recommendation defaults are absent');\n\t}\n\treturn {\n\t\t...recommendation,\n\t\tconfidence: recommendation.confidence,\n\t\trationale: recommendation.rationale,\n\t\tpriority: recommendation.priority,\n\t};\n}\n\nfunction parseStepRecommendation(\n\tstep: PersistedStepRecommendation,\n\tsourcePath: string\n): StepRecommendation {\n\tif (step.step_description === undefined || step.expected_outcome === undefined) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'step recommendation defaults are absent');\n\t}\n\tconst { recommended_tools, recommended_skills, ...fields } = step;\n\treturn {\n\t\t...fields,\n\t\tstep_description: step.step_description,\n\t\texpected_outcome: step.expected_outcome,\n\t\trecommended_tools: recommended_tools.map((tool) => parseToolRecommendation(tool, sourcePath)),\n\t\t...(recommended_skills === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\trecommended_skills: recommended_skills.map((skill) =>\n\t\t\t\t\t\tparseSkillRecommendation(skill, sourcePath)\n\t\t\t\t\t),\n\t\t\t\t}),\n\t};\n}\n\nexport function parseThoughtData(raw: unknown, sourcePath: string): ThoughtData {\n\tconst parsed = v.parse(SequentialThinkingSchema, raw);\n\tconst {\n\t\tid,\n\t\tsession_id,\n\t\tbranch_id,\n\t\tmerge_branch_ids,\n\t\tcontinuation_token,\n\t\tcurrent_step,\n\t\tprevious_steps,\n\t\t...thought\n\t} = parsed;\n\treturn {\n\t\t...thought,\n\t\t...(id === undefined ? {} : { id: asThoughtId(id) }),\n\t\tsession_id: asSessionId(session_id),\n\t\t...(branch_id === undefined\n\t\t\t? {}\n\t\t\t: { branch_id: parsePersistenceBranchId(branch_id, sourcePath) }),\n\t\t...(merge_branch_ids === undefined\n\t\t\t? {}\n\t\t\t: { merge_branch_ids: merge_branch_ids.map(asBranchId) }),\n\t\t...(continuation_token === undefined\n\t\t\t? {}\n\t\t\t: { continuation_token: asSuspensionToken(continuation_token) }),\n\t\t...(current_step === undefined\n\t\t\t? {}\n\t\t\t: { current_step: parseStepRecommendation(current_step, sourcePath) }),\n\t\t...(previous_steps === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tprevious_steps: previous_steps.map((step) => parseStepRecommendation(step, sourcePath)),\n\t\t\t\t}),\n\t};\n}\n\nexport function parseEdge(raw: unknown): Edge {\n\tconst parsed = v.parse(EdgeSchema, raw);\n\treturn {\n\t\t...parsed,\n\t\tid: asEdgeId(parsed.id),\n\t\tfrom: asThoughtId(parsed.from),\n\t\tto: asThoughtId(parsed.to),\n\t\tsessionId: asSessionId(parsed.sessionId),\n\t};\n}\n\nexport function parseSummary(raw: unknown, sourcePath: string): Summary {\n\tconst parsed = v.parse(SummarySchema, raw);\n\tconst { branchId, sessionId, rootThoughtId, coveredIds, coveredRange, ...summary } = parsed;\n\tconst [rangeStart, rangeEnd] = coveredRange;\n\tif (rangeStart === undefined || rangeEnd === undefined) {\n\t\tthrow new PersistenceCompatibilityError(\n\t\t\tsourcePath,\n\t\t\t'summary coveredRange must contain two values'\n\t\t);\n\t}\n\treturn {\n\t\t...summary,\n\t\tsessionId: asSessionId(sessionId),\n\t\t...(branchId === undefined ? {} : { branchId: parsePersistenceBranchId(branchId, sourcePath) }),\n\t\trootThoughtId: asThoughtId(rootThoughtId),\n\t\tcoveredIds: coveredIds.map(asThoughtId),\n\t\tcoveredRange: [rangeStart, rangeEnd],\n\t};\n}\n"],"names":["parseToolRecommendation","recommendation","sourcePath","undefined","PersistenceCompatibilityError","parseSkillRecommendation","parseStepRecommendation","step","recommended_tools","recommended_skills","fields","tool","skill","parseThoughtData","raw","parsed","v","SequentialThinkingSchema","id","session_id","branch_id","merge_branch_ids","continuation_token","current_step","previous_steps","thought","asThoughtId","asSessionId","parsePersistenceBranchId","asBranchId","asSuspensionToken","parseEdge","EdgeSchema","asEdgeId","parseSummary","SummarySchema","branchId","sessionId","rootThoughtId","coveredIds","coveredRange","summary","rangeStart","rangeEnd"],"mappings":"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"}