@fgv/ts-agent-memory 5.1.0-47 → 5.1.0-48
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/store/fileTreeMemoryStore.js +52 -131
- 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/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 +297 -66
- 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/store/fileTreeMemoryStore.d.ts +66 -59
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +52 -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/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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vectorIndex.js","sourceRoot":"","sources":["../../../src/packlets/vector/vectorIndex.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Result } from '@fgv/ts-utils';\nimport { IEdgeTarget, IMemoryRecord } from '../types';\n\n/**\n * A half-open `[start, end)` span into a record's body — the in-record locator a\n * {@link IFragmentVectorIndex} may carry on a fragment. `start` is inclusive,\n * `end` exclusive. The unit (character / byte / token offsets) is the consumer's\n * choice: the index stores the two integers opaquely and never interprets them,\n * so they line up with whatever locator the consumer's own read side uses.\n *\n * @remarks\n * **The span is advisory.** It names the region of the body a fragment was\n * *derived from*; it is NOT a slice guaranteed to reproduce the fragment's text.\n * `body.slice(start, end)` round-trips only under a segmenter that merely chooses\n * boundaries. Under a **rewriting** segmenter — one that turns a span into a\n * curated block, an increasingly common ingestion shape when a model both selects\n * and rewrites — the fragment text is not a substring of the body at all, and the\n * fragmentation is not re-derivable from the body. Treat the span as a pointer for\n * locating context, never as an extraction recipe.\n *\n * A fragment whose provenance cannot honestly be expressed as a body span should\n * omit the locator entirely and carry an {@link IEmbeddedFragment.fragmentId}\n * instead.\n * @public\n */\nexport interface IFragmentLocator {\n /** Inclusive start offset into the record body. */\n readonly start: number;\n /** Exclusive end offset into the record body. */\n readonly end: number;\n}\n\n/**\n * A single hit returned by {@link IVectorIndex.query} (or\n * {@link IFragmentVectorIndex.query}): the matched record's scope-qualified\n * {@link IEdgeTarget | address} and the backend's similarity score (higher = more\n * similar; the exact scale is backend-defined). Hits are returned in descending\n * score order.\n *\n * @remarks\n * The address is a `(scope, id)` pair, NOT a bare {@link MemoryId} — per-scope\n * codecs (e.g. the medium-term codec's `turn-<n>` stems) legally mint the same\n * stem under different scopes, so a bare id could not disambiguate two records\n * that share a stem. The caller re-resolves the hit against the record index by\n * the same scoped address.\n *\n * **No single field discriminates a fragment hit from a record-granular hit.** A\n * record hit carries neither `locator` nor `fragmentId`; a fragment hit carries at\n * least one of the two, but not necessarily any particular one — a fragment with a\n * body span but no consumer-minted id, and a fragment with an id but no honest span,\n * are both legal. Testing one field for presence therefore cannot tell you which\n * kind of hit you hold.\n *\n * That \"at least one\" requirement is enforced on the upsert side by\n * {@link embeddedFragmentConverter} — a different boundary from this type — and is\n * deliberately NOT offered here as a discriminator either. A caller keyed off it\n * would be coupled to an invariant this type does not own, and would fail silently\n * if the invariant were ever relaxed.\n *\n * **The robust rule is that fragment-ness is determined by which index produced the\n * hit**: {@link IFragmentVectorIndex.query} returns fragment hits and\n * {@link IVectorIndex.query} returns record hits. The caller chose the index it\n * queried, so it already knows which kind it is holding.\n *\n * Note in particular that an absent `locator` now carries **two** distinct meanings\n * — a record-granular hit, or a fragment with no honest body span (see\n * {@link IFragmentLocator}) — which is precisely why presence-branching is unsafe.\n * @public\n */\nexport interface IVectorQueryHit {\n /** The scope-qualified address of the matched record. */\n readonly target: IEdgeTarget;\n /** Backend similarity score; higher is more similar. */\n readonly score: number;\n /**\n * The advisory in-record span the matched fragment was derived from, when the\n * producing fragment carried one. Absent on record-granular hits AND on fragment\n * hits with no honest span — see the remarks above; do not branch on its presence.\n */\n readonly locator?: IFragmentLocator;\n /**\n * The opaque identity the producing fragment was stored with, carried back\n * verbatim. Absent on record-granular hits AND on fragment hits stored without\n * one — see the remarks above; do not branch on its presence.\n */\n readonly fragmentId?: string;\n}\n\n/**\n * The vector-index seam an embedding backend implements to make\n * {@link SemanticRetriever | semantic recall} operational.\n *\n * @remarks\n * Vectors cross this seam as `Float32Array` (the in-memory representation an\n * embedding model produces); `number[]` is reserved for the JSON-wire edges\n * (e.g. a provider's embedding response). The in-package brute-force cosine\n * implementation is {@link InMemoryCosineIndex}; a consumer can swap an external\n * ANN backend behind the same seam once N grows beyond the in-memory regime.\n *\n * Every operation returns a `Result` (async, since a real backend does I/O) so\n * failure is explicit and never throws across the seam.\n * @public\n */\nexport interface IVectorIndex {\n /**\n * Add (or replace) the embedding for the scope-qualified `target`. Returns the\n * opaque {@link IMemoryEnvelope.embeddingRef | embeddingRef} the store stamps\n * onto the envelope so a later read knows the record is embedded. Keying on the\n * `(scope, id)` address (not a bare id) is load-bearing: two records that share\n * a filename stem across scopes must not clobber each other's embedding.\n */\n add(target: IEdgeTarget, vector: Float32Array): Promise<Result<string>>;\n\n /**\n * Remove the embedding for the scope-qualified `target`. Returns the removed\n * target. Idempotent — removing a target with no embedding still succeeds\n * (returns the target).\n */\n remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;\n\n /**\n * Return the `topK` nearest records to `vector`, in descending score order.\n */\n query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;\n}\n\n/**\n * One embedded fragment of a record: the fragment's vector, plus at least one of the\n * two ways to identify it — its advisory in-record {@link IFragmentLocator | span}\n * and/or an opaque consumer-minted {@link IEmbeddedFragment.fragmentId | fragmentId}.\n * Produced by a {@link FragmentEmbedder} and stored via\n * {@link IFragmentVectorIndex.addFragments}.\n *\n * @remarks\n * Both identity fields are optional **in the type**, but the \"at least one\"\n * requirement is real — a fragment carrying neither is unidentifiable at the read\n * side. It is enforced by {@link embeddedFragmentConverter} (and re-checked by the\n * in-package index implementations) rather than by a conditional-required union\n * (`{ locator; fragmentId? } | { locator?; fragmentId }`), which was considered and\n * declined: the union costs at every construction site and buys nothing at the read\n * site, where each field reads as `… | undefined` either way.\n * @public\n */\nexport interface IEmbeddedFragment {\n /**\n * The region of the record body this fragment was derived from, when one can be\n * stated honestly. Advisory — see {@link IFragmentLocator}; it is NOT a slice that\n * reproduces the fragment text. Omit it for a fragment with no honest body span (a\n * rewriting segmenter), in which case `fragmentId` must be supplied.\n */\n readonly locator?: IFragmentLocator;\n /**\n * An opaque, consumer-minted identity for this fragment, carried verbatim through\n * the index and returned on the corresponding {@link IVectorQueryHit}. The index\n * **never parses it, never filters on it, and never assigns meaning to it** — it is\n * a bytestring, not part of the query path. It exists so a fragment stays\n * identifiable when its text is not re-derivable from the record body.\n *\n * The guarantee is \"we never parse it\", NOT \"we keep it stable\". Because\n * `addFragments` is whole-record-replace, an updated record re-emits its entire\n * fragment set, so **any stability of a fragment id across re-embeds is the\n * consumer's responsibility**, not the index's.\n */\n readonly fragmentId?: string;\n /** The embedding vector for this fragment. */\n readonly vector: Float32Array;\n}\n\n/**\n * The fragment-granular sibling of {@link IVectorIndex}: instead of one vector per\n * record it holds many vectors per record, each tagged with the identity its\n * {@link IEmbeddedFragment} carried, and its `query` returns per-fragment hits\n * carrying that identity back. This is the seam behind sub-document semantic search\n * — the \"discovery\" half of a search-then-read contract, where a hit tells the\n * consumer which record AND which fragment of it to read.\n *\n * @remarks\n * Deliberately NOT `extends IVectorIndex`: an index holding many vectors per record\n * has no well-defined single-vector `add(target, vector)`. It is a parallel contract\n * with three operations — `addFragments`, `remove`, `query` — reusing\n * {@link IVectorQueryHit}, on which both `locator` and `fragmentId` are optional. A\n * fragment hit populates whichever of the two its stored fragment carried; see\n * {@link IVectorQueryHit} for why that is not a discriminator and why fragment-ness\n * is determined by the index queried, not by field presence. Kept distinct from the\n * record-granular index per the consumer contract: memory recall stays\n * record-granular; sub-document knowledge uses a separate fragment index.\n * @public\n */\nexport interface IFragmentVectorIndex {\n /**\n * Add (or replace) all fragments for the scope-qualified `target`. Whole-record\n * semantics: every fragment previously held for `target` is dropped and replaced\n * by `fragments`, so a re-authored document never leaves stale fragments behind.\n * Returns the number of fragments now held for the record.\n */\n addFragments(target: IEdgeTarget, fragments: ReadonlyArray<IEmbeddedFragment>): Promise<Result<number>>;\n\n /**\n * Remove every fragment for the scope-qualified `target`. Returns the removed\n * target. Idempotent — removing a target with no fragments still succeeds.\n */\n remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;\n\n /**\n * Return the `topK` nearest fragments to `vector`, in descending score order,\n * each hit carrying its record `target` plus whichever of `locator` /\n * `fragmentId` the stored fragment was added with. When\n * `maxPerRecord` is supplied, no more than that many fragments of any single\n * record appear in the result — the cap is applied during selection (before the\n * `topK` cut) so one long document cannot crowd out others.\n */\n query(\n vector: Float32Array,\n topK: number,\n maxPerRecord?: number\n ): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;\n}\n\n/**\n * Embeds a complete record into a vector for the store's embed-on-write hook.\n * Async and `Result`-returning, since a real embedder does a network call (cloud\n * provider) or in-process model inference. The consumer wires this — the core\n * package never calls an embedding provider directly, staying embedder-agnostic.\n * @public\n */\nexport type MemoryEmbedder = (record: IMemoryRecord<unknown>) => Promise<Result<Float32Array>>;\n\n/**\n * The fragment-granular sibling of {@link MemoryEmbedder}: chunks a record's body\n * and embeds each chunk, returning one {@link IEmbeddedFragment} per chunk. The\n * chunking policy (window size, overlap) lives entirely in the consumer's embedder\n * — the core stays chunking-agnostic, exactly as it stays embedder-agnostic for\n * the record-granular path. Used by the store's fragment-embed-on-write hook.\n * @public\n */\nexport type FragmentEmbedder = (\n record: IMemoryRecord<unknown>\n) => Promise<Result<ReadonlyArray<IEmbeddedFragment>>>;\n\n/**\n * A record paired with its scope-qualified {@link IEdgeTarget | address}, as\n * yielded by {@link IMemoryRecordSource.list}. The address is required because\n * {@link InMemoryCosineIndex.rebuild} keys each re-embedded entry on the\n * scope-qualified target, not a bare {@link MemoryId} — two records that share a\n * filename stem across scopes must not collide when the whole vault is re-indexed.\n * @public\n */\nexport interface IScopedMemoryRecord {\n /** The record's scope-qualified `(scope, id)` address. */\n readonly target: IEdgeTarget;\n /** The record itself, passed to the embedder. */\n readonly record: IMemoryRecord<unknown>;\n}\n\n/**\n * The minimal record-source surface {@link InMemoryCosineIndex.rebuild} reads to\n * re-embed an entire vault. Each entry carries the record's scope-qualified\n * address (see {@link IScopedMemoryRecord}) so the rebuild keys the vector index\n * exactly as the incremental embed-on-write path does. A consumer backs this with\n * the store's scoped index — the vector packlet does not import the store packlet\n * (which depends on the vector packlet for {@link IVectorIndex}, so the reverse\n * import would be a cycle).\n * @public\n */\nexport interface IMemoryRecordSource {\n /** List every record in the vault, each paired with its scoped address. */\n list(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"vectorIndex.js","sourceRoot":"","sources":["../../../src/packlets/vector/vectorIndex.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Result } from '@fgv/ts-utils';\nimport { IEdgeTarget, IMemoryRecord } from '../types';\n\n/**\n * A half-open `[start, end)` span into a record's body — the in-record locator a\n * {@link IFragmentVectorIndex} may carry on a fragment. `start` is inclusive,\n * `end` exclusive. The unit (character / byte / token offsets) is the consumer's\n * choice: the index stores the two integers opaquely and never interprets them,\n * so they line up with whatever locator the consumer's own read side uses.\n *\n * @remarks\n * **The span is advisory.** It names the region of the body a fragment was\n * *derived from*; it is NOT a slice guaranteed to reproduce the fragment's text.\n * `body.slice(start, end)` round-trips only under a segmenter that merely chooses\n * boundaries. Under a **rewriting** segmenter — one that turns a span into a\n * curated block, an increasingly common ingestion shape when a model both selects\n * and rewrites — the fragment text is not a substring of the body at all, and the\n * fragmentation is not re-derivable from the body. Treat the span as a pointer for\n * locating context, never as an extraction recipe.\n *\n * A fragment whose provenance cannot honestly be expressed as a body span should\n * omit the locator entirely and carry an {@link IEmbeddedFragment.fragmentId}\n * instead.\n * @public\n */\nexport interface IFragmentLocator {\n /** Inclusive start offset into the record body. */\n readonly start: number;\n /** Exclusive end offset into the record body. */\n readonly end: number;\n}\n\n/**\n * A single hit returned by {@link IVectorIndex.query} (or\n * {@link IFragmentVectorIndex.query}): the matched record's scope-qualified\n * {@link IEdgeTarget | address} and the backend's similarity score (higher = more\n * similar; the exact scale is backend-defined). Hits are returned in descending\n * score order.\n *\n * @remarks\n * The address is a `(scope, id)` pair, NOT a bare {@link MemoryId} — per-scope\n * codecs (e.g. the medium-term codec's `turn-<n>` stems) legally mint the same\n * stem under different scopes, so a bare id could not disambiguate two records\n * that share a stem. The caller re-resolves the hit against the record index by\n * the same scoped address.\n *\n * **No single field discriminates a fragment hit from a record-granular hit.** A\n * record hit carries neither `locator` nor `fragmentId`; a fragment hit carries at\n * least one of the two, but not necessarily any particular one — a fragment with a\n * body span but no consumer-minted id, and a fragment with an id but no honest span,\n * are both legal. Testing one field for presence therefore cannot tell you which\n * kind of hit you hold.\n *\n * That \"at least one\" requirement is enforced on the upsert side by\n * {@link embeddedFragmentConverter} — a different boundary from this type — and is\n * deliberately NOT offered here as a discriminator either. A caller keyed off it\n * would be coupled to an invariant this type does not own, and would fail silently\n * if the invariant were ever relaxed.\n *\n * **The robust rule is that fragment-ness is determined by which index produced the\n * hit**: {@link IFragmentVectorIndex.query} returns fragment hits and\n * {@link IVectorIndex.query} returns record hits. The caller chose the index it\n * queried, so it already knows which kind it is holding.\n *\n * Note in particular that an absent `locator` now carries **two** distinct meanings\n * — a record-granular hit, or a fragment with no honest body span (see\n * {@link IFragmentLocator}) — which is precisely why presence-branching is unsafe.\n * @public\n */\nexport interface IVectorQueryHit {\n /** The scope-qualified address of the matched record. */\n readonly target: IEdgeTarget;\n /** Backend similarity score; higher is more similar. */\n readonly score: number;\n /**\n * The advisory in-record span the matched fragment was derived from, when the\n * producing fragment carried one. Absent on record-granular hits AND on fragment\n * hits with no honest span — see the remarks above; do not branch on its presence.\n */\n readonly locator?: IFragmentLocator;\n /**\n * The opaque identity the producing fragment was stored with, carried back\n * verbatim. Absent on record-granular hits AND on fragment hits stored without\n * one — see the remarks above; do not branch on its presence.\n */\n readonly fragmentId?: string;\n}\n\n/**\n * The vector-index seam an embedding backend implements to make\n * {@link SemanticRetriever | semantic recall} operational.\n *\n * @remarks\n * Vectors cross this seam as `Float32Array` (the in-memory representation an\n * embedding model produces); `number[]` is reserved for the JSON-wire edges\n * (e.g. a provider's embedding response). The in-package brute-force cosine\n * implementation is {@link InMemoryCosineIndex}; a consumer can swap an external\n * ANN backend behind the same seam once N grows beyond the in-memory regime.\n *\n * Every operation returns a `Result` (async, since a real backend does I/O) so\n * failure is explicit and never throws across the seam.\n * @public\n */\nexport interface IVectorIndex {\n /**\n * Add (or replace) the embedding for the scope-qualified `target`. Returns the\n * opaque {@link IMemoryEnvelope.embeddingRef | embeddingRef} the store stamps\n * onto the envelope so a later read knows the record is embedded. Keying on the\n * `(scope, id)` address (not a bare id) is load-bearing: two records that share\n * a filename stem across scopes must not clobber each other's embedding.\n */\n add(target: IEdgeTarget, vector: Float32Array): Promise<Result<string>>;\n\n /**\n * Remove the embedding for the scope-qualified `target`. Returns the removed\n * target. Idempotent — removing a target with no embedding still succeeds\n * (returns the target).\n */\n remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;\n\n /**\n * Return the `topK` nearest records to `vector`, in descending score order.\n */\n query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;\n\n /**\n * The number of vectors currently held.\n *\n * @remarks\n * On the contract because without it a caller cannot distinguish *\"the index is\n * empty\"* from *\"nothing matched\"*: {@link IVectorIndex.query} answers an empty\n * index with `succeed([])`, which is indistinguishable from a genuine miss. The\n * only other check available to a caller — \"is a vector index wired?\" — tests the\n * **wiring**, and that stays true while the index holds nothing.\n *\n * Note the narrow scope: this answers *how many vectors are held*, **not** how\n * many there ought to be. Full coverage — \"is every record that should be indexed\n * actually indexed?\" — still requires comparing against the record source and\n * {@link IMemoryStore.embedsKind}.\n *\n * Synchronous and non-`Result` because both shipped implementations can answer it\n * without I/O that can fail — the in-memory index reads a `Map`'s size, and the\n * SQLite-backed one a prepared `COUNT` against an open connection it already owns.\n */\n readonly size: number;\n\n /**\n * Re-embed every record from `source` and rebuild the index from scratch — the\n * **backfill / reconcile** operation.\n *\n * @remarks\n * On the contract because a persisted index is unusable without it. Records\n * written while the index was unwired, a re-embed after a dimension change (where\n * the backend supports one — a `vec0`-backed table's dimension is fixed at\n * creation, so there it needs a drop-and-re-index instead), and reconciliation\n * after a swallowed embed-on-write failure are all unreachable otherwise — and the store's own docstring already promises *\"the derived index\n * is reconciled by a later `rebuild`\"*, a promise the contract could not keep for\n * any index but the bundled one. A caller moving from the bundled implementation\n * to a persistent one found the swap type-checked everywhere **except** the one\n * place it backfills, which is the place that mattered.\n *\n * See {@link IVectorRebuildReport} for what it reports and\n * {@link IVectorRebuildOptions} for the failure mode.\n */\n rebuild(\n source: IMemoryRecordSource,\n embed: MemoryEmbedder,\n options?: IVectorRebuildOptions\n ): Promise<Result<IVectorRebuildReport>>;\n}\n\n/**\n * One embedded fragment of a record: the fragment's vector, plus at least one of the\n * two ways to identify it — its advisory in-record {@link IFragmentLocator | span}\n * and/or an opaque consumer-minted {@link IEmbeddedFragment.fragmentId | fragmentId}.\n * Produced by a {@link FragmentEmbedder} and stored via\n * {@link IFragmentVectorIndex.addFragments}.\n *\n * @remarks\n * Both identity fields are optional **in the type**, but the \"at least one\"\n * requirement is real — a fragment carrying neither is unidentifiable at the read\n * side. It is enforced by {@link embeddedFragmentConverter} (and re-checked by the\n * in-package index implementations) rather than by a conditional-required union\n * (`{ locator; fragmentId? } | { locator?; fragmentId }`), which was considered and\n * declined: the union costs at every construction site and buys nothing at the read\n * site, where each field reads as `… | undefined` either way.\n * @public\n */\nexport interface IEmbeddedFragment {\n /**\n * The region of the record body this fragment was derived from, when one can be\n * stated honestly. Advisory — see {@link IFragmentLocator}; it is NOT a slice that\n * reproduces the fragment text. Omit it for a fragment with no honest body span (a\n * rewriting segmenter), in which case `fragmentId` must be supplied.\n */\n readonly locator?: IFragmentLocator;\n /**\n * An opaque, consumer-minted identity for this fragment, carried verbatim through\n * the index and returned on the corresponding {@link IVectorQueryHit}. The index\n * **never parses it, never filters on it, and never assigns meaning to it** — it is\n * a bytestring, not part of the query path. It exists so a fragment stays\n * identifiable when its text is not re-derivable from the record body.\n *\n * The guarantee is \"we never parse it\", NOT \"we keep it stable\". Because\n * `addFragments` is whole-record-replace, an updated record re-emits its entire\n * fragment set, so **any stability of a fragment id across re-embeds is the\n * consumer's responsibility**, not the index's.\n */\n readonly fragmentId?: string;\n /** The embedding vector for this fragment. */\n readonly vector: Float32Array;\n}\n\n/**\n * The fragment-granular sibling of {@link IVectorIndex}: instead of one vector per\n * record it holds many vectors per record, each tagged with the identity its\n * {@link IEmbeddedFragment} carried, and its `query` returns per-fragment hits\n * carrying that identity back. This is the seam behind sub-document semantic search\n * — the \"discovery\" half of a search-then-read contract, where a hit tells the\n * consumer which record AND which fragment of it to read.\n *\n * @remarks\n * Deliberately NOT `extends IVectorIndex`: an index holding many vectors per record\n * has no well-defined single-vector `add(target, vector)`. It is a parallel contract\n * with three operations — `addFragments`, `remove`, `query` — reusing\n * {@link IVectorQueryHit}, on which both `locator` and `fragmentId` are optional. A\n * fragment hit populates whichever of the two its stored fragment carried; see\n * {@link IVectorQueryHit} for why that is not a discriminator and why fragment-ness\n * is determined by the index queried, not by field presence. Kept distinct from the\n * record-granular index per the consumer contract: memory recall stays\n * record-granular; sub-document knowledge uses a separate fragment index.\n * @public\n */\nexport interface IFragmentVectorIndex {\n /**\n * Add (or replace) all fragments for the scope-qualified `target`. Whole-record\n * semantics: every fragment previously held for `target` is dropped and replaced\n * by `fragments`, so a re-authored document never leaves stale fragments behind.\n * Returns the number of fragments now held for the record.\n */\n addFragments(target: IEdgeTarget, fragments: ReadonlyArray<IEmbeddedFragment>): Promise<Result<number>>;\n\n /**\n * Remove every fragment for the scope-qualified `target`. Returns the removed\n * target. Idempotent — removing a target with no fragments still succeeds.\n */\n remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;\n\n /**\n * Return the `topK` nearest fragments to `vector`, in descending score order,\n * each hit carrying its record `target` plus whichever of `locator` /\n * `fragmentId` the stored fragment was added with. When\n * `maxPerRecord` is supplied, no more than that many fragments of any single\n * record appear in the result — the cap is applied during selection (before the\n * `topK` cut) so one long document cannot crowd out others.\n */\n query(\n vector: Float32Array,\n topK: number,\n maxPerRecord?: number\n ): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;\n}\n\n/**\n * How a vector-index rebuild treats a record it cannot index — whether the\n * **embedding** failed or the subsequent **add** did. Both are governed by this\n * one mode; neither is unconditionally fatal.\n *\n * @remarks\n * Deliberately mirrors the store's own open-time `onRecordError` mode, including\n * its default: `'fail'` preserves the historical all-or-nothing contract exactly,\n * and `'skip'` is opt-in. Defined here rather than imported from the store packlet\n * — the `vector` packlet does not depend on `store`, and the two modes describe\n * different domains that merely happen to share a shape.\n *\n * A **decline** (a {@link MemoryEmbedder} resolving `undefined`) is not an error\n * and is unaffected by this mode: it is always **excluded** from the index and\n * counted on {@link IVectorRebuildReport.declined}, **never** appearing in\n * {@link IVectorRebuildReport.skipped}. The word is worth being careful with here:\n * `skipped` is now a formal field meaning *a fault*, and a decline is the opposite.\n * @public\n */\nexport type VectorRebuildErrorMode = 'skip' | 'fail';\n\n/**\n * A record a rebuild could not index — because the embed failed or because the\n * subsequent add did — retained so a partial rebuild reports what it lost rather\n * than merely how much it kept.\n * @public\n */\nexport interface ISkippedVectorRecord {\n /** The scope-qualified address of the record that could not be indexed. */\n readonly target: IEdgeTarget;\n /** The failure message, from either the embed or the subsequent add. */\n readonly error: string;\n}\n\n/**\n * What a rebuild actually did — the structural answer to \"is this index complete?\".\n *\n * @remarks\n * A bare count cannot distinguish the three ways a record can be absent from the\n * index, and that distinction is the entire point: **`declined` was intentional,\n * `skipped` was a fault, and neither is the same as \"never attempted\"**. A caller\n * deriving coverage from a count alone cannot tell an embedder outage from a\n * deliberate policy, which is precisely the confusion this type exists to end.\n * @public\n */\nexport interface IVectorRebuildReport {\n /** Records embedded and added to the index. */\n readonly indexed: number;\n /** Records the embedder deliberately declined (resolved `undefined`). */\n readonly declined: number;\n /**\n * Records whose embedding or add FAILED and were skipped. Non-empty only under\n * {@link VectorRebuildErrorMode | `onRecordError: 'skip'`} — under `'fail'` the\n * first failure aborts the rebuild and no report is returned at all.\n */\n readonly skipped: ReadonlyArray<ISkippedVectorRecord>;\n}\n\n/**\n * Options for a vector-index rebuild.\n * @public\n */\nexport interface IVectorRebuildOptions {\n /**\n * How to treat a record the rebuild cannot index — an embed failure OR an add\n * failure. Defaults to `'fail'` — the historical behavior, unchanged for every\n * existing caller.\n */\n readonly onRecordError?: VectorRebuildErrorMode;\n}\n\n/**\n * Embeds a complete record into a vector for the store's embed-on-write hook.\n * Async and `Result`-returning, since a real embedder does a network call (cloud\n * provider) or in-process model inference. The consumer wires this — the core\n * package never calls an embedding provider directly, staying embedder-agnostic.\n *\n * @remarks\n * Resolving to `undefined` means **\"intentionally not embedded\"** — a deliberate\n * decline, not an error. The record is stored without an embedding reference, no\n * failure is reported, and **the decline itself logs nothing**. This is distinct\n * from a `Failure`, which means the embedder *tried and could not*.\n *\n * \"Logs nothing\" is a statement about the decline, not a promise of silence: a\n * decline on a record that was already embedded also prunes the vector that\n * reference named, and if that prune fails it is a genuine fault and warns like\n * any other. What a decline never does is warn merely for having happened.\n *\n * The distinction is load-bearing wherever the two are treated differently. On the\n * rebuild path a declined record is **excluded** from the index and counted on\n * {@link IVectorRebuildReport.declined}; a failed one is a genuine error and, under\n * `onRecordError: 'skip'`, is reported on {@link IVectorRebuildReport.skipped}. Collapsing \"I chose not to\" into `fail` would\n * make a deliberate policy indistinguishable from an embedder outage in the logs,\n * and would put a routine decision on whatever error path the caller has wired.\n *\n * The embedder receives the whole record, so the usual reason to decline is the\n * record's `kind` — a control or bookkeeping row that no query should ever return.\n *\n * @public\n */\nexport type MemoryEmbedder = (record: IMemoryRecord<unknown>) => Promise<Result<Float32Array | undefined>>;\n\n/**\n * The fragment-granular sibling of {@link MemoryEmbedder}: chunks a record's body\n * and embeds each chunk, returning one {@link IEmbeddedFragment} per chunk. The\n * chunking policy (window size, overlap) lives entirely in the consumer's embedder\n * — the core stays chunking-agnostic, exactly as it stays embedder-agnostic for\n * the record-granular path. Used by the store's fragment-embed-on-write hook.\n * @public\n */\nexport type FragmentEmbedder = (\n record: IMemoryRecord<unknown>\n) => Promise<Result<ReadonlyArray<IEmbeddedFragment>>>;\n\n/**\n * A record paired with its scope-qualified {@link IEdgeTarget | address}, as\n * yielded by {@link IMemoryRecordSource.list}. The address is required because\n * {@link InMemoryCosineIndex.rebuild} keys each re-embedded entry on the\n * scope-qualified target, not a bare {@link MemoryId} — two records that share a\n * filename stem across scopes must not collide when the whole vault is re-indexed.\n * @public\n */\nexport interface IScopedMemoryRecord {\n /** The record's scope-qualified `(scope, id)` address. */\n readonly target: IEdgeTarget;\n /** The record itself, passed to the embedder. */\n readonly record: IMemoryRecord<unknown>;\n}\n\n/**\n * The minimal record-source surface {@link InMemoryCosineIndex.rebuild} reads to\n * re-embed an entire vault. Each entry carries the record's scope-qualified\n * address (see {@link IScopedMemoryRecord}) so the rebuild keys the vector index\n * exactly as the incremental embed-on-write path does. A consumer backs this with\n * the store's scoped index — the vector packlet does not import the store packlet\n * (which depends on the vector packlet for {@link IVectorIndex}, so the reverse\n * import would be a cycle).\n * @public\n */\nexport interface IMemoryRecordSource {\n /** List every record in the vault, each paired with its scoped address. */\n list(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;\n}\n"]}
|
|
@@ -329,6 +329,8 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
329
329
|
private readonly _writePolicies;
|
|
330
330
|
private readonly _codecs;
|
|
331
331
|
private readonly _rankProjectors;
|
|
332
|
+
/** `undefined` = no declaration = every kind participates. */
|
|
333
|
+
private readonly _embedKinds;
|
|
332
334
|
private readonly _defaultCodec;
|
|
333
335
|
private readonly _defaultPolicy;
|
|
334
336
|
private readonly _scopeEncoding;
|
|
@@ -336,11 +338,9 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
336
338
|
private readonly _index;
|
|
337
339
|
private readonly _hasher;
|
|
338
340
|
private readonly _observers;
|
|
341
|
+
/** Record- and fragment-vector maintenance; every operation is best-effort. */
|
|
342
|
+
private readonly _vectors;
|
|
339
343
|
private readonly _logger;
|
|
340
|
-
private readonly _vectorIndex;
|
|
341
|
-
private readonly _embed;
|
|
342
|
-
private readonly _fragmentIndex;
|
|
343
|
-
private readonly _fragmentEmbedder;
|
|
344
344
|
/**
|
|
345
345
|
* Records the initial walk could not load. Populated during `create()` in
|
|
346
346
|
* {@link MemoryRecordErrorMode | `'skip'` mode}; empty otherwise.
|
|
@@ -457,39 +457,6 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
457
457
|
* later eviction failure never loses data with nothing written in its place.
|
|
458
458
|
*/
|
|
459
459
|
private _admitWrite;
|
|
460
|
-
/**
|
|
461
|
-
* Best-effort embed-on-write. When a vector index AND an embedder are wired,
|
|
462
|
-
* embeds the built record, `add`s the vector (replace semantics handle a same-id
|
|
463
|
-
* re-embed — no explicit remove), and stamps the returned `embeddingRef`. A
|
|
464
|
-
* failure (returned `fail` OR a thrown/rejected hook) is logged and the
|
|
465
|
-
* unembedded record is returned unchanged — the put still persists, and the
|
|
466
|
-
* derived index is reconciled by a later `rebuild`. A pass-through no-op when
|
|
467
|
-
* unwired (byte-identical record).
|
|
468
|
-
*
|
|
469
|
-
* Always succeeds (`Result` is the chain's shape, never a vector-induced
|
|
470
|
-
* failure).
|
|
471
|
-
*/
|
|
472
|
-
private _embedOnWrite;
|
|
473
|
-
/**
|
|
474
|
-
* Best-effort fragment-embed-on-write. When a fragment index AND a fragment
|
|
475
|
-
* embedder are wired, chunks + embeds the built record and replaces its
|
|
476
|
-
* fragments in the index (`addFragments` is whole-record-replace, so a re-authored
|
|
477
|
-
* document never leaves stale fragments behind — no explicit remove needed). A
|
|
478
|
-
* failure (returned `fail` OR a thrown/rejected hook) is logged and the record is
|
|
479
|
-
* returned unchanged — the put still persists, and the fragment index is a derived
|
|
480
|
-
* view a later `rebuild` reconciles. Unlike {@link FileTreeMemoryStore._embedOnWrite}
|
|
481
|
-
* it stamps nothing on the record (fragments have no per-record `embeddingRef`
|
|
482
|
-
* analog). A pass-through no-op when unwired (byte-identical record).
|
|
483
|
-
*/
|
|
484
|
-
private _embedFragmentsOnWrite;
|
|
485
|
-
/**
|
|
486
|
-
* Best-effort fragment removal. A no-op unless the full fragment lifecycle is
|
|
487
|
-
* wired (both an index AND an embedder), so an unwired store does no fragment
|
|
488
|
-
* work and behaves byte-identically. Failures are logged, never surfaced — a
|
|
489
|
-
* committed delete/eviction must not fail because a derived fragment index could
|
|
490
|
-
* not be pruned.
|
|
491
|
-
*/
|
|
492
|
-
private _removeFragmentsBestEffort;
|
|
493
460
|
/**
|
|
494
461
|
* Evict the records named by a `cull-oldest` decision, best-effort. Runs only
|
|
495
462
|
* after the authoritative `_persist`, so a failed eviction is logged (never
|
|
@@ -498,26 +465,6 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
498
465
|
* `accept` / `reject` decisions evict nothing.
|
|
499
466
|
*/
|
|
500
467
|
private _applyEvictions;
|
|
501
|
-
/**
|
|
502
|
-
* Best-effort vector removal for each evicted record (never fails the put).
|
|
503
|
-
* Every evicted record is in the same `scope` as the incoming write (the
|
|
504
|
-
* cull-oldest cohort is the incoming record's `(scope, kind)` cohort), so that
|
|
505
|
-
* scope qualifies each removal target.
|
|
506
|
-
*/
|
|
507
|
-
private _removeEvictedVectors;
|
|
508
|
-
/**
|
|
509
|
-
* Run a consumer-supplied vector hook, normalizing a thrown/rejected hook into a
|
|
510
|
-
* `Failure` and logging any failure at `warn`. Best-effort: the caller proceeds
|
|
511
|
-
* regardless, since the index is rebuildable.
|
|
512
|
-
*/
|
|
513
|
-
private _tryVectorOp;
|
|
514
|
-
/**
|
|
515
|
-
* Best-effort vector removal. A no-op unless the full vector lifecycle is wired
|
|
516
|
-
* (both an index AND an embedder), so an unwired store does no vector work and
|
|
517
|
-
* behaves byte-identically. Failures are logged, never surfaced — a committed
|
|
518
|
-
* delete/eviction must not fail because a derived index could not be pruned.
|
|
519
|
-
*/
|
|
520
|
-
private _removeVectorBestEffort;
|
|
521
468
|
/**
|
|
522
469
|
* Build the record to persist. On a first write the incoming envelope is the
|
|
523
470
|
* base (final content equals the incoming content, so the dedup `hash` is
|
|
@@ -651,6 +598,8 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
651
598
|
private _policyFor;
|
|
652
599
|
/** {@inheritDoc IMemoryStore.dedupScopeFor} */
|
|
653
600
|
dedupScopeFor(kind: Kind): DedupScope;
|
|
601
|
+
/** {@inheritDoc IMemoryStore.embedsKind} */
|
|
602
|
+
embedsKind(kind: Kind): boolean;
|
|
654
603
|
/**
|
|
655
604
|
* Read and validate the record at `<scope>/<idStem>.md`, returning `undefined`
|
|
656
605
|
* when the scope directory or file is absent. Verifies the on-disk id ↔
|
|
@@ -1174,6 +1123,37 @@ export declare interface IFileTreeMemoryStoreCreateParams {
|
|
|
1174
1123
|
* guard-host-callbacks conventions).
|
|
1175
1124
|
*/
|
|
1176
1125
|
readonly rankProjectors?: ReadonlyMap<Kind, RankProjector>;
|
|
1126
|
+
/**
|
|
1127
|
+
* The kinds whose records participate in the **record-granular** vector index.
|
|
1128
|
+
*
|
|
1129
|
+
* @remarks
|
|
1130
|
+
* **Absent means every kind participates**, which is the pre-existing behavior —
|
|
1131
|
+
* so omitting this is byte-identical to before it existed. Supplying it makes the
|
|
1132
|
+
* set an allowlist: a kind outside it is never handed to the {@link MemoryEmbedder}
|
|
1133
|
+
* on write, and is omitted from {@link IMemoryStore.asRecordSource | asRecordSource},
|
|
1134
|
+
* so a rebuild driven from this store does not pay for it either.
|
|
1135
|
+
*
|
|
1136
|
+
* Two costs motivate it, and the second is the one that is easy to miss:
|
|
1137
|
+
*
|
|
1138
|
+
* - **Embedder work on the critical path.** Embed-on-write is synchronous with
|
|
1139
|
+
* the write. A bookkeeping row — a status, a counter, a lease — that no query
|
|
1140
|
+
* will ever return still pays a full embedding round trip, and on a
|
|
1141
|
+
* locally-hosted model the first call after a restart pays a cold model load
|
|
1142
|
+
* on top.
|
|
1143
|
+
* - **Un-queried kinds crowd the `topK` window.** `IVectorIndex.query` applies
|
|
1144
|
+
* `topK` *before* any kind filter the retriever adds, so vectors that can never
|
|
1145
|
+
* be returned still occupy candidate slots. Over-fetching to compensate hides
|
|
1146
|
+
* this until the un-queried kinds start scoring well — at which point recall is
|
|
1147
|
+
* silently lost. Restricting what is indexed fixes the recall problem, not just
|
|
1148
|
+
* the cost.
|
|
1149
|
+
*
|
|
1150
|
+
* Applies to the record-granular path only. The fragment path
|
|
1151
|
+
* ({@link IFileTreeMemoryStoreCreateParams.fragmentIndex | fragmentIndex} /
|
|
1152
|
+
* `fragmentEmbedder`) is independent and unaffected — a kind may legitimately be
|
|
1153
|
+
* fragment-embedded and not record-embedded, which is the right shape for a long
|
|
1154
|
+
* document whose whole body exceeds the model's context.
|
|
1155
|
+
*/
|
|
1156
|
+
readonly embedKinds?: ReadonlySet<Kind>;
|
|
1177
1157
|
/** Default codec for kinds without an explicit entry. */
|
|
1178
1158
|
readonly defaultCodec?: IIdentityCodec;
|
|
1179
1159
|
/**
|
|
@@ -1830,6 +1810,12 @@ export declare interface IMemoryObservationQuery {
|
|
|
1830
1810
|
readonly phase?: MemoryObservationPhase;
|
|
1831
1811
|
/** Only records with this outcome. */
|
|
1832
1812
|
readonly outcome?: MemoryObservationOutcome;
|
|
1813
|
+
/**
|
|
1814
|
+
* Only `'write'` records with this embed outcome. Records carrying no embed
|
|
1815
|
+
* outcome never match, so `embed: 'failed'` answers "which writes left the
|
|
1816
|
+
* index short?" without a full scan of every record's `embeddingRef`.
|
|
1817
|
+
*/
|
|
1818
|
+
readonly embed?: MemoryEmbedOutcome;
|
|
1833
1819
|
}
|
|
1834
1820
|
|
|
1835
1821
|
/**
|
|
@@ -1865,6 +1851,12 @@ export declare interface IMemoryObservationRecord {
|
|
|
1865
1851
|
readonly error?: string;
|
|
1866
1852
|
/** Structured provenance of the write, when the operation carried one. */
|
|
1867
1853
|
readonly provenance?: IProvenance;
|
|
1854
|
+
/**
|
|
1855
|
+
* For `'write'` observations: what the record-granular vector index did about
|
|
1856
|
+
* this record. Absent when the question does not apply — see
|
|
1857
|
+
* {@link MemoryEmbedOutcome}.
|
|
1858
|
+
*/
|
|
1859
|
+
readonly embed?: MemoryEmbedOutcome;
|
|
1868
1860
|
/**
|
|
1869
1861
|
* For `'retrieve'` observations: an opaque snapshot of the query that drove
|
|
1870
1862
|
* the retrieval. Carried verbatim; never interpreted by the store.
|
|
@@ -2083,8 +2075,16 @@ export declare interface IMemoryStore {
|
|
|
2083
2075
|
/**
|
|
2084
2076
|
* Adapt this store to the {@link IMemoryRecordSource} seam so it can drive
|
|
2085
2077
|
* {@link IVectorIndex} rebuilds (e.g. `InMemoryCosineIndex.rebuild`). The
|
|
2086
|
-
* returned source's `list()` delegates to {@link IMemoryStore.listScoped}
|
|
2087
|
-
*
|
|
2078
|
+
* returned source's `list()` delegates to {@link IMemoryStore.listScoped},
|
|
2079
|
+
* **filtered to the kinds {@link IMemoryStore.embedsKind | embedsKind} reports** —
|
|
2080
|
+
* this source exists to feed the record vector index, so a kind excluded from
|
|
2081
|
+
* that index is excluded here too, and a reopen does not re-embed records the
|
|
2082
|
+
* index will never return. With no
|
|
2083
|
+
* {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds} declaration
|
|
2084
|
+
* every kind participates and the filter is the identity. `listScoped` itself is
|
|
2085
|
+
* **not** filtered and remains the whole-vault surface.
|
|
2086
|
+
*
|
|
2087
|
+
* The store cannot implement {@link IMemoryRecordSource} directly because its
|
|
2088
2088
|
* `list(filter?)` returns bare records (the ergonomic query surface) while the
|
|
2089
2089
|
* seam's `list()` returns scope-qualified records.
|
|
2090
2090
|
*/
|
|
@@ -2117,6 +2117,25 @@ export declare interface IMemoryStore {
|
|
|
2117
2117
|
* invoking admission or merge logic out of band.
|
|
2118
2118
|
*/
|
|
2119
2119
|
dedupScopeFor(kind: Kind): DedupScope;
|
|
2120
|
+
/**
|
|
2121
|
+
* Whether records of `kind` participate in the **record-granular** vector index.
|
|
2122
|
+
*
|
|
2123
|
+
* @remarks
|
|
2124
|
+
* A read accessor over the store's injected {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds}
|
|
2125
|
+
* declaration, in the same spirit as {@link IMemoryStore.dedupScopeFor} — one
|
|
2126
|
+
* place to ask, so the store's write path and any caller reasoning about index
|
|
2127
|
+
* coverage cannot disagree. `true` for every kind when no declaration was made.
|
|
2128
|
+
*
|
|
2129
|
+
* **This is distinct from a {@link MemoryEmbedder} decline, and the difference is
|
|
2130
|
+
* cost.** An embedder that returns `undefined` has already been called: the
|
|
2131
|
+
* round trip is paid, and on a locally-hosted model that round trip is the
|
|
2132
|
+
* expense. A kind excluded here is never handed to the embedder at all. The
|
|
2133
|
+
* decline makes the intent *expressible*; this makes it *free*.
|
|
2134
|
+
*
|
|
2135
|
+
* Deliberately synchronous, total, and NOT `Result`-returning: it reads
|
|
2136
|
+
* constructor-injected configuration, touches no I/O, and cannot fail.
|
|
2137
|
+
*/
|
|
2138
|
+
embedsKind(kind: Kind): boolean;
|
|
2120
2139
|
/**
|
|
2121
2140
|
* Write a record. Validates the body, computes a content hash, deduplicates
|
|
2122
2141
|
* (scope-wide, before policy), applies the kind's {@link IWritePolicy}, stamps
|
|
@@ -2269,17 +2288,40 @@ export declare class InMemoryCosineIndex implements IVectorIndex {
|
|
|
2269
2288
|
/**
|
|
2270
2289
|
* Re-embed every record from `source` and rebuild the index from scratch.
|
|
2271
2290
|
* Clears the current contents (and the established dimension) first, so a
|
|
2272
|
-
* re-embed with a different model is supported. Returns
|
|
2273
|
-
* indexed.
|
|
2291
|
+
* re-embed with a different model is supported. Returns an
|
|
2292
|
+
* {@link IVectorRebuildReport} describing what was indexed, declined and skipped.
|
|
2293
|
+
*
|
|
2294
|
+
* @remarks
|
|
2295
|
+
* **A failure to LIST is always fatal**, under either mode — and **leaves the
|
|
2296
|
+
* existing index untouched**: an unreadable source says nothing about which
|
|
2297
|
+
* records exist, so there is neither an honest partial to report nor any reason
|
|
2298
|
+
* to discard what is already held.
|
|
2299
|
+
*
|
|
2300
|
+
* Per-record embed/add failures are governed by
|
|
2301
|
+
* {@link IVectorRebuildOptions.onRecordError}, which defaults to `'fail'` —
|
|
2302
|
+
* **the historical all-or-nothing contract, unchanged**: the index is rolled back
|
|
2303
|
+
* to empty rather than left partially rebuilt, so a caller that retries a query
|
|
2304
|
+
* sees a clean empty index it can reason about.
|
|
2305
|
+
*
|
|
2306
|
+
* `'skip'` opts into the lenient shape the store's own open already uses: the
|
|
2307
|
+
* rebuild continues and every casualty is returned structurally on
|
|
2308
|
+
* {@link IVectorRebuildReport.skipped}. **It reports more, it does not report
|
|
2309
|
+
* less** — the point is to stop one bad record emptying an entire index, not to
|
|
2310
|
+
* make failures quieter. A caller that ignores `skipped` under `'skip'` has
|
|
2311
|
+
* chosen to, rather than been given no way to know.
|
|
2274
2312
|
*
|
|
2275
|
-
*
|
|
2276
|
-
*
|
|
2277
|
-
*
|
|
2313
|
+
* A {@link MemoryEmbedder} decline is not a failure under either mode: it is
|
|
2314
|
+
* counted on {@link IVectorRebuildReport.declined} and never appears in `skipped`.
|
|
2315
|
+
*
|
|
2316
|
+
* Both consumer-supplied hooks are capture-wrapped, so a `source` or `embed`
|
|
2317
|
+
* that throws or rejects becomes a `Failure` on the path above rather than an
|
|
2318
|
+
* exception escaping mid-rebuild — which would bypass the rollback entirely.
|
|
2278
2319
|
*
|
|
2279
2320
|
* @param source - The scope-qualified record source to re-embed.
|
|
2280
2321
|
* @param embed - The embedder applied to each record.
|
|
2322
|
+
* @param options - Rebuild options; omit for the historical `'fail'` behavior.
|
|
2281
2323
|
*/
|
|
2282
|
-
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder): Promise<Result<
|
|
2324
|
+
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder, options?: IVectorRebuildOptions): Promise<Result<IVectorRebuildReport>>;
|
|
2283
2325
|
/** Empty the index and forget the established dimension. */
|
|
2284
2326
|
private _reset;
|
|
2285
2327
|
/** The Euclidean magnitude (L2 norm) of a vector. */
|
|
@@ -2350,6 +2392,13 @@ export declare class InMemoryFragmentCosineIndex implements IFragmentVectorIndex
|
|
|
2350
2392
|
* On any failure (list, embed, or add) the index is rolled back to empty rather
|
|
2351
2393
|
* than left in a partially-rebuilt state.
|
|
2352
2394
|
*
|
|
2395
|
+
* @remarks
|
|
2396
|
+
* **Deliberately still returns a bare count**, unlike the record-granular
|
|
2397
|
+
* {@link InMemoryCosineIndex.rebuild}, which reports an
|
|
2398
|
+
* {@link IVectorRebuildReport}. The asymmetry is scope, not oversight: the
|
|
2399
|
+
* fragment path is tracked separately and gains the same treatment when the
|
|
2400
|
+
* `IVectorIndex`/`IFragmentVectorIndex` contracts are revisited together.
|
|
2401
|
+
*
|
|
2353
2402
|
* @param source - The scope-qualified record source to re-embed.
|
|
2354
2403
|
* @param embed - The fragment embedder applied to each record.
|
|
2355
2404
|
*/
|
|
@@ -2495,6 +2544,19 @@ export declare interface ISkippedRecord {
|
|
|
2495
2544
|
readonly error: string;
|
|
2496
2545
|
}
|
|
2497
2546
|
|
|
2547
|
+
/**
|
|
2548
|
+
* A record a rebuild could not index — because the embed failed or because the
|
|
2549
|
+
* subsequent add did — retained so a partial rebuild reports what it lost rather
|
|
2550
|
+
* than merely how much it kept.
|
|
2551
|
+
* @public
|
|
2552
|
+
*/
|
|
2553
|
+
export declare interface ISkippedVectorRecord {
|
|
2554
|
+
/** The scope-qualified address of the record that could not be indexed. */
|
|
2555
|
+
readonly target: IEdgeTarget;
|
|
2556
|
+
/** The failure message, from either the embed or the subsequent add. */
|
|
2557
|
+
readonly error: string;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2498
2560
|
/**
|
|
2499
2561
|
* Narrow an {@link IIdentityCodec} to {@link ITemporalIdentityCodec} by probing
|
|
2500
2562
|
* for the versioned methods. Used by the store when an `encode` result reports
|
|
@@ -2612,6 +2674,45 @@ export declare interface IVectorIndex {
|
|
|
2612
2674
|
* Return the `topK` nearest records to `vector`, in descending score order.
|
|
2613
2675
|
*/
|
|
2614
2676
|
query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;
|
|
2677
|
+
/**
|
|
2678
|
+
* The number of vectors currently held.
|
|
2679
|
+
*
|
|
2680
|
+
* @remarks
|
|
2681
|
+
* On the contract because without it a caller cannot distinguish *"the index is
|
|
2682
|
+
* empty"* from *"nothing matched"*: {@link IVectorIndex.query} answers an empty
|
|
2683
|
+
* index with `succeed([])`, which is indistinguishable from a genuine miss. The
|
|
2684
|
+
* only other check available to a caller — "is a vector index wired?" — tests the
|
|
2685
|
+
* **wiring**, and that stays true while the index holds nothing.
|
|
2686
|
+
*
|
|
2687
|
+
* Note the narrow scope: this answers *how many vectors are held*, **not** how
|
|
2688
|
+
* many there ought to be. Full coverage — "is every record that should be indexed
|
|
2689
|
+
* actually indexed?" — still requires comparing against the record source and
|
|
2690
|
+
* {@link IMemoryStore.embedsKind}.
|
|
2691
|
+
*
|
|
2692
|
+
* Synchronous and non-`Result` because both shipped implementations can answer it
|
|
2693
|
+
* without I/O that can fail — the in-memory index reads a `Map`'s size, and the
|
|
2694
|
+
* SQLite-backed one a prepared `COUNT` against an open connection it already owns.
|
|
2695
|
+
*/
|
|
2696
|
+
readonly size: number;
|
|
2697
|
+
/**
|
|
2698
|
+
* Re-embed every record from `source` and rebuild the index from scratch — the
|
|
2699
|
+
* **backfill / reconcile** operation.
|
|
2700
|
+
*
|
|
2701
|
+
* @remarks
|
|
2702
|
+
* On the contract because a persisted index is unusable without it. Records
|
|
2703
|
+
* written while the index was unwired, a re-embed after a dimension change (where
|
|
2704
|
+
* the backend supports one — a `vec0`-backed table's dimension is fixed at
|
|
2705
|
+
* creation, so there it needs a drop-and-re-index instead), and reconciliation
|
|
2706
|
+
* after a swallowed embed-on-write failure are all unreachable otherwise — and the store's own docstring already promises *"the derived index
|
|
2707
|
+
* is reconciled by a later `rebuild`"*, a promise the contract could not keep for
|
|
2708
|
+
* any index but the bundled one. A caller moving from the bundled implementation
|
|
2709
|
+
* to a persistent one found the swap type-checked everywhere **except** the one
|
|
2710
|
+
* place it backfills, which is the place that mattered.
|
|
2711
|
+
*
|
|
2712
|
+
* See {@link IVectorRebuildReport} for what it reports and
|
|
2713
|
+
* {@link IVectorRebuildOptions} for the failure mode.
|
|
2714
|
+
*/
|
|
2715
|
+
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder, options?: IVectorRebuildOptions): Promise<Result<IVectorRebuildReport>>;
|
|
2615
2716
|
}
|
|
2616
2717
|
|
|
2617
2718
|
/**
|
|
@@ -2670,6 +2771,43 @@ export declare interface IVectorQueryHit {
|
|
|
2670
2771
|
readonly fragmentId?: string;
|
|
2671
2772
|
}
|
|
2672
2773
|
|
|
2774
|
+
/**
|
|
2775
|
+
* Options for a vector-index rebuild.
|
|
2776
|
+
* @public
|
|
2777
|
+
*/
|
|
2778
|
+
export declare interface IVectorRebuildOptions {
|
|
2779
|
+
/**
|
|
2780
|
+
* How to treat a record the rebuild cannot index — an embed failure OR an add
|
|
2781
|
+
* failure. Defaults to `'fail'` — the historical behavior, unchanged for every
|
|
2782
|
+
* existing caller.
|
|
2783
|
+
*/
|
|
2784
|
+
readonly onRecordError?: VectorRebuildErrorMode;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
/**
|
|
2788
|
+
* What a rebuild actually did — the structural answer to "is this index complete?".
|
|
2789
|
+
*
|
|
2790
|
+
* @remarks
|
|
2791
|
+
* A bare count cannot distinguish the three ways a record can be absent from the
|
|
2792
|
+
* index, and that distinction is the entire point: **`declined` was intentional,
|
|
2793
|
+
* `skipped` was a fault, and neither is the same as "never attempted"**. A caller
|
|
2794
|
+
* deriving coverage from a count alone cannot tell an embedder outage from a
|
|
2795
|
+
* deliberate policy, which is precisely the confusion this type exists to end.
|
|
2796
|
+
* @public
|
|
2797
|
+
*/
|
|
2798
|
+
export declare interface IVectorRebuildReport {
|
|
2799
|
+
/** Records embedded and added to the index. */
|
|
2800
|
+
readonly indexed: number;
|
|
2801
|
+
/** Records the embedder deliberately declined (resolved `undefined`). */
|
|
2802
|
+
readonly declined: number;
|
|
2803
|
+
/**
|
|
2804
|
+
* Records whose embedding or add FAILED and were skipped. Non-empty only under
|
|
2805
|
+
* {@link VectorRebuildErrorMode | `onRecordError: 'skip'`} — under `'fail'` the
|
|
2806
|
+
* first failure aborts the rebuild and no report is returned at all.
|
|
2807
|
+
*/
|
|
2808
|
+
readonly skipped: ReadonlyArray<ISkippedVectorRecord>;
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2673
2811
|
/**
|
|
2674
2812
|
* A per-kind write policy, injected at store construction. Invoked AFTER
|
|
2675
2813
|
* content-hash dedup (dedup is always pre-policy). The policy decides
|
|
@@ -3019,9 +3157,81 @@ export declare type MemoryDetailTier = 'gist' | 'full';
|
|
|
3019
3157
|
* Async and `Result`-returning, since a real embedder does a network call (cloud
|
|
3020
3158
|
* provider) or in-process model inference. The consumer wires this — the core
|
|
3021
3159
|
* package never calls an embedding provider directly, staying embedder-agnostic.
|
|
3160
|
+
*
|
|
3161
|
+
* @remarks
|
|
3162
|
+
* Resolving to `undefined` means **"intentionally not embedded"** — a deliberate
|
|
3163
|
+
* decline, not an error. The record is stored without an embedding reference, no
|
|
3164
|
+
* failure is reported, and **the decline itself logs nothing**. This is distinct
|
|
3165
|
+
* from a `Failure`, which means the embedder *tried and could not*.
|
|
3166
|
+
*
|
|
3167
|
+
* "Logs nothing" is a statement about the decline, not a promise of silence: a
|
|
3168
|
+
* decline on a record that was already embedded also prunes the vector that
|
|
3169
|
+
* reference named, and if that prune fails it is a genuine fault and warns like
|
|
3170
|
+
* any other. What a decline never does is warn merely for having happened.
|
|
3171
|
+
*
|
|
3172
|
+
* The distinction is load-bearing wherever the two are treated differently. On the
|
|
3173
|
+
* rebuild path a declined record is **excluded** from the index and counted on
|
|
3174
|
+
* {@link IVectorRebuildReport.declined}; a failed one is a genuine error and, under
|
|
3175
|
+
* `onRecordError: 'skip'`, is reported on {@link IVectorRebuildReport.skipped}. Collapsing "I chose not to" into `fail` would
|
|
3176
|
+
* make a deliberate policy indistinguishable from an embedder outage in the logs,
|
|
3177
|
+
* and would put a routine decision on whatever error path the caller has wired.
|
|
3178
|
+
*
|
|
3179
|
+
* The embedder receives the whole record, so the usual reason to decline is the
|
|
3180
|
+
* record's `kind` — a control or bookkeeping row that no query should ever return.
|
|
3181
|
+
*
|
|
3182
|
+
* @public
|
|
3183
|
+
*/
|
|
3184
|
+
export declare type MemoryEmbedder = (record: IMemoryRecord<unknown>) => Promise<Result<Float32Array | undefined>>;
|
|
3185
|
+
|
|
3186
|
+
/**
|
|
3187
|
+
* What the record-granular vector index did about a written record.
|
|
3188
|
+
*
|
|
3189
|
+
* @remarks
|
|
3190
|
+
* This exists because **`embeddingRef` absence is three-ways ambiguous**: a
|
|
3191
|
+
* record with no reference may have been declined, excluded, or genuinely
|
|
3192
|
+
* failed to embed, and the `put`'s own `outcome` cannot tell you which — it is
|
|
3193
|
+
* `'success'` in all three, because embed-on-write is best-effort by design and
|
|
3194
|
+
* never fails a durable write. Deriving index coverage from the absent field
|
|
3195
|
+
* alone therefore cannot distinguish a policy decision from an outage.
|
|
3196
|
+
*
|
|
3197
|
+
* - `'embedded'` — embedded and added; the record carries an `embeddingRef`.
|
|
3198
|
+
* - `'declined'` — the {@link MemoryEmbedder} resolved `undefined`: deliberately
|
|
3199
|
+
* not embedded. Not a fault.
|
|
3200
|
+
* - `'excluded'` — the record's kind is outside the store's `embedKinds`
|
|
3201
|
+
* declaration, so the embedder was never called. Also not a fault, and the
|
|
3202
|
+
* cheaper of the two.
|
|
3203
|
+
* - `'failed'` — the embedder returned a `Failure` (or threw), **or** the index
|
|
3204
|
+
* `add` did. Both are faults, and what they leave behind depends on whether
|
|
3205
|
+
* the record had been embedded before: a **first** write ends up with no
|
|
3206
|
+
* `embeddingRef` and nothing in the index, while an **update** keeps the
|
|
3207
|
+
* reference and vector it already had — so the index goes on answering on the
|
|
3208
|
+
* record's **previous** content until a `rebuild` reconciles it. Stale, not
|
|
3209
|
+
* absent. The store's diagnostic logger names which fault it was, because the
|
|
3210
|
+
* remediation differs (an embedder outage versus an index outage) while the
|
|
3211
|
+
* coverage answer — "this record needs a re-embed" — does not.
|
|
3212
|
+
*
|
|
3213
|
+
* Absent on a write observation means **no outcome is being reported**, which
|
|
3214
|
+
* covers three cases:
|
|
3215
|
+
*
|
|
3216
|
+
* 1. no vector index / embedder is wired, so there is no index for the record to
|
|
3217
|
+
* be absent from;
|
|
3218
|
+
* 2. the `put` was a dedup no-op, which attempted nothing;
|
|
3219
|
+
* 3. the `put` **failed** (`outcome: 'failure'`). An embed step may well have run
|
|
3220
|
+
* before the failure — a record can even have been added to the index and then
|
|
3221
|
+
* lost its durable write, leaving an orphan vector that a later `rebuild`
|
|
3222
|
+
* reconciles. That is deliberately not reported here: the field answers
|
|
3223
|
+
* "is this *stored* record in the index?", and on a failed write there is no
|
|
3224
|
+
* stored record for it to be a statement about.
|
|
3225
|
+
*
|
|
3226
|
+
* So `embed` is a property of successful writes. Never present on `'read'` /
|
|
3227
|
+
* `'delete'` / `'retrieve'`.
|
|
3228
|
+
*
|
|
3229
|
+
* Record-granular only. The fragment path is independent and reports nothing
|
|
3230
|
+
* here — a record may be fragment-embedded while its record-level outcome is
|
|
3231
|
+
* `'excluded'`.
|
|
3022
3232
|
* @public
|
|
3023
3233
|
*/
|
|
3024
|
-
export declare type
|
|
3234
|
+
export declare type MemoryEmbedOutcome = 'embedded' | 'declined' | 'excluded' | 'failed';
|
|
3025
3235
|
|
|
3026
3236
|
/**
|
|
3027
3237
|
* Stable file-stem identifier for a memory record. Equals the codec-produced
|
|
@@ -3870,4 +4080,25 @@ export declare class TemporalVersionedPolicy implements IWritePolicy {
|
|
|
3870
4080
|
private _rebuild;
|
|
3871
4081
|
}
|
|
3872
4082
|
|
|
4083
|
+
/**
|
|
4084
|
+
* How a vector-index rebuild treats a record it cannot index — whether the
|
|
4085
|
+
* **embedding** failed or the subsequent **add** did. Both are governed by this
|
|
4086
|
+
* one mode; neither is unconditionally fatal.
|
|
4087
|
+
*
|
|
4088
|
+
* @remarks
|
|
4089
|
+
* Deliberately mirrors the store's own open-time `onRecordError` mode, including
|
|
4090
|
+
* its default: `'fail'` preserves the historical all-or-nothing contract exactly,
|
|
4091
|
+
* and `'skip'` is opt-in. Defined here rather than imported from the store packlet
|
|
4092
|
+
* — the `vector` packlet does not depend on `store`, and the two modes describe
|
|
4093
|
+
* different domains that merely happen to share a shape.
|
|
4094
|
+
*
|
|
4095
|
+
* A **decline** (a {@link MemoryEmbedder} resolving `undefined`) is not an error
|
|
4096
|
+
* and is unaffected by this mode: it is always **excluded** from the index and
|
|
4097
|
+
* counted on {@link IVectorRebuildReport.declined}, **never** appearing in
|
|
4098
|
+
* {@link IVectorRebuildReport.skipped}. The word is worth being careful with here:
|
|
4099
|
+
* `skipped` is now a formal field meaning *a fault*, and a decline is the opposite.
|
|
4100
|
+
* @public
|
|
4101
|
+
*/
|
|
4102
|
+
export declare type VectorRebuildErrorMode = 'skip' | 'fail';
|
|
4103
|
+
|
|
3873
4104
|
export { }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/orchestrator.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -246,7 +246,17 @@ class MemoryIngestOrchestrator {
|
|
|
246
246
|
if (embedded.isFailure()) {
|
|
247
247
|
return (0, ts_utils_1.fail)(embedded.message);
|
|
248
248
|
}
|
|
249
|
-
|
|
249
|
+
// The embedder deliberately declined this candidate, so there is no vector to
|
|
250
|
+
// search with and layer-2 similarity dedup cannot run for it. That is the same
|
|
251
|
+
// position as a search that found nothing similar — `'new'` — and not an
|
|
252
|
+
// error: declining to embed a kind must not make it un-ingestable.
|
|
253
|
+
if (embedded.value === undefined) {
|
|
254
|
+
return (0, ts_utils_1.succeed)({ verdict: 'new' });
|
|
255
|
+
}
|
|
256
|
+
// Hoisted: the `undefined` check above does not narrow across the callback
|
|
257
|
+
// boundary below, and a local keeps the non-null assertion out of the code.
|
|
258
|
+
const vector = embedded.value;
|
|
259
|
+
const queried = await this._capture(() => wiring.vectorIndex.query(vector, this._similarityTopK), `ingest '${candidate.envelope.entityId}': similarity query`);
|
|
250
260
|
if (queried.isFailure()) {
|
|
251
261
|
return (0, ts_utils_1.fail)(queried.message);
|
|
252
262
|
}
|