@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,15 @@
|
|
|
1
|
+
import type { FileSnapshotV2 } from './FileSnapshotTypes.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates semantic invariants that are stricter than the File v2 shape schema.
|
|
4
|
+
*
|
|
5
|
+
* @param snapshot - Parsed or canonical File v2 snapshot.
|
|
6
|
+
* @param sourcePath - Source path included in compatibility errors.
|
|
7
|
+
* @returns Nothing when all snapshot invariants hold.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* validateFileSnapshotV2(snapshot, '/data/snapshot.json');
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function validateFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): void;
|
|
15
|
+
//# sourceMappingURL=FileSnapshotValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSnapshotValidation.d.ts","sourceRoot":"","sources":["../../src/persistence/FileSnapshotValidation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AA+D7D;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAgDzF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PersistenceCompatibilityError } from "../errors.js";
|
|
2
|
+
import { assertBranchScope, assertPersistableThoughtCollections, assertThoughtScope, compareCodePoint, compareCreatedThenId } from "./PersistenceScope.js";
|
|
3
|
+
function assertUniqueOrderedRecords(records, sourcePath, label) {
|
|
4
|
+
for(let index = 0; index < records.length; index++){
|
|
5
|
+
const current = records[index];
|
|
6
|
+
const previous = records[index - 1];
|
|
7
|
+
if (void 0 !== current && void 0 !== previous && compareCodePoint(previous.sessionId, current.sessionId) >= 0) throw new PersistenceCompatibilityError(sourcePath, `${label} records are duplicate or out of order`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function assertUniqueIds(values, sourcePath, label) {
|
|
11
|
+
const identifiers = new Set();
|
|
12
|
+
for (const value of values){
|
|
13
|
+
if (identifiers.has(value.id)) throw new PersistenceCompatibilityError(sourcePath, `duplicate ${label} id '${value.id}'`);
|
|
14
|
+
identifiers.add(value.id);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function assertSorted(values, sourcePath, label) {
|
|
18
|
+
for(let index = 1; index < values.length; index++){
|
|
19
|
+
const previous = values[index - 1];
|
|
20
|
+
const current = values[index];
|
|
21
|
+
if (void 0 !== previous && void 0 !== current && compareCreatedThenId(previous, current) > 0) throw new PersistenceCompatibilityError(sourcePath, `${label} records are out of order`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function validateFileSnapshotV2(snapshot, sourcePath) {
|
|
25
|
+
assertUniqueOrderedRecords(snapshot.thoughts, sourcePath, 'thought');
|
|
26
|
+
assertUniqueOrderedRecords(snapshot.edges, sourcePath, 'edge');
|
|
27
|
+
assertUniqueOrderedRecords(snapshot.summaries, sourcePath, 'summary');
|
|
28
|
+
const thoughtCollections = [];
|
|
29
|
+
for (const record of snapshot.thoughts){
|
|
30
|
+
if (0 === record.thoughts.length) throw new PersistenceCompatibilityError(sourcePath, 'empty thought record');
|
|
31
|
+
for (const thought of record.thoughts)assertThoughtScope('saveThoughtForSession', record.sessionId, thought);
|
|
32
|
+
thoughtCollections.push({
|
|
33
|
+
sessionId: record.sessionId,
|
|
34
|
+
thoughts: record.thoughts
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
let previousBranchKey;
|
|
38
|
+
for (const record of snapshot.branches){
|
|
39
|
+
const branchKey = `${record.sessionId}\u0000${record.branchId}`;
|
|
40
|
+
if (void 0 !== previousBranchKey && compareCodePoint(previousBranchKey, branchKey) >= 0) throw new PersistenceCompatibilityError(sourcePath, 'branch records are duplicate or out of order');
|
|
41
|
+
previousBranchKey = branchKey;
|
|
42
|
+
assertBranchScope('saveBranchForSession', record.sessionId, record.branchId, record.thoughts);
|
|
43
|
+
thoughtCollections.push({
|
|
44
|
+
sessionId: record.sessionId,
|
|
45
|
+
thoughts: record.thoughts
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
assertPersistableThoughtCollections(thoughtCollections, sourcePath);
|
|
49
|
+
for (const record of snapshot.edges){
|
|
50
|
+
if (0 === record.edges.length) throw new PersistenceCompatibilityError(sourcePath, 'empty edge record');
|
|
51
|
+
assertUniqueIds(record.edges, sourcePath, 'edge');
|
|
52
|
+
if (record.edges.some((edge)=>edge.sessionId !== record.sessionId)) throw new PersistenceCompatibilityError(sourcePath, 'edge session does not match its record');
|
|
53
|
+
assertSorted(record.edges, sourcePath, 'edge');
|
|
54
|
+
}
|
|
55
|
+
for (const record of snapshot.summaries){
|
|
56
|
+
if (0 === record.summaries.length) throw new PersistenceCompatibilityError(sourcePath, 'empty summary record');
|
|
57
|
+
assertUniqueIds(record.summaries, sourcePath, 'summary');
|
|
58
|
+
if (record.summaries.some((summary)=>summary.sessionId !== record.sessionId)) throw new PersistenceCompatibilityError(sourcePath, 'summary session does not match its record');
|
|
59
|
+
assertSorted(record.summaries, sourcePath, 'summary');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export { validateFileSnapshotV2 };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=FileSnapshotValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence/FileSnapshotValidation.js","sources":["../../src/persistence/FileSnapshotValidation.ts"],"sourcesContent":["import type { SessionId } from '../contracts/ids.js';\nimport { PersistenceCompatibilityError } from '../errors.js';\nimport type { FileSnapshotV2 } from './FileSnapshotTypes.js';\nimport {\n\tassertBranchScope,\n\tassertPersistableThoughtCollections,\n\tassertThoughtScope,\n\tcompareCodePoint,\n\tcompareCreatedThenId,\n\ttype PersistedThoughtCollection,\n} from './PersistenceScope.js';\n\nfunction assertUniqueOrderedRecords(\n\trecords: readonly { readonly sessionId: SessionId }[],\n\tsourcePath: string,\n\tlabel: string\n): void {\n\tfor (let index = 0; index < records.length; index++) {\n\t\tconst current = records[index];\n\t\tconst previous = records[index - 1];\n\t\tif (\n\t\t\tcurrent !== undefined &&\n\t\t\tprevious !== undefined &&\n\t\t\tcompareCodePoint(previous.sessionId, current.sessionId) >= 0\n\t\t) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tsourcePath,\n\t\t\t\t`${label} records are duplicate or out of order`\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction assertUniqueIds(\n\tvalues: readonly { readonly id: string }[],\n\tsourcePath: string,\n\tlabel: string\n): void {\n\tconst identifiers = new Set<string>();\n\tfor (const value of values) {\n\t\tif (identifiers.has(value.id)) {\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, `duplicate ${label} id '${value.id}'`);\n\t\t}\n\t\tidentifiers.add(value.id);\n\t}\n}\n\nfunction assertSorted(\n\tvalues: readonly { readonly createdAt: number; readonly id: string }[],\n\tsourcePath: string,\n\tlabel: string\n): void {\n\tfor (let index = 1; index < values.length; index++) {\n\t\tconst previous = values[index - 1];\n\t\tconst current = values[index];\n\t\tif (\n\t\t\tprevious !== undefined &&\n\t\t\tcurrent !== undefined &&\n\t\t\tcompareCreatedThenId(previous, current) > 0\n\t\t) {\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, `${label} records are out of order`);\n\t\t}\n\t}\n}\n\n/**\n * Validates semantic invariants that are stricter than the File v2 shape schema.\n *\n * @param snapshot - Parsed or canonical File v2 snapshot.\n * @param sourcePath - Source path included in compatibility errors.\n * @returns Nothing when all snapshot invariants hold.\n *\n * @example\n * ```ts\n * validateFileSnapshotV2(snapshot, '/data/snapshot.json');\n * ```\n */\nexport function validateFileSnapshotV2(snapshot: FileSnapshotV2, sourcePath: string): void {\n\tassertUniqueOrderedRecords(snapshot.thoughts, sourcePath, 'thought');\n\tassertUniqueOrderedRecords(snapshot.edges, sourcePath, 'edge');\n\tassertUniqueOrderedRecords(snapshot.summaries, sourcePath, 'summary');\n\tconst thoughtCollections: PersistedThoughtCollection[] = [];\n\tfor (const record of snapshot.thoughts) {\n\t\tif (record.thoughts.length === 0)\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, 'empty thought record');\n\t\tfor (const thought of record.thoughts) {\n\t\t\tassertThoughtScope('saveThoughtForSession', record.sessionId, thought);\n\t\t}\n\t\tthoughtCollections.push({ sessionId: record.sessionId, thoughts: record.thoughts });\n\t}\n\tlet previousBranchKey: string | undefined;\n\tfor (const record of snapshot.branches) {\n\t\tconst branchKey = `${record.sessionId}\\u0000${record.branchId}`;\n\t\tif (previousBranchKey !== undefined && compareCodePoint(previousBranchKey, branchKey) >= 0) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tsourcePath,\n\t\t\t\t'branch records are duplicate or out of order'\n\t\t\t);\n\t\t}\n\t\tpreviousBranchKey = branchKey;\n\t\tassertBranchScope('saveBranchForSession', record.sessionId, record.branchId, record.thoughts);\n\t\tthoughtCollections.push({ sessionId: record.sessionId, thoughts: record.thoughts });\n\t}\n\tassertPersistableThoughtCollections(thoughtCollections, sourcePath);\n\tfor (const record of snapshot.edges) {\n\t\tif (record.edges.length === 0)\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, 'empty edge record');\n\t\tassertUniqueIds(record.edges, sourcePath, 'edge');\n\t\tif (record.edges.some((edge) => edge.sessionId !== record.sessionId)) {\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, 'edge session does not match its record');\n\t\t}\n\t\tassertSorted(record.edges, sourcePath, 'edge');\n\t}\n\tfor (const record of snapshot.summaries) {\n\t\tif (record.summaries.length === 0)\n\t\t\tthrow new PersistenceCompatibilityError(sourcePath, 'empty summary record');\n\t\tassertUniqueIds(record.summaries, sourcePath, 'summary');\n\t\tif (record.summaries.some((summary) => summary.sessionId !== record.sessionId)) {\n\t\t\tthrow new PersistenceCompatibilityError(\n\t\t\t\tsourcePath,\n\t\t\t\t'summary session does not match its record'\n\t\t\t);\n\t\t}\n\t\tassertSorted(record.summaries, sourcePath, 'summary');\n\t}\n}\n"],"names":["assertUniqueOrderedRecords","records","sourcePath","label","index","current","previous","undefined","compareCodePoint","PersistenceCompatibilityError","assertUniqueIds","values","identifiers","Set","value","assertSorted","compareCreatedThenId","validateFileSnapshotV2","snapshot","thoughtCollections","record","thought","assertThoughtScope","previousBranchKey","branchKey","assertBranchScope","assertPersistableThoughtCollections","edge","summary"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface FileWriterOperations {
|
|
2
|
+
readonly mkdir: (path: string) => Promise<void>;
|
|
3
|
+
readonly mkdirExclusive: (path: string) => Promise<void>;
|
|
4
|
+
readonly realpath: (path: string) => Promise<string>;
|
|
5
|
+
readonly rename: (source: string, destination: string) => Promise<void>;
|
|
6
|
+
readonly rmdir: (path: string) => Promise<void>;
|
|
7
|
+
readonly unlink: (path: string) => Promise<void>;
|
|
8
|
+
readonly writeExclusiveUtf8: (path: string, content: string) => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export declare const nodeFileWriterOperations: FileWriterOperations;
|
|
11
|
+
export declare function isFileNotFound(error: unknown): boolean;
|
|
12
|
+
export declare class FileWriter {
|
|
13
|
+
private readonly _configuredDataDir;
|
|
14
|
+
private readonly _operations;
|
|
15
|
+
private _ownershipPromise;
|
|
16
|
+
private _ownership;
|
|
17
|
+
private _tail;
|
|
18
|
+
private _closePromise;
|
|
19
|
+
private _state;
|
|
20
|
+
constructor(dataDir: string, operations?: FileWriterOperations);
|
|
21
|
+
ready(): Promise<void>;
|
|
22
|
+
run<T>(operation: (canonicalDataDir: string) => Promise<T>): Promise<T>;
|
|
23
|
+
publish(targetPath: string, content: string): Promise<void>;
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
private _getOwnership;
|
|
26
|
+
private _acquireOwnership;
|
|
27
|
+
private _cleanupFailedAcquisition;
|
|
28
|
+
private _releaseOwnership;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=FileWriter.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { mkdir, realpath, rename, rmdir, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
import { PersistenceClosedError, PersistenceOwnershipError, PersistencePublicationError } from "../errors.js";
|
|
5
|
+
const WRITER_LOCK_NAME = '.tracelattice-writer.lock';
|
|
6
|
+
const nodeFileWriterOperations = {
|
|
7
|
+
mkdir: async (path)=>{
|
|
8
|
+
await mkdir(path, {
|
|
9
|
+
recursive: true
|
|
10
|
+
});
|
|
11
|
+
},
|
|
12
|
+
mkdirExclusive: async (path)=>await mkdir(path),
|
|
13
|
+
realpath: async (path)=>await realpath(path),
|
|
14
|
+
rename: async (source, destination)=>await rename(source, destination),
|
|
15
|
+
rmdir: async (path)=>await rmdir(path),
|
|
16
|
+
unlink: async (path)=>await unlink(path),
|
|
17
|
+
writeExclusiveUtf8: async (path, content)=>{
|
|
18
|
+
await writeFile(path, content, {
|
|
19
|
+
encoding: 'utf-8',
|
|
20
|
+
flag: 'wx'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function isFileNotFound(error) {
|
|
25
|
+
return error instanceof Error && 'code' in error && 'ENOENT' === error.code;
|
|
26
|
+
}
|
|
27
|
+
function isFileAlreadyPresent(error) {
|
|
28
|
+
return error instanceof Error && 'code' in error && 'EEXIST' === error.code;
|
|
29
|
+
}
|
|
30
|
+
function isDirectoryNotEmpty(error) {
|
|
31
|
+
return error instanceof Error && 'code' in error && 'ENOTEMPTY' === error.code;
|
|
32
|
+
}
|
|
33
|
+
class FileWriter {
|
|
34
|
+
_configuredDataDir;
|
|
35
|
+
_operations;
|
|
36
|
+
_ownershipPromise;
|
|
37
|
+
_ownership;
|
|
38
|
+
_tail = Promise.resolve();
|
|
39
|
+
_closePromise;
|
|
40
|
+
_state = 'open';
|
|
41
|
+
constructor(dataDir, operations = nodeFileWriterOperations){
|
|
42
|
+
this._configuredDataDir = dataDir;
|
|
43
|
+
this._operations = operations;
|
|
44
|
+
}
|
|
45
|
+
async ready() {
|
|
46
|
+
if ('open' !== this._state) throw new PersistenceClosedError(this._configuredDataDir);
|
|
47
|
+
await this._getOwnership();
|
|
48
|
+
}
|
|
49
|
+
run(operation) {
|
|
50
|
+
if ('open' !== this._state) return Promise.reject(new PersistenceClosedError(this._configuredDataDir));
|
|
51
|
+
const queued = this._tail.then(async ()=>{
|
|
52
|
+
const ownership = await this._getOwnership();
|
|
53
|
+
return await operation(ownership.canonicalDataDir);
|
|
54
|
+
});
|
|
55
|
+
this._tail = queued.then(()=>void 0, ()=>void 0);
|
|
56
|
+
return queued;
|
|
57
|
+
}
|
|
58
|
+
async publish(targetPath, content) {
|
|
59
|
+
const temporaryPath = join(dirname(targetPath), `.${basename(targetPath)}.${process.pid}.${randomUUID()}.tmp`);
|
|
60
|
+
let stage = 'temporary-write';
|
|
61
|
+
try {
|
|
62
|
+
await this._operations.writeExclusiveUtf8(temporaryPath, content);
|
|
63
|
+
stage = 'atomic-replacement';
|
|
64
|
+
await this._operations.rename(temporaryPath, targetPath);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const publicationError = new PersistencePublicationError(targetPath, stage, error);
|
|
67
|
+
try {
|
|
68
|
+
await this._operations.unlink(temporaryPath);
|
|
69
|
+
} catch (cleanupError) {
|
|
70
|
+
if (!isFileNotFound(cleanupError)) throw new PersistencePublicationError(targetPath, 'cleanup', new AggregateError([
|
|
71
|
+
publicationError,
|
|
72
|
+
cleanupError
|
|
73
|
+
]));
|
|
74
|
+
}
|
|
75
|
+
throw publicationError;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
close() {
|
|
79
|
+
if (this._closePromise) return this._closePromise;
|
|
80
|
+
this._state = 'closing';
|
|
81
|
+
this._closePromise = (async ()=>{
|
|
82
|
+
try {
|
|
83
|
+
await this._tail;
|
|
84
|
+
await this._releaseOwnership();
|
|
85
|
+
} finally{
|
|
86
|
+
this._state = 'closed';
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
return this._closePromise;
|
|
90
|
+
}
|
|
91
|
+
_getOwnership() {
|
|
92
|
+
this._ownershipPromise ??= this._acquireOwnership();
|
|
93
|
+
return this._ownershipPromise;
|
|
94
|
+
}
|
|
95
|
+
async _acquireOwnership() {
|
|
96
|
+
await this._operations.mkdir(this._configuredDataDir);
|
|
97
|
+
const canonicalDataDir = await this._operations.realpath(this._configuredDataDir);
|
|
98
|
+
const lockPath = join(canonicalDataDir, WRITER_LOCK_NAME);
|
|
99
|
+
const markerName = `${process.pid}-${randomUUID()}.owner`;
|
|
100
|
+
const markerPath = join(lockPath, markerName);
|
|
101
|
+
try {
|
|
102
|
+
await this._operations.mkdirExclusive(lockPath);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (isFileAlreadyPresent(error)) throw new PersistenceOwnershipError(canonicalDataDir, lockPath, error);
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
await this._operations.writeExclusiveUtf8(markerPath, `${process.pid}\n`);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
await this._cleanupFailedAcquisition(lockPath, markerPath, error);
|
|
111
|
+
}
|
|
112
|
+
const ownership = {
|
|
113
|
+
canonicalDataDir,
|
|
114
|
+
lockPath,
|
|
115
|
+
markerPath
|
|
116
|
+
};
|
|
117
|
+
this._ownership = ownership;
|
|
118
|
+
return ownership;
|
|
119
|
+
}
|
|
120
|
+
async _cleanupFailedAcquisition(lockPath, markerPath, acquisitionError) {
|
|
121
|
+
const failures = [
|
|
122
|
+
acquisitionError
|
|
123
|
+
];
|
|
124
|
+
try {
|
|
125
|
+
await this._operations.unlink(markerPath);
|
|
126
|
+
} catch (unlinkError) {
|
|
127
|
+
if (!isFileNotFound(unlinkError)) failures.push(unlinkError);
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
await this._operations.rmdir(lockPath);
|
|
131
|
+
} catch (removeDirectoryError) {
|
|
132
|
+
if (!isFileNotFound(removeDirectoryError) && !isDirectoryNotEmpty(removeDirectoryError)) failures.push(removeDirectoryError);
|
|
133
|
+
}
|
|
134
|
+
throw new PersistencePublicationError(lockPath, 'cleanup', new AggregateError(failures));
|
|
135
|
+
}
|
|
136
|
+
async _releaseOwnership() {
|
|
137
|
+
const ownership = this._ownership;
|
|
138
|
+
this._ownership = void 0;
|
|
139
|
+
if (!ownership) return;
|
|
140
|
+
try {
|
|
141
|
+
await this._operations.unlink(ownership.markerPath);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (isFileNotFound(error)) return;
|
|
144
|
+
throw new PersistencePublicationError(ownership.markerPath, 'cleanup', error);
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
await this._operations.rmdir(ownership.lockPath);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (!isFileNotFound(error) && !isDirectoryNotEmpty(error)) throw new PersistencePublicationError(ownership.lockPath, 'cleanup', error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export { FileWriter, isFileNotFound, nodeFileWriterOperations };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=FileWriter.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ThoughtData } from '../core/thought.js';
|
|
2
|
+
import type { Edge } from '../core/graph/Edge.js';
|
|
3
|
+
import type { Summary } from '../core/compression/Summary.js';
|
|
4
|
+
import type { SessionScopedPersistenceBackend } from '../contracts/PersistenceBackend.js';
|
|
5
|
+
import { type BranchId, type SessionId } from '../contracts/ids.js';
|
|
6
|
+
export interface MemoryPersistenceOptions {
|
|
7
|
+
maxSize?: number;
|
|
8
|
+
maxHistorySize?: number;
|
|
9
|
+
persistBranches?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class MemoryPersistence implements SessionScopedPersistenceBackend {
|
|
12
|
+
private readonly _histories;
|
|
13
|
+
private readonly _branches;
|
|
14
|
+
private readonly _edges;
|
|
15
|
+
private readonly _summaries;
|
|
16
|
+
private readonly _maxSize;
|
|
17
|
+
private readonly _persistBranches;
|
|
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[]>;
|
|
22
|
+
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>;
|
|
26
|
+
deleteBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<void>;
|
|
27
|
+
loadBranch(branchId: BranchId): Promise<ThoughtData[] | undefined>;
|
|
28
|
+
loadBranchForSession(sessionId: SessionId, branchId: BranchId): Promise<ThoughtData[] | undefined>;
|
|
29
|
+
listBranches(): Promise<BranchId[]>;
|
|
30
|
+
listBranchesForSession(sessionId: SessionId): Promise<BranchId[]>;
|
|
31
|
+
listSessions(): Promise<SessionId[]>;
|
|
32
|
+
healthy(): Promise<boolean>;
|
|
33
|
+
clear(): Promise<void>;
|
|
34
|
+
clearSession(sessionId: SessionId): Promise<void>;
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
saveEdges(sessionId: SessionId, edges: readonly Edge[]): Promise<void>;
|
|
37
|
+
loadEdges(sessionId: SessionId): Promise<Edge[]>;
|
|
38
|
+
listEdgeSessions(): Promise<SessionId[]>;
|
|
39
|
+
saveSummaries(sessionId: SessionId, summaries: readonly Summary[]): Promise<void>;
|
|
40
|
+
loadSummaries(sessionId: SessionId): Promise<Summary[]>;
|
|
41
|
+
getHistorySize(): number;
|
|
42
|
+
getBranchCount(): number;
|
|
43
|
+
getBranchIds(): BranchId[];
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=MemoryPersistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MemoryPersistence.d.ts","sourceRoot":"","sources":["../../src/persistence/MemoryPersistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { GLOBAL_SESSION_ID, asSessionId } from "../contracts/ids.js";
|
|
2
|
+
import { assertBranchScope, assertEdgeScopes, assertPersistableThoughtCollections, assertSummaryScopes, assertThoughtScope, assertUniqueRecordIds, compareCodePoint, compareCreatedThenId, parsePersistenceBranchId } from "./PersistenceScope.js";
|
|
3
|
+
class MemoryPersistence {
|
|
4
|
+
_histories = new Map();
|
|
5
|
+
_branches = new Map();
|
|
6
|
+
_edges = new Map();
|
|
7
|
+
_summaries = new Map();
|
|
8
|
+
_maxSize;
|
|
9
|
+
_persistBranches;
|
|
10
|
+
constructor(options = {}){
|
|
11
|
+
const configuredSize = options.maxHistorySize ?? options.maxSize;
|
|
12
|
+
this._maxSize = void 0 !== configuredSize && configuredSize > 0 ? configuredSize : void 0;
|
|
13
|
+
this._persistBranches = options.persistBranches ?? true;
|
|
14
|
+
}
|
|
15
|
+
async saveThought(thought) {
|
|
16
|
+
await this.saveThoughtForSession(GLOBAL_SESSION_ID, thought, 'saveThought');
|
|
17
|
+
}
|
|
18
|
+
async saveThoughtForSession(sessionId, thought, operation = 'saveThoughtForSession') {
|
|
19
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
20
|
+
assertThoughtScope(operation, validatedSessionId, thought);
|
|
21
|
+
const history = [
|
|
22
|
+
...this._histories.get(validatedSessionId) ?? [],
|
|
23
|
+
thought
|
|
24
|
+
];
|
|
25
|
+
const collections = [
|
|
26
|
+
{
|
|
27
|
+
sessionId: validatedSessionId,
|
|
28
|
+
thoughts: history
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
for (const branch of this._branches.get(validatedSessionId)?.values() ?? [])collections.push({
|
|
32
|
+
sessionId: validatedSessionId,
|
|
33
|
+
thoughts: branch
|
|
34
|
+
});
|
|
35
|
+
assertPersistableThoughtCollections(collections, `${validatedSessionId}/thoughts`);
|
|
36
|
+
this._histories.set(validatedSessionId, void 0 === this._maxSize ? history : history.slice(-this._maxSize));
|
|
37
|
+
}
|
|
38
|
+
async loadHistory() {
|
|
39
|
+
return await this.loadHistoryForSession(GLOBAL_SESSION_ID);
|
|
40
|
+
}
|
|
41
|
+
async loadHistoryForSession(sessionId) {
|
|
42
|
+
return [
|
|
43
|
+
...this._histories.get(asSessionId(sessionId)) ?? []
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
async saveBranch(branchId, thoughts) {
|
|
47
|
+
await this.saveBranchForSession(GLOBAL_SESSION_ID, branchId, thoughts, 'saveBranch');
|
|
48
|
+
}
|
|
49
|
+
async saveBranchForSession(sessionId, branchId, thoughts, operation = 'saveBranchForSession') {
|
|
50
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
51
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);
|
|
52
|
+
assertBranchScope(operation, validatedSessionId, validatedBranchId, thoughts);
|
|
53
|
+
const branches = new Map(this._branches.get(validatedSessionId) ?? []);
|
|
54
|
+
branches.set(validatedBranchId, [
|
|
55
|
+
...thoughts
|
|
56
|
+
]);
|
|
57
|
+
const collections = [
|
|
58
|
+
{
|
|
59
|
+
sessionId: validatedSessionId,
|
|
60
|
+
thoughts: this._histories.get(validatedSessionId) ?? []
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
for (const branch of branches.values())collections.push({
|
|
64
|
+
sessionId: validatedSessionId,
|
|
65
|
+
thoughts: branch
|
|
66
|
+
});
|
|
67
|
+
assertPersistableThoughtCollections(collections, `${validatedSessionId}/branches/${validatedBranchId}`);
|
|
68
|
+
if (!this._persistBranches) return;
|
|
69
|
+
this._branches.set(validatedSessionId, branches);
|
|
70
|
+
}
|
|
71
|
+
async deleteBranch(branchId) {
|
|
72
|
+
await this.deleteBranchForSession(GLOBAL_SESSION_ID, branchId);
|
|
73
|
+
}
|
|
74
|
+
async deleteBranchForSession(sessionId, branchId) {
|
|
75
|
+
if (!this._persistBranches) return;
|
|
76
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
77
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);
|
|
78
|
+
const branches = this._branches.get(validatedSessionId);
|
|
79
|
+
if (void 0 === branches) return;
|
|
80
|
+
branches.delete(validatedBranchId);
|
|
81
|
+
if (0 === branches.size) this._branches.delete(validatedSessionId);
|
|
82
|
+
}
|
|
83
|
+
async loadBranch(branchId) {
|
|
84
|
+
return await this.loadBranchForSession(GLOBAL_SESSION_ID, branchId);
|
|
85
|
+
}
|
|
86
|
+
async loadBranchForSession(sessionId, branchId) {
|
|
87
|
+
if (!this._persistBranches) return;
|
|
88
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
89
|
+
const validatedBranchId = parsePersistenceBranchId(branchId, `${validatedSessionId}/branches`);
|
|
90
|
+
const branch = this._branches.get(validatedSessionId)?.get(validatedBranchId);
|
|
91
|
+
return void 0 === branch ? void 0 : [
|
|
92
|
+
...branch
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
async listBranches() {
|
|
96
|
+
return await this.listBranchesForSession(GLOBAL_SESSION_ID);
|
|
97
|
+
}
|
|
98
|
+
async listBranchesForSession(sessionId) {
|
|
99
|
+
if (!this._persistBranches) return [];
|
|
100
|
+
return [
|
|
101
|
+
...this._branches.get(asSessionId(sessionId))?.keys() ?? []
|
|
102
|
+
].sort(compareCodePoint);
|
|
103
|
+
}
|
|
104
|
+
async listSessions() {
|
|
105
|
+
const sessions = new Set();
|
|
106
|
+
for (const namespace of [
|
|
107
|
+
this._histories,
|
|
108
|
+
this._branches,
|
|
109
|
+
this._edges,
|
|
110
|
+
this._summaries
|
|
111
|
+
])for (const sessionId of namespace.keys())sessions.add(sessionId);
|
|
112
|
+
return [
|
|
113
|
+
...sessions
|
|
114
|
+
].sort(compareCodePoint);
|
|
115
|
+
}
|
|
116
|
+
async healthy() {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
async clear() {
|
|
120
|
+
this._histories.clear();
|
|
121
|
+
this._branches.clear();
|
|
122
|
+
this._edges.clear();
|
|
123
|
+
this._summaries.clear();
|
|
124
|
+
}
|
|
125
|
+
async clearSession(sessionId) {
|
|
126
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
127
|
+
this._histories.delete(validatedSessionId);
|
|
128
|
+
this._branches.delete(validatedSessionId);
|
|
129
|
+
this._edges.delete(validatedSessionId);
|
|
130
|
+
this._summaries.delete(validatedSessionId);
|
|
131
|
+
}
|
|
132
|
+
async close() {}
|
|
133
|
+
async saveEdges(sessionId, edges) {
|
|
134
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
135
|
+
assertEdgeScopes(validatedSessionId, edges);
|
|
136
|
+
assertUniqueRecordIds(edges, `${validatedSessionId}/edges`, 'edge');
|
|
137
|
+
if (0 === edges.length) this._edges.delete(validatedSessionId);
|
|
138
|
+
else this._edges.set(validatedSessionId, [
|
|
139
|
+
...edges
|
|
140
|
+
].sort(compareCreatedThenId));
|
|
141
|
+
}
|
|
142
|
+
async loadEdges(sessionId) {
|
|
143
|
+
return [
|
|
144
|
+
...this._edges.get(asSessionId(sessionId)) ?? []
|
|
145
|
+
].sort(compareCreatedThenId);
|
|
146
|
+
}
|
|
147
|
+
async listEdgeSessions() {
|
|
148
|
+
return [
|
|
149
|
+
...this._edges.keys()
|
|
150
|
+
].sort(compareCodePoint);
|
|
151
|
+
}
|
|
152
|
+
async saveSummaries(sessionId, summaries) {
|
|
153
|
+
const validatedSessionId = asSessionId(sessionId);
|
|
154
|
+
assertSummaryScopes(validatedSessionId, summaries);
|
|
155
|
+
assertUniqueRecordIds(summaries, `${validatedSessionId}/summaries`, 'summary');
|
|
156
|
+
if (0 === summaries.length) this._summaries.delete(validatedSessionId);
|
|
157
|
+
else this._summaries.set(validatedSessionId, [
|
|
158
|
+
...summaries
|
|
159
|
+
].sort(compareCreatedThenId));
|
|
160
|
+
}
|
|
161
|
+
async loadSummaries(sessionId) {
|
|
162
|
+
return [
|
|
163
|
+
...this._summaries.get(asSessionId(sessionId)) ?? []
|
|
164
|
+
].sort(compareCreatedThenId);
|
|
165
|
+
}
|
|
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
|
+
}
|
|
178
|
+
export { MemoryPersistence };
|
|
179
|
+
|
|
180
|
+
//# sourceMappingURL=MemoryPersistence.js.map
|
|
@@ -0,0 +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":";;AAwBO,MAAMA;IACK,aAAa,IAAIC,MAAgC;IACjD,YAAY,IAAIA,MAA+C;IAC/D,SAAS,IAAIA,MAAyB;IACtC,aAAa,IAAIA,MAA4B;IAC7C,SAA6B;IAC7B,iBAA0B;IAE3C,YAAYC,UAAoC,CAAC,CAAC,CAAE;QACnD,MAAMC,iBAAiBD,QAAQ,cAAc,IAAIA,QAAQ,OAAO;QAChE,IAAI,CAAC,QAAQ,GAAGC,AAAmBC,WAAnBD,kBAAgCA,iBAAiB,IAAIA,iBAAiBC;QACtF,IAAI,CAAC,gBAAgB,GAAGF,QAAQ,eAAe,IAAI;IACpD;IAEA,MAAa,YAAYG,OAAoB,EAAiB;QAC7D,MAAM,IAAI,CAAC,qBAAqB,CAACC,mBAAmBD,SAAS;IAC9D;IAEA,MAAa,sBACZE,SAAoB,EACpBF,OAAoB,EACpBG,YAAqD,uBAAuB,EAC5D;QAChB,MAAMC,qBAAqBC,YAAYH;QACvCI,mBAAmBH,WAAWC,oBAAoBJ;QAClD,MAAMO,UAAU;eAAK,IAAI,CAAC,UAAU,CAAC,GAAG,CAACH,uBAAuB,EAAE;YAAGJ;SAAQ;QAC7E,MAAMQ,cAA4C;YACjD;gBAAE,WAAWJ;gBAAoB,UAAUG;YAAQ;SACnD;QACD,KAAK,MAAME,UAAU,IAAI,CAAC,SAAS,CAAC,GAAG,CAACL,qBAAqB,YAAY,EAAE,CAC1EI,YAAY,IAAI,CAAC;YAAE,WAAWJ;YAAoB,UAAUK;QAAO;QAEpEC,oCAAoCF,aAAa,GAAGJ,mBAAmB,SAAS,CAAC;QACjF,IAAI,CAAC,UAAU,CAAC,GAAG,CAClBA,oBACA,AAAkBL,WAAlB,IAAI,CAAC,QAAQ,GAAiBQ,UAAUA,QAAQ,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ;IAEtE;IAEA,MAAa,cAAsC;QAClD,OAAO,MAAM,IAAI,CAAC,qBAAqB,CAACN;IACzC;IAEA,MAAa,sBAAsBC,SAAoB,EAA0B;QAChF,OAAO;eAAK,IAAI,CAAC,UAAU,CAAC,GAAG,CAACG,YAAYH,eAAe,EAAE;SAAE;IAChE;IAEA,MAAa,WAAWS,QAAkB,EAAEC,QAAuB,EAAiB;QACnF,MAAM,IAAI,CAAC,oBAAoB,CAACX,mBAAmBU,UAAUC,UAAU;IACxE;IAEA,MAAa,qBACZV,SAAoB,EACpBS,QAAkB,EAClBC,QAAgC,EAChCT,YAAmD,sBAAsB,EACzD;QAChB,MAAMC,qBAAqBC,YAAYH;QACvC,MAAMW,oBAAoBC,yBAAyBH,UAAU,GAAGP,mBAAmB,SAAS,CAAC;QAC7FW,kBAAkBZ,WAAWC,oBAAoBS,mBAAmBD;QACpE,MAAMI,WAAW,IAAIpB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAACQ,uBAAuB,EAAE;QACrEY,SAAS,GAAG,CAACH,mBAAmB;eAAID;SAAS;QAC7C,MAAMJ,cAA4C;YACjD;gBACC,WAAWJ;gBACX,UAAU,IAAI,CAAC,UAAU,CAAC,GAAG,CAACA,uBAAuB,EAAE;YACxD;SACA;QACD,KAAK,MAAMK,UAAUO,SAAS,MAAM,GACnCR,YAAY,IAAI,CAAC;YAAE,WAAWJ;YAAoB,UAAUK;QAAO;QAEpEC,oCACCF,aACA,GAAGJ,mBAAmB,UAAU,EAAES,mBAAmB;QAEtD,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAACT,oBAAoBY;IACxC;IAEA,MAAa,aAAaL,QAAkB,EAAiB;QAC5D,MAAM,IAAI,CAAC,sBAAsB,CAACV,mBAAmBU;IACtD;IAEA,MAAa,uBAAuBT,SAAoB,EAAES,QAAkB,EAAiB;QAC5F,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;QAC5B,MAAMP,qBAAqBC,YAAYH;QACvC,MAAMW,oBAAoBC,yBAAyBH,UAAU,GAAGP,mBAAmB,SAAS,CAAC;QAC7F,MAAMY,WAAW,IAAI,CAAC,SAAS,CAAC,GAAG,CAACZ;QACpC,IAAIY,AAAajB,WAAbiB,UAAwB;QAC5BA,SAAS,MAAM,CAACH;QAChB,IAAIG,AAAkB,MAAlBA,SAAS,IAAI,EAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,CAACZ;IAChD;IAEA,MAAa,WAAWO,QAAkB,EAAsC;QAC/E,OAAO,MAAM,IAAI,CAAC,oBAAoB,CAACV,mBAAmBU;IAC3D;IAEA,MAAa,qBACZT,SAAoB,EACpBS,QAAkB,EACmB;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;QAC5B,MAAMP,qBAAqBC,YAAYH;QACvC,MAAMW,oBAAoBC,yBAAyBH,UAAU,GAAGP,mBAAmB,SAAS,CAAC;QAC7F,MAAMK,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAACL,qBAAqB,IAAIS;QAC3D,OAAOJ,AAAWV,WAAXU,SAAuBV,SAAY;eAAIU;SAAO;IACtD;IAEA,MAAa,eAAoC;QAChD,OAAO,MAAM,IAAI,CAAC,sBAAsB,CAACR;IAC1C;IAEA,MAAa,uBAAuBC,SAAoB,EAAuB;QAC9E,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,EAAE;QACrC,OAAO;eAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAACG,YAAYH,aAAa,UAAU,EAAE;SAAE,CAAC,IAAI,CAACe;IAC7E;IAEA,MAAa,eAAqC;QACjD,MAAMC,WAAW,IAAIC;QACrB,KAAK,MAAMC,aAAa;YAAC,IAAI,CAAC,UAAU;YAAE,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,UAAU;SAAC,CACtF,KAAK,MAAMlB,aAAakB,UAAU,IAAI,GAAIF,SAAS,GAAG,CAAChB;QAExD,OAAO;eAAIgB;SAAS,CAAC,IAAI,CAACD;IAC3B;IAEA,MAAa,UAA4B;QACxC,OAAO;IACR;IAEA,MAAa,QAAuB;QACnC,IAAI,CAAC,UAAU,CAAC,KAAK;QACrB,IAAI,CAAC,SAAS,CAAC,KAAK;QACpB,IAAI,CAAC,MAAM,CAAC,KAAK;QACjB,IAAI,CAAC,UAAU,CAAC,KAAK;IACtB;IAEA,MAAa,aAAaf,SAAoB,EAAiB;QAC9D,MAAME,qBAAqBC,YAAYH;QACvC,IAAI,CAAC,UAAU,CAAC,MAAM,CAACE;QACvB,IAAI,CAAC,SAAS,CAAC,MAAM,CAACA;QACtB,IAAI,CAAC,MAAM,CAAC,MAAM,CAACA;QACnB,IAAI,CAAC,UAAU,CAAC,MAAM,CAACA;IACxB;IAEA,MAAa,QAAuB,CAAC;IAErC,MAAa,UAAUF,SAAoB,EAAEmB,KAAsB,EAAiB;QACnF,MAAMjB,qBAAqBC,YAAYH;QACvCoB,iBAAiBlB,oBAAoBiB;QACrCE,sBAAsBF,OAAO,GAAGjB,mBAAmB,MAAM,CAAC,EAAE;QAC5D,IAAIiB,AAAiB,MAAjBA,MAAM,MAAM,EAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAACjB;aACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAACA,oBAAoB;eAAIiB;SAAM,CAAC,IAAI,CAACG;IAC1D;IAEA,MAAa,UAAUtB,SAAoB,EAAmB;QAC7D,OAAO;eAAK,IAAI,CAAC,MAAM,CAAC,GAAG,CAACG,YAAYH,eAAe,EAAE;SAAE,CAAC,IAAI,CAACsB;IAClE;IAEA,MAAa,mBAAyC;QACrD,OAAO;eAAI,IAAI,CAAC,MAAM,CAAC,IAAI;SAAG,CAAC,IAAI,CAACP;IACrC;IAEA,MAAa,cAAcf,SAAoB,EAAEuB,SAA6B,EAAiB;QAC9F,MAAMrB,qBAAqBC,YAAYH;QACvCwB,oBAAoBtB,oBAAoBqB;QACxCF,sBAAsBE,WAAW,GAAGrB,mBAAmB,UAAU,CAAC,EAAE;QACpE,IAAIqB,AAAqB,MAArBA,UAAU,MAAM,EAAQ,IAAI,CAAC,UAAU,CAAC,MAAM,CAACrB;aAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAACA,oBAAoB;eAAIqB;SAAU,CAAC,IAAI,CAACD;IAClE;IAEA,MAAa,cAActB,SAAoB,EAAsB;QACpE,OAAO;eAAK,IAAI,CAAC,UAAU,CAAC,GAAG,CAACG,YAAYH,eAAe,EAAE;SAAE,CAAC,IAAI,CAACsB;IACtE;IAEO,iBAAyB;QAC/B,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAACvB,oBAAoB,UAAU;IAC1D;IAEO,iBAAyB;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAACA,oBAAoB,QAAQ;IACvD;IAEO,eAA2B;QACjC,OAAO;eAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAACA,oBAAoB,UAAU,EAAE;SAAE,CAAC,IAAI,CAACgB;IACxE;AACD"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Summary } from '../core/compression/Summary.js';
|
|
2
|
+
import type { Edge } from '../core/graph/Edge.js';
|
|
3
|
+
import type { ThoughtData } from '../core/thought.js';
|
|
4
|
+
export declare function parseThoughtData(raw: unknown, sourcePath: string): ThoughtData;
|
|
5
|
+
export declare function parseEdge(raw: unknown): Edge;
|
|
6
|
+
export declare function parseSummary(raw: unknown, sourcePath: string): Summary;
|
|
7
|
+
//# sourceMappingURL=PersistenceCodec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistenceCodec.d.ts","sourceRoot":"","sources":["../../src/persistence/PersistenceCodec.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAE9D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AA2FtD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAkC9E;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAS5C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAkBtE"}
|