@iworkforces/tracelattice 2.0.3
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.
- package/LICENSE +24 -0
- package/README.md +260 -0
- package/dist/CliLifecycle.d.ts +31 -0
- package/dist/CliLifecycle.d.ts.map +1 -0
- package/dist/CliLifecycle.js +90 -0
- package/dist/CliLifecycle.js.map +1 -0
- package/dist/ServerConfig.d.ts +290 -0
- package/dist/ServerConfig.d.ts.map +1 -0
- package/dist/ServerConfig.js +175 -0
- package/dist/ServerConfig.js.map +1 -0
- package/dist/cache/DiscoveryCache.d.ts +269 -0
- package/dist/cache/DiscoveryCache.d.ts.map +1 -0
- package/dist/cache/DiscoveryCache.js +104 -0
- package/dist/cache/DiscoveryCache.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +5177 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/ConfigLoader.d.ts +270 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +186 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/context/RequestContext.d.ts +43 -0
- package/dist/context/RequestContext.d.ts.map +1 -0
- package/dist/context/RequestContext.js +14 -0
- package/dist/context/RequestContext.js.map +1 -0
- package/dist/contracts/PersistenceBackend.d.ts +134 -0
- package/dist/contracts/PersistenceBackend.d.ts.map +1 -0
- package/dist/contracts/PersistenceBackend.js +6 -0
- package/dist/contracts/PersistenceBackend.js.map +1 -0
- package/dist/contracts/calibrator.d.ts +97 -0
- package/dist/contracts/calibrator.d.ts.map +1 -0
- package/dist/contracts/calibrator.js +1 -0
- package/dist/contracts/features.d.ts +35 -0
- package/dist/contracts/features.d.ts.map +1 -0
- package/dist/contracts/features.js +12 -0
- package/dist/contracts/features.js.map +1 -0
- package/dist/contracts/ids.d.ts +68 -0
- package/dist/contracts/ids.d.ts.map +1 -0
- package/dist/contracts/ids.js +40 -0
- package/dist/contracts/ids.js.map +1 -0
- package/dist/contracts/interfaces.d.ts +254 -0
- package/dist/contracts/interfaces.d.ts.map +1 -0
- package/dist/contracts/interfaces.js +1 -0
- package/dist/contracts/persistence-work.d.ts +96 -0
- package/dist/contracts/persistence-work.d.ts.map +1 -0
- package/dist/contracts/persistence-work.js +1 -0
- package/dist/contracts/reasoning-types.d.ts +21 -0
- package/dist/contracts/reasoning-types.d.ts.map +1 -0
- package/dist/contracts/reasoning-types.js +1 -0
- package/dist/contracts/strategy.d.ts +107 -0
- package/dist/contracts/strategy.d.ts.map +1 -0
- package/dist/contracts/strategy.js +1 -0
- package/dist/contracts/summary.d.ts +110 -0
- package/dist/contracts/summary.d.ts.map +1 -0
- package/dist/contracts/summary.js +1 -0
- package/dist/contracts/suspension.d.ts +215 -0
- package/dist/contracts/suspension.d.ts.map +1 -0
- package/dist/contracts/suspension.js +1 -0
- package/dist/contracts/transport.d.ts +26 -0
- package/dist/contracts/transport.d.ts.map +1 -0
- package/dist/contracts/transport.js +1 -0
- package/dist/core/CrossReferenceValidator.d.ts +18 -0
- package/dist/core/CrossReferenceValidator.d.ts.map +1 -0
- package/dist/core/CrossReferenceValidator.js +125 -0
- package/dist/core/CrossReferenceValidator.js.map +1 -0
- package/dist/core/HistoryManager.d.ts +215 -0
- package/dist/core/HistoryManager.d.ts.map +1 -0
- package/dist/core/HistoryManager.js +594 -0
- package/dist/core/HistoryManager.js.map +1 -0
- package/dist/core/IHistoryManager.d.ts +163 -0
- package/dist/core/IHistoryManager.d.ts.map +1 -0
- package/dist/core/IHistoryManager.js +1 -0
- package/dist/core/IThoughtFormatter.d.ts +51 -0
- package/dist/core/IThoughtFormatter.d.ts.map +1 -0
- package/dist/core/IThoughtFormatter.js +1 -0
- package/dist/core/InputNormalizer.d.ts +140 -0
- package/dist/core/InputNormalizer.d.ts.map +1 -0
- package/dist/core/InputNormalizer.js +95 -0
- package/dist/core/InputNormalizer.js.map +1 -0
- package/dist/core/PersistenceBuffer.d.ts +204 -0
- package/dist/core/PersistenceBuffer.d.ts.map +1 -0
- package/dist/core/PersistenceBuffer.js +382 -0
- package/dist/core/PersistenceBuffer.js.map +1 -0
- package/dist/core/PersistenceBufferErrors.d.ts +22 -0
- package/dist/core/PersistenceBufferErrors.d.ts.map +1 -0
- package/dist/core/PersistenceBufferErrors.js +30 -0
- package/dist/core/PersistenceBufferErrors.js.map +1 -0
- package/dist/core/PersistenceRestore.d.ts +21 -0
- package/dist/core/PersistenceRestore.d.ts.map +1 -0
- package/dist/core/PersistenceRestore.js +87 -0
- package/dist/core/PersistenceRestore.js.map +1 -0
- package/dist/core/PersistenceWorkQueue.d.ts +155 -0
- package/dist/core/PersistenceWorkQueue.d.ts.map +1 -0
- package/dist/core/PersistenceWorkQueue.js +298 -0
- package/dist/core/PersistenceWorkQueue.js.map +1 -0
- package/dist/core/PersistenceWriter.d.ts +55 -0
- package/dist/core/PersistenceWriter.d.ts.map +1 -0
- package/dist/core/PersistenceWriter.js +112 -0
- package/dist/core/PersistenceWriter.js.map +1 -0
- package/dist/core/SessionErrors.d.ts +37 -0
- package/dist/core/SessionErrors.d.ts.map +1 -0
- package/dist/core/SessionErrors.js +50 -0
- package/dist/core/SessionErrors.js.map +1 -0
- package/dist/core/SessionLifecycleCoordinator.d.ts +74 -0
- package/dist/core/SessionLifecycleCoordinator.d.ts.map +1 -0
- package/dist/core/SessionLifecycleCoordinator.js +222 -0
- package/dist/core/SessionLifecycleCoordinator.js.map +1 -0
- package/dist/core/SessionLock.d.ts +59 -0
- package/dist/core/SessionLock.d.ts.map +1 -0
- package/dist/core/SessionLock.js +39 -0
- package/dist/core/SessionLock.js.map +1 -0
- package/dist/core/SessionManager.d.ts +62 -0
- package/dist/core/SessionManager.d.ts.map +1 -0
- package/dist/core/SessionManager.js +75 -0
- package/dist/core/SessionManager.js.map +1 -0
- package/dist/core/SessionResetCoordinator.d.ts +37 -0
- package/dist/core/SessionResetCoordinator.d.ts.map +1 -0
- package/dist/core/SessionResetCoordinator.js +80 -0
- package/dist/core/SessionResetCoordinator.js.map +1 -0
- package/dist/core/ThoughtEvaluator.d.ts +48 -0
- package/dist/core/ThoughtEvaluator.d.ts.map +1 -0
- package/dist/core/ThoughtEvaluator.js +85 -0
- package/dist/core/ThoughtEvaluator.js.map +1 -0
- package/dist/core/ThoughtFormatter.d.ts +134 -0
- package/dist/core/ThoughtFormatter.d.ts.map +1 -0
- package/dist/core/ThoughtFormatter.js +118 -0
- package/dist/core/ThoughtFormatter.js.map +1 -0
- package/dist/core/ThoughtProcessor.d.ts +259 -0
- package/dist/core/ThoughtProcessor.d.ts.map +1 -0
- package/dist/core/ThoughtProcessor.js +451 -0
- package/dist/core/ThoughtProcessor.js.map +1 -0
- package/dist/core/ThoughtReferenceIndex.d.ts +23 -0
- package/dist/core/ThoughtReferenceIndex.d.ts.map +1 -0
- package/dist/core/ThoughtReferenceIndex.js +66 -0
- package/dist/core/ThoughtReferenceIndex.js.map +1 -0
- package/dist/core/VerificationOutcomeAdmission.d.ts +15 -0
- package/dist/core/VerificationOutcomeAdmission.d.ts.map +1 -0
- package/dist/core/VerificationOutcomeAdmission.js +28 -0
- package/dist/core/VerificationOutcomeAdmission.js.map +1 -0
- package/dist/core/compression/CompressionService.d.ts +76 -0
- package/dist/core/compression/CompressionService.d.ts.map +1 -0
- package/dist/core/compression/CompressionService.js +160 -0
- package/dist/core/compression/CompressionService.js.map +1 -0
- package/dist/core/compression/DehydrationPolicy.d.ts +75 -0
- package/dist/core/compression/DehydrationPolicy.d.ts.map +1 -0
- package/dist/core/compression/DehydrationPolicy.js +45 -0
- package/dist/core/compression/DehydrationPolicy.js.map +1 -0
- package/dist/core/compression/InMemorySummaryStore.d.ts +132 -0
- package/dist/core/compression/InMemorySummaryStore.d.ts.map +1 -0
- package/dist/core/compression/InMemorySummaryStore.js +69 -0
- package/dist/core/compression/InMemorySummaryStore.js.map +1 -0
- package/dist/core/compression/Summary.d.ts +74 -0
- package/dist/core/compression/Summary.d.ts.map +1 -0
- package/dist/core/compression/Summary.js +16 -0
- package/dist/core/compression/Summary.js.map +1 -0
- package/dist/core/evaluator/Aggregator.d.ts +40 -0
- package/dist/core/evaluator/Aggregator.d.ts.map +1 -0
- package/dist/core/evaluator/Aggregator.js +36 -0
- package/dist/core/evaluator/Aggregator.js.map +1 -0
- package/dist/core/evaluator/Calibrator.d.ts +52 -0
- package/dist/core/evaluator/Calibrator.d.ts.map +1 -0
- package/dist/core/evaluator/Calibrator.js +135 -0
- package/dist/core/evaluator/Calibrator.js.map +1 -0
- package/dist/core/evaluator/PatternDetector.d.ts +69 -0
- package/dist/core/evaluator/PatternDetector.d.ts.map +1 -0
- package/dist/core/evaluator/PatternDetector.js +192 -0
- package/dist/core/evaluator/PatternDetector.js.map +1 -0
- package/dist/core/evaluator/SignalComputer.d.ts +116 -0
- package/dist/core/evaluator/SignalComputer.d.ts.map +1 -0
- package/dist/core/evaluator/SignalComputer.js +110 -0
- package/dist/core/evaluator/SignalComputer.js.map +1 -0
- package/dist/core/evaluator/calibration-math.d.ts +39 -0
- package/dist/core/evaluator/calibration-math.d.ts.map +1 -0
- package/dist/core/evaluator/calibration-math.js +42 -0
- package/dist/core/evaluator/calibration-math.js.map +1 -0
- package/dist/core/evaluator/internals.d.ts +36 -0
- package/dist/core/evaluator/internals.d.ts.map +1 -0
- package/dist/core/evaluator/internals.js +43 -0
- package/dist/core/evaluator/internals.js.map +1 -0
- package/dist/core/graph/Edge.d.ts +58 -0
- package/dist/core/graph/Edge.d.ts.map +1 -0
- package/dist/core/graph/Edge.js +1 -0
- package/dist/core/graph/EdgeEmitter.d.ts +68 -0
- package/dist/core/graph/EdgeEmitter.d.ts.map +1 -0
- package/dist/core/graph/EdgeEmitter.js +118 -0
- package/dist/core/graph/EdgeEmitter.js.map +1 -0
- package/dist/core/graph/EdgeStore.d.ts +116 -0
- package/dist/core/graph/EdgeStore.d.ts.map +1 -0
- package/dist/core/graph/EdgeStore.js +107 -0
- package/dist/core/graph/EdgeStore.js.map +1 -0
- package/dist/core/graph/GraphView.d.ts +157 -0
- package/dist/core/graph/GraphView.d.ts.map +1 -0
- package/dist/core/graph/GraphView.js +149 -0
- package/dist/core/graph/GraphView.js.map +1 -0
- package/dist/core/ids.d.ts +33 -0
- package/dist/core/ids.d.ts.map +1 -0
- package/dist/core/ids.js +11 -0
- package/dist/core/ids.js.map +1 -0
- package/dist/core/reasoning/OutcomeRecorder.d.ts +88 -0
- package/dist/core/reasoning/OutcomeRecorder.d.ts.map +1 -0
- package/dist/core/reasoning/OutcomeRecorder.js +51 -0
- package/dist/core/reasoning/OutcomeRecorder.js.map +1 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.d.ts +54 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.js +22 -0
- package/dist/core/reasoning/strategies/SequentialStrategy.js.map +1 -0
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts +25 -0
- package/dist/core/reasoning/strategies/StrategyFactory.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/StrategyFactory.js +16 -0
- package/dist/core/reasoning/strategies/StrategyFactory.js.map +1 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts +58 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js +103 -0
- package/dist/core/reasoning/strategies/TreeOfThoughtStrategy.js.map +1 -0
- package/dist/core/reasoning/strategies/plateau.d.ts +18 -0
- package/dist/core/reasoning/strategies/plateau.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/plateau.js +12 -0
- package/dist/core/reasoning/strategies/plateau.js.map +1 -0
- package/dist/core/reasoning/strategies/totScoring.d.ts +91 -0
- package/dist/core/reasoning/strategies/totScoring.d.ts.map +1 -0
- package/dist/core/reasoning/strategies/totScoring.js +88 -0
- package/dist/core/reasoning/strategies/totScoring.js.map +1 -0
- package/dist/core/reasoning.d.ts +179 -0
- package/dist/core/reasoning.d.ts.map +1 -0
- package/dist/core/reasoning.js +1 -0
- package/dist/core/step.d.ts +50 -0
- package/dist/core/step.d.ts.map +1 -0
- package/dist/core/step.js +1 -0
- package/dist/core/thought.d.ts +113 -0
- package/dist/core/thought.d.ts.map +1 -0
- package/dist/core/thought.js +1 -0
- package/dist/core/tools/InMemorySuspensionStore.d.ts +66 -0
- package/dist/core/tools/InMemorySuspensionStore.d.ts.map +1 -0
- package/dist/core/tools/InMemorySuspensionStore.js +121 -0
- package/dist/core/tools/InMemorySuspensionStore.js.map +1 -0
- package/dist/di/Container.d.ts +253 -0
- package/dist/di/Container.d.ts.map +1 -0
- package/dist/di/Container.js +111 -0
- package/dist/di/Container.js.map +1 -0
- package/dist/di/ServiceRegistry.d.ts +50 -0
- package/dist/di/ServiceRegistry.d.ts.map +1 -0
- package/dist/di/ServiceRegistry.js +1 -0
- package/dist/errors.d.ts +663 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +282 -0
- package/dist/errors.js.map +1 -0
- package/dist/health/HealthChecker.d.ts +73 -0
- package/dist/health/HealthChecker.d.ts.map +1 -0
- package/dist/health/HealthChecker.js +70 -0
- package/dist/health/HealthChecker.js.map +1 -0
- package/dist/lib.d.ts +273 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +409 -0
- package/dist/lib.js.map +1 -0
- package/dist/logger/NullLogger.d.ts +154 -0
- package/dist/logger/NullLogger.d.ts.map +1 -0
- package/dist/logger/NullLogger.js +24 -0
- package/dist/logger/NullLogger.js.map +1 -0
- package/dist/logger/StructuredLogger.d.ts +327 -0
- package/dist/logger/StructuredLogger.d.ts.map +1 -0
- package/dist/logger/StructuredLogger.js +72 -0
- package/dist/logger/StructuredLogger.js.map +1 -0
- package/dist/metrics/metrics.impl.d.ts +252 -0
- package/dist/metrics/metrics.impl.d.ts.map +1 -0
- package/dist/metrics/metrics.impl.js +197 -0
- package/dist/metrics/metrics.impl.js.map +1 -0
- package/dist/persistence/FileLegacyImport.d.ts +2 -0
- package/dist/persistence/FileLegacyImport.d.ts.map +1 -0
- package/dist/persistence/FileLegacyImport.js +183 -0
- package/dist/persistence/FileLegacyImport.js.map +1 -0
- package/dist/persistence/FilePersistence.d.ts +53 -0
- package/dist/persistence/FilePersistence.d.ts.map +1 -0
- package/dist/persistence/FilePersistence.js +312 -0
- package/dist/persistence/FilePersistence.js.map +1 -0
- package/dist/persistence/FileSnapshotTypes.d.ts +29 -0
- package/dist/persistence/FileSnapshotTypes.d.ts.map +1 -0
- package/dist/persistence/FileSnapshotTypes.js +1 -0
- package/dist/persistence/FileSnapshotV2.d.ts +377 -0
- package/dist/persistence/FileSnapshotV2.d.ts.map +1 -0
- package/dist/persistence/FileSnapshotV2.js +124 -0
- package/dist/persistence/FileSnapshotV2.js.map +1 -0
- package/dist/persistence/FileSnapshotValidation.d.ts +15 -0
- package/dist/persistence/FileSnapshotValidation.d.ts.map +1 -0
- package/dist/persistence/FileSnapshotValidation.js +64 -0
- package/dist/persistence/FileSnapshotValidation.js.map +1 -0
- package/dist/persistence/FileWriter.d.ts +30 -0
- package/dist/persistence/FileWriter.d.ts.map +1 -0
- package/dist/persistence/FileWriter.js +155 -0
- package/dist/persistence/FileWriter.js.map +1 -0
- package/dist/persistence/MemoryPersistence.d.ts +45 -0
- package/dist/persistence/MemoryPersistence.d.ts.map +1 -0
- package/dist/persistence/MemoryPersistence.js +180 -0
- package/dist/persistence/MemoryPersistence.js.map +1 -0
- package/dist/persistence/PersistenceCodec.d.ts +7 -0
- package/dist/persistence/PersistenceCodec.d.ts.map +1 -0
- package/dist/persistence/PersistenceCodec.js +97 -0
- package/dist/persistence/PersistenceCodec.js.map +1 -0
- package/dist/persistence/PersistenceErrors.d.ts +23 -0
- package/dist/persistence/PersistenceErrors.d.ts.map +1 -0
- package/dist/persistence/PersistenceErrors.js +26 -0
- package/dist/persistence/PersistenceErrors.js.map +1 -0
- package/dist/persistence/PersistenceFactory.d.ts +21 -0
- package/dist/persistence/PersistenceFactory.d.ts.map +1 -0
- package/dist/persistence/PersistenceFactory.js +28 -0
- package/dist/persistence/PersistenceFactory.js.map +1 -0
- package/dist/persistence/PersistenceScope.d.ts +42 -0
- package/dist/persistence/PersistenceScope.d.ts.map +1 -0
- package/dist/persistence/PersistenceScope.js +93 -0
- package/dist/persistence/PersistenceScope.js.map +1 -0
- package/dist/persistence/SessionScopedPersistence.d.ts +4 -0
- package/dist/persistence/SessionScopedPersistence.d.ts.map +1 -0
- package/dist/persistence/SessionScopedPersistence.js +9 -0
- package/dist/persistence/SessionScopedPersistence.js.map +1 -0
- package/dist/persistence/SqliteDriver.d.ts +22 -0
- package/dist/persistence/SqliteDriver.d.ts.map +1 -0
- package/dist/persistence/SqliteDriver.js +29 -0
- package/dist/persistence/SqliteDriver.js.map +1 -0
- package/dist/persistence/SqliteLegacyImport.d.ts +14 -0
- package/dist/persistence/SqliteLegacyImport.d.ts.map +1 -0
- package/dist/persistence/SqliteLegacyImport.js +136 -0
- package/dist/persistence/SqliteLegacyImport.js.map +1 -0
- package/dist/persistence/SqliteLegacySchema.d.ts +15 -0
- package/dist/persistence/SqliteLegacySchema.d.ts.map +1 -0
- package/dist/persistence/SqliteLegacySchema.js +72 -0
- package/dist/persistence/SqliteLegacySchema.js.map +1 -0
- package/dist/persistence/SqlitePayload.d.ts +11 -0
- package/dist/persistence/SqlitePayload.d.ts.map +1 -0
- package/dist/persistence/SqlitePayload.js +86 -0
- package/dist/persistence/SqlitePayload.js.map +1 -0
- package/dist/persistence/SqlitePersistence.d.ts +49 -0
- package/dist/persistence/SqlitePersistence.d.ts.map +1 -0
- package/dist/persistence/SqlitePersistence.js +248 -0
- package/dist/persistence/SqlitePersistence.js.map +1 -0
- package/dist/persistence/SqliteSchemaV2.d.ts +14 -0
- package/dist/persistence/SqliteSchemaV2.d.ts.map +1 -0
- package/dist/persistence/SqliteSchemaV2.js +129 -0
- package/dist/persistence/SqliteSchemaV2.js.map +1 -0
- package/dist/persistence/SqliteSnapshotWriter.d.ts +17 -0
- package/dist/persistence/SqliteSnapshotWriter.d.ts.map +1 -0
- package/dist/persistence/SqliteSnapshotWriter.js +30 -0
- package/dist/persistence/SqliteSnapshotWriter.js.map +1 -0
- package/dist/pool/ConnectionPool.d.ts +203 -0
- package/dist/pool/ConnectionPool.d.ts.map +1 -0
- package/dist/pool/ConnectionPool.js +303 -0
- package/dist/pool/ConnectionPool.js.map +1 -0
- package/dist/pool/IConnectionPool.d.ts +143 -0
- package/dist/pool/IConnectionPool.d.ts.map +1 -0
- package/dist/pool/IConnectionPool.js +1 -0
- package/dist/pool/PoolErrors.d.ts +11 -0
- package/dist/pool/PoolErrors.d.ts.map +1 -0
- package/dist/pool/PoolErrors.js +16 -0
- package/dist/pool/PoolErrors.js.map +1 -0
- package/dist/registry/BaseRegistry.d.ts +219 -0
- package/dist/registry/BaseRegistry.d.ts.map +1 -0
- package/dist/registry/BaseRegistry.js +215 -0
- package/dist/registry/BaseRegistry.js.map +1 -0
- package/dist/registry/SkillRegistry.d.ts +67 -0
- package/dist/registry/SkillRegistry.d.ts.map +1 -0
- package/dist/registry/SkillRegistry.js +87 -0
- package/dist/registry/SkillRegistry.js.map +1 -0
- package/dist/registry/ToolRegistry.d.ts +70 -0
- package/dist/registry/ToolRegistry.d.ts.map +1 -0
- package/dist/registry/ToolRegistry.js +96 -0
- package/dist/registry/ToolRegistry.js.map +1 -0
- package/dist/sanitize.d.ts +164 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +100 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/schema.d.ts +562 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +251 -0
- package/dist/schema.js.map +1 -0
- package/dist/transport/BaseTransport.d.ts +166 -0
- package/dist/transport/BaseTransport.d.ts.map +1 -0
- package/dist/transport/BaseTransport.js +199 -0
- package/dist/transport/BaseTransport.js.map +1 -0
- package/dist/transport/HttpHelpers.d.ts +53 -0
- package/dist/transport/HttpHelpers.d.ts.map +1 -0
- package/dist/transport/HttpHelpers.js +44 -0
- package/dist/transport/HttpHelpers.js.map +1 -0
- package/dist/transport/HttpRequestLifecycle.d.ts +37 -0
- package/dist/transport/HttpRequestLifecycle.d.ts.map +1 -0
- package/dist/transport/HttpRequestLifecycle.js +87 -0
- package/dist/transport/HttpRequestLifecycle.js.map +1 -0
- package/dist/transport/HttpTransport.d.ts +140 -0
- package/dist/transport/HttpTransport.d.ts.map +1 -0
- package/dist/transport/HttpTransport.js +245 -0
- package/dist/transport/HttpTransport.js.map +1 -0
- package/dist/transport/SseTransport.d.ts +149 -0
- package/dist/transport/SseTransport.d.ts.map +1 -0
- package/dist/transport/SseTransport.js +470 -0
- package/dist/transport/SseTransport.js.map +1 -0
- package/dist/transport/StreamableHttpTransport.d.ts +225 -0
- package/dist/transport/StreamableHttpTransport.d.ts.map +1 -0
- package/dist/transport/StreamableHttpTransport.js +449 -0
- package/dist/transport/StreamableHttpTransport.js.map +1 -0
- package/dist/types/disposable.d.ts +22 -0
- package/dist/types/disposable.d.ts.map +1 -0
- package/dist/types/disposable.js +1 -0
- package/dist/types/server-config.d.ts +32 -0
- package/dist/types/server-config.d.ts.map +1 -0
- package/dist/types/server-config.js +1 -0
- package/dist/types/skill.d.ts +74 -0
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/skill.js +1 -0
- package/dist/types/tool.d.ts +78 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +1 -0
- package/dist/utils.d.ts +27 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +6 -0
- package/dist/utils.js.map +1 -0
- package/dist/watchers/SkillWatcher.d.ts +25 -0
- package/dist/watchers/SkillWatcher.d.ts.map +1 -0
- package/dist/watchers/SkillWatcher.js +96 -0
- package/dist/watchers/SkillWatcher.js.map +1 -0
- package/dist/watchers/ToolWatcher.d.ts +24 -0
- package/dist/watchers/ToolWatcher.d.ts.map +1 -0
- package/dist/watchers/ToolWatcher.js +92 -0
- package/dist/watchers/ToolWatcher.js.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
|
|
5
|
+
import { PersistenceCompatibilityError, PersistenceCorruptionError } from "../errors.js";
|
|
6
|
+
import { runSqliteReadTransaction, runSqliteTransaction } from "./SqliteDriver.js";
|
|
7
|
+
import { decodeEdgeRow, decodeSummaryRow, decodeThoughtRow, numberField, stringField } from "./SqlitePayload.js";
|
|
8
|
+
import { assertBranchScope, assertEdgeScopes, assertPersistableThoughtCollections, assertPersistableThoughts, assertSummaryScopes, assertThoughtScope, compareCodePoint, parsePersistenceBranchId } from "./PersistenceScope.js";
|
|
9
|
+
import { initializeOrValidateSqliteV2 } from "./SqliteSchemaV2.js";
|
|
10
|
+
class SqlitePersistence {
|
|
11
|
+
_db;
|
|
12
|
+
_sourcePath;
|
|
13
|
+
_maxHistorySize;
|
|
14
|
+
_persistBranches;
|
|
15
|
+
constructor(_db, _sourcePath, _maxHistorySize, _persistBranches){
|
|
16
|
+
this._db = _db;
|
|
17
|
+
this._sourcePath = _sourcePath;
|
|
18
|
+
this._maxHistorySize = _maxHistorySize;
|
|
19
|
+
this._persistBranches = _persistBranches;
|
|
20
|
+
}
|
|
21
|
+
static createWithDatabase(database, options = {}, sourcePath = '<structural-sqlite>') {
|
|
22
|
+
initializeOrValidateSqliteV2(database, sourcePath);
|
|
23
|
+
return new SqlitePersistence(database, sourcePath, options?.maxHistorySize ?? 10000, options?.persistBranches ?? true);
|
|
24
|
+
}
|
|
25
|
+
static async create(options) {
|
|
26
|
+
const defaultDataDir = existsSync('.claude/data') ? '.claude/data' : join(homedir(), '.claude/data');
|
|
27
|
+
const dbPath = options?.dbPath ?? join(defaultDataDir, 'history.db');
|
|
28
|
+
let Database;
|
|
29
|
+
try {
|
|
30
|
+
const module = await import("better-sqlite3");
|
|
31
|
+
Database = module.default;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new PersistenceCompatibilityError(dbPath, "SQLite persistence requires the optional 'better-sqlite3' package", error);
|
|
34
|
+
}
|
|
35
|
+
const database = new Database(dbPath);
|
|
36
|
+
try {
|
|
37
|
+
const persistence = SqlitePersistence.createWithDatabase(database, options, dbPath);
|
|
38
|
+
if (options?.enableWAL !== false) database.pragma('journal_mode = WAL');
|
|
39
|
+
database.pragma('synchronous = NORMAL');
|
|
40
|
+
database.pragma('foreign_keys = ON');
|
|
41
|
+
database.pragma('busy_timeout = 5000');
|
|
42
|
+
database.pragma('cache_size = -64000');
|
|
43
|
+
database.pragma('temp_store = MEMORY');
|
|
44
|
+
return persistence;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
database.close();
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async saveThought(thought) {
|
|
51
|
+
assertThoughtScope('saveThought', GLOBAL_SESSION_ID, thought);
|
|
52
|
+
this._saveThought(GLOBAL_SESSION_ID, thought);
|
|
53
|
+
}
|
|
54
|
+
async saveThoughtForSession(sessionId, thought) {
|
|
55
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
56
|
+
assertThoughtScope('saveThoughtForSession', validatedSessionId, thought);
|
|
57
|
+
this._saveThought(validatedSessionId, thought);
|
|
58
|
+
}
|
|
59
|
+
_saveThought(sessionId, thought) {
|
|
60
|
+
runSqliteTransaction(this._db, ()=>{
|
|
61
|
+
this._loadValidatedThoughtState(sessionId, [
|
|
62
|
+
thought
|
|
63
|
+
]);
|
|
64
|
+
this._db.prepare('INSERT INTO thoughts (session_id, data) VALUES (?, ?)').run(sessionId, JSON.stringify(thought));
|
|
65
|
+
if (this._maxHistorySize > 0) {
|
|
66
|
+
const countRow = this._db.prepare('SELECT COUNT(*) AS count FROM thoughts WHERE session_id = ?').get(sessionId);
|
|
67
|
+
const excess = numberField(countRow, 'count', `${this._sourcePath}:thought-count`) - this._maxHistorySize;
|
|
68
|
+
if (excess > 0) this._db.prepare('DELETE FROM thoughts WHERE id IN (SELECT id FROM thoughts WHERE session_id = ? ORDER BY id ASC LIMIT ?)').run(sessionId, excess);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async loadHistory() {
|
|
73
|
+
return await this.loadHistoryForSession(GLOBAL_SESSION_ID);
|
|
74
|
+
}
|
|
75
|
+
async loadHistoryForSession(sessionId) {
|
|
76
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
77
|
+
return runSqliteReadTransaction(this._db, ()=>this._loadValidatedThoughtState(validatedSessionId).history);
|
|
78
|
+
}
|
|
79
|
+
async saveBranch(branchId, thoughts) {
|
|
80
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${this._sourcePath}:branches`);
|
|
81
|
+
assertBranchScope('saveBranch', GLOBAL_SESSION_ID, validatedBranchId, thoughts);
|
|
82
|
+
this._saveBranch(GLOBAL_SESSION_ID, validatedBranchId, thoughts);
|
|
83
|
+
}
|
|
84
|
+
async saveBranchForSession(sessionId, branchId, thoughts) {
|
|
85
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
86
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${this._sourcePath}:branches`);
|
|
87
|
+
assertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);
|
|
88
|
+
this._saveBranch(validatedSessionId, validatedBranchId, thoughts);
|
|
89
|
+
}
|
|
90
|
+
_saveBranch(sessionId, branchId, thoughts) {
|
|
91
|
+
assertPersistableThoughts(thoughts, `${this._sourcePath}:branch:${branchId}`);
|
|
92
|
+
if (!this._persistBranches) return void runSqliteReadTransaction(this._db, ()=>this._loadValidatedThoughtState(sessionId, thoughts, branchId));
|
|
93
|
+
runSqliteTransaction(this._db, ()=>{
|
|
94
|
+
this._loadValidatedThoughtState(sessionId, thoughts, branchId);
|
|
95
|
+
this._db.prepare('INSERT OR REPLACE INTO branches (session_id, branch_id, data) VALUES (?, ?, ?)').run(sessionId, branchId, JSON.stringify(thoughts));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async deleteBranch(branchId) {
|
|
99
|
+
await this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);
|
|
100
|
+
}
|
|
101
|
+
async deleteBranchForSession(sessionId, branchId) {
|
|
102
|
+
if (!this._persistBranches) return;
|
|
103
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
104
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${this._sourcePath}:branches`);
|
|
105
|
+
runSqliteTransaction(this._db, ()=>{
|
|
106
|
+
this._db.prepare('DELETE FROM branches WHERE session_id = ? AND branch_id = ?').run(validatedSessionId, validatedBranchId);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async loadBranch(branchId) {
|
|
110
|
+
return await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);
|
|
111
|
+
}
|
|
112
|
+
async loadBranchForSession(sessionId, branchId) {
|
|
113
|
+
if (!this._persistBranches) return;
|
|
114
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
115
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${this._sourcePath}:branches`);
|
|
116
|
+
return runSqliteReadTransaction(this._db, ()=>this._loadValidatedThoughtState(validatedSessionId).branches.get(validatedBranchId));
|
|
117
|
+
}
|
|
118
|
+
async listBranches() {
|
|
119
|
+
return await this.listBranchesForSession(GLOBAL_SESSION_ID);
|
|
120
|
+
}
|
|
121
|
+
async listBranchesForSession(sessionId) {
|
|
122
|
+
if (!this._persistBranches) return [];
|
|
123
|
+
return this._db.prepare('SELECT branch_id FROM branches WHERE session_id = ? ORDER BY branch_id ASC').all(asSessionId(sessionId)).map((row)=>parsePersistenceBranchId(stringField(row, 'branch_id', this._sourcePath), this._sourcePath));
|
|
124
|
+
}
|
|
125
|
+
async listSessions() {
|
|
126
|
+
return this._db.prepare('SELECT session_id FROM thoughts UNION SELECT session_id FROM branches UNION SELECT session_id FROM edges UNION SELECT session_id FROM summaries').all().map((row)=>asSessionId(stringField(row, 'session_id', this._sourcePath))).sort(compareCodePoint);
|
|
127
|
+
}
|
|
128
|
+
async clear() {
|
|
129
|
+
runSqliteTransaction(this._db, ()=>{
|
|
130
|
+
for (const table of [
|
|
131
|
+
'thoughts',
|
|
132
|
+
'branches',
|
|
133
|
+
'edges',
|
|
134
|
+
'summaries'
|
|
135
|
+
])this._db.exec(`DELETE FROM ${table}`);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async clearSession(sessionId) {
|
|
139
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
140
|
+
runSqliteTransaction(this._db, ()=>{
|
|
141
|
+
for (const table of [
|
|
142
|
+
'thoughts',
|
|
143
|
+
'branches',
|
|
144
|
+
'edges',
|
|
145
|
+
'summaries'
|
|
146
|
+
])this._db.prepare(`DELETE FROM ${table} WHERE session_id = ?`).run(validatedSessionId);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
async saveEdges(sessionId, edges) {
|
|
150
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
151
|
+
assertEdgeScopes(validatedSessionId, edges);
|
|
152
|
+
runSqliteTransaction(this._db, ()=>{
|
|
153
|
+
this._db.prepare('DELETE FROM edges WHERE session_id = ?').run(validatedSessionId);
|
|
154
|
+
const insert = this._db.prepare('INSERT INTO edges (id, session_id, from_id, to_id, kind, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)');
|
|
155
|
+
for (const edge of edges)insert.run(edge.id, edge.sessionId, edge.from, edge.to, edge.kind, edge.createdAt, void 0 === edge.metadata ? null : JSON.stringify(edge.metadata));
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async loadEdges(sessionId) {
|
|
159
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
160
|
+
return this._db.prepare('SELECT id, session_id, from_id, to_id, kind, created_at, metadata FROM edges WHERE session_id = ? ORDER BY created_at ASC, id ASC').all(validatedSessionId).map((row, index)=>decodeEdgeRow(row, `${this._sourcePath}:edges:${index}`));
|
|
161
|
+
}
|
|
162
|
+
async listEdgeSessions() {
|
|
163
|
+
return this._db.prepare('SELECT DISTINCT session_id FROM edges ORDER BY session_id ASC').all().map((row)=>asSessionId(stringField(row, 'session_id', this._sourcePath)));
|
|
164
|
+
}
|
|
165
|
+
async saveSummaries(sessionId, summaries) {
|
|
166
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
167
|
+
assertSummaryScopes(validatedSessionId, summaries);
|
|
168
|
+
runSqliteTransaction(this._db, ()=>{
|
|
169
|
+
this._db.prepare('DELETE FROM summaries WHERE session_id = ?').run(validatedSessionId);
|
|
170
|
+
const insert = this._db.prepare('INSERT INTO summaries (id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
|
171
|
+
for (const summary of summaries)insert.run(summary.id, summary.sessionId, summary.branchId ?? null, summary.rootThoughtId, JSON.stringify(summary.coveredIds), summary.coveredRange[0], summary.coveredRange[1], JSON.stringify(summary.topics), summary.aggregateConfidence, summary.createdAt, void 0 === summary.meta ? null : JSON.stringify(summary.meta));
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
async loadSummaries(sessionId) {
|
|
175
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
176
|
+
return this._db.prepare('SELECT id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta FROM summaries WHERE session_id = ? ORDER BY created_at ASC, id ASC').all(validatedSessionId).map((row, index)=>decodeSummaryRow(row, `${this._sourcePath}:summaries:${index}`));
|
|
177
|
+
}
|
|
178
|
+
async healthy() {
|
|
179
|
+
try {
|
|
180
|
+
this._db.prepare('SELECT 1').get();
|
|
181
|
+
return true;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof Error) return false;
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async close() {
|
|
188
|
+
this._db.close();
|
|
189
|
+
}
|
|
190
|
+
getStats() {
|
|
191
|
+
const thoughtCount = numberField(this._db.prepare('SELECT COUNT(*) AS count FROM thoughts').get(), 'count', this._sourcePath);
|
|
192
|
+
const branchCount = numberField(this._db.prepare('SELECT COUNT(*) AS count FROM branches').get(), 'count', this._sourcePath);
|
|
193
|
+
return {
|
|
194
|
+
thoughtCount,
|
|
195
|
+
branchCount: this._persistBranches ? branchCount : 0,
|
|
196
|
+
dbSize: 0
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
_loadValidatedThoughtState(sessionId, candidates = [], replacingBranch) {
|
|
200
|
+
const history = this.loadHistoryRows(sessionId);
|
|
201
|
+
for (const thought of history)assertThoughtScope('saveThoughtForSession', sessionId, thought);
|
|
202
|
+
const collections = [
|
|
203
|
+
{
|
|
204
|
+
sessionId,
|
|
205
|
+
thoughts: void 0 === replacingBranch ? [
|
|
206
|
+
...history,
|
|
207
|
+
...candidates
|
|
208
|
+
] : history
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
const branches = new Map();
|
|
212
|
+
for (const row of this._db.prepare('SELECT branch_id, data FROM branches WHERE session_id = ?').all(sessionId)){
|
|
213
|
+
const branchId = parsePersistenceBranchId(stringField(row, 'branch_id', this._sourcePath), this._sourcePath);
|
|
214
|
+
const data = stringField(row, 'data', this._sourcePath);
|
|
215
|
+
let values;
|
|
216
|
+
try {
|
|
217
|
+
values = JSON.parse(data);
|
|
218
|
+
} catch (error) {
|
|
219
|
+
throw new PersistenceCorruptionError(this._sourcePath, error);
|
|
220
|
+
}
|
|
221
|
+
if (!Array.isArray(values)) throw new PersistenceCorruptionError(this._sourcePath, new TypeError('branch data is not an array'));
|
|
222
|
+
const thoughts = values.map((value, index)=>decodeThoughtRow({
|
|
223
|
+
data: JSON.stringify(value)
|
|
224
|
+
}, `${this._sourcePath}:branch:${sessionId}:${branchId}:${index}`));
|
|
225
|
+
assertBranchScope('saveBranchForSession', sessionId, branchId, thoughts);
|
|
226
|
+
branches.set(branchId, thoughts);
|
|
227
|
+
if (branchId !== replacingBranch) collections.push({
|
|
228
|
+
sessionId,
|
|
229
|
+
thoughts
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (void 0 !== replacingBranch) collections.push({
|
|
233
|
+
sessionId,
|
|
234
|
+
thoughts: candidates
|
|
235
|
+
});
|
|
236
|
+
assertPersistableThoughtCollections(collections, this._sourcePath);
|
|
237
|
+
return {
|
|
238
|
+
history,
|
|
239
|
+
branches
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
loadHistoryRows(sessionId) {
|
|
243
|
+
return this._db.prepare('SELECT data FROM thoughts WHERE session_id = ? ORDER BY id ASC').all(sessionId).map((row)=>decodeThoughtRow(row, this._sourcePath));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
export { SqlitePersistence };
|
|
247
|
+
|
|
248
|
+
//# sourceMappingURL=SqlitePersistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence/SqlitePersistence.js","sources":["../../src/persistence/SqlitePersistence.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\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 { PersistenceCompatibilityError, PersistenceCorruptionError } from '../errors.js';\nimport type { SqliteDatabase, SqliteDatabaseConstructor } from './SqliteDriver.js';\nimport { runSqliteReadTransaction, runSqliteTransaction } from './SqliteDriver.js';\nimport {\n\tdecodeEdgeRow,\n\tdecodeSummaryRow,\n\tdecodeThoughtRow,\n\tnumberField,\n\tstringField,\n} from './SqlitePayload.js';\nimport {\n\tassertBranchScope,\n\tassertEdgeScopes,\n\tassertPersistableThoughtCollections,\n\tassertPersistableThoughts,\n\tassertSummaryScopes,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tparsePersistenceBranchId,\n\ttype PersistedThoughtCollection,\n} from './PersistenceScope.js';\nimport { initializeOrValidateSqliteV2 } from './SqliteSchemaV2.js';\n\ntype SqliteOptions = PersistenceConfig['options'];\n\ntype ValidatedThoughtState = {\n\treadonly history: ThoughtData[];\n\treadonly branches: ReadonlyMap<BranchId, ThoughtData[]>;\n};\n\nexport class SqlitePersistence implements SessionScopedPersistenceBackend {\n\tprivate constructor(\n\t\tprivate readonly _db: SqliteDatabase,\n\t\tprivate readonly _sourcePath: string,\n\t\tprivate readonly _maxHistorySize: number,\n\t\tprivate readonly _persistBranches: boolean\n\t) {}\n\n\tpublic static createWithDatabase(\n\t\tdatabase: SqliteDatabase,\n\t\toptions: SqliteOptions = {},\n\t\tsourcePath = '<structural-sqlite>'\n\t): SqlitePersistence {\n\t\tinitializeOrValidateSqliteV2(database, sourcePath);\n\t\treturn new SqlitePersistence(\n\t\t\tdatabase,\n\t\t\tsourcePath,\n\t\t\toptions?.maxHistorySize ?? 10000,\n\t\t\toptions?.persistBranches ?? true\n\t\t);\n\t}\n\n\tpublic static async create(options?: SqliteOptions): Promise<SqlitePersistence> {\n\t\tconst defaultDataDir = existsSync('.claude/data')\n\t\t\t? '.claude/data'\n\t\t\t: join(homedir(), '.claude/data');\n\t\tconst dbPath = options?.dbPath ?? join(defaultDataDir, 'history.db');\n\t\tlet Database: SqliteDatabaseConstructor;\n\t\ttry {\n\t\t\tconst module = await import('better-sqlite3');\n\t\t\tDatabase = module.default;\n\t\t} catch (error) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tdbPath,\n\t\t\t\t\"SQLite persistence requires the optional 'better-sqlite3' package\",\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t\tconst database = new Database(dbPath);\n\t\ttry {\n\t\t\tconst persistence = SqlitePersistence.createWithDatabase(database, options, dbPath);\n\t\t\tif (options?.enableWAL !== false) database.pragma('journal_mode = WAL');\n\t\t\tdatabase.pragma('synchronous = NORMAL');\n\t\t\tdatabase.pragma('foreign_keys = ON');\n\t\t\tdatabase.pragma('busy_timeout = 5000');\n\t\t\tdatabase.pragma('cache_size = -64000');\n\t\t\tdatabase.pragma('temp_store = MEMORY');\n\t\t\treturn persistence;\n\t\t} catch (error) {\n\t\t\tdatabase.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\tthis._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\tthis._saveThought(validatedSessionId, thought);\n\t}\n\n\tprivate _saveThought(sessionId: SessionId, thought: ThoughtData): void {\n\t\trunSqliteTransaction(this._db, () => {\n\t\t\tthis._loadValidatedThoughtState(sessionId, [thought]);\n\t\t\tthis._db\n\t\t\t\t.prepare('INSERT INTO thoughts (session_id, data) VALUES (?, ?)')\n\t\t\t\t.run(sessionId, JSON.stringify(thought));\n\t\t\tif (this._maxHistorySize > 0) {\n\t\t\t\tconst countRow = this._db\n\t\t\t\t\t.prepare('SELECT COUNT(*) AS count FROM thoughts WHERE session_id = ?')\n\t\t\t\t\t.get(sessionId);\n\t\t\t\tconst excess =\n\t\t\t\t\tnumberField(countRow, 'count', `${this._sourcePath}:thought-count`) -\n\t\t\t\t\tthis._maxHistorySize;\n\t\t\t\tif (excess > 0) {\n\t\t\t\t\tthis._db\n\t\t\t\t\t\t.prepare(\n\t\t\t\t\t\t\t'DELETE FROM thoughts WHERE id IN (SELECT id FROM thoughts WHERE session_id = ? ORDER BY id ASC LIMIT ?)'\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.run(sessionId, excess);\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 runSqliteReadTransaction(\n\t\t\tthis._db,\n\t\t\t() => this._loadValidatedThoughtState(validatedSessionId).history\n\t\t);\n\t}\n\n\tpublic async saveBranch(branchId: BranchId, thoughts: ThoughtData[]): Promise<void> {\n\t\tconst validatedBranchId = parsePersistenceBranchId(branchId, `${this._sourcePath}:branches`);\n\t\tassertBranchScope('saveBranch', GLOBAL_SESSION_ID, validatedBranchId, thoughts);\n\t\tthis._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, `${this._sourcePath}:branches`);\n\t\tassertBranchScope('saveBranchForSession', validatedSessionId, validatedBranchId, thoughts);\n\t\tthis._saveBranch(validatedSessionId, validatedBranchId, thoughts);\n\t}\n\n\tprivate _saveBranch(\n\t\tsessionId: SessionId,\n\t\tbranchId: BranchId,\n\t\tthoughts: readonly ThoughtData[]\n\t): void {\n\t\tassertPersistableThoughts(thoughts, `${this._sourcePath}:branch:${branchId}`);\n\t\tif (!this._persistBranches) {\n\t\t\trunSqliteReadTransaction(this._db, () =>\n\t\t\t\tthis._loadValidatedThoughtState(sessionId, thoughts, branchId)\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\trunSqliteTransaction(this._db, () => {\n\t\t\tthis._loadValidatedThoughtState(sessionId, thoughts, branchId);\n\t\t\tthis._db\n\t\t\t\t.prepare('INSERT OR REPLACE INTO branches (session_id, branch_id, data) VALUES (?, ?, ?)')\n\t\t\t\t.run(sessionId, branchId, JSON.stringify(thoughts));\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, `${this._sourcePath}:branches`);\n\t\trunSqliteTransaction(this._db, () => {\n\t\t\tthis._db\n\t\t\t\t.prepare('DELETE FROM branches WHERE session_id = ? AND branch_id = ?')\n\t\t\t\t.run(validatedSessionId, validatedBranchId);\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, `${this._sourcePath}:branches`);\n\t\treturn runSqliteReadTransaction(this._db, () =>\n\t\t\tthis._loadValidatedThoughtState(validatedSessionId).branches.get(validatedBranchId)\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\treturn this._db\n\t\t\t.prepare('SELECT branch_id FROM branches WHERE session_id = ? ORDER BY branch_id ASC')\n\t\t\t.all(asSessionId(sessionId))\n\t\t\t.map((row) =>\n\t\t\t\tparsePersistenceBranchId(stringField(row, 'branch_id', this._sourcePath), this._sourcePath)\n\t\t\t);\n\t}\n\n\tpublic async listSessions(): Promise<SessionId[]> {\n\t\treturn this._db\n\t\t\t.prepare(\n\t\t\t\t'SELECT session_id FROM thoughts UNION SELECT session_id FROM branches UNION SELECT session_id FROM edges UNION SELECT session_id FROM summaries'\n\t\t\t)\n\t\t\t.all()\n\t\t\t.map((row) => asSessionId(stringField(row, 'session_id', this._sourcePath)))\n\t\t\t.sort(compareCodePoint);\n\t}\n\n\tpublic async clear(): Promise<void> {\n\t\trunSqliteTransaction(this._db, () => {\n\t\t\tfor (const table of ['thoughts', 'branches', 'edges', 'summaries'])\n\t\t\t\tthis._db.exec(`DELETE FROM ${table}`);\n\t\t});\n\t}\n\n\tpublic async clearSession(sessionId: SessionId): Promise<void> {\n\t\tconst validatedSessionId = asSessionId(sessionId);\n\t\trunSqliteTransaction(this._db, () => {\n\t\t\tfor (const table of ['thoughts', 'branches', 'edges', 'summaries']) {\n\t\t\t\tthis._db.prepare(`DELETE FROM ${table} WHERE session_id = ?`).run(validatedSessionId);\n\t\t\t}\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\trunSqliteTransaction(this._db, () => {\n\t\t\tthis._db.prepare('DELETE FROM edges WHERE session_id = ?').run(validatedSessionId);\n\t\t\tconst insert = this._db.prepare(\n\t\t\t\t'INSERT INTO edges (id, session_id, from_id, to_id, kind, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)'\n\t\t\t);\n\t\t\tfor (const edge of edges)\n\t\t\t\tinsert.run(\n\t\t\t\t\tedge.id,\n\t\t\t\t\tedge.sessionId,\n\t\t\t\t\tedge.from,\n\t\t\t\t\tedge.to,\n\t\t\t\t\tedge.kind,\n\t\t\t\t\tedge.createdAt,\n\t\t\t\t\tedge.metadata === undefined ? null : JSON.stringify(edge.metadata)\n\t\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 this._db\n\t\t\t.prepare(\n\t\t\t\t'SELECT id, session_id, from_id, to_id, kind, created_at, metadata FROM edges WHERE session_id = ? ORDER BY created_at ASC, id ASC'\n\t\t\t)\n\t\t\t.all(validatedSessionId)\n\t\t\t.map((row, index) => decodeEdgeRow(row, `${this._sourcePath}:edges:${index}`));\n\t}\n\n\tpublic async listEdgeSessions(): Promise<SessionId[]> {\n\t\treturn this._db\n\t\t\t.prepare('SELECT DISTINCT session_id FROM edges ORDER BY session_id ASC')\n\t\t\t.all()\n\t\t\t.map((row) => asSessionId(stringField(row, 'session_id', this._sourcePath)));\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\trunSqliteTransaction(this._db, () => {\n\t\t\tthis._db.prepare('DELETE FROM summaries WHERE session_id = ?').run(validatedSessionId);\n\t\t\tconst insert = this._db.prepare(\n\t\t\t\t'INSERT INTO summaries (id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'\n\t\t\t);\n\t\t\tfor (const summary of summaries)\n\t\t\t\tinsert.run(\n\t\t\t\t\tsummary.id,\n\t\t\t\t\tsummary.sessionId,\n\t\t\t\t\tsummary.branchId ?? null,\n\t\t\t\t\tsummary.rootThoughtId,\n\t\t\t\t\tJSON.stringify(summary.coveredIds),\n\t\t\t\t\tsummary.coveredRange[0],\n\t\t\t\t\tsummary.coveredRange[1],\n\t\t\t\t\tJSON.stringify(summary.topics),\n\t\t\t\t\tsummary.aggregateConfidence,\n\t\t\t\t\tsummary.createdAt,\n\t\t\t\t\tsummary.meta === undefined ? null : JSON.stringify(summary.meta)\n\t\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 this._db\n\t\t\t.prepare(\n\t\t\t\t'SELECT id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta FROM summaries WHERE session_id = ? ORDER BY created_at ASC, id ASC'\n\t\t\t)\n\t\t\t.all(validatedSessionId)\n\t\t\t.map((row, index) => decodeSummaryRow(row, `${this._sourcePath}:summaries:${index}`));\n\t}\n\n\tpublic async healthy(): Promise<boolean> {\n\t\ttry {\n\t\t\tthis._db.prepare('SELECT 1').get();\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 async close(): Promise<void> {\n\t\tthis._db.close();\n\t}\n\n\tpublic getStats(): {\n\t\treadonly thoughtCount: number;\n\t\treadonly branchCount: number;\n\t\treadonly dbSize: number;\n\t} {\n\t\tconst thoughtCount = numberField(\n\t\t\tthis._db.prepare('SELECT COUNT(*) AS count FROM thoughts').get(),\n\t\t\t'count',\n\t\t\tthis._sourcePath\n\t\t);\n\t\tconst branchCount = numberField(\n\t\t\tthis._db.prepare('SELECT COUNT(*) AS count FROM branches').get(),\n\t\t\t'count',\n\t\t\tthis._sourcePath\n\t\t);\n\t\treturn { thoughtCount, branchCount: this._persistBranches ? branchCount : 0, dbSize: 0 };\n\t}\n\n\tprivate _loadValidatedThoughtState(\n\t\tsessionId: SessionId,\n\t\tcandidates: readonly ThoughtData[] = [],\n\t\treplacingBranch?: BranchId\n\t): ValidatedThoughtState {\n\t\tconst history = this.loadHistoryRows(sessionId);\n\t\tfor (const thought of history) {\n\t\t\tassertThoughtScope('saveThoughtForSession', sessionId, thought);\n\t\t}\n\t\tconst collections: PersistedThoughtCollection[] = [\n\t\t\t{\n\t\t\t\tsessionId,\n\t\t\t\tthoughts: replacingBranch === undefined ? [...history, ...candidates] : history,\n\t\t\t},\n\t\t];\n\t\tconst branches = new Map<BranchId, ThoughtData[]>();\n\t\tfor (const row of this._db\n\t\t\t.prepare('SELECT branch_id, data FROM branches WHERE session_id = ?')\n\t\t\t.all(sessionId)) {\n\t\t\tconst branchId = parsePersistenceBranchId(\n\t\t\t\tstringField(row, 'branch_id', this._sourcePath),\n\t\t\t\tthis._sourcePath\n\t\t\t);\n\t\t\tconst data = stringField(row, 'data', this._sourcePath);\n\t\t\tlet values: unknown;\n\t\t\ttry {\n\t\t\t\tvalues = JSON.parse(data);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new PersistenceCorruptionError(this._sourcePath, error);\n\t\t\t}\n\t\t\tif (!Array.isArray(values))\n\t\t\t\tthrow new PersistenceCorruptionError(\n\t\t\t\t\tthis._sourcePath,\n\t\t\t\t\tnew TypeError('branch data is not an array')\n\t\t\t\t);\n\t\t\tconst thoughts = values.map((value, index) =>\n\t\t\t\tdecodeThoughtRow(\n\t\t\t\t\t{ data: JSON.stringify(value) },\n\t\t\t\t\t`${this._sourcePath}:branch:${sessionId}:${branchId}:${index}`\n\t\t\t\t)\n\t\t\t);\n\t\t\tassertBranchScope('saveBranchForSession', sessionId, branchId, thoughts);\n\t\t\tbranches.set(branchId, thoughts);\n\t\t\tif (branchId !== replacingBranch) collections.push({ sessionId, thoughts });\n\t\t}\n\t\tif (replacingBranch !== undefined) {\n\t\t\tcollections.push({ sessionId, thoughts: candidates });\n\t\t}\n\t\tassertPersistableThoughtCollections(collections, this._sourcePath);\n\t\treturn { history, branches };\n\t}\n\n\tprivate loadHistoryRows(sessionId: SessionId): ThoughtData[] {\n\t\treturn this._db\n\t\t\t.prepare('SELECT data FROM thoughts WHERE session_id = ? ORDER BY id ASC')\n\t\t\t.all(sessionId)\n\t\t\t.map((row) => decodeThoughtRow(row, this._sourcePath));\n\t}\n}\n"],"names":["SqlitePersistence","_db","_sourcePath","_maxHistorySize","_persistBranches","database","options","sourcePath","initializeOrValidateSqliteV2","defaultDataDir","existsSync","join","homedir","dbPath","Database","module","error","PersistenceCompatibilityError","persistence","thought","assertThoughtScope","GLOBAL_SESSION_ID","sessionId","validatedSessionId","asSessionId","runSqliteTransaction","JSON","countRow","excess","numberField","runSqliteReadTransaction","branchId","thoughts","validatedBranchId","parsePersistenceBranchId","assertBranchScope","assertPersistableThoughts","row","stringField","compareCodePoint","table","edges","assertEdgeScopes","insert","edge","undefined","index","decodeEdgeRow","summaries","assertSummaryScopes","summary","decodeSummaryRow","Error","thoughtCount","branchCount","candidates","replacingBranch","history","collections","branches","Map","data","values","PersistenceCorruptionError","Array","TypeError","value","decodeThoughtRow","assertPersistableThoughtCollections"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SqliteDatabase } from './SqliteDriver.js';
|
|
2
|
+
export declare const SQLITE_V2_SCHEMA_DDL = "\nCREATE TABLE schema_version (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n version INTEGER NOT NULL CHECK (version = 2)\n);\nCREATE TABLE thoughts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n data TEXT NOT NULL,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE INDEX idx_thoughts_session_id ON thoughts(session_id, id);\nCREATE TABLE branches (\n session_id TEXT NOT NULL,\n branch_id TEXT NOT NULL,\n data TEXT NOT NULL,\n updated_at INTEGER NOT NULL DEFAULT (unixepoch()),\n PRIMARY KEY (session_id, branch_id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),\n CHECK (length(branch_id) BETWEEN 1 AND 50),\n CHECK (branch_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE TABLE edges (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n metadata TEXT,\n PRIMARY KEY (session_id, id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE INDEX idx_edges_session_created ON edges(session_id, created_at, id);\nCREATE INDEX idx_edges_from ON edges(session_id, from_id);\nCREATE INDEX idx_edges_to ON edges(session_id, to_id);\nCREATE TABLE summaries (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n branch_id TEXT,\n root_thought_id TEXT NOT NULL,\n covered_ids TEXT NOT NULL,\n covered_range_start INTEGER NOT NULL,\n covered_range_end INTEGER NOT NULL,\n topics TEXT NOT NULL,\n aggregate_confidence REAL NOT NULL,\n created_at INTEGER NOT NULL,\n meta TEXT,\n PRIMARY KEY (session_id, id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),\n CHECK (branch_id IS NULL OR (\n length(branch_id) BETWEEN 1 AND 50\n AND branch_id NOT GLOB '*[^A-Za-z0-9_-]*'\n )),\n CHECK (aggregate_confidence >= 0.0 AND aggregate_confidence <= 1.0)\n);\nCREATE INDEX idx_summaries_session_created\n ON summaries(session_id, created_at, id);\nCREATE INDEX idx_summaries_session_branch\n ON summaries(session_id, branch_id);\n";
|
|
3
|
+
export declare const SQLITE_V2_VERSION_INSERT = "INSERT INTO schema_version (singleton, version) VALUES (1, 2);";
|
|
4
|
+
type SchemaObject = {
|
|
5
|
+
readonly type: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly tableName: string;
|
|
8
|
+
readonly sql: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function sqliteSchemaObjects(database: SqliteDatabase, sourcePath: string): SchemaObject[];
|
|
11
|
+
export declare function validateSqliteV2Schema(database: SqliteDatabase, sourcePath: string): void;
|
|
12
|
+
export declare function initializeOrValidateSqliteV2(database: SqliteDatabase, sourcePath: string): void;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=SqliteSchemaV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqliteSchemaV2.d.ts","sourceRoot":"","sources":["../../src/persistence/SqliteSchemaV2.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxD,eAAO,MAAM,oBAAoB,4tEAiEhC,CAAC;AAEF,eAAO,MAAM,wBAAwB,mEAC4B,CAAC;AAElE,KAAK,YAAY,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB,CAAC;AAuCF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAOhG;AAYD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CA8BzF;AAED,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAS/F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { PersistenceCompatibilityError, PersistenceImportRequiredError } from "../errors.js";
|
|
2
|
+
import { runSqliteTransaction } from "./SqliteDriver.js";
|
|
3
|
+
const SQLITE_V2_SCHEMA_DDL = `
|
|
4
|
+
CREATE TABLE schema_version (
|
|
5
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
6
|
+
version INTEGER NOT NULL CHECK (version = 2)
|
|
7
|
+
);
|
|
8
|
+
CREATE TABLE thoughts (
|
|
9
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
10
|
+
session_id TEXT NOT NULL,
|
|
11
|
+
data TEXT NOT NULL,
|
|
12
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
13
|
+
CHECK (length(session_id) BETWEEN 1 AND 100),
|
|
14
|
+
CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')
|
|
15
|
+
);
|
|
16
|
+
CREATE INDEX idx_thoughts_session_id ON thoughts(session_id, id);
|
|
17
|
+
CREATE TABLE branches (
|
|
18
|
+
session_id TEXT NOT NULL,
|
|
19
|
+
branch_id TEXT NOT NULL,
|
|
20
|
+
data TEXT NOT NULL,
|
|
21
|
+
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
22
|
+
PRIMARY KEY (session_id, branch_id),
|
|
23
|
+
CHECK (length(session_id) BETWEEN 1 AND 100),
|
|
24
|
+
CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),
|
|
25
|
+
CHECK (length(branch_id) BETWEEN 1 AND 50),
|
|
26
|
+
CHECK (branch_id NOT GLOB '*[^A-Za-z0-9_-]*')
|
|
27
|
+
);
|
|
28
|
+
CREATE TABLE edges (
|
|
29
|
+
id TEXT NOT NULL,
|
|
30
|
+
session_id TEXT NOT NULL,
|
|
31
|
+
from_id TEXT NOT NULL,
|
|
32
|
+
to_id TEXT NOT NULL,
|
|
33
|
+
kind TEXT NOT NULL,
|
|
34
|
+
created_at INTEGER NOT NULL,
|
|
35
|
+
metadata TEXT,
|
|
36
|
+
PRIMARY KEY (session_id, id),
|
|
37
|
+
CHECK (length(session_id) BETWEEN 1 AND 100),
|
|
38
|
+
CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')
|
|
39
|
+
);
|
|
40
|
+
CREATE INDEX idx_edges_session_created ON edges(session_id, created_at, id);
|
|
41
|
+
CREATE INDEX idx_edges_from ON edges(session_id, from_id);
|
|
42
|
+
CREATE INDEX idx_edges_to ON edges(session_id, to_id);
|
|
43
|
+
CREATE TABLE summaries (
|
|
44
|
+
id TEXT NOT NULL,
|
|
45
|
+
session_id TEXT NOT NULL,
|
|
46
|
+
branch_id TEXT,
|
|
47
|
+
root_thought_id TEXT NOT NULL,
|
|
48
|
+
covered_ids TEXT NOT NULL,
|
|
49
|
+
covered_range_start INTEGER NOT NULL,
|
|
50
|
+
covered_range_end INTEGER NOT NULL,
|
|
51
|
+
topics TEXT NOT NULL,
|
|
52
|
+
aggregate_confidence REAL NOT NULL,
|
|
53
|
+
created_at INTEGER NOT NULL,
|
|
54
|
+
meta TEXT,
|
|
55
|
+
PRIMARY KEY (session_id, id),
|
|
56
|
+
CHECK (length(session_id) BETWEEN 1 AND 100),
|
|
57
|
+
CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),
|
|
58
|
+
CHECK (branch_id IS NULL OR (
|
|
59
|
+
length(branch_id) BETWEEN 1 AND 50
|
|
60
|
+
AND branch_id NOT GLOB '*[^A-Za-z0-9_-]*'
|
|
61
|
+
)),
|
|
62
|
+
CHECK (aggregate_confidence >= 0.0 AND aggregate_confidence <= 1.0)
|
|
63
|
+
);
|
|
64
|
+
CREATE INDEX idx_summaries_session_created
|
|
65
|
+
ON summaries(session_id, created_at, id);
|
|
66
|
+
CREATE INDEX idx_summaries_session_branch
|
|
67
|
+
ON summaries(session_id, branch_id);
|
|
68
|
+
`;
|
|
69
|
+
const SQLITE_V2_VERSION_INSERT = 'INSERT INTO schema_version (singleton, version) VALUES (1, 2);';
|
|
70
|
+
function normalizeSql(sql) {
|
|
71
|
+
return sql.replace(/\s+/g, ' ').replace(/;$/, '').trim().toLowerCase();
|
|
72
|
+
}
|
|
73
|
+
function expectedV2Objects() {
|
|
74
|
+
const objects = new Map();
|
|
75
|
+
for (const statement of SQLITE_V2_SCHEMA_DDL.split(';').map((sql)=>sql.trim()).filter(Boolean)){
|
|
76
|
+
const match = /^CREATE\s+(TABLE|INDEX)\s+([^\s(]+)/i.exec(statement);
|
|
77
|
+
if (match?.[1] !== void 0 && void 0 !== match[2]) objects.set(`${match[1].toLowerCase()}:${match[2]}`, normalizeSql(statement));
|
|
78
|
+
}
|
|
79
|
+
return objects;
|
|
80
|
+
}
|
|
81
|
+
const V2_OBJECTS = expectedV2Objects();
|
|
82
|
+
function readSchemaObject(row, sourcePath) {
|
|
83
|
+
if ('object' != typeof row || null === row) throw new PersistenceCompatibilityError(sourcePath, 'invalid sqlite_master row');
|
|
84
|
+
const type = 'type' in row ? row.type : void 0;
|
|
85
|
+
const name = 'name' in row ? row.name : void 0;
|
|
86
|
+
const tableName = 'tbl_name' in row ? row.tbl_name : void 0;
|
|
87
|
+
const sql = 'sql' in row ? row.sql : void 0;
|
|
88
|
+
if ('string' != typeof type || 'string' != typeof name || 'string' != typeof tableName || 'string' != typeof sql) throw new PersistenceCompatibilityError(sourcePath, 'invalid sqlite_master fields');
|
|
89
|
+
return {
|
|
90
|
+
type,
|
|
91
|
+
name,
|
|
92
|
+
tableName,
|
|
93
|
+
sql
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function sqliteSchemaObjects(database, sourcePath) {
|
|
97
|
+
return database.prepare("SELECT type, name, tbl_name, sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%' ORDER BY type, name").all().map((row)=>readSchemaObject(row, sourcePath));
|
|
98
|
+
}
|
|
99
|
+
function hasLegacyShape(objects) {
|
|
100
|
+
const names = new Set(objects.map(({ type, name })=>`${type}:${name}`));
|
|
101
|
+
return names.has('table:thoughts') && names.has('table:edges') && names.has('table:summaries') && !names.has('table:schema_version');
|
|
102
|
+
}
|
|
103
|
+
function validateSqliteV2Schema(database, sourcePath) {
|
|
104
|
+
const objects = sqliteSchemaObjects(database, sourcePath);
|
|
105
|
+
if (objects.length !== V2_OBJECTS.size) {
|
|
106
|
+
if (hasLegacyShape(objects)) throw new PersistenceImportRequiredError(sourcePath, [
|
|
107
|
+
'unversioned SQLite v1 schema'
|
|
108
|
+
]);
|
|
109
|
+
throw new PersistenceCompatibilityError(sourcePath, 'SQLite v2 object set does not match');
|
|
110
|
+
}
|
|
111
|
+
for (const object of objects){
|
|
112
|
+
const expected = V2_OBJECTS.get(`${object.type}:${object.name}`);
|
|
113
|
+
if (void 0 === expected || normalizeSql(object.sql) !== expected) throw new PersistenceCompatibilityError(sourcePath, `SQLite v2 drift at '${object.name}'`);
|
|
114
|
+
}
|
|
115
|
+
const versionRows = database.prepare('SELECT singleton, version FROM schema_version').all();
|
|
116
|
+
const versionRow = versionRows[0];
|
|
117
|
+
if (1 !== versionRows.length || 'object' != typeof versionRow || null === versionRow || !('singleton' in versionRow) || 1 !== versionRow.singleton || !('version' in versionRow) || 2 !== versionRow.version) throw new PersistenceCompatibilityError(sourcePath, 'schema_version must contain exactly (1, 2)');
|
|
118
|
+
}
|
|
119
|
+
function initializeOrValidateSqliteV2(database, sourcePath) {
|
|
120
|
+
const objects = sqliteSchemaObjects(database, sourcePath);
|
|
121
|
+
if (0 === objects.length) runSqliteTransaction(database, ()=>{
|
|
122
|
+
database.exec(SQLITE_V2_SCHEMA_DDL);
|
|
123
|
+
database.exec(SQLITE_V2_VERSION_INSERT);
|
|
124
|
+
});
|
|
125
|
+
validateSqliteV2Schema(database, sourcePath);
|
|
126
|
+
}
|
|
127
|
+
export { SQLITE_V2_SCHEMA_DDL, SQLITE_V2_VERSION_INSERT, initializeOrValidateSqliteV2, sqliteSchemaObjects, validateSqliteV2Schema };
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=SqliteSchemaV2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence/SqliteSchemaV2.js","sources":["../../src/persistence/SqliteSchemaV2.ts"],"sourcesContent":["import { PersistenceCompatibilityError, PersistenceImportRequiredError } from '../errors.js';\nimport type { SqliteDatabase } from './SqliteDriver.js';\nimport { runSqliteTransaction } from './SqliteDriver.js';\n\nexport const SQLITE_V2_SCHEMA_DDL = `\nCREATE TABLE schema_version (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n version INTEGER NOT NULL CHECK (version = 2)\n);\nCREATE TABLE thoughts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n data TEXT NOT NULL,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE INDEX idx_thoughts_session_id ON thoughts(session_id, id);\nCREATE TABLE branches (\n session_id TEXT NOT NULL,\n branch_id TEXT NOT NULL,\n data TEXT NOT NULL,\n updated_at INTEGER NOT NULL DEFAULT (unixepoch()),\n PRIMARY KEY (session_id, branch_id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),\n CHECK (length(branch_id) BETWEEN 1 AND 50),\n CHECK (branch_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE TABLE edges (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n metadata TEXT,\n PRIMARY KEY (session_id, id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*')\n);\nCREATE INDEX idx_edges_session_created ON edges(session_id, created_at, id);\nCREATE INDEX idx_edges_from ON edges(session_id, from_id);\nCREATE INDEX idx_edges_to ON edges(session_id, to_id);\nCREATE TABLE summaries (\n id TEXT NOT NULL,\n session_id TEXT NOT NULL,\n branch_id TEXT,\n root_thought_id TEXT NOT NULL,\n covered_ids TEXT NOT NULL,\n covered_range_start INTEGER NOT NULL,\n covered_range_end INTEGER NOT NULL,\n topics TEXT NOT NULL,\n aggregate_confidence REAL NOT NULL,\n created_at INTEGER NOT NULL,\n meta TEXT,\n PRIMARY KEY (session_id, id),\n CHECK (length(session_id) BETWEEN 1 AND 100),\n CHECK (session_id NOT GLOB '*[^A-Za-z0-9_-]*'),\n CHECK (branch_id IS NULL OR (\n length(branch_id) BETWEEN 1 AND 50\n AND branch_id NOT GLOB '*[^A-Za-z0-9_-]*'\n )),\n CHECK (aggregate_confidence >= 0.0 AND aggregate_confidence <= 1.0)\n);\nCREATE INDEX idx_summaries_session_created\n ON summaries(session_id, created_at, id);\nCREATE INDEX idx_summaries_session_branch\n ON summaries(session_id, branch_id);\n`;\n\nexport const SQLITE_V2_VERSION_INSERT =\n\t'INSERT INTO schema_version (singleton, version) VALUES (1, 2);';\n\ntype SchemaObject = {\n\treadonly type: string;\n\treadonly name: string;\n\treadonly tableName: string;\n\treadonly sql: string;\n};\n\nfunction normalizeSql(sql: string): string {\n\treturn sql.replace(/\\s+/g, ' ').replace(/;$/, '').trim().toLowerCase();\n}\n\nfunction expectedV2Objects(): Map<string, string> {\n\tconst objects = new Map<string, string>();\n\tfor (const statement of SQLITE_V2_SCHEMA_DDL.split(';')\n\t\t.map((sql) => sql.trim())\n\t\t.filter(Boolean)) {\n\t\tconst match = /^CREATE\\s+(TABLE|INDEX)\\s+([^\\s(]+)/i.exec(statement);\n\t\tif (match?.[1] === undefined || match[2] === undefined) continue;\n\t\tobjects.set(`${match[1].toLowerCase()}:${match[2]}`, normalizeSql(statement));\n\t}\n\treturn objects;\n}\n\nconst V2_OBJECTS = expectedV2Objects();\n\nfunction readSchemaObject(row: unknown, sourcePath: string): SchemaObject {\n\tif (typeof row !== 'object' || row === null) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'invalid sqlite_master row');\n\t}\n\tconst type = 'type' in row ? row.type : undefined;\n\tconst name = 'name' in row ? row.name : undefined;\n\tconst tableName = 'tbl_name' in row ? row.tbl_name : undefined;\n\tconst sql = 'sql' in row ? row.sql : undefined;\n\tif (\n\t\ttypeof type !== 'string' ||\n\t\ttypeof name !== 'string' ||\n\t\ttypeof tableName !== 'string' ||\n\t\ttypeof sql !== 'string'\n\t) {\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'invalid sqlite_master fields');\n\t}\n\treturn { type, name, tableName, sql };\n}\n\nexport function sqliteSchemaObjects(database: SqliteDatabase, sourcePath: string): SchemaObject[] {\n\treturn database\n\t\t.prepare(\n\t\t\t\"SELECT type, name, tbl_name, sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%' ORDER BY type, name\"\n\t\t)\n\t\t.all()\n\t\t.map((row) => readSchemaObject(row, sourcePath));\n}\n\nfunction hasLegacyShape(objects: readonly SchemaObject[]): boolean {\n\tconst names = new Set(objects.map(({ type, name }) => `${type}:${name}`));\n\treturn (\n\t\tnames.has('table:thoughts') &&\n\t\tnames.has('table:edges') &&\n\t\tnames.has('table:summaries') &&\n\t\t!names.has('table:schema_version')\n\t);\n}\n\nexport function validateSqliteV2Schema(database: SqliteDatabase, sourcePath: string): void {\n\tconst objects = sqliteSchemaObjects(database, sourcePath);\n\tif (objects.length !== V2_OBJECTS.size) {\n\t\tif (hasLegacyShape(objects)) {\n\t\t\tthrow new PersistenceImportRequiredError(sourcePath, ['unversioned SQLite v1 schema']);\n\t\t}\n\t\tthrow new PersistenceCompatibilityError(sourcePath, 'SQLite v2 object set does not match');\n\t}\n\tfor (const object of objects) {\n\t\tconst expected = V2_OBJECTS.get(`${object.type}:${object.name}`);\n\t\tif (expected === undefined || normalizeSql(object.sql) !== expected) {\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, `SQLite v2 drift at '${object.name}'`);\n\t\t}\n\t}\n\tconst versionRows = database.prepare('SELECT singleton, version FROM schema_version').all();\n\tconst versionRow = versionRows[0];\n\tif (\n\t\tversionRows.length !== 1 ||\n\t\ttypeof versionRow !== 'object' ||\n\t\tversionRow === null ||\n\t\t!('singleton' in versionRow) ||\n\t\tversionRow.singleton !== 1 ||\n\t\t!('version' in versionRow) ||\n\t\tversionRow.version !== 2\n\t) {\n\t\tthrow new PersistenceCompatibilityError(\n\t\t\tsourcePath,\n\t\t\t'schema_version must contain exactly (1, 2)'\n\t\t);\n\t}\n}\n\nexport function initializeOrValidateSqliteV2(database: SqliteDatabase, sourcePath: string): void {\n\tconst objects = sqliteSchemaObjects(database, sourcePath);\n\tif (objects.length === 0) {\n\t\trunSqliteTransaction(database, () => {\n\t\t\tdatabase.exec(SQLITE_V2_SCHEMA_DDL);\n\t\t\tdatabase.exec(SQLITE_V2_VERSION_INSERT);\n\t\t});\n\t}\n\tvalidateSqliteV2Schema(database, sourcePath);\n}\n"],"names":["SQLITE_V2_SCHEMA_DDL","SQLITE_V2_VERSION_INSERT","normalizeSql","sql","expectedV2Objects","objects","Map","statement","Boolean","match","undefined","V2_OBJECTS","readSchemaObject","row","sourcePath","PersistenceCompatibilityError","type","name","tableName","sqliteSchemaObjects","database","hasLegacyShape","names","Set","validateSqliteV2Schema","PersistenceImportRequiredError","object","expected","versionRows","versionRow","initializeOrValidateSqliteV2","runSqliteTransaction"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FileSnapshotV2 } from './FileSnapshotTypes.js';
|
|
2
|
+
import type { SqliteDatabase } from './SqliteDriver.js';
|
|
3
|
+
/**
|
|
4
|
+
* Writes and validates a canonical File v2 snapshot into an empty SQLite v2 database.
|
|
5
|
+
*
|
|
6
|
+
* @param database - Empty SQLite destination database.
|
|
7
|
+
* @param snapshot - Validated snapshot to write.
|
|
8
|
+
* @param destinationPath - Destination path included in compatibility errors.
|
|
9
|
+
* @returns Nothing after the transaction commits successfully.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* writeSqliteSnapshot(database, snapshot, '/data/history.db');
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeSqliteSnapshot(database: SqliteDatabase, snapshot: FileSnapshotV2, destinationPath: string): void;
|
|
17
|
+
//# sourceMappingURL=SqliteSnapshotWriter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqliteSnapshotWriter.d.ts","sourceRoot":"","sources":["../../src/persistence/SqliteSnapshotWriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEX,cAAc,EAEd,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AA4DxD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,cAAc,EACxB,eAAe,EAAE,MAAM,GACrB,IAAI,CAaN"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { runSqliteTransaction } from "./SqliteDriver.js";
|
|
2
|
+
import { SQLITE_V2_SCHEMA_DDL, SQLITE_V2_VERSION_INSERT, validateSqliteV2Schema } from "./SqliteSchemaV2.js";
|
|
3
|
+
function insertThoughts(database, records) {
|
|
4
|
+
const insert = database.prepare('INSERT INTO thoughts (session_id, data) VALUES (?, ?)');
|
|
5
|
+
for (const record of records)for (const thought of record.thoughts)insert.run(record.sessionId, JSON.stringify(thought));
|
|
6
|
+
}
|
|
7
|
+
function insertBranches(database, records) {
|
|
8
|
+
const insert = database.prepare('INSERT INTO branches (session_id, branch_id, data) VALUES (?, ?, ?)');
|
|
9
|
+
for (const record of records)insert.run(record.sessionId, record.branchId, JSON.stringify(record.thoughts));
|
|
10
|
+
}
|
|
11
|
+
function insertEdge(database, edge) {
|
|
12
|
+
database.prepare('INSERT INTO edges (id, session_id, from_id, to_id, kind, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)').run(edge.id, edge.sessionId, edge.from, edge.to, edge.kind, edge.createdAt, void 0 === edge.metadata ? null : JSON.stringify(edge.metadata));
|
|
13
|
+
}
|
|
14
|
+
function insertSummary(database, summary) {
|
|
15
|
+
database.prepare('INSERT INTO summaries (id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(summary.id, summary.sessionId, summary.branchId ?? null, summary.rootThoughtId, JSON.stringify(summary.coveredIds), summary.coveredRange[0], summary.coveredRange[1], JSON.stringify(summary.topics), summary.aggregateConfidence, summary.createdAt, void 0 === summary.meta ? null : JSON.stringify(summary.meta));
|
|
16
|
+
}
|
|
17
|
+
function writeSqliteSnapshot(database, snapshot, destinationPath) {
|
|
18
|
+
runSqliteTransaction(database, ()=>{
|
|
19
|
+
database.exec(SQLITE_V2_SCHEMA_DDL);
|
|
20
|
+
insertThoughts(database, snapshot.thoughts);
|
|
21
|
+
insertBranches(database, snapshot.branches);
|
|
22
|
+
for (const record of snapshot.edges)for (const edge of record.edges)insertEdge(database, edge);
|
|
23
|
+
for (const record of snapshot.summaries)for (const summary of record.summaries)insertSummary(database, summary);
|
|
24
|
+
database.exec(SQLITE_V2_VERSION_INSERT);
|
|
25
|
+
validateSqliteV2Schema(database, destinationPath);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export { writeSqliteSnapshot };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=SqliteSnapshotWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence/SqliteSnapshotWriter.js","sources":["../../src/persistence/SqliteSnapshotWriter.ts"],"sourcesContent":["import type { Summary } from '../core/compression/Summary.js';\nimport type { Edge } from '../core/graph/Edge.js';\nimport type {\n\tBranchRecordV2,\n\tFileSnapshotV2,\n\tThoughtSessionV2,\n} from './FileSnapshotTypes.js';\nimport type { SqliteDatabase } from './SqliteDriver.js';\nimport { runSqliteTransaction } from './SqliteDriver.js';\nimport {\n\tSQLITE_V2_SCHEMA_DDL,\n\tSQLITE_V2_VERSION_INSERT,\n\tvalidateSqliteV2Schema,\n} from './SqliteSchemaV2.js';\n\nfunction insertThoughts(database: SqliteDatabase, records: readonly ThoughtSessionV2[]): void {\n\tconst insert = database.prepare('INSERT INTO thoughts (session_id, data) VALUES (?, ?)');\n\tfor (const record of records) {\n\t\tfor (const thought of record.thoughts) insert.run(record.sessionId, JSON.stringify(thought));\n\t}\n}\n\nfunction insertBranches(database: SqliteDatabase, records: readonly BranchRecordV2[]): void {\n\tconst insert = database.prepare(\n\t\t'INSERT INTO branches (session_id, branch_id, data) VALUES (?, ?, ?)'\n\t);\n\tfor (const record of records) {\n\t\tinsert.run(record.sessionId, record.branchId, JSON.stringify(record.thoughts));\n\t}\n}\n\nfunction insertEdge(database: SqliteDatabase, edge: Edge): void {\n\tdatabase\n\t\t.prepare(\n\t\t\t'INSERT INTO edges (id, session_id, from_id, to_id, kind, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)'\n\t\t)\n\t\t.run(\n\t\t\tedge.id,\n\t\t\tedge.sessionId,\n\t\t\tedge.from,\n\t\t\tedge.to,\n\t\t\tedge.kind,\n\t\t\tedge.createdAt,\n\t\t\tedge.metadata === undefined ? null : JSON.stringify(edge.metadata)\n\t\t);\n}\n\nfunction insertSummary(database: SqliteDatabase, summary: Summary): void {\n\tdatabase\n\t\t.prepare(\n\t\t\t'INSERT INTO summaries (id, session_id, branch_id, root_thought_id, covered_ids, covered_range_start, covered_range_end, topics, aggregate_confidence, created_at, meta) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'\n\t\t)\n\t\t.run(\n\t\t\tsummary.id,\n\t\t\tsummary.sessionId,\n\t\t\tsummary.branchId ?? null,\n\t\t\tsummary.rootThoughtId,\n\t\t\tJSON.stringify(summary.coveredIds),\n\t\t\tsummary.coveredRange[0],\n\t\t\tsummary.coveredRange[1],\n\t\t\tJSON.stringify(summary.topics),\n\t\t\tsummary.aggregateConfidence,\n\t\t\tsummary.createdAt,\n\t\t\tsummary.meta === undefined ? null : JSON.stringify(summary.meta)\n\t\t);\n}\n\n/**\n * Writes and validates a canonical File v2 snapshot into an empty SQLite v2 database.\n *\n * @param database - Empty SQLite destination database.\n * @param snapshot - Validated snapshot to write.\n * @param destinationPath - Destination path included in compatibility errors.\n * @returns Nothing after the transaction commits successfully.\n *\n * @example\n * ```ts\n * writeSqliteSnapshot(database, snapshot, '/data/history.db');\n * ```\n */\nexport function writeSqliteSnapshot(\n\tdatabase: SqliteDatabase,\n\tsnapshot: FileSnapshotV2,\n\tdestinationPath: string\n): void {\n\trunSqliteTransaction(database, () => {\n\t\tdatabase.exec(SQLITE_V2_SCHEMA_DDL);\n\t\tinsertThoughts(database, snapshot.thoughts);\n\t\tinsertBranches(database, snapshot.branches);\n\t\tfor (const record of snapshot.edges)\n\t\t\tfor (const edge of record.edges) insertEdge(database, edge);\n\t\tfor (const record of snapshot.summaries) {\n\t\t\tfor (const summary of record.summaries) insertSummary(database, summary);\n\t\t}\n\t\tdatabase.exec(SQLITE_V2_VERSION_INSERT);\n\t\tvalidateSqliteV2Schema(database, destinationPath);\n\t});\n}\n"],"names":["insertThoughts","database","records","insert","record","thought","JSON","insertBranches","insertEdge","edge","undefined","insertSummary","summary","writeSqliteSnapshot","snapshot","destinationPath","runSqliteTransaction","SQLITE_V2_SCHEMA_DDL","SQLITE_V2_VERSION_INSERT","validateSqliteV2Schema"],"mappings":";;AAeA,SAASA,eAAeC,QAAwB,EAAEC,OAAoC;IACrF,MAAMC,SAASF,SAAS,OAAO,CAAC;IAChC,KAAK,MAAMG,UAAUF,QACpB,KAAK,MAAMG,WAAWD,OAAO,QAAQ,CAAED,OAAO,GAAG,CAACC,OAAO,SAAS,EAAEE,KAAK,SAAS,CAACD;AAErF;AAEA,SAASE,eAAeN,QAAwB,EAAEC,OAAkC;IACnF,MAAMC,SAASF,SAAS,OAAO,CAC9B;IAED,KAAK,MAAMG,UAAUF,QACpBC,OAAO,GAAG,CAACC,OAAO,SAAS,EAAEA,OAAO,QAAQ,EAAEE,KAAK,SAAS,CAACF,OAAO,QAAQ;AAE9E;AAEA,SAASI,WAAWP,QAAwB,EAAEQ,IAAU;IACvDR,SACE,OAAO,CACP,+GAEA,GAAG,CACHQ,KAAK,EAAE,EACPA,KAAK,SAAS,EACdA,KAAK,IAAI,EACTA,KAAK,EAAE,EACPA,KAAK,IAAI,EACTA,KAAK,SAAS,EACdA,AAAkBC,WAAlBD,KAAK,QAAQ,GAAiB,OAAOH,KAAK,SAAS,CAACG,KAAK,QAAQ;AAEpE;AAEA,SAASE,cAAcV,QAAwB,EAAEW,OAAgB;IAChEX,SACE,OAAO,CACP,oNAEA,GAAG,CACHW,QAAQ,EAAE,EACVA,QAAQ,SAAS,EACjBA,QAAQ,QAAQ,IAAI,MACpBA,QAAQ,aAAa,EACrBN,KAAK,SAAS,CAACM,QAAQ,UAAU,GACjCA,QAAQ,YAAY,CAAC,EAAE,EACvBA,QAAQ,YAAY,CAAC,EAAE,EACvBN,KAAK,SAAS,CAACM,QAAQ,MAAM,GAC7BA,QAAQ,mBAAmB,EAC3BA,QAAQ,SAAS,EACjBA,AAAiBF,WAAjBE,QAAQ,IAAI,GAAiB,OAAON,KAAK,SAAS,CAACM,QAAQ,IAAI;AAElE;AAeO,SAASC,oBACfZ,QAAwB,EACxBa,QAAwB,EACxBC,eAAuB;IAEvBC,qBAAqBf,UAAU;QAC9BA,SAAS,IAAI,CAACgB;QACdjB,eAAeC,UAAUa,SAAS,QAAQ;QAC1CP,eAAeN,UAAUa,SAAS,QAAQ;QAC1C,KAAK,MAAMV,UAAUU,SAAS,KAAK,CAClC,KAAK,MAAML,QAAQL,OAAO,KAAK,CAAEI,WAAWP,UAAUQ;QACvD,KAAK,MAAML,UAAUU,SAAS,SAAS,CACtC,KAAK,MAAMF,WAAWR,OAAO,SAAS,CAAEO,cAAcV,UAAUW;QAEjEX,SAAS,IAAI,CAACiB;QACdC,uBAAuBlB,UAAUc;IAClC;AACD"}
|