@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 @@
|
|
|
1
|
+
{"version":3,"file":"core/InputNormalizer.js","sources":["../../src/core/InputNormalizer.ts"],"sourcesContent":["/**\n * Input normalization for common LLM field name mistakes.\n *\n * This module provides normalization logic to handle common mistakes\n * that LLMs make when generating field names, such as using singular\n * instead of plural forms (e.g., `recommended_tool` vs `recommended_tools`).\n *\n * It also fills in sensible defaults for missing fields in `previous_steps`,\n * which LLMs naturally provide as partial/skeletal data (historical context).\n *\n * @module processor\n */\n\nimport { ValidationError } from '../errors.js';\nimport {\n\tsanitizeString,\n\tsanitizeRationale,\n\tsanitizeStepField,\n\tsanitizeSuggestedInputs,\n} from '../sanitize.js';\nimport type { ThoughtData } from './thought.js';\nimport { SESSION_ID_PATTERN, MAX_SESSION_ID_LENGTH } from './ids.js';\nimport { asBranchId, asSessionId, generateThoughtId, type BranchId } from '../contracts/ids.js';\n\n/**\n * Default values for missing partial recommendation fields.\n *\n * Shared between tool and skill recommendations (identical defaults).\n */\nconst DEFAULT_RECOMMENDATION_CONFIDENCE = 0.5;\nconst DEFAULT_RECOMMENDATION_PRIORITY = 999;\nconst DEFAULT_RECOMMENDATION_RATIONALE = '';\nconst DEFAULT_STEP_OUTCOME = '';\n\n/**\n * Recursively sanitizes all string values within an unknown structure.\n * Walks into plain objects and arrays to reach deeply nested strings.\n * Non-plain objects (Date, RegExp, etc.) are returned as-is.\n *\n * @param value - The value to sanitize recursively\n * @returns The sanitized value with all nested strings cleaned\n *\n * @example\n * ```typescript\n * sanitizeRecursive('<script>x</script>'); // 'x'\n * sanitizeRecursive({ a: { b: '<iframe>y' } }); // { a: { b: 'y' } }\n * sanitizeRecursive(['a\\x00b', 42]); // ['ab', 42]\n * ```\n */\nexport function sanitizeRecursive(value: unknown): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\tif (typeof value === 'string') {\n\t\treturn sanitizeString(value);\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => sanitizeRecursive(item));\n\t}\n\tif (typeof value === 'object') {\n\t\t// Only recurse into plain objects — skip Date, RegExp, Map, Set, etc.\n\t\tconst proto = Object.getPrototypeOf(value);\n\t\tif (proto !== Object.prototype && proto !== null) {\n\t\t\treturn value;\n\t\t}\n\t\tconst result: Record<string, unknown> = {};\n\t\tfor (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n\t\t\tresult[key] = sanitizeRecursive(val);\n\t\t}\n\t\treturn result;\n\t}\n\treturn value;\n}\n\n/**\n * Valid branch ID pattern: alphanumeric, hyphens, underscores only.\n * Prevents path traversal attacks by rejecting special characters like / . \\ etc.\n */\nconst BRANCH_ID_PATTERN = /^[a-zA-Z0-9_-]{1,64}$/;\n\n/**\n * Sanitizes and validates a branch ID to prevent path traversal attacks.\n *\n * @param branchId - The branch ID to sanitize\n * @returns The sanitized branch ID\n * @throws ValidationError if the branch ID contains invalid characters\n *\n * @example\n * ```typescript\n * sanitizeBranchId('my-branch_01'); // 'my-branch_01'\n * sanitizeBranchId('../etc/passwd'); // throws ValidationError\n * ```\n */\nexport function sanitizeBranchId(branchId: string): BranchId {\n\t// Validate format\n\tif (!BRANCH_ID_PATTERN.test(branchId)) {\n\t\tthrow new ValidationError(\n\t\t\t'branch_id',\n\t\t\t'Invalid format - must be 1-64 alphanumeric characters, hyphens, or underscores only'\n\t\t);\n\t}\n\treturn asBranchId(branchId);\n}\n\n/**\n * Sanitizes and validates a session ID.\n *\n * @param sessionId - The session ID to sanitize\n * @returns The sanitized session ID, or undefined if invalid after sanitization\n *\n * @example\n * ```typescript\n * sanitizeSessionId('analysis-task-42'); // 'analysis-task-42'\n * sanitizeSessionId('bad session!'); // undefined (stripped)\n * ```\n */\nexport function sanitizeSessionId(sessionId: string): string | undefined {\n\t// First sanitize control characters\n\tconst cleaned = sanitizeString(sessionId);\n\t// Validate format after sanitization\n\tif (cleaned.length > MAX_SESSION_ID_LENGTH || !SESSION_ID_PATTERN.test(cleaned)) {\n\t\treturn undefined;\n\t}\n\treturn cleaned;\n}\n\n/**\n * Normalizes a recommendation object (tool or skill) with default values.\n *\n * Fills in sensible defaults for missing optional fields:\n * - `confidence`: 0.5\n * - `priority`: 999\n * - `rationale`: empty string\n *\n * @param rec - The recommendation object to normalize\n * @returns The normalized recommendation with defaults filled in\n *\n * @example\n * ```typescript\n * const input = { tool_name: 'Read', rationale: 'Read the file' };\n * const normalized = normalizeRecommendation(input);\n * // { tool_name: 'Read', rationale: 'Read the file', confidence: 0.5, priority: 999 }\n * ```\n */\nfunction normalizeRecommendation(rec: Record<string, unknown>): Record<string, unknown> {\n\tconst normalized: Record<string, unknown> = { ...rec };\n\n\t// Fill in default confidence if missing\n\tif (!('confidence' in normalized) || normalized.confidence === undefined) {\n\t\tnormalized.confidence = DEFAULT_RECOMMENDATION_CONFIDENCE;\n\t}\n\n\t// Fill in default priority if missing\n\tif (!('priority' in normalized) || normalized.priority === undefined) {\n\t\tnormalized.priority = DEFAULT_RECOMMENDATION_PRIORITY;\n\t}\n\n\t// Fill in default rationale if missing\n\t// Fill in default rationale if missing, otherwise sanitize urgency phrases + cap length\n\tif (!('rationale' in normalized) || normalized.rationale === undefined) {\n\t\tnormalized.rationale = DEFAULT_RECOMMENDATION_RATIONALE;\n\t} else if (typeof normalized.rationale === 'string') {\n\t\tnormalized.rationale = sanitizeRationale(normalized.rationale);\n\t}\n\t// Sanitize suggested_inputs: enforce flat primitives, key cap, value-length cap\n\tif (\n\t\tnormalized.suggested_inputs &&\n\t\ttypeof normalized.suggested_inputs === 'object' &&\n\t\t!Array.isArray(normalized.suggested_inputs)\n\t) {\n\t\tnormalized.suggested_inputs = sanitizeSuggestedInputs(\n\t\t\tnormalized.suggested_inputs as Record<string, unknown>\n\t\t);\n\t}\n\n\treturn normalized;\n}\n/**\n * Normalizes step recommendation objects.\n *\n * Handles common field name mistakes:\n * - `recommended_tool` (singular) → `recommended_tools` (plural)\n * - `recommended_skill` (singular) → `recommended_skills` (plural)\n *\n * Also normalizes tool recommendations within the step to fill in defaults.\n *\n * @param step - The step recommendation to normalize\n * @param lenient - Whether to use lenient mode (fill in defaults for missing fields)\n * @returns The normalized step recommendation\n *\n * @example\n * ```typescript\n * // Strict mode (for current_step)\n * const input = {\n * step_description: 'Analyze data',\n * recommended_tool: [{ tool_name: 'Read', confidence: 0.9, rationale: 'test', priority: 1 }],\n * expected_outcome: 'Data analyzed'\n * };\n * const normalized = normalizeStepRecommendation(input, false);\n * // normalized.recommended_tools exists (plural form)\n *\n * // Lenient mode (for previous_steps)\n * const partialInput = {\n * step_description: 'Read file',\n * recommended_tools: [{ tool_name: 'Read', rationale: 'Read file' }]\n * };\n * const normalized = normalizeStepRecommendation(partialInput, true);\n * // confidence: 0.5, priority: 999, expected_outcome: '' filled in\n * ```\n */\nfunction normalizeStepRecommendation(\n\tstep: Record<string, unknown>,\n\tlenient: boolean\n): Record<string, unknown> {\n\tconst normalized: Record<string, unknown> = { ...step };\n\n\t// Transform `recommended_tool` (singular) → `recommended_tools` (plural)\n\tif ('recommended_tool' in normalized && !('recommended_tools' in normalized)) {\n\t\tnormalized.recommended_tools = normalized.recommended_tool;\n\t\tdelete normalized.recommended_tool;\n\t}\n\n\t// Transform `recommended_skill` (singular) → `recommended_skills` (plural)\n\tif ('recommended_skill' in normalized && !('recommended_skills' in normalized)) {\n\t\tnormalized.recommended_skills = normalized.recommended_skill;\n\t\tdelete normalized.recommended_skill;\n\t}\n\n\t// Normalize recommended_tools array if present\n\tif (Array.isArray(normalized.recommended_tools)) {\n\t\tnormalized.recommended_tools = normalized.recommended_tools.map((tool) =>\n\t\t\ttypeof tool === 'object' && tool !== null\n\t\t\t\t? normalizeRecommendation(tool as Record<string, unknown>)\n\t\t\t\t: tool\n\t\t);\n\t}\n\n\t// Normalize recommended_skills array if present\n\tif (Array.isArray(normalized.recommended_skills)) {\n\t\tnormalized.recommended_skills = normalized.recommended_skills.map((skill) =>\n\t\t\ttypeof skill === 'object' && skill !== null\n\t\t\t\t? normalizeRecommendation(skill as Record<string, unknown>)\n\t\t\t\t: skill\n\t\t);\n\t}\n\t// Sanitize step-level string fields for prompt injection prevention\n\tif (typeof normalized.step_description === 'string') {\n\t\tnormalized.step_description = sanitizeStepField(normalized.step_description);\n\t}\n\tif (typeof normalized.expected_outcome === 'string') {\n\t\tnormalized.expected_outcome = sanitizeStepField(normalized.expected_outcome);\n\t}\n\tif (Array.isArray(normalized.next_step_conditions)) {\n\t\tnormalized.next_step_conditions = normalized.next_step_conditions.map((cond: unknown) =>\n\t\t\ttypeof cond === 'string' ? sanitizeStepField(cond) : cond\n\t\t);\n\t}\n\t// In lenient mode, fill in default expected_outcome if missing\n\tif (lenient && !('expected_outcome' in normalized)) {\n\t\tnormalized.expected_outcome = DEFAULT_STEP_OUTCOME;\n\t}\n\n\treturn normalized;\n}\n\n/**\n * Normalizes reasoning-specific fields on a thought input object.\n * Always applies reasoning normalization — reasoning is the default pipeline.\n * Applies the following normalization rules:\n * - Defaults `thought_type` to `'regular'` if not provided\n * - Clamps `quality_score` to [0, 1] range\n * - Clamps `confidence` to [0, 1] range\n * - Sanitizes `hypothesis_id` using `sanitizeBranchId` pattern\n * - Filters `synthesis_sources` to positive integers only\n * - Filters `merge_from_thoughts` to positive integers only\n * - Sanitizes each entry in `merge_branch_ids`\n * - Defaults `reasoning_depth` to `'moderate'` for hypothesis/verification types\n *\n * @param input - The mutable normalized input object to apply reasoning defaults to\n *\n * @example\n * ```typescript\n * const input: Record<string, unknown> = { thought_type: 'hypothesis', quality_score: 1.5 };\n * normalizeReasoningFields(input);\n * // input.quality_score === 1, input.reasoning_depth === 'moderate'\n * ```\n */\nexport function normalizeReasoningFields(input: Record<string, unknown>): void {\n\t// Always apply reasoning field normalization — reasoning is the default pipeline\n\t// Default thought_type to 'regular'\n\n\tif (!('thought_type' in input) || input.thought_type === undefined) {\n\t\tinput.thought_type = 'regular';\n\t}\n\n\t// Clamp quality_score to [0, 1]\n\tif (typeof input.quality_score === 'number') {\n\t\tinput.quality_score = Math.max(0, Math.min(1, input.quality_score));\n\t}\n\n\t// Clamp confidence to [0, 1]\n\tif (typeof input.confidence === 'number') {\n\t\tinput.confidence = Math.max(0, Math.min(1, input.confidence));\n\t}\n\n\t// Sanitize hypothesis_id (same rules as branch_id)\n\tif (typeof input.hypothesis_id === 'string') {\n\t\tinput.hypothesis_id = sanitizeBranchId(input.hypothesis_id);\n\t}\n\n\t// Filter synthesis_sources to positive integers only\n\tif (Array.isArray(input.synthesis_sources)) {\n\t\tinput.synthesis_sources = input.synthesis_sources.filter(\n\t\t\t(v: unknown) => typeof v === 'number' && Number.isInteger(v) && v > 0\n\t\t);\n\t}\n\n\t// Filter merge_from_thoughts to positive integers only\n\tif (Array.isArray(input.merge_from_thoughts)) {\n\t\tinput.merge_from_thoughts = input.merge_from_thoughts.filter(\n\t\t\t(v: unknown) => typeof v === 'number' && Number.isInteger(v) && v > 0\n\t\t);\n\t}\n\n\t// Sanitize merge_branch_ids entries\n\tif (Array.isArray(input.merge_branch_ids)) {\n\t\tinput.merge_branch_ids = input.merge_branch_ids.map((id: unknown) => {\n\t\t\tif (typeof id === 'string') {\n\t\t\t\treturn sanitizeBranchId(id);\n\t\t\t}\n\t\t\treturn id;\n\t\t});\n\t}\n\n\t// Default reasoning_depth to 'moderate' for hypothesis/verification types\n\tif (\n\t\t(input.thought_type === 'hypothesis' || input.thought_type === 'verification') &&\n\t\t!('reasoning_depth' in input)\n\t) {\n\t\tinput.reasoning_depth = 'moderate';\n\t}\n}\n\n/**\n * Normalizes thought input data by fixing common LLM field name mistakes.\n *\n * This function handles cases where LLMs incorrectly use singular forms\n * of field names that should be plural. It applies normalization to both\n * `current_step` and `previous_steps` fields.\n *\n * The normalization is applied BEFORE schema validation, allowing the\n * strict Valibot schema to remain correct while still being tolerant\n * of common LLM mistakes.\n *\n * @param input - The raw thought input data to normalize\n * @returns Normalized thought data with correct field names\n *\n * @remarks\n * **Normalization Rules:**\n * - `recommended_tool` (singular) → `recommended_tools` (plural)\n * - `recommended_skill` (singular) → `recommended_skills` (plural)\n * - Applied to `current_step` if present (strict mode)\n * - Applied to all items in `previous_steps` if present (lenient mode with defaults)\n *\n * **Design Rationale:**\n * LLMs sometimes use singular field names even when the schema explicitly\n * defines plural forms. Rather than forcing the LLM to be perfect (which\n * leads to cryptic validation errors), we normalize the input to handle\n * these common mistakes gracefully.\n *\n * Additionally, LLMs naturally provide complete data for `current_step`\n * but only partial/skeletal data for `previous_steps` (historical context).\n * The lenient mode for `previous_steps` fills in sensible defaults:\n * - `confidence`: 0.5 for missing tool recommendation confidence\n * - `priority`: 999 for missing tool recommendation priority\n * - `rationale`: empty string for missing tool recommendation rationale\n * - `expected_outcome`: empty string for missing step expected outcome\n *\n * @example\n * ```typescript\n * const input = {\n * thought: 'I need to analyze the data',\n * thought_number: 1,\n * total_thoughts: 3,\n * next_thought_needed: true,\n * current_step: {\n * step_description: 'Read the data file',\n * recommended_tool: [{ tool_name: 'Read', confidence: 0.9, rationale: 'test', priority: 1 }],\n * expected_outcome: 'Data loaded'\n * },\n * previous_steps: [{\n * step_description: 'Previous step',\n * recommended_tools: [{ tool_name: 'Grep', rationale: 'Search code' }]\n * }]\n * };\n *\n * const normalized = normalizeInput(input);\n * // current_step: recommended_tools exists (plural form)\n * // previous_steps[0]: confidence=0.5, priority=999, expected_outcome='' filled in\n * ```\n */\nexport function normalizeInput(input: unknown): ThoughtData {\n\tif (typeof input !== 'object' || input === null) {\n\t\treturn input as ThoughtData;\n\t}\n\n\tconst normalized = { ...input } as Record<string, unknown>;\n\n\t// Normalize current_step if present (strict mode - no defaults)\n\tif (normalized.current_step && typeof normalized.current_step === 'object') {\n\t\tnormalized.current_step = normalizeStepRecommendation(\n\t\t\tnormalized.current_step as Record<string, unknown>,\n\t\t\tfalse // strict mode\n\t\t);\n\t}\n\n\t// Normalize all items in previous_steps if present (lenient mode - with defaults)\n\tif (Array.isArray(normalized.previous_steps) && normalized.previous_steps.length > 0) {\n\t\tnormalized.previous_steps = normalized.previous_steps.map((step) =>\n\t\t\ttypeof step === 'object' && step !== null\n\t\t\t\t? normalizeStepRecommendation(step as Record<string, unknown>, true) // lenient mode\n\t\t\t\t: step\n\t\t);\n\t}\n\n\t// Sanitize branch_id to prevent path traversal attacks\n\tif (typeof normalized.branch_id === 'string') {\n\t\tnormalized.branch_id = sanitizeBranchId(normalized.branch_id);\n\t}\n\n\t// Explicit identity is validated, never sanitized into another namespace.\n\tif (typeof normalized.session_id === 'string') {\n\t\tnormalized.session_id = asSessionId(normalized.session_id);\n\t}\n\n\tif (typeof normalized.register_branch_id === 'string') {\n\t\tnormalized.register_branch_id = sanitizeBranchId(normalized.register_branch_id);\n\t}\n\n\t// Auto-generate id if not provided (for DAG node identity)\n\tif (!normalized.id || typeof normalized.id !== 'string') {\n\t\tnormalized.id = generateThoughtId();\n\t}\n\n\t// Normalize reasoning fields\n\tnormalizeReasoningFields(normalized);\n\n\t// Sanitize meta_observation for prompt injection prevention\n\tif (typeof normalized.meta_observation === 'string') {\n\t\tnormalized.meta_observation = sanitizeStepField(normalized.meta_observation);\n\t}\n\n\t// Sanitize all free-text string fields recursively (dangerous HTML tags + null bytes)\n\t// This was moved from schema transforms because v.transform() cannot be converted to JSON Schema\n\tconst sanitized = sanitizeRecursive(normalized);\n\n\treturn sanitized as ThoughtData;\n}\n"],"names":["DEFAULT_RECOMMENDATION_CONFIDENCE","DEFAULT_RECOMMENDATION_PRIORITY","DEFAULT_RECOMMENDATION_RATIONALE","DEFAULT_STEP_OUTCOME","sanitizeRecursive","value","sanitizeString","Array","item","proto","Object","result","key","val","BRANCH_ID_PATTERN","sanitizeBranchId","branchId","ValidationError","asBranchId","sanitizeSessionId","sessionId","cleaned","MAX_SESSION_ID_LENGTH","SESSION_ID_PATTERN","normalizeRecommendation","rec","normalized","undefined","sanitizeRationale","sanitizeSuggestedInputs","normalizeStepRecommendation","step","lenient","tool","skill","sanitizeStepField","cond","normalizeReasoningFields","input","Math","v","Number","id","normalizeInput","asSessionId","generateThoughtId","sanitized"],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joinable coordinator for attributable persistence work.
|
|
3
|
+
*
|
|
4
|
+
* @module PersistenceBuffer
|
|
5
|
+
*/
|
|
6
|
+
import type { PersistenceBackend } from '../contracts/PersistenceBackend.js';
|
|
7
|
+
import type { IEdgeStore } from '../contracts/interfaces.js';
|
|
8
|
+
import type { BranchId, SessionId } from '../contracts/ids.js';
|
|
9
|
+
import type { Logger } from '../logger/StructuredLogger.js';
|
|
10
|
+
import type { Summary } from './compression/Summary.js';
|
|
11
|
+
import type { Edge } from './graph/Edge.js';
|
|
12
|
+
import { type PersistenceDelay } from './PersistenceWriter.js';
|
|
13
|
+
import type { ThoughtData } from './thought.js';
|
|
14
|
+
/** Minimal compatibility view for legacy callers that own a `writeBuffer`. */
|
|
15
|
+
export interface BufferedSession {
|
|
16
|
+
writeBuffer: ThoughtData[];
|
|
17
|
+
}
|
|
18
|
+
/** Event emitter contract for persistence error events. */
|
|
19
|
+
export interface PersistenceEventEmitter {
|
|
20
|
+
emit(event: 'persistenceError', payload: {
|
|
21
|
+
operation: string;
|
|
22
|
+
error: Error;
|
|
23
|
+
}): boolean;
|
|
24
|
+
}
|
|
25
|
+
/** Observable persistence state relevant to safe in-memory session eviction. */
|
|
26
|
+
export type SessionEvictionState = 'quiescent' | 'pending' | 'failed' | 'barrier';
|
|
27
|
+
/** Configuration options for {@link PersistenceBuffer}. */
|
|
28
|
+
export interface PersistenceBufferConfig<S extends BufferedSession> {
|
|
29
|
+
readonly persistence: PersistenceBackend;
|
|
30
|
+
readonly bufferSize: number;
|
|
31
|
+
readonly flushInterval: number;
|
|
32
|
+
readonly maxRetries: number;
|
|
33
|
+
readonly defaultSessionId: SessionId;
|
|
34
|
+
/** Compatibility-only session source retained until producer wiring is migrated. */
|
|
35
|
+
readonly getSessions: () => Map<SessionId, S>;
|
|
36
|
+
/** Compatibility-only default session retained until producer wiring is migrated. */
|
|
37
|
+
readonly getDefaultSession: () => S;
|
|
38
|
+
/** Compatibility-only edge source retained until producers register snapshots. */
|
|
39
|
+
readonly edgeStore?: IEdgeStore;
|
|
40
|
+
/** Optional emitter for `persistenceError` events. */
|
|
41
|
+
readonly eventEmitter?: PersistenceEventEmitter | null;
|
|
42
|
+
readonly logger?: Logger;
|
|
43
|
+
/** Optional retry scheduler for deterministic coordination and testing. */
|
|
44
|
+
readonly delay?: PersistenceDelay;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Coordinates one globally joinable persistence generation at a time.
|
|
48
|
+
*
|
|
49
|
+
* Accepted work is owned by a queue independent of live session state. Explicit
|
|
50
|
+
* callers can join and upgrade a background generation without starting another writer.
|
|
51
|
+
*/
|
|
52
|
+
export declare class PersistenceBuffer<S extends BufferedSession> {
|
|
53
|
+
private readonly _bufferSize;
|
|
54
|
+
private readonly _flushInterval;
|
|
55
|
+
private readonly _defaultSessionId;
|
|
56
|
+
private readonly _queue;
|
|
57
|
+
private readonly _writer;
|
|
58
|
+
private _eventEmitter;
|
|
59
|
+
private readonly _logger;
|
|
60
|
+
private _flushTimer;
|
|
61
|
+
private _activeDrain;
|
|
62
|
+
private readonly _sessionBarriers;
|
|
63
|
+
private readonly _sessionBarrierOwnership;
|
|
64
|
+
private readonly _sessionProgressWaiters;
|
|
65
|
+
private readonly _quarantinedSessions;
|
|
66
|
+
private readonly _evictionQuarantinedSessions;
|
|
67
|
+
private _globalResetTail;
|
|
68
|
+
private _globalResetOwners;
|
|
69
|
+
private _globalQuarantined;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a persistence-drain coordinator.
|
|
72
|
+
*
|
|
73
|
+
* @param config - Persistence dependencies, trigger thresholds, and retry policy.
|
|
74
|
+
*/
|
|
75
|
+
constructor(config: PersistenceBufferConfig<S>);
|
|
76
|
+
/** @returns The underlying flush timer for lifecycle introspection. */
|
|
77
|
+
get timer(): ReturnType<typeof setInterval> | null;
|
|
78
|
+
/** @returns Whether a global drain generation is active. */
|
|
79
|
+
get isFlushing(): boolean;
|
|
80
|
+
/** @returns Number of accepted thought writes not yet acknowledged successful. */
|
|
81
|
+
get pendingThoughtCount(): number;
|
|
82
|
+
/**
|
|
83
|
+
* Sets or clears the persistence error event emitter.
|
|
84
|
+
*
|
|
85
|
+
* @param emitter - Replacement emitter, or `null` to disable events.
|
|
86
|
+
*/
|
|
87
|
+
setEventEmitter(emitter: PersistenceEventEmitter | null): void;
|
|
88
|
+
/**
|
|
89
|
+
* Accepts a thought with authoritative session attribution.
|
|
90
|
+
*
|
|
91
|
+
* The legacy session overload derives attribution from `thought.session_id` and
|
|
92
|
+
* falls back to the configured default session without using the live write buffer.
|
|
93
|
+
*
|
|
94
|
+
* @param sessionId - Session that owns the accepted thought.
|
|
95
|
+
* @param thought - Thought to persist.
|
|
96
|
+
*/
|
|
97
|
+
bufferThought(sessionId: SessionId, thought: ThoughtData): void;
|
|
98
|
+
bufferThought(session: BufferedSession, thought: ThoughtData): void;
|
|
99
|
+
/**
|
|
100
|
+
* Accepts the latest snapshot for one session-owned branch.
|
|
101
|
+
*
|
|
102
|
+
* @param sessionId - Session that owns the branch.
|
|
103
|
+
* @param branchId - Stable branch coordinate.
|
|
104
|
+
* @param thoughts - Branch snapshot copied by the queue.
|
|
105
|
+
*/
|
|
106
|
+
bufferBranch(sessionId: SessionId, branchId: BranchId, thoughts: readonly ThoughtData[]): void;
|
|
107
|
+
/**
|
|
108
|
+
* @param sessionId - Session that owns the branch.
|
|
109
|
+
* @param branchId - Stable branch coordinate to delete.
|
|
110
|
+
*/
|
|
111
|
+
deleteBranch(sessionId: SessionId, branchId: BranchId): void;
|
|
112
|
+
/**
|
|
113
|
+
* Accepts the latest edge snapshot for one session.
|
|
114
|
+
*
|
|
115
|
+
* @param sessionId - Session that owns the edges.
|
|
116
|
+
* @param edges - Edge snapshot copied by the queue.
|
|
117
|
+
*/
|
|
118
|
+
bufferEdges(sessionId: SessionId, edges: readonly Edge[]): void;
|
|
119
|
+
/**
|
|
120
|
+
* Accepts the latest summary snapshot for one session.
|
|
121
|
+
*
|
|
122
|
+
* @param sessionId - Session that owns the summaries.
|
|
123
|
+
* @param summaries - Summary snapshot copied by the queue.
|
|
124
|
+
*/
|
|
125
|
+
bufferSummaries(sessionId: SessionId, summaries: readonly Summary[]): void;
|
|
126
|
+
/** Rejects synchronously when lifecycle coordination has closed persistence admission. */
|
|
127
|
+
assertSessionAdmissionOpen(sessionId: SessionId): void;
|
|
128
|
+
/** Starts the periodic background-drain timer without keeping the process alive. */
|
|
129
|
+
startFlushTimer(): void;
|
|
130
|
+
/** Stops the periodic background-drain timer. */
|
|
131
|
+
stopFlushTimer(): void;
|
|
132
|
+
/**
|
|
133
|
+
* Starts or joins an explicit global drain generation.
|
|
134
|
+
*
|
|
135
|
+
* @returns The exact shared promise for the active generation.
|
|
136
|
+
*/
|
|
137
|
+
drain(): Promise<void>;
|
|
138
|
+
/** @returns The exact same promise as {@link drain} for the active generation. */
|
|
139
|
+
flush(): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Joins the global explicit generation and projects its terminal failures to one session.
|
|
142
|
+
* This method does not close admission; lifecycle owners must use
|
|
143
|
+
* {@link withSessionBarrier} when work must not cross an owner callback.
|
|
144
|
+
*
|
|
145
|
+
* @param sessionId - Session whose accepted writes form the barrier projection.
|
|
146
|
+
* @returns A promise that rejects only for that session's failures or an unknown fault.
|
|
147
|
+
*/
|
|
148
|
+
drainSession(sessionId: SessionId): Promise<void>;
|
|
149
|
+
/** Returns queue-derived persistence state for safe session eviction planning. */
|
|
150
|
+
sessionEvictionState(sessionId: SessionId): SessionEvictionState;
|
|
151
|
+
/**
|
|
152
|
+
* Drains accepted session work before ordinary in-memory eviction cleanup.
|
|
153
|
+
*
|
|
154
|
+
* Unlike reset barriers, this operation never clears durable state or discards
|
|
155
|
+
* accepted work. Failure retains admission quarantine until a later explicit
|
|
156
|
+
* invocation successfully drains and completes cleanup.
|
|
157
|
+
*/
|
|
158
|
+
withSessionEvictionBarrier<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T>;
|
|
159
|
+
/** Forgets queue coordinates only when the session is fully quiescent. */
|
|
160
|
+
forgetQuiescentSession(sessionId: SessionId): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Runs one lifecycle operation while persistence admission is closed for a session.
|
|
163
|
+
*
|
|
164
|
+
* Admission closes synchronously when this method is called. Already accepted work for
|
|
165
|
+
* the session is settled first; an exhausted session failure rejects without invoking
|
|
166
|
+
* `operation`. Concurrent calls for the same session execute in FIFO call order and keep
|
|
167
|
+
* admission closed until the final callback settles. Other sessions remain admissible and
|
|
168
|
+
* may be owned by a nested callback. Reacquiring the same session from the owning callback's
|
|
169
|
+
* async call chain rejects before joining the FIFO because awaiting it would deadlock its owner.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* await buffer.withSessionBarrier(sessionId, async () => {
|
|
174
|
+
* await persistence.clearSession(sessionId);
|
|
175
|
+
* });
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* @param sessionId - Session exclusively owned for the callback duration.
|
|
179
|
+
* @param operation - Awaited lifecycle operation run only after prior work settles.
|
|
180
|
+
* @returns The callback result after admission has reopened when no owner remains.
|
|
181
|
+
* @throws {@link PersistenceSessionBarrierReentrancyError} when the owning async call chain
|
|
182
|
+
* attempts to reacquire `sessionId`.
|
|
183
|
+
*/
|
|
184
|
+
withSessionBarrier<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T>;
|
|
185
|
+
/**
|
|
186
|
+
* Runs a scoped reset, retaining admission quarantine on failure.
|
|
187
|
+
* A retry may pass retained write failures because successful durable deletion
|
|
188
|
+
* invalidates those stale queue entries before admission reopens.
|
|
189
|
+
*/
|
|
190
|
+
withSessionResetBarrier<T>(sessionId: SessionId, operation: () => Promise<T>): Promise<T>;
|
|
191
|
+
/** Runs a trusted global reset behind a global admission barrier. */
|
|
192
|
+
withGlobalResetBarrier<T>(operation: () => Promise<T>): Promise<T>;
|
|
193
|
+
private _joinOrStart;
|
|
194
|
+
private _triggerBackgroundDrain;
|
|
195
|
+
private _runDrain;
|
|
196
|
+
private _closeGeneration;
|
|
197
|
+
private _awaitSessionQuiescence;
|
|
198
|
+
private _sessionQuiescence;
|
|
199
|
+
private _waitForSessionProgress;
|
|
200
|
+
private _notifySessionProgress;
|
|
201
|
+
private _assertSessionAdmissionOpen;
|
|
202
|
+
private _observeFailure;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=PersistenceBuffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PersistenceBuffer.d.ts","sourceRoot":"","sources":["../../src/core/PersistenceBuffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { PersistenceDrainError, PersistenceSessionAdmissionClosedError, PersistenceSessionBarrierReentrancyError } from "./PersistenceBufferErrors.js";
|
|
3
|
+
import { NullLogger } from "../logger/NullLogger.js";
|
|
4
|
+
import { assertNever } from "../utils.js";
|
|
5
|
+
import { PersistenceWorkQueue } from "./PersistenceWorkQueue.js";
|
|
6
|
+
import { PersistenceWriter } from "./PersistenceWriter.js";
|
|
7
|
+
class PersistenceBuffer {
|
|
8
|
+
_bufferSize;
|
|
9
|
+
_flushInterval;
|
|
10
|
+
_defaultSessionId;
|
|
11
|
+
_queue = new PersistenceWorkQueue();
|
|
12
|
+
_writer;
|
|
13
|
+
_eventEmitter;
|
|
14
|
+
_logger;
|
|
15
|
+
_flushTimer = null;
|
|
16
|
+
_activeDrain = null;
|
|
17
|
+
_sessionBarriers = new Map();
|
|
18
|
+
_sessionBarrierOwnership = new AsyncLocalStorage();
|
|
19
|
+
_sessionProgressWaiters = new Map();
|
|
20
|
+
_quarantinedSessions = new Set();
|
|
21
|
+
_evictionQuarantinedSessions = new Set();
|
|
22
|
+
_globalResetTail = Promise.resolve();
|
|
23
|
+
_globalResetOwners = 0;
|
|
24
|
+
_globalQuarantined = false;
|
|
25
|
+
constructor(config){
|
|
26
|
+
this._bufferSize = config.bufferSize;
|
|
27
|
+
this._flushInterval = config.flushInterval;
|
|
28
|
+
this._defaultSessionId = config.defaultSessionId;
|
|
29
|
+
this._eventEmitter = config.eventEmitter ?? null;
|
|
30
|
+
this._logger = config.logger ?? new NullLogger();
|
|
31
|
+
this._writer = new PersistenceWriter({
|
|
32
|
+
persistence: config.persistence,
|
|
33
|
+
maxRetries: config.maxRetries,
|
|
34
|
+
delay: config.delay
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
get timer() {
|
|
38
|
+
return this._flushTimer;
|
|
39
|
+
}
|
|
40
|
+
get isFlushing() {
|
|
41
|
+
return null !== this._activeDrain;
|
|
42
|
+
}
|
|
43
|
+
get pendingThoughtCount() {
|
|
44
|
+
return this._queue.pendingThoughtCount;
|
|
45
|
+
}
|
|
46
|
+
setEventEmitter(emitter) {
|
|
47
|
+
this._eventEmitter = emitter;
|
|
48
|
+
}
|
|
49
|
+
bufferThought(source, thought) {
|
|
50
|
+
const sessionId = 'string' == typeof source ? source : thought.session_id ?? this._defaultSessionId;
|
|
51
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
52
|
+
if (this._queue.pendingThoughtCount >= this._bufferSize && this.isFlushing) this._logger.info('Write buffer full and flush in progress, applying backpressure', {
|
|
53
|
+
bufferSize: this._queue.pendingThoughtCount,
|
|
54
|
+
maxSize: this._bufferSize
|
|
55
|
+
});
|
|
56
|
+
this._queue.enqueueThought(sessionId, thought);
|
|
57
|
+
if (this._queue.pendingThoughtCount >= this._bufferSize) this._triggerBackgroundDrain();
|
|
58
|
+
}
|
|
59
|
+
bufferBranch(sessionId, branchId, thoughts) {
|
|
60
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
61
|
+
this._queue.replaceBranch(sessionId, branchId, thoughts);
|
|
62
|
+
}
|
|
63
|
+
deleteBranch(sessionId, branchId) {
|
|
64
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
65
|
+
this._queue.deleteBranch(sessionId, branchId);
|
|
66
|
+
}
|
|
67
|
+
bufferEdges(sessionId, edges) {
|
|
68
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
69
|
+
this._queue.replaceEdges(sessionId, edges);
|
|
70
|
+
}
|
|
71
|
+
bufferSummaries(sessionId, summaries) {
|
|
72
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
73
|
+
this._queue.replaceSummaries(sessionId, summaries);
|
|
74
|
+
}
|
|
75
|
+
assertSessionAdmissionOpen(sessionId) {
|
|
76
|
+
this._assertSessionAdmissionOpen(sessionId);
|
|
77
|
+
}
|
|
78
|
+
startFlushTimer() {
|
|
79
|
+
if (null !== this._flushTimer) return;
|
|
80
|
+
this._flushTimer = setInterval(()=>this._triggerBackgroundDrain(), this._flushInterval);
|
|
81
|
+
if ('object' == typeof this._flushTimer && 'unref' in this._flushTimer) this._flushTimer.unref();
|
|
82
|
+
}
|
|
83
|
+
stopFlushTimer() {
|
|
84
|
+
if (null === this._flushTimer) return;
|
|
85
|
+
clearInterval(this._flushTimer);
|
|
86
|
+
this._flushTimer = null;
|
|
87
|
+
}
|
|
88
|
+
drain() {
|
|
89
|
+
return this._joinOrStart('explicit').promise;
|
|
90
|
+
}
|
|
91
|
+
flush() {
|
|
92
|
+
return this.drain();
|
|
93
|
+
}
|
|
94
|
+
drainSession(sessionId) {
|
|
95
|
+
const generation = this._joinOrStart('explicit');
|
|
96
|
+
return generation.promise.catch((reason)=>{
|
|
97
|
+
if (!(reason instanceof PersistenceDrainError)) throw reason;
|
|
98
|
+
const failures = reason.failures.filter((failure)=>failure.sessionId === sessionId);
|
|
99
|
+
if (failures.length > 0) throw new PersistenceDrainError(failures);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
sessionEvictionState(sessionId) {
|
|
103
|
+
if (this._globalResetOwners > 0 || this._sessionBarriers.has(sessionId)) return 'barrier';
|
|
104
|
+
if (this._globalQuarantined || this._queue.hasSessionTerminalFailure(sessionId) || this._quarantinedSessions.has(sessionId) || this._evictionQuarantinedSessions.has(sessionId)) return 'failed';
|
|
105
|
+
return this._queue.hasSessionWork(sessionId) ? 'pending' : 'quiescent';
|
|
106
|
+
}
|
|
107
|
+
withSessionEvictionBarrier(sessionId, operation) {
|
|
108
|
+
if (this._globalResetOwners > 0 || this._globalQuarantined || this._quarantinedSessions.has(sessionId)) return Promise.reject(new PersistenceSessionAdmissionClosedError(sessionId));
|
|
109
|
+
const currentOwnership = this._sessionBarrierOwnership.getStore();
|
|
110
|
+
if (currentOwnership?.has(sessionId) === true) return Promise.reject(new PersistenceSessionBarrierReentrancyError(sessionId));
|
|
111
|
+
const operationOwnership = new Set(currentOwnership);
|
|
112
|
+
operationOwnership.add(sessionId);
|
|
113
|
+
const state = this._sessionBarriers.get(sessionId) ?? {
|
|
114
|
+
tail: Promise.resolve(),
|
|
115
|
+
pendingOwners: 0
|
|
116
|
+
};
|
|
117
|
+
this._sessionBarriers.set(sessionId, state);
|
|
118
|
+
state.pendingOwners += 1;
|
|
119
|
+
const result = state.tail.then(async ()=>{
|
|
120
|
+
try {
|
|
121
|
+
await this._awaitSessionQuiescence(sessionId);
|
|
122
|
+
const value = await this._sessionBarrierOwnership.run(operationOwnership, operation);
|
|
123
|
+
this._queue.forgetQuiescentSession(sessionId);
|
|
124
|
+
this._evictionQuarantinedSessions.delete(sessionId);
|
|
125
|
+
return value;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
this._evictionQuarantinedSessions.add(sessionId);
|
|
128
|
+
throw error;
|
|
129
|
+
} finally{
|
|
130
|
+
state.pendingOwners -= 1;
|
|
131
|
+
if (0 === state.pendingOwners) this._sessionBarriers.delete(sessionId);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
state.tail = result.then(()=>void 0, ()=>void 0);
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
forgetQuiescentSession(sessionId) {
|
|
138
|
+
return 'quiescent' === this.sessionEvictionState(sessionId) ? this._queue.forgetQuiescentSession(sessionId) : false;
|
|
139
|
+
}
|
|
140
|
+
withSessionBarrier(sessionId, operation) {
|
|
141
|
+
const currentOwnership = this._sessionBarrierOwnership.getStore();
|
|
142
|
+
if (currentOwnership?.has(sessionId) === true) return Promise.reject(new PersistenceSessionBarrierReentrancyError(sessionId));
|
|
143
|
+
const operationOwnership = new Set(currentOwnership);
|
|
144
|
+
operationOwnership.add(sessionId);
|
|
145
|
+
const state = this._sessionBarriers.get(sessionId) ?? {
|
|
146
|
+
tail: Promise.resolve(),
|
|
147
|
+
pendingOwners: 0
|
|
148
|
+
};
|
|
149
|
+
this._sessionBarriers.set(sessionId, state);
|
|
150
|
+
state.pendingOwners += 1;
|
|
151
|
+
const result = state.tail.then(async ()=>{
|
|
152
|
+
try {
|
|
153
|
+
await this._awaitSessionQuiescence(sessionId);
|
|
154
|
+
return await this._sessionBarrierOwnership.run(operationOwnership, operation);
|
|
155
|
+
} finally{
|
|
156
|
+
state.pendingOwners -= 1;
|
|
157
|
+
if (0 === state.pendingOwners) this._sessionBarriers.delete(sessionId);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
state.tail = result.then(()=>void 0, ()=>void 0);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
withSessionResetBarrier(sessionId, operation) {
|
|
164
|
+
if (this._globalResetOwners > 0 || this._globalQuarantined) return Promise.reject(new PersistenceSessionAdmissionClosedError(sessionId));
|
|
165
|
+
const currentOwnership = this._sessionBarrierOwnership.getStore();
|
|
166
|
+
if (currentOwnership?.has(sessionId) === true) return Promise.reject(new PersistenceSessionBarrierReentrancyError(sessionId));
|
|
167
|
+
const operationOwnership = new Set(currentOwnership);
|
|
168
|
+
operationOwnership.add(sessionId);
|
|
169
|
+
const state = this._sessionBarriers.get(sessionId) ?? {
|
|
170
|
+
tail: Promise.resolve(),
|
|
171
|
+
pendingOwners: 0
|
|
172
|
+
};
|
|
173
|
+
this._sessionBarriers.set(sessionId, state);
|
|
174
|
+
state.pendingOwners += 1;
|
|
175
|
+
const result = state.tail.then(async ()=>{
|
|
176
|
+
try {
|
|
177
|
+
try {
|
|
178
|
+
await this._awaitSessionQuiescence(sessionId);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (!(error instanceof PersistenceDrainError)) throw error;
|
|
181
|
+
}
|
|
182
|
+
const value = await this._sessionBarrierOwnership.run(operationOwnership, operation);
|
|
183
|
+
this._queue.discardSession(sessionId);
|
|
184
|
+
this._quarantinedSessions.delete(sessionId);
|
|
185
|
+
this._evictionQuarantinedSessions.delete(sessionId);
|
|
186
|
+
return value;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
this._quarantinedSessions.add(sessionId);
|
|
189
|
+
throw error;
|
|
190
|
+
} finally{
|
|
191
|
+
state.pendingOwners -= 1;
|
|
192
|
+
if (0 === state.pendingOwners) this._sessionBarriers.delete(sessionId);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
state.tail = result.then(()=>void 0, ()=>void 0);
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
withGlobalResetBarrier(operation) {
|
|
199
|
+
this._globalResetOwners += 1;
|
|
200
|
+
const prior = this._globalResetTail;
|
|
201
|
+
const result = prior.then(async ()=>{
|
|
202
|
+
try {
|
|
203
|
+
await Promise.all(Array.from(this._sessionBarriers.values(), (state)=>state.tail));
|
|
204
|
+
try {
|
|
205
|
+
await this.drain();
|
|
206
|
+
} catch (error) {
|
|
207
|
+
if (!(error instanceof PersistenceDrainError)) throw error;
|
|
208
|
+
}
|
|
209
|
+
const value = await operation();
|
|
210
|
+
this._queue.discardAll();
|
|
211
|
+
this._quarantinedSessions.clear();
|
|
212
|
+
this._evictionQuarantinedSessions.clear();
|
|
213
|
+
this._globalQuarantined = false;
|
|
214
|
+
return value;
|
|
215
|
+
} catch (error) {
|
|
216
|
+
this._globalQuarantined = true;
|
|
217
|
+
throw error;
|
|
218
|
+
} finally{
|
|
219
|
+
this._globalResetOwners -= 1;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
this._globalResetTail = result.then(()=>void 0, ()=>void 0);
|
|
223
|
+
return result;
|
|
224
|
+
}
|
|
225
|
+
_joinOrStart(mode) {
|
|
226
|
+
const active = this._activeDrain;
|
|
227
|
+
if (null !== active) {
|
|
228
|
+
if ('explicit' === mode) active.mode = mode;
|
|
229
|
+
return active;
|
|
230
|
+
}
|
|
231
|
+
let resolveGeneration = ()=>void 0;
|
|
232
|
+
let rejectGeneration = (_reason)=>void 0;
|
|
233
|
+
const promise = new Promise((resolve, reject)=>{
|
|
234
|
+
resolveGeneration = resolve;
|
|
235
|
+
rejectGeneration = reject;
|
|
236
|
+
});
|
|
237
|
+
const generation = {
|
|
238
|
+
promise,
|
|
239
|
+
resolve: resolveGeneration,
|
|
240
|
+
reject: rejectGeneration,
|
|
241
|
+
selectedTokens: new Set(),
|
|
242
|
+
mode,
|
|
243
|
+
backgroundObserved: false,
|
|
244
|
+
inFlightWork: null,
|
|
245
|
+
settlement: null
|
|
246
|
+
};
|
|
247
|
+
this._activeDrain = generation;
|
|
248
|
+
this._runDrain(generation).catch((fault)=>{
|
|
249
|
+
this._closeGeneration(generation, {
|
|
250
|
+
kind: 'fault',
|
|
251
|
+
fault
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
return generation;
|
|
255
|
+
}
|
|
256
|
+
_triggerBackgroundDrain() {
|
|
257
|
+
const generation = this._joinOrStart('background');
|
|
258
|
+
if (generation.backgroundObserved) return;
|
|
259
|
+
generation.backgroundObserved = true;
|
|
260
|
+
generation.promise.catch(()=>void 0);
|
|
261
|
+
}
|
|
262
|
+
async _runDrain(generation) {
|
|
263
|
+
while(true){
|
|
264
|
+
const work = this._queue.nextEligibleWork(generation.selectedTokens, generation.mode);
|
|
265
|
+
if (void 0 === work) return void this._closeGeneration(generation, {
|
|
266
|
+
kind: 'result'
|
|
267
|
+
});
|
|
268
|
+
generation.inFlightWork = work;
|
|
269
|
+
const result = await this._writer.write(work);
|
|
270
|
+
if (true === result) this._queue.acknowledgeSuccess(work);
|
|
271
|
+
else this._queue.acknowledgeFailure(work, result);
|
|
272
|
+
generation.inFlightWork = null;
|
|
273
|
+
this._notifySessionProgress();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
_closeGeneration(generation, termination) {
|
|
277
|
+
if (this._activeDrain !== generation) return;
|
|
278
|
+
let settlement;
|
|
279
|
+
switch(termination.kind){
|
|
280
|
+
case 'result':
|
|
281
|
+
{
|
|
282
|
+
const result = this._queue.generationResult(generation.selectedTokens);
|
|
283
|
+
settlement = 0 === result.failures.length ? {
|
|
284
|
+
kind: 'resolved'
|
|
285
|
+
} : {
|
|
286
|
+
kind: 'rejected',
|
|
287
|
+
reason: new PersistenceDrainError(result.failures)
|
|
288
|
+
};
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case 'fault':
|
|
292
|
+
settlement = {
|
|
293
|
+
kind: 'rejected',
|
|
294
|
+
reason: termination.fault
|
|
295
|
+
};
|
|
296
|
+
break;
|
|
297
|
+
default:
|
|
298
|
+
assertNever(termination);
|
|
299
|
+
}
|
|
300
|
+
generation.inFlightWork = null;
|
|
301
|
+
generation.settlement = settlement;
|
|
302
|
+
this._activeDrain = null;
|
|
303
|
+
this._notifySessionProgress();
|
|
304
|
+
switch(settlement.kind){
|
|
305
|
+
case 'resolved':
|
|
306
|
+
generation.resolve();
|
|
307
|
+
return;
|
|
308
|
+
case 'rejected':
|
|
309
|
+
generation.reject(settlement.reason);
|
|
310
|
+
if (settlement.reason instanceof PersistenceDrainError) this._observeFailure(generation, settlement.reason);
|
|
311
|
+
return;
|
|
312
|
+
default:
|
|
313
|
+
assertNever(settlement);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async _awaitSessionQuiescence(sessionId) {
|
|
317
|
+
const generation = this._joinOrStart('explicit');
|
|
318
|
+
generation.promise.catch(()=>void 0);
|
|
319
|
+
while(true){
|
|
320
|
+
const quiescence = this._sessionQuiescence(generation, sessionId);
|
|
321
|
+
switch(quiescence.kind){
|
|
322
|
+
case 'pending':
|
|
323
|
+
await this._waitForSessionProgress(sessionId);
|
|
324
|
+
break;
|
|
325
|
+
case 'resolved':
|
|
326
|
+
return;
|
|
327
|
+
case 'rejected':
|
|
328
|
+
throw quiescence.reason;
|
|
329
|
+
default:
|
|
330
|
+
return assertNever(quiescence);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
_sessionQuiescence(generation, sessionId) {
|
|
335
|
+
if (generation.settlement?.kind === 'rejected' && !(generation.settlement.reason instanceof PersistenceDrainError)) return {
|
|
336
|
+
kind: 'rejected',
|
|
337
|
+
reason: generation.settlement.reason
|
|
338
|
+
};
|
|
339
|
+
if (generation.inFlightWork?.sessionId === sessionId) return {
|
|
340
|
+
kind: 'pending'
|
|
341
|
+
};
|
|
342
|
+
if (this._queue.hasEligibleWork(generation.selectedTokens, generation.mode, sessionId)) return {
|
|
343
|
+
kind: 'pending'
|
|
344
|
+
};
|
|
345
|
+
const failures = this._queue.currentFailures(generation.selectedTokens, sessionId);
|
|
346
|
+
return 0 === failures.length ? {
|
|
347
|
+
kind: 'resolved'
|
|
348
|
+
} : {
|
|
349
|
+
kind: 'rejected',
|
|
350
|
+
reason: new PersistenceDrainError(failures)
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
_waitForSessionProgress(sessionId) {
|
|
354
|
+
return new Promise((resolve)=>{
|
|
355
|
+
const waiters = this._sessionProgressWaiters.get(sessionId) ?? new Set();
|
|
356
|
+
waiters.add(resolve);
|
|
357
|
+
this._sessionProgressWaiters.set(sessionId, waiters);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
_notifySessionProgress() {
|
|
361
|
+
for (const [sessionId, waiters] of this._sessionProgressWaiters){
|
|
362
|
+
this._sessionProgressWaiters.delete(sessionId);
|
|
363
|
+
for (const resolve of waiters)resolve();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
_assertSessionAdmissionOpen(sessionId) {
|
|
367
|
+
if (this._globalResetOwners > 0 || this._globalQuarantined || this._sessionBarriers.has(sessionId) || this._quarantinedSessions.has(sessionId) || this._evictionQuarantinedSessions.has(sessionId)) throw new PersistenceSessionAdmissionClosedError(sessionId);
|
|
368
|
+
}
|
|
369
|
+
_observeFailure(generation, error) {
|
|
370
|
+
this._logger.info('Persistence drain completed with failures', {
|
|
371
|
+
failed: error.failures.length,
|
|
372
|
+
selected: generation.selectedTokens.size
|
|
373
|
+
});
|
|
374
|
+
this._eventEmitter?.emit('persistenceError', {
|
|
375
|
+
operation: 'flushBuffer',
|
|
376
|
+
error
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
export { PersistenceBuffer };
|
|
381
|
+
|
|
382
|
+
//# sourceMappingURL=PersistenceBuffer.js.map
|