@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
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2026 Erik Fortune
|
|
3
|
-
* SPDX-License-Identifier: MIT
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Converter, Converters, Result, fail, succeed } from '@fgv/ts-utils';
|
|
7
|
-
import { JsonSchema } from '@fgv/ts-json-base';
|
|
8
|
-
import { Kind } from '../types';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Registry of per-kind body Converters. Each memory {@link Kind} registers the
|
|
12
|
-
* validated shape of its body; the store dispatches an `unknown` body through
|
|
13
|
-
* the registered Converter on every write. Type-safe — no `any`.
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export interface IBodyConverterRegistry {
|
|
17
|
-
/**
|
|
18
|
-
* Register a Converter for a kind. Replaces any prior registration for the
|
|
19
|
-
* same kind.
|
|
20
|
-
*/
|
|
21
|
-
register<T>(kind: Kind, converter: Converter<T>): void;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Register a `JsonSchema` validator (from `@fgv/ts-json-base`) for a kind —
|
|
25
|
-
* the schema IS a Validator. Replaces any prior registration for the same
|
|
26
|
-
* kind.
|
|
27
|
-
*/
|
|
28
|
-
registerSchema<T>(kind: Kind, schema: JsonSchema.ISchemaValidator<T>): void;
|
|
29
|
-
|
|
30
|
-
/** Returns `true` if a converter is registered for the kind. */
|
|
31
|
-
has(kind: Kind): boolean;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Get the raw converter registered for a kind. Fails if the kind is
|
|
35
|
-
* unregistered. Exposed for implementors that need to re-validate a patched
|
|
36
|
-
* body (e.g. a temporal-versioned policy's `applyUpdate`).
|
|
37
|
-
*/
|
|
38
|
-
getConverter(kind: Kind): Result<Converter<unknown>>;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Convert an `unknown` body value for the given kind. Fails with
|
|
42
|
-
* `no converter registered for kind '<k>'` when unregistered.
|
|
43
|
-
*/
|
|
44
|
-
convert(kind: Kind, body: unknown): Result<unknown>;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Default in-memory {@link IBodyConverterRegistry}.
|
|
49
|
-
*
|
|
50
|
-
* @remarks
|
|
51
|
-
* Both `register` and `registerSchema` adapt the supplied converter/validator
|
|
52
|
-
* into a `Converter<unknown>` via `Converters.generic`, so the heterogeneous
|
|
53
|
-
* per-kind types are stored uniformly with no cast and no `any`. A
|
|
54
|
-
* `Converter<T>` is not structurally a `Converter<unknown>` (the `map` callback
|
|
55
|
-
* makes the type invariant), so the `generic` wrapper — whose callback returns
|
|
56
|
-
* `Result<T>` (assignable to `Result<unknown>`) — is the type-safe bridge.
|
|
57
|
-
* @public
|
|
58
|
-
*/
|
|
59
|
-
export class BodyConverterRegistry implements IBodyConverterRegistry {
|
|
60
|
-
private readonly _converters: Map<Kind, Converter<unknown>>;
|
|
61
|
-
|
|
62
|
-
private constructor() {
|
|
63
|
-
this._converters = new Map<Kind, Converter<unknown>>();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** Family-convention factory. */
|
|
67
|
-
public static create(): Result<BodyConverterRegistry> {
|
|
68
|
-
return succeed(new BodyConverterRegistry());
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** {@inheritDoc IBodyConverterRegistry.register} */
|
|
72
|
-
public register<T>(kind: Kind, converter: Converter<T>): void {
|
|
73
|
-
this._converters.set(
|
|
74
|
-
kind,
|
|
75
|
-
Converters.generic<unknown>((from: unknown) => converter.convert(from))
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** {@inheritDoc IBodyConverterRegistry.registerSchema} */
|
|
80
|
-
public registerSchema<T>(kind: Kind, schema: JsonSchema.ISchemaValidator<T>): void {
|
|
81
|
-
this._converters.set(
|
|
82
|
-
kind,
|
|
83
|
-
Converters.generic<unknown>((from: unknown) => schema.convert(from))
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** {@inheritDoc IBodyConverterRegistry.has} */
|
|
88
|
-
public has(kind: Kind): boolean {
|
|
89
|
-
return this._converters.has(kind);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/** {@inheritDoc IBodyConverterRegistry.getConverter} */
|
|
93
|
-
public getConverter(kind: Kind): Result<Converter<unknown>> {
|
|
94
|
-
const converter: Converter<unknown> | undefined = this._converters.get(kind);
|
|
95
|
-
if (converter === undefined) {
|
|
96
|
-
return fail(`no converter registered for kind '${kind}'`);
|
|
97
|
-
}
|
|
98
|
-
return succeed(converter);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** {@inheritDoc IBodyConverterRegistry.convert} */
|
|
102
|
-
public convert(kind: Kind, body: unknown): Result<unknown> {
|
|
103
|
-
return this.getConverter(kind).onSuccess((converter) => converter.convert(body));
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2026 Erik Fortune
|
|
3
|
-
* SPDX-License-Identifier: MIT
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Converter, Converters, Result, fail, succeed } from '@fgv/ts-utils';
|
|
7
|
-
import { Yaml } from '@fgv/ts-extras';
|
|
8
|
-
import {
|
|
9
|
-
Convert,
|
|
10
|
-
IEdge,
|
|
11
|
-
IEdgeTarget,
|
|
12
|
-
IMemoryEnvelope,
|
|
13
|
-
IMemoryRecord,
|
|
14
|
-
IProvenance,
|
|
15
|
-
ITemporalBlock
|
|
16
|
-
} from '../types';
|
|
17
|
-
import { IBodyConverterRegistry } from './bodyConverterRegistry';
|
|
18
|
-
|
|
19
|
-
/** Matches exactly the JSON `null` literal. */
|
|
20
|
-
// eslint-disable-next-line @rushstack/no-new-null -- the envelope nullable fields (invalid_at, embeddingRef) carry meaningful null; design-lock §2.3-2.5
|
|
21
|
-
const nullConverter: Converter<null> = Converters.generic<null>((from: unknown) =>
|
|
22
|
-
from === null ? succeed(null) : fail('expected null')
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
/** A nullable epoch-ms value (`number | null`). */
|
|
26
|
-
// eslint-disable-next-line @rushstack/no-new-null -- meaningful null for IEdge/ITemporalBlock.invalid_at; design-lock §2.3-2.4
|
|
27
|
-
const numberOrNull: Converter<number | null> = Converters.oneOf<number | null>([
|
|
28
|
-
Converters.number,
|
|
29
|
-
nullConverter
|
|
30
|
-
]);
|
|
31
|
-
|
|
32
|
-
/** A nullable string value (`string | null`). */
|
|
33
|
-
// eslint-disable-next-line @rushstack/no-new-null -- meaningful null for IMemoryEnvelope.embeddingRef; design-lock §2.5
|
|
34
|
-
const stringOrNull: Converter<string | null> = Converters.oneOf<string | null>([
|
|
35
|
-
Converters.string,
|
|
36
|
-
nullConverter
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Converter for a scope-qualified {@link IEdgeTarget}. Both `scope` and `id`
|
|
41
|
-
* are required — the whole point of the scoped target is that a bare id is
|
|
42
|
-
* ambiguous across scopes.
|
|
43
|
-
* @public
|
|
44
|
-
*/
|
|
45
|
-
export const edgeTargetConverter: Converter<IEdgeTarget> = Converters.object<IEdgeTarget>({
|
|
46
|
-
scope: Convert.scopeKey,
|
|
47
|
-
id: Convert.memoryId
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Converter for the known {@link IProvenance} fields. The full
|
|
52
|
-
* {@link provenanceConverter} layers extension-key preservation on top.
|
|
53
|
-
* `derivedFrom` is serialized as the nested `{ scope, id }` object (mirroring
|
|
54
|
-
* {@link edgeConverter | edge}'s scope-qualified `target`) so the provenance
|
|
55
|
-
* back-reference is unambiguous across scopes.
|
|
56
|
-
*/
|
|
57
|
-
const knownProvenanceConverter: Converter<IProvenance> = Converters.object<IProvenance>(
|
|
58
|
-
{
|
|
59
|
-
source: Converters.string,
|
|
60
|
-
by: Converters.string.optional(),
|
|
61
|
-
model: Converters.string.optional(),
|
|
62
|
-
confidence: Converters.number.optional(),
|
|
63
|
-
derivedFrom: edgeTargetConverter.optional()
|
|
64
|
-
},
|
|
65
|
-
{ optionalFields: ['by', 'model', 'confidence', 'derivedFrom'] }
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Converter for {@link IProvenance}. Validates the known fields and preserves
|
|
70
|
-
* any extension keys verbatim (the `[key: string]: unknown` opaque payload),
|
|
71
|
-
* so a round-trip never drops consumer-attached data.
|
|
72
|
-
* @public
|
|
73
|
-
*/
|
|
74
|
-
export const provenanceConverter: Converter<IProvenance> = Converters.generic<IProvenance>(
|
|
75
|
-
(from: unknown): Result<IProvenance> =>
|
|
76
|
-
knownProvenanceConverter.convert(from).onSuccess((known) => {
|
|
77
|
-
// `from` is guaranteed to be a non-null object here — the known-field
|
|
78
|
-
// converter only succeeds on objects. Spread the original keys first,
|
|
79
|
-
// then the validated/normalized known fields on top, so extension keys
|
|
80
|
-
// survive while the known fields carry their converted values.
|
|
81
|
-
const merged: IProvenance = { ...(from as Record<string, unknown>), ...known };
|
|
82
|
-
return succeed(merged);
|
|
83
|
-
})
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Converter for an attributed {@link IEdge}.
|
|
88
|
-
* @public
|
|
89
|
-
*/
|
|
90
|
-
export const edgeConverter: Converter<IEdge> = Converters.object<IEdge>(
|
|
91
|
-
{
|
|
92
|
-
type: Convert.linkType,
|
|
93
|
-
target: edgeTargetConverter,
|
|
94
|
-
confidence: Converters.number.optional(),
|
|
95
|
-
provenance: provenanceConverter.optional(),
|
|
96
|
-
valid_at: Converters.number.optional(),
|
|
97
|
-
invalid_at: numberOrNull.optional()
|
|
98
|
-
},
|
|
99
|
-
{ optionalFields: ['confidence', 'provenance', 'valid_at', 'invalid_at'] }
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Converter for the optional {@link ITemporalBlock}.
|
|
104
|
-
* @public
|
|
105
|
-
*/
|
|
106
|
-
export const temporalConverter: Converter<ITemporalBlock> = Converters.object<ITemporalBlock>(
|
|
107
|
-
{
|
|
108
|
-
valid_at: Converters.number.optional(),
|
|
109
|
-
invalid_at: numberOrNull.optional()
|
|
110
|
-
},
|
|
111
|
-
{ optionalFields: ['valid_at', 'invalid_at'] }
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Converter for the invariant {@link IMemoryEnvelope}. Validates a plain
|
|
116
|
-
* object (e.g. parsed YAML frontmatter) into a typed envelope.
|
|
117
|
-
* @public
|
|
118
|
-
*/
|
|
119
|
-
export const envelopeConverter: Converter<IMemoryEnvelope> = Converters.object<IMemoryEnvelope>(
|
|
120
|
-
{
|
|
121
|
-
id: Convert.memoryId,
|
|
122
|
-
entityId: Convert.entityId,
|
|
123
|
-
kind: Convert.kind,
|
|
124
|
-
tags: Converters.arrayOf(Convert.tag),
|
|
125
|
-
links: Converters.arrayOf(edgeConverter),
|
|
126
|
-
created: Converters.number,
|
|
127
|
-
updated: Converters.number,
|
|
128
|
-
seq: Converters.number,
|
|
129
|
-
contentHash: Converters.string,
|
|
130
|
-
rank: Converters.number.optional(),
|
|
131
|
-
provenance: provenanceConverter,
|
|
132
|
-
temporal: temporalConverter.optional(),
|
|
133
|
-
embeddingRef: stringOrNull.optional()
|
|
134
|
-
},
|
|
135
|
-
{ optionalFields: ['rank', 'temporal', 'embeddingRef'] }
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Converter that parses a YAML frontmatter string into an
|
|
140
|
-
* {@link IMemoryEnvelope}.
|
|
141
|
-
* @public
|
|
142
|
-
*/
|
|
143
|
-
export const envelopeYamlConverter: Converter<IMemoryEnvelope> = Yaml.yamlConverter(envelopeConverter);
|
|
144
|
-
|
|
145
|
-
/** The frontmatter delimiter line. */
|
|
146
|
-
const FRONTMATTER_DELIMITER: string = '---';
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* The two parts of a memory file: the YAML frontmatter (between the `---`
|
|
150
|
-
* delimiters) and the markdown body (everything after the closing delimiter).
|
|
151
|
-
* @public
|
|
152
|
-
*/
|
|
153
|
-
export interface IMemoryFileParts {
|
|
154
|
-
/** The raw YAML frontmatter (delimiters stripped). */
|
|
155
|
-
readonly frontmatter: string;
|
|
156
|
-
/** The raw body text following the closing delimiter. */
|
|
157
|
-
readonly body: string;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Split a `---\n<yaml>\n---\n<body>` memory file into its frontmatter and
|
|
162
|
-
* body parts. Pure string handling — no external dependency.
|
|
163
|
-
* @public
|
|
164
|
-
*/
|
|
165
|
-
export function splitFrontmatter(raw: string): Result<IMemoryFileParts> {
|
|
166
|
-
// Split on '\n' and strip a trailing '\r' per line so CRLF-authored files
|
|
167
|
-
// parse identically to LF — otherwise the '\r' would ride along into the
|
|
168
|
-
// returned frontmatter (perturbing YAML parsing) and body (corrupting
|
|
169
|
-
// round-trip fidelity).
|
|
170
|
-
const lines: string[] = raw.split('\n').map((line) => (line.endsWith('\r') ? line.slice(0, -1) : line));
|
|
171
|
-
if (lines[0].trim() !== FRONTMATTER_DELIMITER) {
|
|
172
|
-
return fail("memory file: missing opening frontmatter delimiter '---'");
|
|
173
|
-
}
|
|
174
|
-
let closeIndex: number = -1;
|
|
175
|
-
for (let i = 1; i < lines.length; i++) {
|
|
176
|
-
if (lines[i].trim() === FRONTMATTER_DELIMITER) {
|
|
177
|
-
closeIndex = i;
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (closeIndex === -1) {
|
|
182
|
-
return fail("memory file: missing closing frontmatter delimiter '---'");
|
|
183
|
-
}
|
|
184
|
-
return succeed({
|
|
185
|
-
frontmatter: lines.slice(1, closeIndex).join('\n'),
|
|
186
|
-
body: lines.slice(closeIndex + 1).join('\n')
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Join a YAML frontmatter string and a body into the canonical
|
|
192
|
-
* `---\n<yaml>\n---\n<body>` memory-file format.
|
|
193
|
-
* @public
|
|
194
|
-
*/
|
|
195
|
-
export function joinFrontmatter(frontmatter: string, body: string): string {
|
|
196
|
-
const normalized: string = frontmatter.endsWith('\n') ? frontmatter : `${frontmatter}\n`;
|
|
197
|
-
return `${FRONTMATTER_DELIMITER}\n${normalized}${FRONTMATTER_DELIMITER}\n${body}`;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Parse a complete memory file into a typed {@link IMemoryRecord}. Splits the
|
|
202
|
-
* frontmatter, validates the envelope, and dispatches the body through the
|
|
203
|
-
* registered Converter for the envelope's kind.
|
|
204
|
-
* @public
|
|
205
|
-
*/
|
|
206
|
-
export function parseMemoryFile(
|
|
207
|
-
raw: string,
|
|
208
|
-
registry: IBodyConverterRegistry
|
|
209
|
-
): Result<IMemoryRecord<unknown>> {
|
|
210
|
-
return splitFrontmatter(raw).onSuccess((parts) =>
|
|
211
|
-
envelopeYamlConverter
|
|
212
|
-
.convert(parts.frontmatter)
|
|
213
|
-
.withErrorFormat((msg) => `memory file: invalid envelope: ${msg}`)
|
|
214
|
-
.onSuccess((envelope) =>
|
|
215
|
-
registry
|
|
216
|
-
.convert(envelope.kind, parts.body)
|
|
217
|
-
.withErrorFormat((msg) => `memory file '${envelope.id}': invalid body: ${msg}`)
|
|
218
|
-
.onSuccess((body) => succeed({ envelope, body }))
|
|
219
|
-
)
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Serialize an envelope and its rendered body text into a memory file. The
|
|
225
|
-
* envelope is emitted as YAML frontmatter; the body is written verbatim after
|
|
226
|
-
* the closing delimiter.
|
|
227
|
-
* @public
|
|
228
|
-
*/
|
|
229
|
-
export function serializeMemoryFile(envelope: IMemoryEnvelope, body: string): Result<string> {
|
|
230
|
-
return Yaml.yamlStringify(envelope)
|
|
231
|
-
.withErrorFormat((msg) => `memory file '${envelope.id}': failed to serialize envelope: ${msg}`)
|
|
232
|
-
.onSuccess((frontmatter) => succeed(joinFrontmatter(frontmatter, body)));
|
|
233
|
-
}
|
|
@@ -1,332 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2026 Erik Fortune
|
|
3
|
-
* SPDX-License-Identifier: MIT
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Result, succeed } from '@fgv/ts-utils';
|
|
7
|
-
import { IEdgeTarget, IMemoryRecord, Kind, MemoryId, MemoryScopeKey, Tag, edgeTargetKey } from '../types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The mutation a {@link IMemoryIndex.patch | patch} applies: a record was
|
|
11
|
-
* written (`'put'`) or removed (`'delete'`).
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
export type MemoryIndexPatchOp = 'put' | 'delete';
|
|
15
|
-
|
|
16
|
-
/** Shared empty key set for `byKind` / `byTag` misses (avoids per-call allocation). */
|
|
17
|
-
const EMPTY_KEY_SET: ReadonlySet<string> = new Set<string>();
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A memory record paired with the {@link MemoryScopeKey | scope} it lives
|
|
21
|
-
* under. The scope is not carried on the {@link IMemoryEnvelope} (it is derived
|
|
22
|
-
* from the entity id by the codec), so the store threads it alongside the
|
|
23
|
-
* record when patching or rebuilding the index. The `(scope, id)` pair is the
|
|
24
|
-
* index's primary key, keeping records distinct across scopes that reuse a
|
|
25
|
-
* filename stem (e.g. `turn-0` under different conversations in Phase C).
|
|
26
|
-
* @public
|
|
27
|
-
*/
|
|
28
|
-
export interface IIndexedMemoryRecord {
|
|
29
|
-
/** The scope the record is stored under. */
|
|
30
|
-
readonly scope: MemoryScopeKey;
|
|
31
|
-
/** The memory record itself. */
|
|
32
|
-
readonly record: IMemoryRecord<unknown>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The derived, in-memory secondary indexes the store maintains over its
|
|
37
|
-
* records. Never the source of truth — the FileTree is. The index is fully
|
|
38
|
-
* rebuildable from a walk of the store ({@link IMemoryIndex.rebuild}) and is
|
|
39
|
-
* patched incrementally on every write ({@link IMemoryIndex.patch}).
|
|
40
|
-
*
|
|
41
|
-
* @remarks
|
|
42
|
-
* B1 builds the maps; link-traversal BFS over {@link IMemoryIndex.backlinks}
|
|
43
|
-
* is B2. The accessors return records (not bare ids) so the B2 retrievers can
|
|
44
|
-
* consume them directly.
|
|
45
|
-
* @public
|
|
46
|
-
*/
|
|
47
|
-
export interface IMemoryIndex {
|
|
48
|
-
/**
|
|
49
|
-
* Replace the entire index from a full set of records (a store walk).
|
|
50
|
-
* @returns The number of records indexed.
|
|
51
|
-
*/
|
|
52
|
-
rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number>;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Apply a single incremental change. `'put'` inserts or replaces the entry
|
|
56
|
-
* at its `(scope, id)` key (removing any prior associations first); `'delete'`
|
|
57
|
-
* removes it.
|
|
58
|
-
* @returns The entry that was applied.
|
|
59
|
-
*/
|
|
60
|
-
patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord>;
|
|
61
|
-
|
|
62
|
-
/** Every indexed entry (scope + record). Primary read surface for the store. */
|
|
63
|
-
entries(): ReadonlyArray<IIndexedMemoryRecord>;
|
|
64
|
-
|
|
65
|
-
/** Records of the given kind, in recency order (most-recently-updated first). */
|
|
66
|
-
byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>>;
|
|
67
|
-
|
|
68
|
-
/** Records carrying the given tag, in recency order. */
|
|
69
|
-
byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>>;
|
|
70
|
-
|
|
71
|
-
/** All records in recency order (most-recently-updated first). */
|
|
72
|
-
byRecency(): ReadonlyArray<IMemoryRecord<unknown>>;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* All records ordered by store-computed {@link IMemoryEnvelope.rank} descending,
|
|
76
|
-
* with recency (most-recently-updated, then `seq`) as a tiebreak. Records with
|
|
77
|
-
* an absent `rank` sort LAST (after every ranked record), then by recency among
|
|
78
|
-
* themselves. Serves a bounded top-M ({@link IMemoryEnvelope.rank}-ordered) page
|
|
79
|
-
* from the in-memory index with no full-vault (filesystem) scan.
|
|
80
|
-
*/
|
|
81
|
-
byRank(): ReadonlyArray<IMemoryRecord<unknown>>;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* The scope-qualified sources of records whose `links` point AT `target`
|
|
85
|
-
* (inbound edges), keyed on the target's `(scope, id)` address. The seed map
|
|
86
|
-
* for B2 link-traversal; results are {@link IEdgeTarget}s so a caller can feed
|
|
87
|
-
* them straight back in as further traversal seeds.
|
|
88
|
-
*/
|
|
89
|
-
backlinks(target: IEdgeTarget): ReadonlyArray<IEdgeTarget>;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Default in-memory {@link IMemoryIndex}. Maintains the derived `byKind` /
|
|
94
|
-
* `byTag` / `byRecency` / `backlinks` views incrementally; a `'put'` for an
|
|
95
|
-
* already-indexed key first removes the prior entry's associations so a changed
|
|
96
|
-
* kind / tag / link set never leaves a stale reference behind.
|
|
97
|
-
* @public
|
|
98
|
-
*/
|
|
99
|
-
export class MemoryIndex implements IMemoryIndex {
|
|
100
|
-
/** Primary store: `(scope, id)` composite key → indexed entry. */
|
|
101
|
-
private readonly _byKey: Map<string, IIndexedMemoryRecord>;
|
|
102
|
-
/** kind → set of composite keys. */
|
|
103
|
-
private readonly _byKind: Map<Kind, Set<string>>;
|
|
104
|
-
/** tag → set of composite keys. */
|
|
105
|
-
private readonly _byTag: Map<Tag, Set<string>>;
|
|
106
|
-
/**
|
|
107
|
-
* canonical target key (`edgeTargetKey`) → (source composite key → source
|
|
108
|
-
* {@link IEdgeTarget}). The OUTER map is keyed on the scope-qualified target's
|
|
109
|
-
* canonical `(scope, id)` string — NOT the target's bare id — so an edge to
|
|
110
|
-
* `turn-3` in one conversation is tracked separately from `turn-3` in another.
|
|
111
|
-
* The INNER map is keyed by the source's `(scope, id)` composite so two distinct
|
|
112
|
-
* source records that share an id across scopes are tracked independently and
|
|
113
|
-
* removing one never drops the other's edge.
|
|
114
|
-
*/
|
|
115
|
-
private readonly _backlinks: Map<string, Map<string, IEdgeTarget>>;
|
|
116
|
-
|
|
117
|
-
private constructor() {
|
|
118
|
-
this._byKey = new Map<string, IIndexedMemoryRecord>();
|
|
119
|
-
this._byKind = new Map<Kind, Set<string>>();
|
|
120
|
-
this._byTag = new Map<Tag, Set<string>>();
|
|
121
|
-
this._backlinks = new Map<string, Map<string, IEdgeTarget>>();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Family-convention factory. */
|
|
125
|
-
public static create(): Result<MemoryIndex> {
|
|
126
|
-
return succeed(new MemoryIndex());
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* The composite primary key for an entry: scope + id, NUL-separated. NUL
|
|
131
|
-
* is excluded from both components (scope segments pass
|
|
132
|
-
* `assertPortableFilenameStem`; `MemoryId` is portable-filename-safe), so it
|
|
133
|
-
* is a collision-proof separator across every scope/id pair the codecs produce.
|
|
134
|
-
*/
|
|
135
|
-
private static _keyOf(scope: MemoryScopeKey, id: MemoryId): string {
|
|
136
|
-
return edgeTargetKey({ scope, id });
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/** {@inheritDoc IMemoryIndex.rebuild} */
|
|
140
|
-
public rebuild(entries: ReadonlyArray<IIndexedMemoryRecord>): Result<number> {
|
|
141
|
-
this._byKey.clear();
|
|
142
|
-
this._byKind.clear();
|
|
143
|
-
this._byTag.clear();
|
|
144
|
-
this._backlinks.clear();
|
|
145
|
-
for (const entry of entries) {
|
|
146
|
-
this._add(entry);
|
|
147
|
-
}
|
|
148
|
-
return succeed(this._byKey.size);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/** {@inheritDoc IMemoryIndex.patch} */
|
|
152
|
-
public patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord> {
|
|
153
|
-
const key: string = MemoryIndex._keyOf(entry.scope, entry.record.envelope.id);
|
|
154
|
-
// Always drop any prior associations for this key first, so a 'put' that
|
|
155
|
-
// changes kind/tags/links cannot strand a stale reference.
|
|
156
|
-
this._remove(key);
|
|
157
|
-
if (op === 'put') {
|
|
158
|
-
this._add(entry);
|
|
159
|
-
}
|
|
160
|
-
return succeed(entry);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** {@inheritDoc IMemoryIndex.entries} */
|
|
164
|
-
public entries(): ReadonlyArray<IIndexedMemoryRecord> {
|
|
165
|
-
return Array.from(this._byKey.values());
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/** {@inheritDoc IMemoryIndex.byKind} */
|
|
169
|
-
public byKind(kind: Kind): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
170
|
-
return this._recencyOrdered(this._byKind.get(kind) ?? EMPTY_KEY_SET);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** {@inheritDoc IMemoryIndex.byTag} */
|
|
174
|
-
public byTag(tag: Tag): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
175
|
-
return this._recencyOrdered(this._byTag.get(tag) ?? EMPTY_KEY_SET);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/** {@inheritDoc IMemoryIndex.byRecency} */
|
|
179
|
-
public byRecency(): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
180
|
-
return this._recencyOrdered(this._byKey.keys());
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** {@inheritDoc IMemoryIndex.byRank} */
|
|
184
|
-
public byRank(): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
185
|
-
return this._rankOrdered(this._byKey.keys());
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/** {@inheritDoc IMemoryIndex.backlinks} */
|
|
189
|
-
public backlinks(target: IEdgeTarget): ReadonlyArray<IEdgeTarget> {
|
|
190
|
-
const sources: Map<string, IEdgeTarget> | undefined = this._backlinks.get(edgeTargetKey(target));
|
|
191
|
-
return sources === undefined ? [] : Array.from(sources.values());
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Resolve a set of composite keys to their records, ordered
|
|
196
|
-
* most-recently-updated first (with a `seq` tiebreak so equal-`updated`
|
|
197
|
-
* records sort deterministically).
|
|
198
|
-
*/
|
|
199
|
-
private _recencyOrdered(keys: Iterable<string>): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
200
|
-
const records: IMemoryRecord<unknown>[] = [];
|
|
201
|
-
for (const key of keys) {
|
|
202
|
-
const entry: IIndexedMemoryRecord | undefined = this._byKey.get(key);
|
|
203
|
-
if (entry !== undefined) {
|
|
204
|
-
records.push(entry.record);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return records.sort((a, b) => {
|
|
208
|
-
const byUpdated: number = b.envelope.updated - a.envelope.updated;
|
|
209
|
-
return byUpdated !== 0 ? byUpdated : b.envelope.seq - a.envelope.seq;
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Resolve a set of composite keys to their records, ordered by
|
|
215
|
-
* {@link IMemoryEnvelope.rank} descending with recency (`updated`, then `seq`)
|
|
216
|
-
* as the tiebreak. Records with an absent `rank` sort LAST, then by recency
|
|
217
|
-
* among themselves. Computed on call (mirrors {@link MemoryIndex._recencyOrdered}) —
|
|
218
|
-
* no incremental rank-ordered view is maintained, matching the recency view's
|
|
219
|
-
* approach; the sort is over the in-memory index, never a filesystem walk.
|
|
220
|
-
*/
|
|
221
|
-
private _rankOrdered(keys: Iterable<string>): ReadonlyArray<IMemoryRecord<unknown>> {
|
|
222
|
-
const records: IMemoryRecord<unknown>[] = [];
|
|
223
|
-
for (const key of keys) {
|
|
224
|
-
const entry: IIndexedMemoryRecord | undefined = this._byKey.get(key);
|
|
225
|
-
if (entry !== undefined) {
|
|
226
|
-
records.push(entry.record);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return records.sort(MemoryIndex._compareByRank);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Rank-descending comparator with an absent-`rank`-last rule and a recency
|
|
234
|
-
* (`updated`, then `seq`) tiebreak. Duplicated from the retrieve packlet's
|
|
235
|
-
* `rankCompare` deliberately: the index must not depend on `retrieve` (that
|
|
236
|
-
* package depends on the index), mirroring how `_recencyOrdered` inlines the
|
|
237
|
-
* recency ordering rather than importing `recencyCompare`.
|
|
238
|
-
*/
|
|
239
|
-
private static _compareByRank(a: IMemoryRecord<unknown>, b: IMemoryRecord<unknown>): number {
|
|
240
|
-
const ra: number | undefined = a.envelope.rank;
|
|
241
|
-
const rb: number | undefined = b.envelope.rank;
|
|
242
|
-
// Absent rank sorts last; two absent ranks fall through to the recency tiebreak.
|
|
243
|
-
if (ra === undefined && rb !== undefined) {
|
|
244
|
-
return 1;
|
|
245
|
-
}
|
|
246
|
-
if (rb === undefined && ra !== undefined) {
|
|
247
|
-
return -1;
|
|
248
|
-
}
|
|
249
|
-
if (ra !== undefined && rb !== undefined && ra !== rb) {
|
|
250
|
-
return rb - ra;
|
|
251
|
-
}
|
|
252
|
-
const byUpdated: number = b.envelope.updated - a.envelope.updated;
|
|
253
|
-
return byUpdated !== 0 ? byUpdated : b.envelope.seq - a.envelope.seq;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/** Insert an entry and register all its derived associations. */
|
|
257
|
-
private _add(entry: IIndexedMemoryRecord): void {
|
|
258
|
-
const key: string = MemoryIndex._keyOf(entry.scope, entry.record.envelope.id);
|
|
259
|
-
const envelope: IMemoryRecord<unknown>['envelope'] = entry.record.envelope;
|
|
260
|
-
this._byKey.set(key, entry);
|
|
261
|
-
this._addToSetMap(this._byKind, envelope.kind, key);
|
|
262
|
-
for (const tag of envelope.tags) {
|
|
263
|
-
this._addToSetMap(this._byTag, tag, key);
|
|
264
|
-
}
|
|
265
|
-
for (const edge of envelope.links) {
|
|
266
|
-
this._addBacklink(edge.target, key, { scope: entry.scope, id: envelope.id });
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/** Remove the entry at `key` (if present) and all its derived associations. */
|
|
271
|
-
private _remove(key: string): void {
|
|
272
|
-
const entry: IIndexedMemoryRecord | undefined = this._byKey.get(key);
|
|
273
|
-
if (entry === undefined) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const envelope: IMemoryRecord<unknown>['envelope'] = entry.record.envelope;
|
|
277
|
-
this._byKey.delete(key);
|
|
278
|
-
this._removeFromSetMap(this._byKind, envelope.kind, key);
|
|
279
|
-
for (const tag of envelope.tags) {
|
|
280
|
-
this._removeFromSetMap(this._byTag, tag, key);
|
|
281
|
-
}
|
|
282
|
-
for (const edge of envelope.links) {
|
|
283
|
-
this._removeBacklink(edge.target, key);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/** Register `source` (keyed by its composite `sourceKey`) as linking at `target`. */
|
|
288
|
-
private _addBacklink(target: IEdgeTarget, sourceKey: string, source: IEdgeTarget): void {
|
|
289
|
-
const targetKey: string = edgeTargetKey(target);
|
|
290
|
-
const existing: Map<string, IEdgeTarget> | undefined = this._backlinks.get(targetKey);
|
|
291
|
-
if (existing === undefined) {
|
|
292
|
-
this._backlinks.set(targetKey, new Map<string, IEdgeTarget>([[sourceKey, source]]));
|
|
293
|
-
} else {
|
|
294
|
-
existing.set(sourceKey, source);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/** Drop the backlink from `sourceKey` to `target`, removing the target map when empty. */
|
|
299
|
-
private _removeBacklink(target: IEdgeTarget, sourceKey: string): void {
|
|
300
|
-
const targetKey: string = edgeTargetKey(target);
|
|
301
|
-
const existing: Map<string, IEdgeTarget> | undefined = this._backlinks.get(targetKey);
|
|
302
|
-
if (existing === undefined) {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
existing.delete(sourceKey);
|
|
306
|
-
if (existing.size === 0) {
|
|
307
|
-
this._backlinks.delete(targetKey);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/** Add `member` to the set at `mapKey`, creating the set on first use. */
|
|
312
|
-
private _addToSetMap<K, M>(map: Map<K, Set<M>>, mapKey: K, member: M): void {
|
|
313
|
-
const existing: Set<M> | undefined = map.get(mapKey);
|
|
314
|
-
if (existing === undefined) {
|
|
315
|
-
map.set(mapKey, new Set<M>([member]));
|
|
316
|
-
} else {
|
|
317
|
-
existing.add(member);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/** Remove `member` from the set at `mapKey`, dropping the set when empty. */
|
|
322
|
-
private _removeFromSetMap<K, M>(map: Map<K, Set<M>>, mapKey: K, member: M): void {
|
|
323
|
-
const existing: Set<M> | undefined = map.get(mapKey);
|
|
324
|
-
if (existing === undefined) {
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
existing.delete(member);
|
|
328
|
-
if (existing.size === 0) {
|
|
329
|
-
map.delete(mapKey);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|