@fgv/ts-agent-memory 5.1.0-47 → 5.1.0-49
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/dist/packlets/ingest/orchestrator.js +11 -1
- package/dist/packlets/ingest/orchestrator.js.map +1 -1
- package/dist/packlets/observe/memoryObservationStore.js +6 -0
- package/dist/packlets/observe/memoryObservationStore.js.map +1 -1
- package/dist/packlets/observe/observer.js.map +1 -1
- package/dist/packlets/retrieve/linkTraversalRetriever.js +1 -1
- package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/dist/packlets/retrieve/recencyRetriever.js +1 -1
- package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/dist/packlets/retrieve/retriever.js +11 -5
- package/dist/packlets/retrieve/retriever.js.map +1 -1
- package/dist/packlets/retrieve/structuredFilterRetriever.js +27 -5
- package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/dist/packlets/retrieve/tagRetriever.js +1 -1
- package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
- package/dist/packlets/retrieve/temporalRetrievers.js +1 -1
- package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/dist/packlets/store/fileTreeMemoryStore.js +152 -132
- package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/dist/packlets/store/vectorMaintenance.js +251 -0
- package/dist/packlets/store/vectorMaintenance.js.map +1 -0
- package/dist/packlets/types/envelope.js.map +1 -1
- package/dist/packlets/vector/inMemoryCosineIndex.js +81 -18
- package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/dist/packlets/vector/vectorIndex.js.map +1 -1
- package/dist/ts-agent-memory.d.ts +431 -79
- package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
- package/lib/packlets/ingest/orchestrator.js +11 -1
- package/lib/packlets/ingest/orchestrator.js.map +1 -1
- package/lib/packlets/observe/memoryObservationStore.d.ts.map +1 -1
- package/lib/packlets/observe/memoryObservationStore.js +6 -0
- package/lib/packlets/observe/memoryObservationStore.js.map +1 -1
- package/lib/packlets/observe/observer.d.ts +61 -0
- package/lib/packlets/observe/observer.d.ts.map +1 -1
- package/lib/packlets/observe/observer.js.map +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.js +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/lib/packlets/retrieve/recencyRetriever.d.ts +1 -1
- package/lib/packlets/retrieve/recencyRetriever.js +1 -1
- package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/lib/packlets/retrieve/retriever.d.ts +26 -7
- package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/retriever.js +11 -5
- package/lib/packlets/retrieve/retriever.js.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +26 -4
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.js +27 -5
- package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/lib/packlets/retrieve/tagRetriever.d.ts +1 -1
- package/lib/packlets/retrieve/tagRetriever.js +1 -1
- package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.js +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.d.ts +135 -59
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +151 -131
- package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/lib/packlets/store/vectorMaintenance.d.ts +149 -0
- package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -0
- package/lib/packlets/store/vectorMaintenance.js +255 -0
- package/lib/packlets/store/vectorMaintenance.js.map +1 -0
- package/lib/packlets/types/envelope.d.ts +11 -0
- package/lib/packlets/types/envelope.d.ts.map +1 -1
- package/lib/packlets/types/envelope.js.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts +30 -7
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.js +80 -17
- package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +7 -0
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +7 -0
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/lib/packlets/vector/vectorIndex.d.ts +129 -1
- package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
- package/lib/packlets/vector/vectorIndex.js.map +1 -1
- package/package.json +17 -7
- package/.rush/temp/5667e36f1c0cc503a5c20a3ebff76e7b9a702d41.tar.log +0 -468
- package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +0 -9
- package/.rush/temp/operation/build/all.log +0 -9
- package/.rush/temp/operation/build/log-chunks.jsonl +0 -9
- package/.rush/temp/operation/build/state.json +0 -3
- package/.rush/temp/shrinkwrap-deps.json +0 -689
- package/config/api-extractor.json +0 -343
- package/config/jest.config.json +0 -14
- package/config/rig.json +0 -4
- package/dist/test/unit/converters/antagonistRoundTrip.test.js +0 -95
- package/dist/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
- package/dist/test/unit/converters/bodyConverterRegistry.test.js +0 -72
- package/dist/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
- package/dist/test/unit/converters/envelopeConverter.test.js +0 -313
- package/dist/test/unit/converters/envelopeConverter.test.js.map +0 -1
- package/dist/test/unit/index/memoryIndex.test.js +0 -214
- package/dist/test/unit/index/memoryIndex.test.js.map +0 -1
- package/dist/test/unit/ingest/antagonistCycleAndParity.test.js +0 -277
- package/dist/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
- package/dist/test/unit/ingest/cycleGuard.test.js +0 -81
- package/dist/test/unit/ingest/cycleGuard.test.js.map +0 -1
- package/dist/test/unit/ingest/dedupScope.test.js +0 -434
- package/dist/test/unit/ingest/dedupScope.test.js.map +0 -1
- package/dist/test/unit/ingest/orchestrator.test.js +0 -1058
- package/dist/test/unit/ingest/orchestrator.test.js.map +0 -1
- package/dist/test/unit/observe/memoryObservationStore.test.js +0 -118
- package/dist/test/unit/observe/memoryObservationStore.test.js.map +0 -1
- package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -116
- package/dist/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
- package/dist/test/unit/retrieve/linkTraversalRetriever.test.js +0 -257
- package/dist/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
- package/dist/test/unit/retrieve/retrievers.test.js +0 -768
- package/dist/test/unit/retrieve/retrievers.test.js.map +0 -1
- package/dist/test/unit/retrieve/temporalRetrievers.test.js +0 -182
- package/dist/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
- package/dist/test/unit/store/antagonistTemporalBoundary.test.js +0 -120
- package/dist/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
- package/dist/test/unit/store/embedOnWrite.test.js +0 -317
- package/dist/test/unit/store/embedOnWrite.test.js.map +0 -1
- package/dist/test/unit/store/fileTreeMemoryStore.test.js +0 -778
- package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
- package/dist/test/unit/store/fragmentEmbedOnWrite.test.js +0 -255
- package/dist/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
- package/dist/test/unit/store/indexInjection.test.js +0 -432
- package/dist/test/unit/store/indexInjection.test.js.map +0 -1
- package/dist/test/unit/store/lenientOpen.test.js +0 -248
- package/dist/test/unit/store/lenientOpen.test.js.map +0 -1
- package/dist/test/unit/store/listScoped.test.js +0 -109
- package/dist/test/unit/store/listScoped.test.js.map +0 -1
- package/dist/test/unit/store/observations.test.js +0 -239
- package/dist/test/unit/store/observations.test.js.map +0 -1
- package/dist/test/unit/store/rankAxis.test.js +0 -254
- package/dist/test/unit/store/rankAxis.test.js.map +0 -1
- package/dist/test/unit/store/scopeEncoding.test.js +0 -24
- package/dist/test/unit/store/scopeEncoding.test.js.map +0 -1
- package/dist/test/unit/store/temporalStore.test.js +0 -398
- package/dist/test/unit/store/temporalStore.test.js.map +0 -1
- package/dist/test/unit/tools/memoryTools.test.js +0 -842
- package/dist/test/unit/tools/memoryTools.test.js.map +0 -1
- package/dist/test/unit/types/identityCodec.test.js +0 -187
- package/dist/test/unit/types/identityCodec.test.js.map +0 -1
- package/dist/test/unit/types/ids.test.js +0 -84
- package/dist/test/unit/types/ids.test.js.map +0 -1
- package/dist/test/unit/types/temporalCodec.test.js +0 -203
- package/dist/test/unit/types/temporalCodec.test.js.map +0 -1
- package/dist/test/unit/types/temporalPolicy.test.js +0 -83
- package/dist/test/unit/types/temporalPolicy.test.js.map +0 -1
- package/dist/test/unit/types/writePolicy.test.js +0 -331
- package/dist/test/unit/types/writePolicy.test.js.map +0 -1
- package/dist/test/unit/vector/fragmentConverters.test.js +0 -58
- package/dist/test/unit/vector/fragmentConverters.test.js.map +0 -1
- package/dist/test/unit/vector/inMemoryCosineIndex.test.js +0 -252
- package/dist/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
- package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -362
- package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
- package/dist/test/unit/vector/vectorIndex.test.js +0 -51
- package/dist/test/unit/vector/vectorIndex.test.js.map +0 -1
- package/eslint.config.js +0 -15
- package/etc/ts-agent-memory.api.md +0 -940
- package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts +0 -10
- package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts.map +0 -1
- package/lib/test/unit/converters/antagonistRoundTrip.test.js +0 -97
- package/lib/test/unit/converters/antagonistRoundTrip.test.js.map +0 -1
- package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts +0 -2
- package/lib/test/unit/converters/bodyConverterRegistry.test.d.ts.map +0 -1
- package/lib/test/unit/converters/bodyConverterRegistry.test.js +0 -74
- package/lib/test/unit/converters/bodyConverterRegistry.test.js.map +0 -1
- package/lib/test/unit/converters/envelopeConverter.test.d.ts +0 -2
- package/lib/test/unit/converters/envelopeConverter.test.d.ts.map +0 -1
- package/lib/test/unit/converters/envelopeConverter.test.js +0 -315
- package/lib/test/unit/converters/envelopeConverter.test.js.map +0 -1
- package/lib/test/unit/index/memoryIndex.test.d.ts +0 -2
- package/lib/test/unit/index/memoryIndex.test.d.ts.map +0 -1
- package/lib/test/unit/index/memoryIndex.test.js +0 -216
- package/lib/test/unit/index/memoryIndex.test.js.map +0 -1
- package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts +0 -9
- package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts.map +0 -1
- package/lib/test/unit/ingest/antagonistCycleAndParity.test.js +0 -279
- package/lib/test/unit/ingest/antagonistCycleAndParity.test.js.map +0 -1
- package/lib/test/unit/ingest/cycleGuard.test.d.ts +0 -2
- package/lib/test/unit/ingest/cycleGuard.test.d.ts.map +0 -1
- package/lib/test/unit/ingest/cycleGuard.test.js +0 -83
- package/lib/test/unit/ingest/cycleGuard.test.js.map +0 -1
- package/lib/test/unit/ingest/dedupScope.test.d.ts +0 -2
- package/lib/test/unit/ingest/dedupScope.test.d.ts.map +0 -1
- package/lib/test/unit/ingest/dedupScope.test.js +0 -436
- package/lib/test/unit/ingest/dedupScope.test.js.map +0 -1
- package/lib/test/unit/ingest/orchestrator.test.d.ts +0 -2
- package/lib/test/unit/ingest/orchestrator.test.d.ts.map +0 -1
- package/lib/test/unit/ingest/orchestrator.test.js +0 -1060
- package/lib/test/unit/ingest/orchestrator.test.js.map +0 -1
- package/lib/test/unit/observe/memoryObservationStore.test.d.ts +0 -2
- package/lib/test/unit/observe/memoryObservationStore.test.d.ts.map +0 -1
- package/lib/test/unit/observe/memoryObservationStore.test.js +0 -120
- package/lib/test/unit/observe/memoryObservationStore.test.js.map +0 -1
- package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts +0 -2
- package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.d.ts.map +0 -1
- package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js +0 -118
- package/lib/test/unit/retrieve/fragmentSemanticRetriever.test.js.map +0 -1
- package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts +0 -2
- package/lib/test/unit/retrieve/linkTraversalRetriever.test.d.ts.map +0 -1
- package/lib/test/unit/retrieve/linkTraversalRetriever.test.js +0 -259
- package/lib/test/unit/retrieve/linkTraversalRetriever.test.js.map +0 -1
- package/lib/test/unit/retrieve/retrievers.test.d.ts +0 -2
- package/lib/test/unit/retrieve/retrievers.test.d.ts.map +0 -1
- package/lib/test/unit/retrieve/retrievers.test.js +0 -770
- package/lib/test/unit/retrieve/retrievers.test.js.map +0 -1
- package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts +0 -2
- package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts.map +0 -1
- package/lib/test/unit/retrieve/temporalRetrievers.test.js +0 -184
- package/lib/test/unit/retrieve/temporalRetrievers.test.js.map +0 -1
- package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts +0 -9
- package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts.map +0 -1
- package/lib/test/unit/store/antagonistTemporalBoundary.test.js +0 -122
- package/lib/test/unit/store/antagonistTemporalBoundary.test.js.map +0 -1
- package/lib/test/unit/store/embedOnWrite.test.d.ts +0 -2
- package/lib/test/unit/store/embedOnWrite.test.d.ts.map +0 -1
- package/lib/test/unit/store/embedOnWrite.test.js +0 -319
- package/lib/test/unit/store/embedOnWrite.test.js.map +0 -1
- package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts +0 -2
- package/lib/test/unit/store/fileTreeMemoryStore.test.d.ts.map +0 -1
- package/lib/test/unit/store/fileTreeMemoryStore.test.js +0 -780
- package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +0 -1
- package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts +0 -2
- package/lib/test/unit/store/fragmentEmbedOnWrite.test.d.ts.map +0 -1
- package/lib/test/unit/store/fragmentEmbedOnWrite.test.js +0 -257
- package/lib/test/unit/store/fragmentEmbedOnWrite.test.js.map +0 -1
- package/lib/test/unit/store/indexInjection.test.d.ts +0 -2
- package/lib/test/unit/store/indexInjection.test.d.ts.map +0 -1
- package/lib/test/unit/store/indexInjection.test.js +0 -434
- package/lib/test/unit/store/indexInjection.test.js.map +0 -1
- package/lib/test/unit/store/lenientOpen.test.d.ts +0 -2
- package/lib/test/unit/store/lenientOpen.test.d.ts.map +0 -1
- package/lib/test/unit/store/lenientOpen.test.js +0 -250
- package/lib/test/unit/store/lenientOpen.test.js.map +0 -1
- package/lib/test/unit/store/listScoped.test.d.ts +0 -2
- package/lib/test/unit/store/listScoped.test.d.ts.map +0 -1
- package/lib/test/unit/store/listScoped.test.js +0 -111
- package/lib/test/unit/store/listScoped.test.js.map +0 -1
- package/lib/test/unit/store/observations.test.d.ts +0 -2
- package/lib/test/unit/store/observations.test.d.ts.map +0 -1
- package/lib/test/unit/store/observations.test.js +0 -241
- package/lib/test/unit/store/observations.test.js.map +0 -1
- package/lib/test/unit/store/rankAxis.test.d.ts +0 -2
- package/lib/test/unit/store/rankAxis.test.d.ts.map +0 -1
- package/lib/test/unit/store/rankAxis.test.js +0 -256
- package/lib/test/unit/store/rankAxis.test.js.map +0 -1
- package/lib/test/unit/store/scopeEncoding.test.d.ts +0 -2
- package/lib/test/unit/store/scopeEncoding.test.d.ts.map +0 -1
- package/lib/test/unit/store/scopeEncoding.test.js +0 -26
- package/lib/test/unit/store/scopeEncoding.test.js.map +0 -1
- package/lib/test/unit/store/temporalStore.test.d.ts +0 -2
- package/lib/test/unit/store/temporalStore.test.d.ts.map +0 -1
- package/lib/test/unit/store/temporalStore.test.js +0 -400
- package/lib/test/unit/store/temporalStore.test.js.map +0 -1
- package/lib/test/unit/tools/memoryTools.test.d.ts +0 -2
- package/lib/test/unit/tools/memoryTools.test.d.ts.map +0 -1
- package/lib/test/unit/tools/memoryTools.test.js +0 -844
- package/lib/test/unit/tools/memoryTools.test.js.map +0 -1
- package/lib/test/unit/types/identityCodec.test.d.ts +0 -2
- package/lib/test/unit/types/identityCodec.test.d.ts.map +0 -1
- package/lib/test/unit/types/identityCodec.test.js +0 -189
- package/lib/test/unit/types/identityCodec.test.js.map +0 -1
- package/lib/test/unit/types/ids.test.d.ts +0 -2
- package/lib/test/unit/types/ids.test.d.ts.map +0 -1
- package/lib/test/unit/types/ids.test.js +0 -86
- package/lib/test/unit/types/ids.test.js.map +0 -1
- package/lib/test/unit/types/temporalCodec.test.d.ts +0 -2
- package/lib/test/unit/types/temporalCodec.test.d.ts.map +0 -1
- package/lib/test/unit/types/temporalCodec.test.js +0 -205
- package/lib/test/unit/types/temporalCodec.test.js.map +0 -1
- package/lib/test/unit/types/temporalPolicy.test.d.ts +0 -2
- package/lib/test/unit/types/temporalPolicy.test.d.ts.map +0 -1
- package/lib/test/unit/types/temporalPolicy.test.js +0 -85
- package/lib/test/unit/types/temporalPolicy.test.js.map +0 -1
- package/lib/test/unit/types/writePolicy.test.d.ts +0 -2
- package/lib/test/unit/types/writePolicy.test.d.ts.map +0 -1
- package/lib/test/unit/types/writePolicy.test.js +0 -333
- package/lib/test/unit/types/writePolicy.test.js.map +0 -1
- package/lib/test/unit/vector/fragmentConverters.test.d.ts +0 -2
- package/lib/test/unit/vector/fragmentConverters.test.d.ts.map +0 -1
- package/lib/test/unit/vector/fragmentConverters.test.js +0 -60
- package/lib/test/unit/vector/fragmentConverters.test.js.map +0 -1
- package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts +0 -2
- package/lib/test/unit/vector/inMemoryCosineIndex.test.d.ts.map +0 -1
- package/lib/test/unit/vector/inMemoryCosineIndex.test.js +0 -254
- package/lib/test/unit/vector/inMemoryCosineIndex.test.js.map +0 -1
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts +0 -2
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.d.ts.map +0 -1
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js +0 -364
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +0 -1
- package/lib/test/unit/vector/vectorIndex.test.d.ts +0 -2
- package/lib/test/unit/vector/vectorIndex.test.d.ts.map +0 -1
- package/lib/test/unit/vector/vectorIndex.test.js +0 -53
- package/lib/test/unit/vector/vectorIndex.test.js.map +0 -1
- package/rush-logs/ts-agent-memory.build.cache.log +0 -3
- package/rush-logs/ts-agent-memory.build.log +0 -9
- package/src/index.ts +0 -14
- package/src/packlets/converters/bodyConverterRegistry.ts +0 -105
- package/src/packlets/converters/envelopeConverter.ts +0 -233
- package/src/packlets/converters/index.ts +0 -7
- package/src/packlets/index/index.ts +0 -6
- package/src/packlets/index/memoryIndex.ts +0 -332
- package/src/packlets/ingest/cycleGuard.ts +0 -153
- package/src/packlets/ingest/hostStages.ts +0 -111
- package/src/packlets/ingest/index.ts +0 -9
- package/src/packlets/ingest/model.ts +0 -195
- package/src/packlets/ingest/orchestrator.ts +0 -968
- package/src/packlets/observe/index.ts +0 -7
- package/src/packlets/observe/memoryObservationStore.ts +0 -153
- package/src/packlets/observe/observer.ts +0 -119
- package/src/packlets/retrieve/fragmentSemanticRetriever.ts +0 -138
- package/src/packlets/retrieve/hybridRetriever.ts +0 -194
- package/src/packlets/retrieve/index.ts +0 -14
- package/src/packlets/retrieve/linkTraversalRetriever.ts +0 -158
- package/src/packlets/retrieve/recencyRetriever.ts +0 -54
- package/src/packlets/retrieve/retriever.ts +0 -291
- package/src/packlets/retrieve/semanticRetriever.ts +0 -152
- package/src/packlets/retrieve/structuredFilterRetriever.ts +0 -58
- package/src/packlets/retrieve/tagRetriever.ts +0 -58
- package/src/packlets/retrieve/temporalRetrievers.ts +0 -210
- package/src/packlets/store/fileTreeMemoryStore.ts +0 -1872
- package/src/packlets/store/index.ts +0 -7
- package/src/packlets/store/scopeEncoding.ts +0 -36
- package/src/packlets/tools/index.ts +0 -6
- package/src/packlets/tools/memoryTools.ts +0 -706
- package/src/packlets/types/envelope.ts +0 -196
- package/src/packlets/types/filenameSafety.ts +0 -57
- package/src/packlets/types/identityCodec.ts +0 -447
- package/src/packlets/types/ids.ts +0 -124
- package/src/packlets/types/index.ts +0 -11
- package/src/packlets/types/temporal.ts +0 -96
- package/src/packlets/types/writePolicy.ts +0 -612
- package/src/packlets/vector/fragmentConverters.ts +0 -55
- package/src/packlets/vector/inMemoryCosineIndex.ts +0 -196
- package/src/packlets/vector/inMemoryFragmentCosineIndex.ts +0 -289
- package/src/packlets/vector/index.ts +0 -9
- package/src/packlets/vector/vectorIndex.ts +0 -273
- package/src/test/unit/converters/antagonistRoundTrip.test.ts +0 -110
- package/src/test/unit/converters/bodyConverterRegistry.test.ts +0 -89
- package/src/test/unit/converters/envelopeConverter.test.ts +0 -418
- package/src/test/unit/index/memoryIndex.test.ts +0 -272
- package/src/test/unit/ingest/antagonistCycleAndParity.test.ts +0 -367
- package/src/test/unit/ingest/cycleGuard.test.ts +0 -110
- package/src/test/unit/ingest/dedupScope.test.ts +0 -542
- package/src/test/unit/ingest/orchestrator.test.ts +0 -1355
- package/src/test/unit/observe/memoryObservationStore.test.ts +0 -158
- package/src/test/unit/retrieve/fragmentSemanticRetriever.test.ts +0 -163
- package/src/test/unit/retrieve/linkTraversalRetriever.test.ts +0 -329
- package/src/test/unit/retrieve/retrievers.test.ts +0 -1018
- package/src/test/unit/retrieve/temporalRetrievers.test.ts +0 -226
- package/src/test/unit/store/antagonistTemporalBoundary.test.ts +0 -158
- package/src/test/unit/store/embedOnWrite.test.ts +0 -418
- package/src/test/unit/store/fileTreeMemoryStore.test.ts +0 -1041
- package/src/test/unit/store/fragmentEmbedOnWrite.test.ts +0 -349
- package/src/test/unit/store/indexInjection.test.ts +0 -550
- package/src/test/unit/store/lenientOpen.test.ts +0 -292
- package/src/test/unit/store/listScoped.test.ts +0 -138
- package/src/test/unit/store/observations.test.ts +0 -290
- package/src/test/unit/store/rankAxis.test.ts +0 -349
- package/src/test/unit/store/scopeEncoding.test.ts +0 -37
- package/src/test/unit/store/temporalStore.test.ts +0 -469
- package/src/test/unit/tools/memoryTools.test.ts +0 -1121
- package/src/test/unit/types/identityCodec.test.ts +0 -266
- package/src/test/unit/types/ids.test.ts +0 -94
- package/src/test/unit/types/temporalCodec.test.ts +0 -259
- package/src/test/unit/types/temporalPolicy.test.ts +0 -124
- package/src/test/unit/types/writePolicy.test.ts +0 -446
- package/src/test/unit/vector/fragmentConverters.test.ts +0 -80
- package/src/test/unit/vector/inMemoryCosineIndex.test.ts +0 -318
- package/src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts +0 -477
- package/src/test/unit/vector/vectorIndex.test.ts +0 -64
- package/temp/build/lint/_eslint-5eVG3S6w.json +0 -306
- package/temp/build/typescript/ts_8nwakTlr.json +0 -1
- package/temp/ts-agent-memory.api.json +0 -21030
- package/temp/ts-agent-memory.api.md +0 -940
- package/tsconfig.json +0 -8
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
import { Hash, Logging, fail, mapResults, mapSuccess, succeed } from '@fgv/ts-utils';
|
|
6
6
|
import { FileTree } from '@fgv/ts-json-base';
|
|
7
7
|
import { DEFAULT_DEDUP_SCOPE, KnowledgeLwwPolicy, isTemporalIdentityCodec, isTemporalRecord, isVersionCurrent, selectCurrentVersion, selectVersionAsOf } from '../types';
|
|
8
|
-
import { parseMemoryFile, serializeMemoryFile } from '../converters';
|
|
8
|
+
import { parseMemoryFile, serializeMemoryFile, splitFrontmatter } from '../converters';
|
|
9
|
+
import { VectorMaintenance } from './vectorMaintenance';
|
|
9
10
|
import { MemoryIndex } from '../index';
|
|
10
11
|
import { defaultMemoryScopeEncoding } from './scopeEncoding';
|
|
11
12
|
/** The on-disk extension for a memory record file. */
|
|
@@ -26,11 +27,13 @@ const MEMORY_FILE_EXTENSION = '.md';
|
|
|
26
27
|
*/
|
|
27
28
|
export class FileTreeMemoryStore {
|
|
28
29
|
constructor(params) {
|
|
30
|
+
var _a;
|
|
29
31
|
this._root = params.root;
|
|
30
32
|
this._registry = params.registry;
|
|
31
33
|
this._writePolicies = params.writePolicies;
|
|
32
34
|
this._codecs = params.codecs;
|
|
33
35
|
this._rankProjectors = params.rankProjectors;
|
|
36
|
+
this._embedKinds = (_a = params.embedKinds) !== null && _a !== void 0 ? _a : undefined;
|
|
34
37
|
this._defaultCodec = params.defaultCodec;
|
|
35
38
|
this._defaultPolicy = params.defaultPolicy;
|
|
36
39
|
this._scopeEncoding = params.scopeEncoding;
|
|
@@ -39,10 +42,14 @@ export class FileTreeMemoryStore {
|
|
|
39
42
|
this._hasher = new Hash.Crc32Normalizer();
|
|
40
43
|
this._observers = params.observers;
|
|
41
44
|
this._logger = params.logger;
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
this._vectors = new VectorMaintenance({
|
|
46
|
+
vectorIndex: params.vectorIndex,
|
|
47
|
+
embed: params.embed,
|
|
48
|
+
fragmentIndex: params.fragmentIndex,
|
|
49
|
+
fragmentEmbedder: params.fragmentEmbedder,
|
|
50
|
+
warn: (message) => this._warnSwallowed(message),
|
|
51
|
+
embedsKind: (kind) => this.embedsKind(kind)
|
|
52
|
+
});
|
|
46
53
|
this._skippedRecords = [];
|
|
47
54
|
this._seq = 0;
|
|
48
55
|
this._observationSeq = 0;
|
|
@@ -75,6 +82,7 @@ export class FileTreeMemoryStore {
|
|
|
75
82
|
writePolicies: (_a = params.writePolicies) !== null && _a !== void 0 ? _a : new Map(),
|
|
76
83
|
codecs: (_b = params.codecs) !== null && _b !== void 0 ? _b : new Map(),
|
|
77
84
|
rankProjectors: (_c = params.rankProjectors) !== null && _c !== void 0 ? _c : new Map(),
|
|
85
|
+
embedKinds: params.embedKinds,
|
|
78
86
|
defaultCodec: params.defaultCodec,
|
|
79
87
|
defaultPolicy,
|
|
80
88
|
scopeEncoding: (_d = params.scopeEncoding) !== null && _d !== void 0 ? _d : defaultMemoryScopeEncoding,
|
|
@@ -168,7 +176,14 @@ export class FileTreeMemoryStore {
|
|
|
168
176
|
}
|
|
169
177
|
/** {@inheritDoc IMemoryStore.asRecordSource} */
|
|
170
178
|
asRecordSource() {
|
|
171
|
-
return {
|
|
179
|
+
return {
|
|
180
|
+
// Filtered to the kinds that participate in the record vector index. This
|
|
181
|
+
// source exists to drive `IVectorIndex` rebuilds, so a kind excluded from the
|
|
182
|
+
// index has no business being re-embedded on open — which is where the cost
|
|
183
|
+
// is worst, since a rebuild embeds the whole vault serially. With no
|
|
184
|
+
// `embedKinds` declaration every kind passes and this is the identity filter.
|
|
185
|
+
list: async () => (await this.listScoped()).onSuccess((scoped) => succeed(scoped.filter((s) => this.embedsKind(s.record.envelope.kind))))
|
|
186
|
+
};
|
|
172
187
|
}
|
|
173
188
|
/**
|
|
174
189
|
* Collapse temporal records to the single version valid at `asOf` per entity;
|
|
@@ -203,6 +218,10 @@ export class FileTreeMemoryStore {
|
|
|
203
218
|
}
|
|
204
219
|
return result;
|
|
205
220
|
}
|
|
221
|
+
/** {@inheritDoc IMemoryStore.reconcileRank} */
|
|
222
|
+
async reconcileRank(kind) {
|
|
223
|
+
return this._enqueue(() => this._reconcileRankLocked(kind));
|
|
224
|
+
}
|
|
206
225
|
/** {@inheritDoc IMemoryStore.put} */
|
|
207
226
|
async put(record) {
|
|
208
227
|
const result = await this._enqueue(() => this._putLocked(record));
|
|
@@ -210,7 +229,8 @@ export class FileTreeMemoryStore {
|
|
|
210
229
|
outcome: result.isSuccess() ? 'success' : 'failure',
|
|
211
230
|
id: result.isSuccess() ? result.value.record.envelope.id : record.envelope.id,
|
|
212
231
|
provenance: record.envelope.provenance,
|
|
213
|
-
error: result.isFailure() ? result.message : undefined
|
|
232
|
+
error: result.isFailure() ? result.message : undefined,
|
|
233
|
+
embed: result.isSuccess() ? result.value.embed : undefined
|
|
214
234
|
});
|
|
215
235
|
// Fire one `'delete'` observation per record evicted by cap-cull. The
|
|
216
236
|
// evicted records are always in the same `(scope, kind)` cohort as the
|
|
@@ -266,7 +286,8 @@ export class FileTreeMemoryStore {
|
|
|
266
286
|
kind,
|
|
267
287
|
outcome: details.outcome,
|
|
268
288
|
error: details.error,
|
|
269
|
-
provenance: details.provenance
|
|
289
|
+
provenance: details.provenance,
|
|
290
|
+
embed: details.embed
|
|
270
291
|
};
|
|
271
292
|
const awaited = [];
|
|
272
293
|
for (const observer of this._observers) {
|
|
@@ -419,89 +440,27 @@ export class FileTreeMemoryStore {
|
|
|
419
440
|
}
|
|
420
441
|
return this._buildRecord(record, body, existing, policy, hash)
|
|
421
442
|
.onSuccess((built) => succeed(this._stampRank(built)))
|
|
422
|
-
.thenOnSuccess((built) => this.
|
|
423
|
-
.thenOnSuccess((
|
|
424
|
-
.onSuccess((
|
|
425
|
-
.thenOnSuccess(async (persisted) => {
|
|
443
|
+
.thenOnSuccess((built) => this._vectors.embedOnWrite(built, scope))
|
|
444
|
+
.thenOnSuccess(async (embedded) => (await this._vectors.embedFragmentsOnWrite(embedded.record, scope)).onSuccess((withFragments) => succeed(Object.assign(Object.assign({}, embedded), { record: withFragments }))))
|
|
445
|
+
.onSuccess((embedded) => this._persist(embedded.record, scope, idStem).onSuccess((persisted) => succeed({ persisted, stale: embedded.stale, embed: embedded.embed })))
|
|
446
|
+
.thenOnSuccess(async ({ persisted, stale, embed }) => {
|
|
426
447
|
// Everything after the authoritative `_persist` commit is best-effort and
|
|
427
448
|
// never turns a committed write into a `Failure`:
|
|
449
|
+
// - a stale vector superseded by a decline is pruned here rather than at
|
|
450
|
+
// the point of the decline, because a `_persist` that fails leaves the
|
|
451
|
+
// PREVIOUS content on disk — content that vector is still an accurate
|
|
452
|
+
// embedding of. Pruning early would delete a correct vector on behalf
|
|
453
|
+
// of a write that never landed;
|
|
428
454
|
// - a cull-oldest eviction that fails is logged (the per-(scope,kind)
|
|
429
455
|
// cap may be transiently exceeded; the next write's admission restores
|
|
430
456
|
// it), and only the successfully-evicted ids flow onward;
|
|
431
457
|
// - vector pruning of the evicted cohort is likewise best-effort.
|
|
458
|
+
await this._vectors.pruneStaleVector(stale);
|
|
432
459
|
const evicted = this._applyEvictions(decision, scope);
|
|
433
|
-
await this.
|
|
434
|
-
return succeed({ record: persisted, evicted });
|
|
460
|
+
await this._vectors.removeEvictedVectors(evicted, scope);
|
|
461
|
+
return succeed({ record: persisted, evicted, embed });
|
|
435
462
|
});
|
|
436
463
|
}
|
|
437
|
-
/**
|
|
438
|
-
* Best-effort embed-on-write. When a vector index AND an embedder are wired,
|
|
439
|
-
* embeds the built record, `add`s the vector (replace semantics handle a same-id
|
|
440
|
-
* re-embed — no explicit remove), and stamps the returned `embeddingRef`. A
|
|
441
|
-
* failure (returned `fail` OR a thrown/rejected hook) is logged and the
|
|
442
|
-
* unembedded record is returned unchanged — the put still persists, and the
|
|
443
|
-
* derived index is reconciled by a later `rebuild`. A pass-through no-op when
|
|
444
|
-
* unwired (byte-identical record).
|
|
445
|
-
*
|
|
446
|
-
* Always succeeds (`Result` is the chain's shape, never a vector-induced
|
|
447
|
-
* failure).
|
|
448
|
-
*/
|
|
449
|
-
async _embedOnWrite(built, scope) {
|
|
450
|
-
if (this._vectorIndex === undefined || this._embed === undefined) {
|
|
451
|
-
return succeed(built);
|
|
452
|
-
}
|
|
453
|
-
const vectorIndex = this._vectorIndex;
|
|
454
|
-
const embed = this._embed;
|
|
455
|
-
const target = { scope, id: built.envelope.id };
|
|
456
|
-
const embedded = await this._tryVectorOp(() => embed(built), `embedding '${built.envelope.id}'`);
|
|
457
|
-
if (embedded.isFailure()) {
|
|
458
|
-
return succeed(built);
|
|
459
|
-
}
|
|
460
|
-
const added = await this._tryVectorOp(() => vectorIndex.add(target, embedded.value), `vector add for '${built.envelope.id}'`);
|
|
461
|
-
if (added.isFailure()) {
|
|
462
|
-
return succeed(built);
|
|
463
|
-
}
|
|
464
|
-
return succeed({ envelope: Object.assign(Object.assign({}, built.envelope), { embeddingRef: added.value }), body: built.body });
|
|
465
|
-
}
|
|
466
|
-
/**
|
|
467
|
-
* Best-effort fragment-embed-on-write. When a fragment index AND a fragment
|
|
468
|
-
* embedder are wired, chunks + embeds the built record and replaces its
|
|
469
|
-
* fragments in the index (`addFragments` is whole-record-replace, so a re-authored
|
|
470
|
-
* document never leaves stale fragments behind — no explicit remove needed). A
|
|
471
|
-
* failure (returned `fail` OR a thrown/rejected hook) is logged and the record is
|
|
472
|
-
* returned unchanged — the put still persists, and the fragment index is a derived
|
|
473
|
-
* view a later `rebuild` reconciles. Unlike {@link FileTreeMemoryStore._embedOnWrite}
|
|
474
|
-
* it stamps nothing on the record (fragments have no per-record `embeddingRef`
|
|
475
|
-
* analog). A pass-through no-op when unwired (byte-identical record).
|
|
476
|
-
*/
|
|
477
|
-
async _embedFragmentsOnWrite(built, scope) {
|
|
478
|
-
if (this._fragmentIndex === undefined || this._fragmentEmbedder === undefined) {
|
|
479
|
-
return succeed(built);
|
|
480
|
-
}
|
|
481
|
-
const fragmentIndex = this._fragmentIndex;
|
|
482
|
-
const fragmentEmbedder = this._fragmentEmbedder;
|
|
483
|
-
const target = { scope, id: built.envelope.id };
|
|
484
|
-
const embedded = await this._tryVectorOp(() => fragmentEmbedder(built), `fragment embedding '${built.envelope.id}'`);
|
|
485
|
-
if (embedded.isFailure()) {
|
|
486
|
-
return succeed(built);
|
|
487
|
-
}
|
|
488
|
-
await this._tryVectorOp(() => fragmentIndex.addFragments(target, embedded.value), `fragment add for '${built.envelope.id}'`);
|
|
489
|
-
return succeed(built);
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Best-effort fragment removal. A no-op unless the full fragment lifecycle is
|
|
493
|
-
* wired (both an index AND an embedder), so an unwired store does no fragment
|
|
494
|
-
* work and behaves byte-identically. Failures are logged, never surfaced — a
|
|
495
|
-
* committed delete/eviction must not fail because a derived fragment index could
|
|
496
|
-
* not be pruned.
|
|
497
|
-
*/
|
|
498
|
-
async _removeFragmentsBestEffort(target) {
|
|
499
|
-
if (this._fragmentIndex === undefined || this._fragmentEmbedder === undefined) {
|
|
500
|
-
return;
|
|
501
|
-
}
|
|
502
|
-
const fragmentIndex = this._fragmentIndex;
|
|
503
|
-
await this._tryVectorOp(() => fragmentIndex.remove(target), `fragment removal for '${target.id}'`);
|
|
504
|
-
}
|
|
505
464
|
/**
|
|
506
465
|
* Evict the records named by a `cull-oldest` decision, best-effort. Runs only
|
|
507
466
|
* after the authoritative `_persist`, so a failed eviction is logged (never
|
|
@@ -525,49 +484,6 @@ export class FileTreeMemoryStore {
|
|
|
525
484
|
}
|
|
526
485
|
return evicted;
|
|
527
486
|
}
|
|
528
|
-
/**
|
|
529
|
-
* Best-effort vector removal for each evicted record (never fails the put).
|
|
530
|
-
* Every evicted record is in the same `scope` as the incoming write (the
|
|
531
|
-
* cull-oldest cohort is the incoming record's `(scope, kind)` cohort), so that
|
|
532
|
-
* scope qualifies each removal target.
|
|
533
|
-
*/
|
|
534
|
-
async _removeEvictedVectors(evicted, scope) {
|
|
535
|
-
for (const id of evicted) {
|
|
536
|
-
await this._removeVectorBestEffort({ scope, id });
|
|
537
|
-
await this._removeFragmentsBestEffort({ scope, id });
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Run a consumer-supplied vector hook, normalizing a thrown/rejected hook into a
|
|
542
|
-
* `Failure` and logging any failure at `warn`. Best-effort: the caller proceeds
|
|
543
|
-
* regardless, since the index is rebuildable.
|
|
544
|
-
*/
|
|
545
|
-
async _tryVectorOp(op, label) {
|
|
546
|
-
let result;
|
|
547
|
-
try {
|
|
548
|
-
result = await op();
|
|
549
|
-
}
|
|
550
|
-
catch (err) {
|
|
551
|
-
result = fail(`${label} threw: ${String(err)}`);
|
|
552
|
-
}
|
|
553
|
-
if (result.isFailure()) {
|
|
554
|
-
this._warnSwallowed(`memory: ${label} failed (best-effort; derived index left for rebuild): ${result.message}`);
|
|
555
|
-
}
|
|
556
|
-
return result;
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Best-effort vector removal. A no-op unless the full vector lifecycle is wired
|
|
560
|
-
* (both an index AND an embedder), so an unwired store does no vector work and
|
|
561
|
-
* behaves byte-identically. Failures are logged, never surfaced — a committed
|
|
562
|
-
* delete/eviction must not fail because a derived index could not be pruned.
|
|
563
|
-
*/
|
|
564
|
-
async _removeVectorBestEffort(target) {
|
|
565
|
-
if (this._vectorIndex === undefined || this._embed === undefined) {
|
|
566
|
-
return;
|
|
567
|
-
}
|
|
568
|
-
const vectorIndex = this._vectorIndex;
|
|
569
|
-
await this._tryVectorOp(() => vectorIndex.remove(target), `vector removal for '${target.id}'`);
|
|
570
|
-
}
|
|
571
487
|
/**
|
|
572
488
|
* Build the record to persist. On a first write the incoming envelope is the
|
|
573
489
|
* base (final content equals the incoming content, so the dedup `hash` is
|
|
@@ -637,8 +553,7 @@ export class FileTreeMemoryStore {
|
|
|
637
553
|
return this._deleteFile(scope, idStem)
|
|
638
554
|
.onSuccess(() => this._index.patch('delete', { scope, record: existing }))
|
|
639
555
|
.thenOnSuccess(async () => {
|
|
640
|
-
await this.
|
|
641
|
-
await this._removeFragmentsBestEffort({ scope, id: existing.envelope.id });
|
|
556
|
+
await this._vectors.removeAll({ scope, id: existing.envelope.id });
|
|
642
557
|
return succeed(existing.envelope.id);
|
|
643
558
|
});
|
|
644
559
|
});
|
|
@@ -724,11 +639,15 @@ export class FileTreeMemoryStore {
|
|
|
724
639
|
.withErrorFormat((msg) => `memory put '${entityId}': ${msg}`)
|
|
725
640
|
.thenOnSuccess((versionStem) => this._buildVersionedRecord(record, body, current, policy, hash, versionStem, validAt, now, seq)
|
|
726
641
|
.onSuccess((built) => succeed(this._stampRank(built)))
|
|
727
|
-
.thenOnSuccess((built) => this.
|
|
728
|
-
.thenOnSuccess((
|
|
729
|
-
.onSuccess((
|
|
730
|
-
.onSuccess((persisted) => this._invalidateCurrents(scope, priorCurrents, validAt, now).onSuccess(() => succeed(persisted)))
|
|
731
|
-
|
|
642
|
+
.thenOnSuccess((built) => this._vectors.embedOnWrite(built, scope))
|
|
643
|
+
.thenOnSuccess(async (embedded) => (await this._vectors.embedFragmentsOnWrite(embedded.record, scope)).onSuccess((withFragments) => succeed(Object.assign(Object.assign({}, embedded), { record: withFragments }))))
|
|
644
|
+
.onSuccess((embedded) => this._persist(embedded.record, scope, versionStem).onSuccess((persisted) => succeed({ persisted, stale: embedded.stale, embed: embedded.embed })))
|
|
645
|
+
.onSuccess(({ persisted, stale, embed }) => this._invalidateCurrents(scope, priorCurrents, validAt, now).onSuccess(() => succeed({ persisted, stale, embed })))
|
|
646
|
+
// Post-commit and best-effort, exactly as on the flat path.
|
|
647
|
+
.thenOnSuccess(async ({ persisted, stale, embed }) => {
|
|
648
|
+
await this._vectors.pruneStaleVector(stale);
|
|
649
|
+
return succeed({ record: persisted, evicted: [], embed });
|
|
650
|
+
}));
|
|
732
651
|
});
|
|
733
652
|
});
|
|
734
653
|
}
|
|
@@ -893,6 +812,101 @@ export class FileTreeMemoryStore {
|
|
|
893
812
|
_contentHash(kind, body, links) {
|
|
894
813
|
return this._hasher.computeHash({ kind, body, links });
|
|
895
814
|
}
|
|
815
|
+
/**
|
|
816
|
+
* The locked body of {@link FileTreeMemoryStore.reconcileRank}.
|
|
817
|
+
*
|
|
818
|
+
* @remarks
|
|
819
|
+
* Re-reads each record's file rather than trusting the in-memory index, for
|
|
820
|
+
* two reasons: the index holds converted bodies on some paths and raw ones on
|
|
821
|
+
* others, and re-serializing a *converted* body could change the bytes on disk
|
|
822
|
+
* — a reconcile of an ordering field has no business rewriting content.
|
|
823
|
+
* `splitFrontmatter` hands back the body text unconverted, so the round trip
|
|
824
|
+
* carries the authored characters through untouched and only the envelope
|
|
825
|
+
* moves. The parsed record is additionally put through `_verifyLoaded`, the
|
|
826
|
+
* same id-vs-filename and scope-derived-entityId check the load paths apply —
|
|
827
|
+
* without it, reconcile would be the one path that accepts and rewrites a file
|
|
828
|
+
* the store would refuse to load.
|
|
829
|
+
*
|
|
830
|
+
* "Untouched" is not quite "byte-identical", and the exception is line
|
|
831
|
+
* endings: `splitFrontmatter` strips a trailing `\r` per line and
|
|
832
|
+
* `joinFrontmatter` writes `\n` delimiters, so a CRLF-authored file comes back
|
|
833
|
+
* LF-normalized. That is **the store's behavior on every write path, not
|
|
834
|
+
* something reconcile introduces** — an ordinary `put` normalizes the same way
|
|
835
|
+
* — so reconcile does not rewrite content that a subsequent write would have
|
|
836
|
+
* left alone. The property being claimed here is the narrower and load-bearing
|
|
837
|
+
* one: no body is round-tripped through its registered Converter.
|
|
838
|
+
*
|
|
839
|
+
* The projector is fed an `IMemoryRecord<string>` carrying that raw body,
|
|
840
|
+
* which is exactly the shape {@link FileTreeMemoryStore._stampRank} hands it
|
|
841
|
+
* on the write path — so a projector cannot see one thing on a write and
|
|
842
|
+
* another on a reconcile. `_stampRank` itself is reused verbatim, which also
|
|
843
|
+
* inherits its throw semantics (logged at `warn`, `rank` cleared).
|
|
844
|
+
*/
|
|
845
|
+
async _reconcileRankLocked(kind) {
|
|
846
|
+
if (!this._rankProjectors.has(kind)) {
|
|
847
|
+
return fail(`memory reconcileRank '${kind}': no rank projector is registered for this kind`);
|
|
848
|
+
}
|
|
849
|
+
const targets = this._index
|
|
850
|
+
.entries()
|
|
851
|
+
.filter((entry) => entry.record.envelope.kind === kind);
|
|
852
|
+
let restamped = 0;
|
|
853
|
+
for (const target of targets) {
|
|
854
|
+
const applied = this._restampOne(target.scope, target.record.envelope.id);
|
|
855
|
+
if (applied.isFailure()) {
|
|
856
|
+
return fail(`memory reconcileRank '${kind}': ${applied.message}`);
|
|
857
|
+
}
|
|
858
|
+
if (applied.value) {
|
|
859
|
+
restamped++;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return succeed(restamped);
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Re-apply the rank projector to one record on disk. Returns whether `rank`
|
|
866
|
+
* actually changed — an unchanged rank writes nothing, so a reconcile over an
|
|
867
|
+
* already-consistent store touches no files.
|
|
868
|
+
*/
|
|
869
|
+
_restampOne(scope, id) {
|
|
870
|
+
return this._resolveScopeDir(scope).onSuccess((scopeDir) => {
|
|
871
|
+
/* c8 ignore next 3 - defensive: the scope dir exists for any indexed record */
|
|
872
|
+
if (scopeDir === undefined) {
|
|
873
|
+
return fail(`'${id}': scope '${scope}' not found`);
|
|
874
|
+
}
|
|
875
|
+
return scopeDir.getChildren().onSuccess((children) => {
|
|
876
|
+
const targetName = `${id}${MEMORY_FILE_EXTENSION}`;
|
|
877
|
+
const file = children.find((c) => c.type === 'file' && c.name === targetName);
|
|
878
|
+
/* c8 ignore next 3 - defensive: the file exists for any indexed record */
|
|
879
|
+
if (file === undefined) {
|
|
880
|
+
return fail(`'${id}': file not found`);
|
|
881
|
+
}
|
|
882
|
+
return file.getRawContents().onSuccess((raw) =>
|
|
883
|
+
// `parseMemoryFile` validates the body through the registered Converter,
|
|
884
|
+
// so a corrupt record is refused rather than silently rewritten, and
|
|
885
|
+
// `_verifyLoaded` re-applies the same id-vs-filename and
|
|
886
|
+
// scope-derived-entityId checks the two load paths apply. Reconcile is a
|
|
887
|
+
// read-then-write, and a file can change on disk after the index was
|
|
888
|
+
// built, so skipping them would make this the one path that accepts —
|
|
889
|
+
// and rewrites — a record the store would otherwise refuse to load.
|
|
890
|
+
// `splitFrontmatter` then supplies the body text for the write.
|
|
891
|
+
parseMemoryFile(raw, this._registry)
|
|
892
|
+
.withErrorFormat((msg) => `'${id}': ${msg}`)
|
|
893
|
+
.onSuccess((parsedRecord) => this._verifyLoaded(scope, file, parsedRecord))
|
|
894
|
+
.onSuccess((parsed) => splitFrontmatter(raw)
|
|
895
|
+
.withErrorFormat((msg) => `'${id}': ${msg}`)
|
|
896
|
+
.onSuccess((parts) => {
|
|
897
|
+
const before = parsed.envelope.rank;
|
|
898
|
+
const stamped = this._stampRank({
|
|
899
|
+
envelope: parsed.envelope,
|
|
900
|
+
body: parts.body
|
|
901
|
+
});
|
|
902
|
+
if (stamped.envelope.rank === before) {
|
|
903
|
+
return succeed(false);
|
|
904
|
+
}
|
|
905
|
+
return this._persist(stamped, scope, id).onSuccess(() => succeed(true));
|
|
906
|
+
})));
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
}
|
|
896
910
|
/**
|
|
897
911
|
* Stamp the store-computed {@link IMemoryEnvelope.rank} onto a fully-built,
|
|
898
912
|
* fully-stamped record by running the kind's registered {@link RankProjector}.
|
|
@@ -941,6 +955,12 @@ export class FileTreeMemoryStore {
|
|
|
941
955
|
var _a;
|
|
942
956
|
return (_a = this._policyFor(kind).dedupScope) !== null && _a !== void 0 ? _a : DEFAULT_DEDUP_SCOPE;
|
|
943
957
|
}
|
|
958
|
+
/** {@inheritDoc IMemoryStore.embedsKind} */
|
|
959
|
+
embedsKind(kind) {
|
|
960
|
+
// No declaration means every kind participates — the behavior that predates
|
|
961
|
+
// this param, so an existing consumer is unaffected.
|
|
962
|
+
return this._embedKinds === undefined || this._embedKinds.has(kind);
|
|
963
|
+
}
|
|
944
964
|
/**
|
|
945
965
|
* Read and validate the record at `<scope>/<idStem>.md`, returning `undefined`
|
|
946
966
|
* when the scope directory or file is absent. Verifies the on-disk id ↔
|