@fgv/ts-agent-memory 5.1.0-49 → 5.1.0-50
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/index/memoryIndex.js +23 -16
- package/dist/packlets/index/memoryIndex.js.map +1 -1
- package/dist/packlets/ingest/orchestrator.js +13 -1
- package/dist/packlets/ingest/orchestrator.js.map +1 -1
- package/dist/packlets/retrieve/linkTraversalRetriever.js +12 -26
- package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/dist/packlets/retrieve/recencyRetriever.js +7 -7
- package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/dist/packlets/retrieve/retriever.js +91 -10
- package/dist/packlets/retrieve/retriever.js.map +1 -1
- package/dist/packlets/retrieve/semanticRetriever.js +16 -16
- package/dist/packlets/retrieve/semanticRetriever.js.map +1 -1
- package/dist/packlets/retrieve/structuredFilterRetriever.js +7 -7
- package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/dist/packlets/retrieve/tagRetriever.js +7 -7
- package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
- package/dist/packlets/retrieve/temporalRetrievers.js +23 -20
- package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/dist/packlets/store/coverage.js +6 -0
- package/dist/packlets/store/coverage.js.map +1 -0
- package/dist/packlets/store/fileTreeMemoryStore.js +221 -79
- package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/dist/packlets/store/index.js +4 -0
- package/dist/packlets/store/index.js.map +1 -1
- package/dist/packlets/store/listSelection.js +36 -0
- package/dist/packlets/store/listSelection.js.map +1 -0
- package/dist/packlets/store/memoryStore.js +6 -0
- package/dist/packlets/store/memoryStore.js.map +1 -0
- package/dist/packlets/store/reconcile.js +6 -0
- package/dist/packlets/store/reconcile.js.map +1 -0
- package/dist/packlets/store/storeCoverage.js +102 -0
- package/dist/packlets/store/storeCoverage.js.map +1 -0
- package/dist/packlets/store/storeReconcile.js +122 -0
- package/dist/packlets/store/storeReconcile.js.map +1 -0
- package/dist/packlets/store/vectorMaintenance.js +116 -8
- package/dist/packlets/store/vectorMaintenance.js.map +1 -1
- package/dist/packlets/store/vectorRecordSource.js +44 -0
- package/dist/packlets/store/vectorRecordSource.js.map +1 -0
- package/dist/packlets/tools/memoryTools.js +25 -2
- package/dist/packlets/tools/memoryTools.js.map +1 -1
- package/dist/packlets/types/envelope.js +25 -0
- package/dist/packlets/types/envelope.js.map +1 -1
- package/dist/packlets/types/index.js +1 -0
- package/dist/packlets/types/index.js.map +1 -1
- package/dist/packlets/types/recordResolver.js +6 -0
- package/dist/packlets/types/recordResolver.js.map +1 -0
- package/dist/packlets/types/temporal.js.map +1 -1
- package/dist/packlets/vector/inMemoryCosineIndex.js +39 -18
- package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +67 -12
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/dist/packlets/vector/rebuildHelpers.js +38 -0
- package/dist/packlets/vector/rebuildHelpers.js.map +1 -0
- package/dist/packlets/vector/vectorIndex.js.map +1 -1
- package/dist/ts-agent-memory.d.ts +1035 -106
- package/lib/packlets/index/memoryIndex.d.ts +118 -27
- package/lib/packlets/index/memoryIndex.d.ts.map +1 -1
- package/lib/packlets/index/memoryIndex.js +23 -16
- package/lib/packlets/index/memoryIndex.js.map +1 -1
- package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
- package/lib/packlets/ingest/orchestrator.js +13 -1
- package/lib/packlets/ingest/orchestrator.js.map +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +3 -10
- package/lib/packlets/retrieve/linkTraversalRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/linkTraversalRetriever.js +11 -25
- package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
- package/lib/packlets/retrieve/recencyRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/recencyRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/recencyRetriever.js +6 -6
- package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
- package/lib/packlets/retrieve/retriever.d.ts +88 -7
- package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/retriever.js +94 -9
- package/lib/packlets/retrieve/retriever.js.map +1 -1
- package/lib/packlets/retrieve/semanticRetriever.d.ts +3 -5
- package/lib/packlets/retrieve/semanticRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/semanticRetriever.js +15 -15
- package/lib/packlets/retrieve/semanticRetriever.js.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/structuredFilterRetriever.js +6 -6
- package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
- package/lib/packlets/retrieve/tagRetriever.d.ts +3 -3
- package/lib/packlets/retrieve/tagRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/tagRetriever.js +6 -6
- package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.d.ts +7 -5
- package/lib/packlets/retrieve/temporalRetrievers.d.ts.map +1 -1
- package/lib/packlets/retrieve/temporalRetrievers.js +22 -19
- package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
- package/lib/packlets/store/coverage.d.ts +102 -0
- package/lib/packlets/store/coverage.d.ts.map +1 -0
- package/lib/packlets/store/coverage.js +7 -0
- package/lib/packlets/store/coverage.js.map +1 -0
- package/lib/packlets/store/fileTreeMemoryStore.d.ts +53 -166
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +221 -79
- package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/lib/packlets/store/index.d.ts +4 -0
- package/lib/packlets/store/index.d.ts.map +1 -1
- package/lib/packlets/store/index.js +4 -0
- package/lib/packlets/store/index.js.map +1 -1
- package/lib/packlets/store/listSelection.d.ts +101 -0
- package/lib/packlets/store/listSelection.d.ts.map +1 -0
- package/lib/packlets/store/listSelection.js +40 -0
- package/lib/packlets/store/listSelection.js.map +1 -0
- package/lib/packlets/store/memoryStore.d.ts +237 -0
- package/lib/packlets/store/memoryStore.d.ts.map +1 -0
- package/lib/packlets/store/memoryStore.js +7 -0
- package/lib/packlets/store/memoryStore.js.map +1 -0
- package/lib/packlets/store/reconcile.d.ts +82 -0
- package/lib/packlets/store/reconcile.d.ts.map +1 -0
- package/lib/packlets/store/reconcile.js +7 -0
- package/lib/packlets/store/reconcile.js.map +1 -0
- package/lib/packlets/store/storeCoverage.d.ts +45 -0
- package/lib/packlets/store/storeCoverage.d.ts.map +1 -0
- package/lib/packlets/store/storeCoverage.js +105 -0
- package/lib/packlets/store/storeCoverage.js.map +1 -0
- package/lib/packlets/store/storeReconcile.d.ts +41 -0
- package/lib/packlets/store/storeReconcile.d.ts.map +1 -0
- package/lib/packlets/store/storeReconcile.js +125 -0
- package/lib/packlets/store/storeReconcile.js.map +1 -0
- package/lib/packlets/store/vectorMaintenance.d.ts +74 -0
- package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -1
- package/lib/packlets/store/vectorMaintenance.js +117 -8
- package/lib/packlets/store/vectorMaintenance.js.map +1 -1
- package/lib/packlets/store/vectorRecordSource.d.ts +36 -0
- package/lib/packlets/store/vectorRecordSource.d.ts.map +1 -0
- package/lib/packlets/store/vectorRecordSource.js +47 -0
- package/lib/packlets/store/vectorRecordSource.js.map +1 -0
- package/lib/packlets/tools/memoryTools.d.ts.map +1 -1
- package/lib/packlets/tools/memoryTools.js +25 -2
- package/lib/packlets/tools/memoryTools.js.map +1 -1
- package/lib/packlets/types/envelope.d.ts +24 -2
- package/lib/packlets/types/envelope.d.ts.map +1 -1
- package/lib/packlets/types/envelope.js +26 -0
- package/lib/packlets/types/envelope.js.map +1 -1
- package/lib/packlets/types/index.d.ts +1 -0
- package/lib/packlets/types/index.d.ts.map +1 -1
- package/lib/packlets/types/index.js +1 -0
- package/lib/packlets/types/index.js.map +1 -1
- package/lib/packlets/types/recordResolver.d.ts +39 -0
- package/lib/packlets/types/recordResolver.d.ts.map +1 -0
- package/lib/packlets/types/recordResolver.js +7 -0
- package/lib/packlets/types/recordResolver.js.map +1 -0
- package/lib/packlets/types/temporal.d.ts +26 -6
- package/lib/packlets/types/temporal.d.ts.map +1 -1
- package/lib/packlets/types/temporal.js.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts +9 -2
- package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryCosineIndex.js +40 -19
- package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +6 -3
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +66 -11
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/lib/packlets/vector/rebuildHelpers.d.ts +30 -0
- package/lib/packlets/vector/rebuildHelpers.d.ts.map +1 -0
- package/lib/packlets/vector/rebuildHelpers.js +42 -0
- package/lib/packlets/vector/rebuildHelpers.js.map +1 -0
- package/lib/packlets/vector/vectorIndex.d.ts +270 -15
- package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
- package/lib/packlets/vector/vectorIndex.js.map +1 -1
- package/package.json +7 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AiAssist } from '@fgv/ts-extras';
|
|
2
2
|
import { Brand } from '@fgv/ts-utils';
|
|
3
3
|
import { Converter } from '@fgv/ts-utils';
|
|
4
|
+
import { DetailedResult } from '@fgv/ts-utils';
|
|
4
5
|
import { FileTree } from '@fgv/ts-json-base';
|
|
5
6
|
import { JsonSchema } from '@fgv/ts-json-base';
|
|
6
7
|
import { Logging } from '@fgv/ts-utils';
|
|
@@ -31,11 +32,12 @@ export declare type AdmissionDecision = {
|
|
|
31
32
|
*/
|
|
32
33
|
export declare class AsOfRetriever implements IMemoryRetriever {
|
|
33
34
|
private readonly _index;
|
|
35
|
+
private readonly _resolver;
|
|
34
36
|
private constructor();
|
|
35
37
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
36
38
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
37
39
|
/** Family-convention factory. */
|
|
38
|
-
static create(
|
|
40
|
+
static create(params: IRetrieverCreateParams): Result<AsOfRetriever>;
|
|
39
41
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
40
42
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
41
43
|
}
|
|
@@ -164,11 +166,12 @@ export declare function createMemoryTools(params: ICreateMemoryToolsParams): Rea
|
|
|
164
166
|
*/
|
|
165
167
|
export declare class CurrentValidRetriever implements IMemoryRetriever {
|
|
166
168
|
private readonly _index;
|
|
169
|
+
private readonly _resolver;
|
|
167
170
|
private constructor();
|
|
168
171
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
169
172
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
170
173
|
/** Family-convention factory. */
|
|
171
|
-
static create(
|
|
174
|
+
static create(params: IRetrieverCreateParams): Result<CurrentValidRetriever>;
|
|
172
175
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
173
176
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
174
177
|
}
|
|
@@ -245,6 +248,22 @@ export declare const DEFAULT_SIMILARITY_TOP_K: number;
|
|
|
245
248
|
*/
|
|
246
249
|
export declare function defaultMemoryScopeEncoding(scope: MemoryScopeKey): Result<string>;
|
|
247
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Which derived artifact a {@link IMemoryStore.reconcile} call repairs.
|
|
253
|
+
*
|
|
254
|
+
* @remarks
|
|
255
|
+
* **The operation names its artifact rather than repairing everything wired**,
|
|
256
|
+
* and the reasons are structural rather than stylistic: the record and fragment
|
|
257
|
+
* lanes are independently wirable (so an unnamed repair on a fragment-only store
|
|
258
|
+
* would have to no-op or guess), their units are incommensurable (one vector per
|
|
259
|
+
* record vs. N), and their costs differ by orders of magnitude — a measured case
|
|
260
|
+
* put 68 fragments behind a single 56 KB record. An operation whose cost varies
|
|
261
|
+
* that much along a dimension it does not name is the accidental-expense shape
|
|
262
|
+
* `IMemoryStore.list`'s required selection exists to prevent.
|
|
263
|
+
* @public
|
|
264
|
+
*/
|
|
265
|
+
export declare type DerivedArtifact = 'rank' | 'record-vector' | 'fragment-vector';
|
|
266
|
+
|
|
248
267
|
/**
|
|
249
268
|
* Converter for an attributed {@link IEdge}.
|
|
250
269
|
* @public
|
|
@@ -287,6 +306,29 @@ export declare function edgeTargetKey(target: IEdgeTarget): string;
|
|
|
287
306
|
*/
|
|
288
307
|
export declare const embeddedFragmentConverter: Converter<IEmbeddedFragment>;
|
|
289
308
|
|
|
309
|
+
/**
|
|
310
|
+
* The envelope's embedding reference if it carries a usable one, `undefined`
|
|
311
|
+
* otherwise — **the one place `null`-vs-absent is collapsed.**
|
|
312
|
+
*
|
|
313
|
+
* @remarks
|
|
314
|
+
* {@link IMemoryEnvelope.embeddingRef} is `string | null | undefined`, where
|
|
315
|
+
* `null` and absent both mean *not embedded* (`null` is the explicit sentinel;
|
|
316
|
+
* absent is the backwards-compat seam). That makes the obvious presence check
|
|
317
|
+
* wrong in **both** directions, and both mistakes were shipped before this
|
|
318
|
+
* accessor existed: `!== undefined` counts a `null` as an embedding that is not
|
|
319
|
+
* there, and `=== undefined` misses a `null` when looking for one that is
|
|
320
|
+
* missing. Neither is a type error, and neither is visible to a coverage gate,
|
|
321
|
+
* because the sentinel is a *value* rather than a branch.
|
|
322
|
+
*
|
|
323
|
+
* Returning the reference rather than a boolean is deliberate: a caller that
|
|
324
|
+
* needs the string gets the check for free, so there is no second, weaker way
|
|
325
|
+
* to ask.
|
|
326
|
+
*
|
|
327
|
+
* **Do not test `embeddingRef` for presence directly — call this.**
|
|
328
|
+
* @public
|
|
329
|
+
*/
|
|
330
|
+
export declare function embeddingRefOf(envelope: IMemoryEnvelope): string | undefined;
|
|
331
|
+
|
|
290
332
|
/**
|
|
291
333
|
* Consumer-supplied domain key. The stable entity identity across versions;
|
|
292
334
|
* the package never mints identity. Equals {@link MemoryId} for non-temporal
|
|
@@ -394,9 +436,49 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
394
436
|
/** {@inheritDoc IMemoryStore.getById} */
|
|
395
437
|
getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
396
438
|
/** {@inheritDoc IMemoryStore.list} */
|
|
397
|
-
list(
|
|
439
|
+
list(selection: MemoryListSelection): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
440
|
+
/** {@inheritDoc IMemoryStore.coverage} */
|
|
441
|
+
coverage(): Promise<Result<IDerivedStateCoverage>>;
|
|
442
|
+
/** {@inheritDoc IMemoryStore.listEntries} */
|
|
443
|
+
listEntries(): Promise<Result<ReadonlyArray<IIndexedMemoryEntry>>>;
|
|
398
444
|
/** {@inheritDoc IMemoryStore.listScoped} */
|
|
399
445
|
listScoped(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;
|
|
446
|
+
/** {@inheritDoc IMemoryRecordResolver.resolveRecord} */
|
|
447
|
+
resolveRecord(scope: MemoryScopeKey, id: MemoryId): Result<IMemoryRecord<unknown> | undefined>;
|
|
448
|
+
/**
|
|
449
|
+
* Materialize a selected set of entries into records, dropping any that have
|
|
450
|
+
* vanished since selection.
|
|
451
|
+
*
|
|
452
|
+
* @remarks
|
|
453
|
+
* A miss is not a failure. Selection reads the in-memory index and
|
|
454
|
+
* materialization reads storage, so a record deleted in between is a legitimate
|
|
455
|
+
* race and yields a shorter list rather than an error. A read that FAILS is a
|
|
456
|
+
* real fault and propagates.
|
|
457
|
+
*/
|
|
458
|
+
private _materialize;
|
|
459
|
+
/**
|
|
460
|
+
* Materialize one entry, treating "gone" as a fault rather than a miss.
|
|
461
|
+
*
|
|
462
|
+
* @remarks
|
|
463
|
+
* For paths where a vanished record really does mean the index and the vault
|
|
464
|
+
* disagree, rather than that something legitimately removed it in between.
|
|
465
|
+
*
|
|
466
|
+
* Three of the four callers hold the write lock, so nothing can have removed
|
|
467
|
+
* the record since the entry was read. `get()`'s versioned path does not, and
|
|
468
|
+
* is safe only because temporal kinds never physically delete a version — they
|
|
469
|
+
* invalidate in place, and cap-cull does not apply to them. **If eviction is
|
|
470
|
+
* ever added to the temporal path, that caller must change**, or it
|
|
471
|
+
* reintroduces the race this method exists to detect.
|
|
472
|
+
*
|
|
473
|
+
* `listScoped` also does not hold the lock, and uses this deliberately anyway:
|
|
474
|
+
* it feeds a coverage report, so a silent drop there is worse than a loud
|
|
475
|
+
* failure. See its comment, and `docs/FUTURE.md` for the eviction window.
|
|
476
|
+
*
|
|
477
|
+
* The drop-tolerant counterpart is {@link FileTreeMemoryStore._materialize},
|
|
478
|
+
* for readers where a record that vanished between selection and
|
|
479
|
+
* materialization is a miss rather than a fault.
|
|
480
|
+
*/
|
|
481
|
+
private _resolveRequired;
|
|
400
482
|
/** {@inheritDoc IMemoryStore.asRecordSource} */
|
|
401
483
|
asRecordSource(): IMemoryRecordSource;
|
|
402
484
|
/**
|
|
@@ -407,8 +489,8 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
407
489
|
* contributes nothing.
|
|
408
490
|
*/
|
|
409
491
|
private static _projectAsOf;
|
|
410
|
-
/** {@inheritDoc IMemoryStore.
|
|
411
|
-
|
|
492
|
+
/** {@inheritDoc IMemoryStore.reconcile} */
|
|
493
|
+
reconcile(kind: Kind, artifact: DerivedArtifact): Promise<Result<ReconcileReport>>;
|
|
412
494
|
/** {@inheritDoc IMemoryStore.put} */
|
|
413
495
|
put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
|
|
414
496
|
/** {@inheritDoc IMemoryStore.delete} */
|
|
@@ -584,7 +666,7 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
584
666
|
private _isMutableMetadataUnchanged;
|
|
585
667
|
private _contentHash;
|
|
586
668
|
/**
|
|
587
|
-
* The
|
|
669
|
+
* The rank branch of {@link FileTreeMemoryStore.reconcile}, under the write lock.
|
|
588
670
|
*
|
|
589
671
|
* @remarks
|
|
590
672
|
* Re-reads each record's file rather than trusting the in-memory index, for
|
|
@@ -613,13 +695,15 @@ export declare class FileTreeMemoryStore implements IMemoryStore {
|
|
|
613
695
|
* another on a reconcile. `_stampRank` itself is reused verbatim, which also
|
|
614
696
|
* inherits its throw semantics (logged at `warn`, `rank` cleared).
|
|
615
697
|
*/
|
|
698
|
+
private _reconcileLocked;
|
|
699
|
+
/** The rank branch of {@link FileTreeMemoryStore._reconcileLocked}. */
|
|
616
700
|
private _reconcileRankLocked;
|
|
617
701
|
/**
|
|
618
702
|
* Re-apply the rank projector to one record on disk. Returns whether `rank`
|
|
619
703
|
* actually changed — an unchanged rank writes nothing, so a reconcile over an
|
|
620
704
|
* already-consistent store touches no files.
|
|
621
705
|
*/
|
|
622
|
-
private
|
|
706
|
+
private _rewriteEnvelope;
|
|
623
707
|
/**
|
|
624
708
|
* Stamp the store-computed {@link IMemoryEnvelope.rank} onto a fully-built,
|
|
625
709
|
* fully-stamped record by running the kind's registered {@link RankProjector}.
|
|
@@ -788,11 +872,12 @@ export declare function guardRetrieverCapabilities(query: IMemoryQuery, capabili
|
|
|
788
872
|
*/
|
|
789
873
|
export declare class HistoryRetriever implements IMemoryRetriever {
|
|
790
874
|
private readonly _index;
|
|
875
|
+
private readonly _resolver;
|
|
791
876
|
private constructor();
|
|
792
877
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
793
878
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
794
879
|
/** Family-convention factory. */
|
|
795
|
-
static create(
|
|
880
|
+
static create(params: IRetrieverCreateParams): Result<HistoryRetriever>;
|
|
796
881
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
797
882
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
798
883
|
/** A version's world-truth start: its `valid_at`, defaulting to `created` when absent. */
|
|
@@ -855,6 +940,31 @@ export declare class HybridRetriever implements IMemoryRetriever {
|
|
|
855
940
|
private _projectQuery;
|
|
856
941
|
}
|
|
857
942
|
|
|
943
|
+
/**
|
|
944
|
+
* How much of one derived artifact exists, for one {@link Kind}.
|
|
945
|
+
*
|
|
946
|
+
* @remarks
|
|
947
|
+
* Two numbers rather than a percentage, deliberately: a ratio cannot express
|
|
948
|
+
* *"nothing was expected"*, and a kind that is intentionally not derived (an
|
|
949
|
+
* excluded kind, a kind with no projector) is a normal and healthy state that a
|
|
950
|
+
* `0%` would render as an alarm.
|
|
951
|
+
* @public
|
|
952
|
+
*/
|
|
953
|
+
export declare interface IArtifactCoverage {
|
|
954
|
+
/**
|
|
955
|
+
* Records of this kind the store would derive this artifact for, **after** any
|
|
956
|
+
* exclusion. Read against {@link IDerivedStateCoverage.records} for the same
|
|
957
|
+
* kind: `records: 40, expected: 0` is the exclusion story, stated rather than
|
|
958
|
+
* inferred.
|
|
959
|
+
*/
|
|
960
|
+
readonly expected: number;
|
|
961
|
+
/**
|
|
962
|
+
* Of those, how many the **store believes** are covered. See
|
|
963
|
+
* {@link IIndexCoverage.indexSize} for why the word "believes" is load-bearing.
|
|
964
|
+
*/
|
|
965
|
+
readonly covered: number;
|
|
966
|
+
}
|
|
967
|
+
|
|
858
968
|
/**
|
|
859
969
|
* Registry of per-kind body Converters. Each memory {@link Kind} registers the
|
|
860
970
|
* validated shape of its body; the store dispatches an `unknown` body through
|
|
@@ -998,6 +1108,35 @@ export declare interface ICycleGuardEdge {
|
|
|
998
1108
|
readonly type: LinkType;
|
|
999
1109
|
}
|
|
1000
1110
|
|
|
1111
|
+
/**
|
|
1112
|
+
* A snapshot of how much of the store's **derived state** exists, resolved by
|
|
1113
|
+
* {@link Kind} — the answer to *"is my derived state consistent with my
|
|
1114
|
+
* records?"*.
|
|
1115
|
+
*
|
|
1116
|
+
* @remarks
|
|
1117
|
+
* **Absent is not zero.** Each artifact member is optional, and `undefined` means
|
|
1118
|
+
* *this artifact is not derived here at all* — no rank projector is registered,
|
|
1119
|
+
* or that index lane is not wired. It never means *nothing is covered*. Folding
|
|
1120
|
+
* the two would make a health surface render a confident `0%` for a feature the
|
|
1121
|
+
* deployment deliberately did not turn on, which is the same defect as
|
|
1122
|
+
* `embeddingRef`'s three-way ambiguity one level up.
|
|
1123
|
+
*
|
|
1124
|
+
* So: `fragmentVectors: undefined` is a store with no fragment index and is not a
|
|
1125
|
+
* problem. `fragmentVectors: { indexRecordCount: 0, indexFragmentCount: 0 }` is a
|
|
1126
|
+
* wired fragment index holding nothing, and probably is.
|
|
1127
|
+
* @public
|
|
1128
|
+
*/
|
|
1129
|
+
export declare interface IDerivedStateCoverage {
|
|
1130
|
+
/** Records per kind — the denominator every other number is read against. */
|
|
1131
|
+
readonly records: ReadonlyMap<Kind, number>;
|
|
1132
|
+
/** Absent when no kind has a registered {@link RankProjector}. */
|
|
1133
|
+
readonly rank?: ReadonlyMap<Kind, IArtifactCoverage>;
|
|
1134
|
+
/** Absent when the record-vector lane is not wired. */
|
|
1135
|
+
readonly recordVectors?: IIndexCoverage;
|
|
1136
|
+
/** Absent when the fragment lane is not wired. */
|
|
1137
|
+
readonly fragmentVectors?: IFragmentIndexCoverage;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1001
1140
|
/**
|
|
1002
1141
|
* An attributed link between two records. Carries the relation type, the
|
|
1003
1142
|
* scope-qualified {@link IEdgeTarget | target}, and optional confidence /
|
|
@@ -1121,6 +1260,27 @@ export declare interface IEntityResolver {
|
|
|
1121
1260
|
resolve(candidate: ICandidateRecord, similar: ReadonlyArray<IEntityResolutionCandidate>): Promise<Result<ResolutionVerdict>>;
|
|
1122
1261
|
}
|
|
1123
1262
|
|
|
1263
|
+
/**
|
|
1264
|
+
* The minimum a temporal helper needs: something carrying an envelope.
|
|
1265
|
+
*
|
|
1266
|
+
* @remarks
|
|
1267
|
+
* Every predicate and selector in this module reads `envelope.temporal`,
|
|
1268
|
+
* `envelope.created` and `envelope.seq` and **nothing else** — no body has ever
|
|
1269
|
+
* been consulted. Taking the structural shape rather than `IMemoryRecord` lets
|
|
1270
|
+
* the same helpers serve both an `IMemoryRecord<unknown>` (which satisfies it)
|
|
1271
|
+
* and an `IIndexedMemoryEntry` from the index's projected read surface, so the
|
|
1272
|
+
* temporal `asOf` projection can run over envelopes and materialize only the
|
|
1273
|
+
* versions that survive it.
|
|
1274
|
+
*
|
|
1275
|
+
* The selectors are generic in this shape so they return exactly what they were
|
|
1276
|
+
* given rather than widening to the constraint.
|
|
1277
|
+
* @public
|
|
1278
|
+
*/
|
|
1279
|
+
export declare interface IEnvelopeCarrier {
|
|
1280
|
+
/** The envelope the temporal predicates read. */
|
|
1281
|
+
readonly envelope: IMemoryEnvelope;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1124
1284
|
/**
|
|
1125
1285
|
* Stage 3 — the host's fact extractor. Turns a classified item into zero or more
|
|
1126
1286
|
* {@link ICandidateRecord}s. Each candidate's body is validated against the
|
|
@@ -1328,6 +1488,31 @@ export declare interface IFileTreeMemoryStoreCreateParams {
|
|
|
1328
1488
|
readonly onRecordError?: MemoryRecordErrorMode;
|
|
1329
1489
|
}
|
|
1330
1490
|
|
|
1491
|
+
/**
|
|
1492
|
+
* Coverage of the fragment-granular vector index.
|
|
1493
|
+
*
|
|
1494
|
+
* @remarks
|
|
1495
|
+
* **Aggregate only, and the reason is structural rather than an omission.** The
|
|
1496
|
+
* record lane has a per-record marker on the envelope (`embeddingRef`), so its
|
|
1497
|
+
* numerator falls out of the same free walk that produces the denominator. The
|
|
1498
|
+
* fragment lane has **no envelope marker at all** — nothing on a record says
|
|
1499
|
+
* whether it has fragments — so a per-kind numerator would cost one
|
|
1500
|
+
* `IFragmentVectorIndex.has` call per record, and coverage is contractually
|
|
1501
|
+
* cheap (see {@link IMemoryStore.coverage}).
|
|
1502
|
+
*
|
|
1503
|
+
* The per-kind **denominator** is still available on
|
|
1504
|
+
* {@link IDerivedStateCoverage.records}. A caller who needs the per-kind
|
|
1505
|
+
* numerator runs `reconcile(kind, 'fragment-vector')`, which reports it because
|
|
1506
|
+
* it is already paying for the walk.
|
|
1507
|
+
* @public
|
|
1508
|
+
*/
|
|
1509
|
+
export declare interface IFragmentIndexCoverage {
|
|
1510
|
+
/** Records with at least one fragment held. Mirrors `IFragmentVectorIndex.recordCount`. */
|
|
1511
|
+
readonly indexRecordCount: number;
|
|
1512
|
+
/** Total fragments held — the fan-out. Mirrors `IFragmentVectorIndex.fragmentCount`. */
|
|
1513
|
+
readonly indexFragmentCount: number;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1331
1516
|
/**
|
|
1332
1517
|
* A half-open `[start, end)` span into a record's body — the in-record locator a
|
|
1333
1518
|
* {@link IFragmentVectorIndex} may carry on a fragment. `start` is inclusive,
|
|
@@ -1375,6 +1560,25 @@ export declare interface IFragmentQuery {
|
|
|
1375
1560
|
readonly maxPerRecord?: number;
|
|
1376
1561
|
}
|
|
1377
1562
|
|
|
1563
|
+
/**
|
|
1564
|
+
* A fragment-vector reconcile.
|
|
1565
|
+
*
|
|
1566
|
+
* @remarks
|
|
1567
|
+
* Note there is no `restamped`: the fragment lane has **no envelope marker**, so
|
|
1568
|
+
* there is no reference that can go missing and nothing to restamp. The
|
|
1569
|
+
* asymmetry with {@link IVectorReconcileReport} is real rather than an oversight.
|
|
1570
|
+
* @public
|
|
1571
|
+
*/
|
|
1572
|
+
export declare interface IFragmentReconcileReport extends IReconcileReportBase {
|
|
1573
|
+
readonly artifact: 'fragment-vector';
|
|
1574
|
+
/** Records already represented, needing no embedder call. */
|
|
1575
|
+
readonly alreadyIndexed: number;
|
|
1576
|
+
/** Records whose embedder produced no fragments — this lane's decline. */
|
|
1577
|
+
readonly declined: number;
|
|
1578
|
+
/** Fragments written by this call — the fan-out `repaired` cannot express. */
|
|
1579
|
+
readonly fragments: number;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1378
1582
|
/**
|
|
1379
1583
|
* What a {@link FragmentSemanticRetriever} can do given its wiring.
|
|
1380
1584
|
* @public
|
|
@@ -1439,6 +1643,114 @@ export declare interface IFragmentVectorIndex {
|
|
|
1439
1643
|
* `topK` cut) so one long document cannot crowd out others.
|
|
1440
1644
|
*/
|
|
1441
1645
|
query(vector: Float32Array, topK: number, maxPerRecord?: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;
|
|
1646
|
+
/**
|
|
1647
|
+
* Whether this index holds **any** fragment for the scope-qualified `target`.
|
|
1648
|
+
*
|
|
1649
|
+
* @remarks
|
|
1650
|
+
* The record-granular rationale on {@link IVectorIndex.has} applies verbatim —
|
|
1651
|
+
* a repair that trusts `embeddingRef` is not a repair. Note the granularity
|
|
1652
|
+
* this deliberately does **not** offer: it answers *"is this record
|
|
1653
|
+
* represented?"*, not *"is this particular fragment present?"*. Fragment
|
|
1654
|
+
* writes are whole-record-replace, so a record is either represented by the
|
|
1655
|
+
* current fragment set or not represented at all; a per-fragment membership
|
|
1656
|
+
* check would imply an incremental write path that does not exist.
|
|
1657
|
+
*/
|
|
1658
|
+
has(target: IEdgeTarget): Promise<Result<boolean>>;
|
|
1659
|
+
/**
|
|
1660
|
+
* The number of **records** with at least one fragment held.
|
|
1661
|
+
*
|
|
1662
|
+
* @remarks
|
|
1663
|
+
* Deliberately **not** named `size`, unlike {@link IVectorIndex.size}. This
|
|
1664
|
+
* index is one-to-many, so `size` has two defensible readings and a reader
|
|
1665
|
+
* arriving from the record-granular sibling — where `size` counts vectors —
|
|
1666
|
+
* would take the wrong one silently. Two explicitly-named counts cost one extra
|
|
1667
|
+
* member and cannot be misread.
|
|
1668
|
+
*/
|
|
1669
|
+
readonly recordCount: number;
|
|
1670
|
+
/**
|
|
1671
|
+
* The total number of **fragments** held across all records.
|
|
1672
|
+
*
|
|
1673
|
+
* @remarks
|
|
1674
|
+
* The fan-out, and the number a caller actually watches: fragments-per-record
|
|
1675
|
+
* is what makes a fragment reconcile expensive, and neither `recordCount` nor a
|
|
1676
|
+
* record-granular count answers it.
|
|
1677
|
+
*/
|
|
1678
|
+
readonly fragmentCount: number;
|
|
1679
|
+
/**
|
|
1680
|
+
* Re-embed every record from `source` and rebuild the fragment index from
|
|
1681
|
+
* scratch — the **backfill / reconcile** operation, sibling to
|
|
1682
|
+
* {@link IVectorIndex.rebuild}.
|
|
1683
|
+
*
|
|
1684
|
+
* @remarks
|
|
1685
|
+
* On the contract for exactly the reasons its record-granular sibling is, and
|
|
1686
|
+
* the fragment lane was worse off: `rebuild` existed only on the bundled
|
|
1687
|
+
* in-memory class, and the durable `SqliteVecFragmentIndex` had **no backfill
|
|
1688
|
+
* at all**, so a persistent fragment index could not be reconciled by any
|
|
1689
|
+
* route — contractual or concrete. Records written while it was unwired, a
|
|
1690
|
+
* re-embed after a segmenter change, and reconciliation after a swallowed
|
|
1691
|
+
* fragment-embed failure were all unreachable.
|
|
1692
|
+
*
|
|
1693
|
+
* Semantics are kept observably identical to the record-granular sibling so a
|
|
1694
|
+
* caller who has learned one has learned both: a `source.list()` failure is
|
|
1695
|
+
* fatal and carries no detail (nothing was attempted, and the existing index is
|
|
1696
|
+
* untouched); a genuine rebuild then resets first; `onRecordError` defaults to
|
|
1697
|
+
* `'fail'`; and a failure carries whatever the attempt had established on the
|
|
1698
|
+
* `detail`.
|
|
1699
|
+
*
|
|
1700
|
+
* **A rebuild does NOT re-establish the vector dimension on a persistent
|
|
1701
|
+
* index, and this is the one place the two shipped implementations genuinely
|
|
1702
|
+
* differ.** The in-memory indexes forget their dimension when they reset, so a
|
|
1703
|
+
* rebuild with a different-dimension embedder simply re-establishes it. A
|
|
1704
|
+
* `vec0`-backed index cannot: its reset is a `DELETE FROM`, the table's
|
|
1705
|
+
* declared dimension is part of its schema, and `vec0` has no `ALTER TABLE`.
|
|
1706
|
+
* So a rebuild that changes dimension **succeeds in memory and fails on
|
|
1707
|
+
* SQLite**, where it needs the same drop-and-re-index the package README
|
|
1708
|
+
* prescribes for any schema change (drop the table, or point the index at a
|
|
1709
|
+
* fresh `tableName`). Only embedding time is at risk — vectors are derived and
|
|
1710
|
+
* the vault records remain authoritative.
|
|
1711
|
+
*/
|
|
1712
|
+
rebuild(source: IMemoryRecordSource, embed: FragmentEmbedder, options?: IVectorRebuildOptions): Promise<DetailedResult<IFragmentVectorRebuildReport, IFragmentVectorRebuildReport>>;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* What an {@link IFragmentVectorIndex.rebuild} established, resolved by
|
|
1717
|
+
* {@link Kind} — the fragment-granular sibling of {@link IVectorRebuildReport}.
|
|
1718
|
+
*
|
|
1719
|
+
* @remarks
|
|
1720
|
+
* The rule stated on {@link IVectorRebuildReport} applies here verbatim and is
|
|
1721
|
+
* not re-opened: **every count is resolved by kind unless there is a stated
|
|
1722
|
+
* reason it cannot be**, `excluded` is optional because only the source can know
|
|
1723
|
+
* it, and the report is carried on a failure as well as a success.
|
|
1724
|
+
*
|
|
1725
|
+
* The one member with no record-granular analogue is
|
|
1726
|
+
* {@link IFragmentVectorRebuildReport.fragments | fragments} — the fan-out. It is
|
|
1727
|
+
* the number that distinguishes this lane: `indexed: 40` says forty records are
|
|
1728
|
+
* represented and says nothing about whether that cost forty embedding round
|
|
1729
|
+
* trips or four thousand, which is the difference between a reconcile that
|
|
1730
|
+
* finishes in a second and one that blocks a request past thirty.
|
|
1731
|
+
*
|
|
1732
|
+
* A **declined** record is one whose {@link FragmentEmbedder} returned an empty
|
|
1733
|
+
* array — the fragment lane's way of saying *intentionally not embedded*. Note
|
|
1734
|
+
* this is a different mechanism from a {@link MemoryEmbedder} decline: an empty
|
|
1735
|
+
* array still performs a real whole-record-replace (which is what clears any
|
|
1736
|
+
* stale fragments), where a record-granular decline skips the index entirely.
|
|
1737
|
+
* @public
|
|
1738
|
+
*/
|
|
1739
|
+
export declare interface IFragmentVectorRebuildReport {
|
|
1740
|
+
/** Records that ended with at least one fragment held, per kind. */
|
|
1741
|
+
readonly indexed: ReadonlyMap<Kind, number>;
|
|
1742
|
+
/** Fragments held, per kind — the fan-out `indexed` cannot express. */
|
|
1743
|
+
readonly fragments: ReadonlyMap<Kind, number>;
|
|
1744
|
+
/** Records whose embedder intentionally produced no fragments, per kind. */
|
|
1745
|
+
readonly declined: ReadonlyMap<Kind, number>;
|
|
1746
|
+
/**
|
|
1747
|
+
* Records the source filtered out before the rebuild saw them, per kind.
|
|
1748
|
+
* `undefined` means *this source does not report exclusions*; an empty map
|
|
1749
|
+
* means *it does, and excluded nothing*.
|
|
1750
|
+
*/
|
|
1751
|
+
readonly excluded?: ReadonlyMap<Kind, number>;
|
|
1752
|
+
/** Records that failed, per record, with the error — a fault, never a decline. */
|
|
1753
|
+
readonly skipped: ReadonlyArray<ISkippedVectorRecord>;
|
|
1442
1754
|
}
|
|
1443
1755
|
|
|
1444
1756
|
/**
|
|
@@ -1482,6 +1794,58 @@ export declare interface IIdentityCodecResult {
|
|
|
1482
1794
|
readonly isVersioned: boolean;
|
|
1483
1795
|
}
|
|
1484
1796
|
|
|
1797
|
+
/**
|
|
1798
|
+
* Coverage of the record-granular vector index.
|
|
1799
|
+
* @public
|
|
1800
|
+
*/
|
|
1801
|
+
export declare interface IIndexCoverage {
|
|
1802
|
+
/** Per-kind expected/covered, derived from the envelope walk. */
|
|
1803
|
+
readonly perKind: ReadonlyMap<Kind, IArtifactCoverage>;
|
|
1804
|
+
/**
|
|
1805
|
+
* What the index **actually holds**, whole-index.
|
|
1806
|
+
*
|
|
1807
|
+
* @remarks
|
|
1808
|
+
* **This is a fact and {@link IArtifactCoverage.covered} is a belief, and the
|
|
1809
|
+
* two are reported separately because their disagreement is the only free
|
|
1810
|
+
* signal that distinguishes a persistent index from a fresh one.** `covered`
|
|
1811
|
+
* counts envelopes carrying an `embeddingRef`; `indexSize` counts vectors. With
|
|
1812
|
+
* a persistent index they agree. With an in-memory index at open they do not —
|
|
1813
|
+
* the envelopes still claim references from previous sessions while the index
|
|
1814
|
+
* holds nothing, so `covered` **lies, in the confident direction**.
|
|
1815
|
+
*
|
|
1816
|
+
* Collapsing them into one "coverage %" would destroy that signal, which is why
|
|
1817
|
+
* this type does not offer one.
|
|
1818
|
+
*/
|
|
1819
|
+
readonly indexSize: number;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
/**
|
|
1823
|
+
* What the index HOLDS and what every index read returns: a record's scope and
|
|
1824
|
+
* its {@link IMemoryEnvelope}, and **no body**.
|
|
1825
|
+
*
|
|
1826
|
+
* @remarks
|
|
1827
|
+
* The index is a derived *selection* structure, and selection has never needed a
|
|
1828
|
+
* body — every filter the store and the retrievers apply reads envelope fields
|
|
1829
|
+
* (`scope` / `kind` / `tags` / `contentHash` / `provenance` / `links` /
|
|
1830
|
+
* `temporal` / `updated` / `seq` / `rank`). Returning whole records made every
|
|
1831
|
+
* conforming index hold every body by construction, which was the store's
|
|
1832
|
+
* resident-memory ceiling; returning envelopes removes it from the contract
|
|
1833
|
+
* rather than from one implementation.
|
|
1834
|
+
*
|
|
1835
|
+
* A caller that needs the body **materializes it explicitly** — through
|
|
1836
|
+
* {@link IMemoryStore.getById}, or an `IMemoryRecordResolver` where one is
|
|
1837
|
+
* wired. That is deliberately visible: a lazy `body` getter would have kept
|
|
1838
|
+
* every call site compiling while turning a memory read into a file read behind
|
|
1839
|
+
* an unchanged type, which is a silent performance cliff rather than a migration.
|
|
1840
|
+
* @public
|
|
1841
|
+
*/
|
|
1842
|
+
export declare interface IIndexedMemoryEntry {
|
|
1843
|
+
/** The scope the record is stored under. */
|
|
1844
|
+
readonly scope: MemoryScopeKey;
|
|
1845
|
+
/** The record's envelope. No body — see the remarks. */
|
|
1846
|
+
readonly envelope: IMemoryEnvelope;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1485
1849
|
/**
|
|
1486
1850
|
* A memory record paired with the {@link MemoryScopeKey | scope} it lives
|
|
1487
1851
|
* under. The scope is not carried on the {@link IMemoryEnvelope} (it is derived
|
|
@@ -1689,7 +2053,7 @@ export declare interface IMemoryEnvelope {
|
|
|
1689
2053
|
* below every subsequently-written one regardless of what the projector would
|
|
1690
2054
|
* have scored them, so the result is not a partial ordering but one inverted
|
|
1691
2055
|
* with respect to the projector's intent, with nothing failing to say so. Call
|
|
1692
|
-
* `IMemoryStore.
|
|
2056
|
+
* `IMemoryStore.reconcile(kind, 'rank')` after registering a projector against a
|
|
1693
2057
|
* populated store.
|
|
1694
2058
|
*/
|
|
1695
2059
|
readonly rank?: number;
|
|
@@ -1723,40 +2087,98 @@ export declare interface IMemoryFileParts {
|
|
|
1723
2087
|
* patched incrementally on every write ({@link IMemoryIndex.patch}).
|
|
1724
2088
|
*
|
|
1725
2089
|
* @remarks
|
|
1726
|
-
*
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
2090
|
+
* Every read returns the projected {@link IIndexedMemoryEntry} — scope and
|
|
2091
|
+
* envelope, no body. See that type for why.
|
|
2092
|
+
*
|
|
2093
|
+
* **The conformance rule: an index is a derived, COMPLETE, FAITHFUL projection
|
|
2094
|
+
* of the vault.** An implementation may change *where* entries are stored and
|
|
2095
|
+
* *how* they are looked up; it may not change *which* entries exist or *what any
|
|
2096
|
+
* envelope says*. Concretely, {@link IMemoryIndex.entries} must return exactly
|
|
2097
|
+
* one entry per record the store has written and not deleted, and each entry's
|
|
2098
|
+
* envelope must be the one the store patched in.
|
|
2099
|
+
*
|
|
2100
|
+
* An index that filters, truncates, deduplicates, or synthesizes entries is not
|
|
2101
|
+
* a conforming implementation, and the reason is not tidiness: **the store's
|
|
2102
|
+
* write path derives from these reads** — content-hash dedup, write-policy
|
|
2103
|
+
* admission cohorts, and temporal version histories all read the index. An index
|
|
2104
|
+
* that hides an entry does not merely hide it from queries; it changes what the
|
|
2105
|
+
* next write does. That is why the previous guidance said only a faithful
|
|
2106
|
+
* delegating decorator was safe to inject. This invariant is what that guidance
|
|
2107
|
+
* was reaching for, stated so that a genuinely different implementation (a
|
|
2108
|
+
* SQLite-backed index, a lazily-paged one) is permitted while the reshaping that
|
|
2109
|
+
* was the actual hazard stays out.
|
|
2110
|
+
*
|
|
2111
|
+
* **Ordering is NOT part of the contract.** {@link IMemoryIndex.entries} may
|
|
2112
|
+
* return entries in any order and callers that need one sort explicitly. Note
|
|
2113
|
+
* this is a *behavioural* freedom the compiler cannot police: the bundled
|
|
2114
|
+
* {@link MemoryIndex} iterates a `Map` and so returns insertion order, which is
|
|
2115
|
+
* stable and observable, so code that came to rely on it keeps compiling and
|
|
2116
|
+
* changes results. The ordered accessors ({@link IMemoryIndex.byRecency},
|
|
2117
|
+
* {@link IMemoryIndex.byRank}, and the recency-ordered `byKind` / `byTag`) are
|
|
2118
|
+
* the supported way to ask for an order.
|
|
1729
2119
|
* @public
|
|
1730
2120
|
*/
|
|
1731
2121
|
export declare interface IMemoryIndex {
|
|
1732
2122
|
/**
|
|
1733
|
-
* Replace the entire index from a full set of
|
|
1734
|
-
*
|
|
2123
|
+
* Replace the entire index from a full set of entries (a store walk).
|
|
2124
|
+
*
|
|
2125
|
+
* @remarks
|
|
2126
|
+
* Takes the **projected** {@link IIndexedMemoryEntry} form, not whole records,
|
|
2127
|
+
* and the distinction is load-bearing rather than cosmetic: **`patch` writes,
|
|
2128
|
+
* `rebuild` reads.** A rebuild is a whole-vault read that happens to terminate
|
|
2129
|
+
* in the index, so requiring whole records here would force every caller — the
|
|
2130
|
+
* store's own open path included — to materialize N bodies purely to feed a
|
|
2131
|
+
* structure that projects the envelope back out and discards them. `patch`
|
|
2132
|
+
* keeps whole records because it carries exactly one, which its caller already
|
|
2133
|
+
* holds.
|
|
2134
|
+
*
|
|
2135
|
+
* @returns The number of entries indexed.
|
|
1735
2136
|
*/
|
|
1736
|
-
rebuild(entries: ReadonlyArray<
|
|
2137
|
+
rebuild(entries: ReadonlyArray<IIndexedMemoryEntry>): Result<number>;
|
|
1737
2138
|
/**
|
|
1738
2139
|
* Apply a single incremental change. `'put'` inserts or replaces the entry
|
|
1739
2140
|
* at its `(scope, id)` key (removing any prior associations first); `'delete'`
|
|
1740
2141
|
* removes it.
|
|
2142
|
+
*
|
|
2143
|
+
* @remarks
|
|
2144
|
+
* Takes the whole record — see {@link IMemoryIndex.rebuild} for why this one
|
|
2145
|
+
* does and that one does not. It costs nothing (the caller is mid-write and
|
|
2146
|
+
* holds the record already) and it is the single point at which an index
|
|
2147
|
+
* maintaining a body-derived view could observe content without a re-read.
|
|
2148
|
+
* What is *held* is still only the projection.
|
|
2149
|
+
*
|
|
1741
2150
|
* @returns The entry that was applied.
|
|
1742
2151
|
*/
|
|
1743
2152
|
patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord>;
|
|
1744
|
-
/** Every indexed entry (scope +
|
|
1745
|
-
entries(): ReadonlyArray<
|
|
1746
|
-
/**
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
*
|
|
1754
|
-
*
|
|
1755
|
-
|
|
2153
|
+
/** Every indexed entry (scope + envelope). Primary read surface for the store. */
|
|
2154
|
+
entries(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
2155
|
+
/**
|
|
2156
|
+
* The entry at a scope-qualified address, or `undefined` if none.
|
|
2157
|
+
*
|
|
2158
|
+
* @remarks
|
|
2159
|
+
* On the contract because its absence made every caller that wanted **one**
|
|
2160
|
+
* entry rebuild a map of **all** of them: both `SemanticRetriever` (resolving
|
|
2161
|
+
* at most `topK` hits) and `LinkTraversalRetriever` (resolving a BFS frontier)
|
|
2162
|
+
* built a full-index `Map` per query for want of this. The index already keys
|
|
2163
|
+
* on `(scope, id)` internally, so this exposes a lookup it was doing anyway.
|
|
2164
|
+
*/
|
|
2165
|
+
get(target: IEdgeTarget): IIndexedMemoryEntry | undefined;
|
|
2166
|
+
/** Entries of the given kind, in recency order (most-recently-updated first). */
|
|
2167
|
+
byKind(kind: Kind): ReadonlyArray<IIndexedMemoryEntry>;
|
|
2168
|
+
/** Entries carrying the given tag, in recency order. */
|
|
2169
|
+
byTag(tag: Tag): ReadonlyArray<IIndexedMemoryEntry>;
|
|
2170
|
+
/** All entries in recency order (most-recently-updated first). */
|
|
2171
|
+
byRecency(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
2172
|
+
/**
|
|
2173
|
+
* All entries ordered by store-computed {@link IMemoryEnvelope.rank} descending,
|
|
2174
|
+
* with recency (most-recently-updated, then `seq`) as a tiebreak. Entries with
|
|
2175
|
+
* an absent `rank` sort LAST (after every ranked entry), then by recency among
|
|
1756
2176
|
* themselves. Serves a bounded top-M ({@link IMemoryEnvelope.rank}-ordered) page
|
|
1757
|
-
* from the in-memory index with no full-vault (filesystem) scan
|
|
2177
|
+
* from the in-memory index with no full-vault (filesystem) scan — and since the
|
|
2178
|
+
* page is envelope-only, a caller taking the top M materializes M bodies rather
|
|
2179
|
+
* than the vault.
|
|
1758
2180
|
*/
|
|
1759
|
-
byRank(): ReadonlyArray<
|
|
2181
|
+
byRank(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
1760
2182
|
/**
|
|
1761
2183
|
* The scope-qualified sources of records whose `links` point AT `target`
|
|
1762
2184
|
* (inbound edges), keyed on the target's `(scope, id)` address. The seed map
|
|
@@ -2058,6 +2480,72 @@ export declare interface IMemoryRecord<TBody = unknown> {
|
|
|
2058
2480
|
readonly body: TBody;
|
|
2059
2481
|
}
|
|
2060
2482
|
|
|
2483
|
+
/**
|
|
2484
|
+
* What a {@link IMemoryRecordSource.list} call yields: the records the rebuild
|
|
2485
|
+
* should embed, plus — when the source can say — what it filtered out on the way.
|
|
2486
|
+
*
|
|
2487
|
+
* @remarks
|
|
2488
|
+
* The exclusion count originates here because **this is the layer where the
|
|
2489
|
+
* decision is made**. A rebuild never sees an excluded record, so it cannot count
|
|
2490
|
+
* one; a report assembled without this would silently undercount coverage, and
|
|
2491
|
+
* undercount in the direction of looking healthier.
|
|
2492
|
+
*
|
|
2493
|
+
* A store accessor answering "how many are excluded right now" was considered and
|
|
2494
|
+
* declined: it answers a *different question* than the report does — "excluded
|
|
2495
|
+
* right now" versus "excluded in this reconcile" — and the two legitimately differ
|
|
2496
|
+
* whenever records are written between reconciles. Two correct-and-unequal numbers
|
|
2497
|
+
* are worse than one absent number: they invite treating a real difference as a
|
|
2498
|
+
* bug, or picking whichever supports the conclusion already held.
|
|
2499
|
+
* @public
|
|
2500
|
+
*/
|
|
2501
|
+
export declare interface IMemoryRecordListing {
|
|
2502
|
+
/** Every record the rebuild should embed, each paired with its scoped address. */
|
|
2503
|
+
readonly records: ReadonlyArray<IScopedMemoryRecord>;
|
|
2504
|
+
/**
|
|
2505
|
+
* Records this source filtered out, counted by {@link Kind}. Omit it entirely if
|
|
2506
|
+
* the source does not track exclusions — that reads as *"cannot say"* on
|
|
2507
|
+
* {@link IVectorRebuildReport.excluded}, which is distinct from an empty map
|
|
2508
|
+
* (*"nothing was excluded"*).
|
|
2509
|
+
*/
|
|
2510
|
+
readonly excluded?: ReadonlyMap<Kind, number>;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
/**
|
|
2514
|
+
* Materializes one record's body from its scope-qualified address — the other
|
|
2515
|
+
* half of the partial-read split, and the narrowest seam that can be.
|
|
2516
|
+
*
|
|
2517
|
+
* @remarks
|
|
2518
|
+
* The index holds `IIndexedMemoryEntry` (scope + envelope, no body), so anything
|
|
2519
|
+
* that *selects* works from envelopes and anything that must *return records*
|
|
2520
|
+
* resolves the survivors through this. `FileTreeMemoryStore` implements it over
|
|
2521
|
+
* the same read path `getById` uses, so a resolved record is byte-identical to a
|
|
2522
|
+
* keyed read, verification included.
|
|
2523
|
+
*
|
|
2524
|
+
* **Deliberately one method, and deliberately not the store.** A retriever needs
|
|
2525
|
+
* exactly this capability; handing it an `IMemoryStore` would hand it `put` and
|
|
2526
|
+
* `delete` as well, and would invert the construction direction (the store builds
|
|
2527
|
+
* retrievers today, not the reverse). One method also keeps a test double
|
|
2528
|
+
* trivial.
|
|
2529
|
+
*
|
|
2530
|
+
* Synchronous `Result` rather than `Promise<Result>` because every shipped
|
|
2531
|
+
* `FileTree` backend resolves without awaiting, and an async signature here would
|
|
2532
|
+
* have rippled through retrievers that are otherwise synchronous over the index.
|
|
2533
|
+
* A future backend that genuinely needs I/O should be adapted at its own boundary
|
|
2534
|
+
* rather than by making this contract async for everyone.
|
|
2535
|
+
*
|
|
2536
|
+
* Resolving an address the vault does not hold is `succeed(undefined)`, not a
|
|
2537
|
+
* failure — an entry can legitimately vanish between selection and
|
|
2538
|
+
* materialization (a concurrent delete), and that is a miss rather than a fault.
|
|
2539
|
+
* A failure means the record is there and could not be read.
|
|
2540
|
+
* @public
|
|
2541
|
+
*/
|
|
2542
|
+
export declare interface IMemoryRecordResolver {
|
|
2543
|
+
/**
|
|
2544
|
+
* The record at `(scope, id)`, or `undefined` if the vault does not hold one.
|
|
2545
|
+
*/
|
|
2546
|
+
resolveRecord(scope: MemoryScopeKey, id: MemoryId): Result<IMemoryRecord<unknown> | undefined>;
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2061
2549
|
/**
|
|
2062
2550
|
* The minimal record-source surface {@link InMemoryCosineIndex.rebuild} reads to
|
|
2063
2551
|
* re-embed an entire vault. Each entry carries the record's scope-qualified
|
|
@@ -2069,8 +2557,12 @@ export declare interface IMemoryRecord<TBody = unknown> {
|
|
|
2069
2557
|
* @public
|
|
2070
2558
|
*/
|
|
2071
2559
|
export declare interface IMemoryRecordSource {
|
|
2072
|
-
/**
|
|
2073
|
-
|
|
2560
|
+
/**
|
|
2561
|
+
* List every record the rebuild should embed, each paired with its scoped
|
|
2562
|
+
* address, plus the exclusions this source applied if it tracks them. See
|
|
2563
|
+
* {@link IMemoryRecordListing}.
|
|
2564
|
+
*/
|
|
2565
|
+
list(): Promise<Result<IMemoryRecordListing>>;
|
|
2074
2566
|
}
|
|
2075
2567
|
|
|
2076
2568
|
/**
|
|
@@ -2108,15 +2600,23 @@ export declare interface IMemoryRetrieverCapabilities {
|
|
|
2108
2600
|
|
|
2109
2601
|
/**
|
|
2110
2602
|
* The writable, FileTree-backed, content-hash-deduped memory store.
|
|
2603
|
+
*
|
|
2604
|
+
* @remarks
|
|
2605
|
+
* Extends {@link IMemoryRecordResolver} because the retrievers take a resolver
|
|
2606
|
+
* and a store is the obvious one to hand them — `{ index, resolver: store }` is
|
|
2607
|
+
* the documented wiring, and it has to type-check for the `IMemoryStore` handle
|
|
2608
|
+
* a consumer actually holds, not only for the concrete `FileTreeMemoryStore`.
|
|
2111
2609
|
* @public
|
|
2112
2610
|
*/
|
|
2113
|
-
export declare interface IMemoryStore {
|
|
2611
|
+
export declare interface IMemoryStore extends IMemoryRecordResolver {
|
|
2114
2612
|
/**
|
|
2115
2613
|
* Keyed read by entity id. Resolves `entityId` to a storage address via the
|
|
2116
2614
|
* registered {@link IIdentityCodec} for `kind`. Returns `undefined` when no
|
|
2117
|
-
* record exists. For a versioned (temporal) kind
|
|
2118
|
-
*
|
|
2119
|
-
*
|
|
2615
|
+
* record exists. For a versioned (temporal) kind the current version is
|
|
2616
|
+
* *selected* from the derived in-memory index — the version history is walked
|
|
2617
|
+
* over envelopes, never bodies — and then that one version is read from
|
|
2618
|
+
* storage. So the selection costs no file reads and the result costs exactly
|
|
2619
|
+
* one, rather than one per version.
|
|
2120
2620
|
*/
|
|
2121
2621
|
get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
2122
2622
|
/**
|
|
@@ -2124,9 +2624,77 @@ export declare interface IMemoryStore {
|
|
|
2124
2624
|
*/
|
|
2125
2625
|
getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
|
|
2126
2626
|
/**
|
|
2127
|
-
* List records
|
|
2627
|
+
* List records: select over the derived index, then materialize the survivors.
|
|
2628
|
+
*
|
|
2629
|
+
* @remarks
|
|
2630
|
+
* **The selection is required and must narrow.** Since the index holds
|
|
2631
|
+
* envelopes only, every returned record is read from storage — so a call that
|
|
2632
|
+
* narrows nothing reads the whole vault, and that has to be a decision rather
|
|
2633
|
+
* than a default. Omitting the argument is a compile error; passing one with no
|
|
2634
|
+
* `scope` / `kind` / `tag` fails with a message naming {@link scanEveryRecord},
|
|
2635
|
+
* which is how a caller says it meant it.
|
|
2636
|
+
*
|
|
2637
|
+
* The requirement buys **explicitness, not a cost bound** — `{ kind }` on a
|
|
2638
|
+
* vault dominated by that kind still materializes most of it. What it prevents
|
|
2639
|
+
* is the whole-vault read nobody chose.
|
|
2640
|
+
*
|
|
2641
|
+
* If you only need to select, use {@link IMemoryStore.listEntries} instead: no
|
|
2642
|
+
* selection, no file reads.
|
|
2128
2643
|
*/
|
|
2129
|
-
list(
|
|
2644
|
+
list(selection: MemoryListSelection): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
2645
|
+
/**
|
|
2646
|
+
* How much of the store's **derived state** exists, resolved by {@link Kind}.
|
|
2647
|
+
*
|
|
2648
|
+
* @remarks
|
|
2649
|
+
* Answers *"is my derived state consistent with my records, and if not by how
|
|
2650
|
+
* much?"* for every artifact the store derives — `rank`, record vectors, and
|
|
2651
|
+
* fragment vectors — in one call.
|
|
2652
|
+
*
|
|
2653
|
+
* **Cheap and total, by contract rather than by implementation.** Every input is
|
|
2654
|
+
* an envelope field or an index-side count: it reads **no record bodies** and
|
|
2655
|
+
* calls **no embedder**, and the walk over the vault's own state touches the
|
|
2656
|
+
* filesystem not at all. That is why it takes no selection, unlike
|
|
2657
|
+
* {@link IMemoryStore.list} — the guard there exists because an unnarrowed list
|
|
2658
|
+
* reads the vault, and putting one here would decorate a free operation and make
|
|
2659
|
+
* that guard mean less.
|
|
2660
|
+
*
|
|
2661
|
+
* **The index-side counts are the one exception, and it is the caller's own
|
|
2662
|
+
* index that spends it.** A persistent index answers `size` / `recordCount` /
|
|
2663
|
+
* `fragmentCount` with a query — `SqliteVecVectorIndex` runs a prepared `COUNT`
|
|
2664
|
+
* — so on a durable backend this call does I/O and can **fail**. It is bounded
|
|
2665
|
+
* (one count per wired index, never per record) and it is why the return is a
|
|
2666
|
+
* `Result` rather than a bare value.
|
|
2667
|
+
*
|
|
2668
|
+
* *If a future addition to the report would require reading a record body, it
|
|
2669
|
+
* does not belong on this report.*
|
|
2670
|
+
*
|
|
2671
|
+
* The counterpart is {@link IMemoryStore.reconcile}: coverage says **how big**
|
|
2672
|
+
* the gap is, cheaply; reconcile says **what it was** and closes what it can, at
|
|
2673
|
+
* the cost of re-running the embedder. Neither substitutes for the other.
|
|
2674
|
+
*
|
|
2675
|
+
* **A lane is reported here whenever its *index* is wired**, which is weaker
|
|
2676
|
+
* than what reconcile requires (index **and** embedder). That is intended: an
|
|
2677
|
+
* index without an embedder still holds vectors and still answers queries, so
|
|
2678
|
+
* its coverage is a real number worth reporting. The consequence to expect is a
|
|
2679
|
+
* half-wired store that reports a gap `reconcile` will refuse to close, naming
|
|
2680
|
+
* the missing embedder.
|
|
2681
|
+
*/
|
|
2682
|
+
coverage(): Promise<Result<IDerivedStateCoverage>>;
|
|
2683
|
+
/**
|
|
2684
|
+
* Every entry in the vault — scope and envelope, **no bodies**. Reads no files
|
|
2685
|
+
* and requires no selection, because there is nothing to be careful about: it
|
|
2686
|
+
* returns what the index already holds.
|
|
2687
|
+
*
|
|
2688
|
+
* @remarks
|
|
2689
|
+
* This is the whole-vault read most callers actually want. Selection, grouping,
|
|
2690
|
+
* counting, "which kinds are in here", "what links at this" — all of it is
|
|
2691
|
+
* envelope work. Reach for {@link IMemoryStore.list} with
|
|
2692
|
+
* {@link scanEveryRecord} only when you genuinely need every body.
|
|
2693
|
+
*
|
|
2694
|
+
* Synchronous in spirit but `Promise`-returning for consistency with the rest
|
|
2695
|
+
* of the store surface.
|
|
2696
|
+
*/
|
|
2697
|
+
listEntries(): Promise<Result<ReadonlyArray<IIndexedMemoryEntry>>>;
|
|
2130
2698
|
/**
|
|
2131
2699
|
* List EVERY record in the vault, each paired with its scope-qualified
|
|
2132
2700
|
* `(scope, id)` address — the projection {@link IMemoryRecordSource} requires.
|
|
@@ -2148,6 +2716,11 @@ export declare interface IMemoryStore {
|
|
|
2148
2716
|
* every kind participates and the filter is the identity. `listScoped` itself is
|
|
2149
2717
|
* **not** filtered and remains the whole-vault surface.
|
|
2150
2718
|
*
|
|
2719
|
+
* The filter also **counts what it drops**, onto
|
|
2720
|
+
* {@link IMemoryRecordListing.excluded} — this is the layer where the exclusion
|
|
2721
|
+
* decision is made and so the only one that can. The count is always present
|
|
2722
|
+
* (empty when nothing was excluded).
|
|
2723
|
+
*
|
|
2151
2724
|
* The store cannot implement {@link IMemoryRecordSource} directly because its
|
|
2152
2725
|
* `list(filter?)` returns bare records (the ergonomic query surface) while the
|
|
2153
2726
|
* seam's `list()` returns scope-qualified records.
|
|
@@ -2209,35 +2782,42 @@ export declare interface IMemoryStore {
|
|
|
2209
2782
|
*/
|
|
2210
2783
|
put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
|
|
2211
2784
|
/**
|
|
2212
|
-
*
|
|
2213
|
-
*
|
|
2214
|
-
*
|
|
2785
|
+
* Repair one derived artifact for one {@link Kind} — **targeted and
|
|
2786
|
+
* non-destructive**, unlike `IVectorIndex.rebuild`, which resets the index and
|
|
2787
|
+
* re-embeds everything.
|
|
2215
2788
|
*
|
|
2216
2789
|
* @remarks
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
2222
|
-
*
|
|
2223
|
-
*
|
|
2790
|
+
* The counterpart to {@link IMemoryStore.coverage}: coverage says **how big**
|
|
2791
|
+
* the gap is and costs nothing; reconcile says **what it was** and closes what
|
|
2792
|
+
* it can, at the cost of reading bodies and re-running the embedder. Neither
|
|
2793
|
+
* substitutes for the other — in particular, only reconcile can distinguish a
|
|
2794
|
+
* *declined* record from a *failed* one, because learning that requires calling
|
|
2795
|
+
* the embedder again.
|
|
2796
|
+
*
|
|
2797
|
+
* **It only touches what is missing.** For the vector lanes it asks
|
|
2798
|
+
* `has(target)` per record and skips the ones already held, so a repair after a
|
|
2799
|
+
* brief outage costs a handful of embedder calls rather than a whole vault.
|
|
2800
|
+
* That check is also the only way to see a record whose vector the index holds
|
|
2801
|
+
* but whose envelope lost its `embeddingRef` — which needs a restamp and no
|
|
2802
|
+
* embedder call at all, and which an `embeddingRef`-only repair cannot detect.
|
|
2224
2803
|
*
|
|
2225
|
-
*
|
|
2226
|
-
*
|
|
2227
|
-
* would bump transaction time on every record — trading a wrong `rank` order
|
|
2228
|
-
* for a wrong recency order, and flooding any wired observer with writes that
|
|
2229
|
-
* are not writes. The body is re-serialized verbatim from the file's own
|
|
2230
|
-
* bytes; only the envelope's `rank` moves.
|
|
2804
|
+
* **`artifact` is required and names one lane.** See {@link DerivedArtifact}
|
|
2805
|
+
* for why an operation repairing "everything wired" would be the wrong shape.
|
|
2231
2806
|
*
|
|
2232
|
-
*
|
|
2233
|
-
*
|
|
2807
|
+
* **A vector lane must be wired on BOTH halves — index *and* embedder — or this
|
|
2808
|
+
* fails, and it is deliberately stricter than {@link IMemoryStore.coverage}.**
|
|
2809
|
+
* The two ask different questions of the same wiring. Coverage asks *what does
|
|
2810
|
+
* the index hold*, which an index alone can answer: an index wired without an
|
|
2811
|
+
* embedder is a legal store (queries work; writes simply do not embed), so
|
|
2812
|
+
* coverage reports that lane rather than pretending it is absent. Reconcile
|
|
2813
|
+
* asks to *produce* vectors, which needs the embedder. So a half-wired store
|
|
2814
|
+
* legitimately reports a coverage gap it cannot repair, and reconcile names the
|
|
2815
|
+
* missing half rather than returning a cheerful success with every record in
|
|
2816
|
+
* `failed`.
|
|
2234
2817
|
*
|
|
2235
|
-
*
|
|
2236
|
-
* restamped. That is benign because restamping is idempotent — re-running
|
|
2237
|
-
* converges — which is also why no report shape is offered here. A count is
|
|
2238
|
-
* enough.
|
|
2818
|
+
* Runs under the store's write lock, like any other mutation.
|
|
2239
2819
|
*/
|
|
2240
|
-
|
|
2820
|
+
reconcile(kind: Kind, artifact: DerivedArtifact): Promise<Result<ReconcileReport>>;
|
|
2241
2821
|
/**
|
|
2242
2822
|
* Delete a record by `(kind, entityId)`. Non-temporal kinds physically delete
|
|
2243
2823
|
* the file and return the deleted record's {@link MemoryId}. Temporal
|
|
@@ -2250,9 +2830,29 @@ export declare interface IMemoryStore {
|
|
|
2250
2830
|
|
|
2251
2831
|
/**
|
|
2252
2832
|
* Filter for {@link IMemoryStore.list}. All present fields are ANDed together.
|
|
2833
|
+
*
|
|
2834
|
+
* @remarks
|
|
2835
|
+
* **At least one of `scope` / `kind` / `tag` must be present.** `asOf` is a
|
|
2836
|
+
* temporal *projection*, not a narrowing — it collapses versions rather than
|
|
2837
|
+
* excluding entities — so it does not satisfy the requirement on its own. A
|
|
2838
|
+
* selection that narrows nothing fails with a message naming
|
|
2839
|
+
* {@link scanEveryRecord}.
|
|
2253
2840
|
* @public
|
|
2254
2841
|
*/
|
|
2255
2842
|
export declare interface IMemoryStoreListFilter {
|
|
2843
|
+
/**
|
|
2844
|
+
* Never present on a narrowing filter.
|
|
2845
|
+
*
|
|
2846
|
+
* @remarks
|
|
2847
|
+
* Exclusivity marker, paired with the `never`s on {@link IWholeVaultScan}.
|
|
2848
|
+
* Without it `{ scanEveryRecord: true, kind }` type-checks — TypeScript's
|
|
2849
|
+
* excess-property check on a union admits any property declared by *any*
|
|
2850
|
+
* member — and `list` then takes the scan branch and silently discards the
|
|
2851
|
+
* narrowing. Since the whole point of requiring a selection is that a
|
|
2852
|
+
* whole-vault read must be deliberate, a call that reads the whole vault while
|
|
2853
|
+
* *looking* narrowed is the one outcome this surface must not permit.
|
|
2854
|
+
*/
|
|
2855
|
+
readonly scanEveryRecord?: never;
|
|
2256
2856
|
/** Restrict to records in this scope. */
|
|
2257
2857
|
readonly scope?: MemoryScopeKey;
|
|
2258
2858
|
/** Restrict to records of this kind. */
|
|
@@ -2323,7 +2923,7 @@ export declare interface IMergeStrategy {
|
|
|
2323
2923
|
* are each retriever's own concern.
|
|
2324
2924
|
* @public
|
|
2325
2925
|
*/
|
|
2326
|
-
export declare function indexedRecordMatchesQuery(entry:
|
|
2926
|
+
export declare function indexedRecordMatchesQuery(entry: IIndexedMemoryEntry, query: IMemoryQuery): boolean;
|
|
2327
2927
|
|
|
2328
2928
|
/**
|
|
2329
2929
|
* How a candidate was ultimately written (or not) after resolution.
|
|
@@ -2376,6 +2976,8 @@ export declare class InMemoryCosineIndex implements IVectorIndex {
|
|
|
2376
2976
|
static create(): Result<InMemoryCosineIndex>;
|
|
2377
2977
|
/** {@inheritDoc IVectorIndex.add} */
|
|
2378
2978
|
add(target: IEdgeTarget, vector: Float32Array): Promise<Result<string>>;
|
|
2979
|
+
/** {@inheritDoc IVectorIndex.has} */
|
|
2980
|
+
has(target: IEdgeTarget): Promise<Result<boolean>>;
|
|
2379
2981
|
/** {@inheritDoc IVectorIndex.remove} */
|
|
2380
2982
|
remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;
|
|
2381
2983
|
/** {@inheritDoc IVectorIndex.query} */
|
|
@@ -2408,6 +3010,11 @@ export declare class InMemoryCosineIndex implements IVectorIndex {
|
|
|
2408
3010
|
* A {@link MemoryEmbedder} decline is not a failure under either mode: it is
|
|
2409
3011
|
* counted on {@link IVectorRebuildReport.declined} and never appears in `skipped`.
|
|
2410
3012
|
*
|
|
3013
|
+
* **A `'fail'` failure carries the partial report on its `detail`** — the
|
|
3014
|
+
* rollback still runs, so that report describes the aborted attempt rather than
|
|
3015
|
+
* the (now empty) index. The one failure with no detail is a `list` failure,
|
|
3016
|
+
* which disturbs nothing and has nothing to describe.
|
|
3017
|
+
*
|
|
2411
3018
|
* Both consumer-supplied hooks are capture-wrapped, so a `source` or `embed`
|
|
2412
3019
|
* that throws or rejects becomes a `Failure` on the path above rather than an
|
|
2413
3020
|
* exception escaping mid-rebuild — which would bypass the rollback entirely.
|
|
@@ -2416,7 +3023,7 @@ export declare class InMemoryCosineIndex implements IVectorIndex {
|
|
|
2416
3023
|
* @param embed - The embedder applied to each record.
|
|
2417
3024
|
* @param options - Rebuild options; omit for the historical `'fail'` behavior.
|
|
2418
3025
|
*/
|
|
2419
|
-
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder, options?: IVectorRebuildOptions): Promise<
|
|
3026
|
+
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder, options?: IVectorRebuildOptions): Promise<DetailedResult<IVectorRebuildReport, IVectorRebuildReport>>;
|
|
2420
3027
|
/** Empty the index and forget the established dimension. */
|
|
2421
3028
|
private _reset;
|
|
2422
3029
|
/** The Euclidean magnitude (L2 norm) of a vector. */
|
|
@@ -2474,6 +3081,8 @@ export declare class InMemoryFragmentCosineIndex implements IFragmentVectorIndex
|
|
|
2474
3081
|
static create(): Result<InMemoryFragmentCosineIndex>;
|
|
2475
3082
|
/** {@inheritDoc IFragmentVectorIndex.addFragments} */
|
|
2476
3083
|
addFragments(target: IEdgeTarget, fragments: ReadonlyArray<IEmbeddedFragment>): Promise<Result<number>>;
|
|
3084
|
+
/** {@inheritDoc IFragmentVectorIndex.has} */
|
|
3085
|
+
has(target: IEdgeTarget): Promise<Result<boolean>>;
|
|
2477
3086
|
/** {@inheritDoc IFragmentVectorIndex.remove} */
|
|
2478
3087
|
remove(target: IEdgeTarget): Promise<Result<IEdgeTarget>>;
|
|
2479
3088
|
/** {@inheritDoc IFragmentVectorIndex.query} */
|
|
@@ -2497,7 +3106,8 @@ export declare class InMemoryFragmentCosineIndex implements IFragmentVectorIndex
|
|
|
2497
3106
|
* @param source - The scope-qualified record source to re-embed.
|
|
2498
3107
|
* @param embed - The fragment embedder applied to each record.
|
|
2499
3108
|
*/
|
|
2500
|
-
|
|
3109
|
+
/** {@inheritDoc IFragmentVectorIndex.rebuild} */
|
|
3110
|
+
rebuild(source: IMemoryRecordSource, embed: FragmentEmbedder, options?: IVectorRebuildOptions): Promise<DetailedResult<IFragmentVectorRebuildReport, IFragmentVectorRebuildReport>>;
|
|
2501
3111
|
/** Empty the index and forget the established dimension. */
|
|
2502
3112
|
private _reset;
|
|
2503
3113
|
/** The Euclidean magnitude (L2 norm) of a vector. */
|
|
@@ -2538,6 +3148,23 @@ export declare interface IProvenance {
|
|
|
2538
3148
|
readonly [key: string]: unknown;
|
|
2539
3149
|
}
|
|
2540
3150
|
|
|
3151
|
+
/** A `rank` reconcile: re-run the projector and restamp what changed. @public */
|
|
3152
|
+
export declare interface IRankReconcileReport extends IReconcileReportBase {
|
|
3153
|
+
readonly artifact: 'rank';
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
/** What every reconcile reports, whatever the artifact. @public */
|
|
3157
|
+
export declare interface IReconcileReportBase {
|
|
3158
|
+
/** The kind reconciled — named by the caller, so every count below is scalar. */
|
|
3159
|
+
readonly kind: Kind;
|
|
3160
|
+
/** Records of this kind considered. The denominator for everything else. */
|
|
3161
|
+
readonly examined: number;
|
|
3162
|
+
/** Records whose derived artifact was (re)produced by this call. */
|
|
3163
|
+
readonly repaired: number;
|
|
3164
|
+
/** Records that failed, with the error. A fault, never a decline. */
|
|
3165
|
+
readonly failed: ReadonlyArray<ISkippedVectorRecord>;
|
|
3166
|
+
}
|
|
3167
|
+
|
|
2541
3168
|
/**
|
|
2542
3169
|
* A candidate paired with its resolved reference id, handed to the relation
|
|
2543
3170
|
* extractor so it can source edges from it.
|
|
@@ -2580,6 +3207,24 @@ export declare interface IRelationExtractor {
|
|
|
2580
3207
|
relate(context: IRelationContext): Promise<Result<ReadonlyArray<ICandidateEdge>>>;
|
|
2581
3208
|
}
|
|
2582
3209
|
|
|
3210
|
+
/**
|
|
3211
|
+
* What every index-backed retriever needs: the index it selects over, and the
|
|
3212
|
+
* resolver it materializes survivors through.
|
|
3213
|
+
*
|
|
3214
|
+
* @remarks
|
|
3215
|
+
* The resolver is the whole of the partial-read migration for a caller that
|
|
3216
|
+
* constructs retrievers directly — the index projection itself is invisible to
|
|
3217
|
+
* anyone who only consumes `retrieve()`. `FileTreeMemoryStore` implements
|
|
3218
|
+
* {@link IMemoryRecordResolver}, so wiring is `{ index, resolver: store }`.
|
|
3219
|
+
* @public
|
|
3220
|
+
*/
|
|
3221
|
+
export declare interface IRetrieverCreateParams {
|
|
3222
|
+
/** The derived index to select over. */
|
|
3223
|
+
readonly index: IMemoryIndex;
|
|
3224
|
+
/** Materializes the selected entries' bodies. */
|
|
3225
|
+
readonly resolver: IMemoryRecordResolver;
|
|
3226
|
+
}
|
|
3227
|
+
|
|
2583
3228
|
/**
|
|
2584
3229
|
* A record paired with its scope-qualified {@link IEdgeTarget | address}, as
|
|
2585
3230
|
* yielded by {@link IMemoryRecordSource.list}. The address is required because
|
|
@@ -2613,9 +3258,7 @@ export declare interface ISemanticBackend {
|
|
|
2613
3258
|
* Construction options for {@link SemanticRetriever.create}.
|
|
2614
3259
|
* @public
|
|
2615
3260
|
*/
|
|
2616
|
-
export declare interface ISemanticRetrieverCreateParams {
|
|
2617
|
-
/** The record index, used to resolve vector hits back to full records. */
|
|
2618
|
-
readonly index: IMemoryIndex;
|
|
3261
|
+
export declare interface ISemanticRetrieverCreateParams extends IRetrieverCreateParams {
|
|
2619
3262
|
/**
|
|
2620
3263
|
* The semantic backend. When absent, the retriever reports
|
|
2621
3264
|
* `supportsSemanticRecall: false` and a `query.semantic` request degrades
|
|
@@ -2668,7 +3311,7 @@ export declare function isTemporalIdentityCodec(codec: IIdentityCodec): codec is
|
|
|
2668
3311
|
* divergence (MTM is flat yet has `entityId !== id`).
|
|
2669
3312
|
* @public
|
|
2670
3313
|
*/
|
|
2671
|
-
export declare function isTemporalRecord(record:
|
|
3314
|
+
export declare function isTemporalRecord(record: IEnvelopeCarrier): boolean;
|
|
2672
3315
|
|
|
2673
3316
|
/**
|
|
2674
3317
|
* Whether a temporal record is a *current* version — its `temporal.invalid_at`
|
|
@@ -2676,7 +3319,7 @@ export declare function isTemporalRecord(record: IMemoryRecord<unknown>): boolea
|
|
|
2676
3319
|
* current in this sense (returns `false`).
|
|
2677
3320
|
* @public
|
|
2678
3321
|
*/
|
|
2679
|
-
export declare function isVersionCurrent(record:
|
|
3322
|
+
export declare function isVersionCurrent(record: IEnvelopeCarrier): boolean;
|
|
2680
3323
|
|
|
2681
3324
|
/**
|
|
2682
3325
|
* Whether a temporal record's validity interval contains `asOf` (epoch ms):
|
|
@@ -2685,7 +3328,13 @@ export declare function isVersionCurrent(record: IMemoryRecord<unknown>): boolea
|
|
|
2685
3328
|
* record is never "valid at" a point (returns `false`).
|
|
2686
3329
|
* @public
|
|
2687
3330
|
*/
|
|
2688
|
-
export declare function isVersionValidAt(record:
|
|
3331
|
+
export declare function isVersionValidAt(record: IEnvelopeCarrier, asOf: number): boolean;
|
|
3332
|
+
|
|
3333
|
+
/**
|
|
3334
|
+
* Whether a selection is the explicit whole-vault opt-out.
|
|
3335
|
+
* @public
|
|
3336
|
+
*/
|
|
3337
|
+
export declare function isWholeVaultScan(selection: MemoryListSelection): selection is IWholeVaultScan;
|
|
2689
3338
|
|
|
2690
3339
|
/**
|
|
2691
3340
|
* Optional bi-temporal validity block on an envelope. Present only on
|
|
@@ -2769,6 +3418,32 @@ export declare interface IVectorIndex {
|
|
|
2769
3418
|
* Return the `topK` nearest records to `vector`, in descending score order.
|
|
2770
3419
|
*/
|
|
2771
3420
|
query(vector: Float32Array, topK: number): Promise<Result<ReadonlyArray<IVectorQueryHit>>>;
|
|
3421
|
+
/**
|
|
3422
|
+
* Whether this index holds a vector for the scope-qualified `target`.
|
|
3423
|
+
*
|
|
3424
|
+
* @remarks
|
|
3425
|
+
* On the contract because it is what makes a **targeted** repair possible, and
|
|
3426
|
+
* the reason is sharper than convenience: the only other way to ask *"is this
|
|
3427
|
+
* record indexed?"* is {@link IMemoryEnvelope.embeddingRef} — and that field is
|
|
3428
|
+
* the store's **belief**, which is wrong in precisely the situation a repair
|
|
3429
|
+
* runs in. A reopened vault backed by a fresh in-memory index carries an
|
|
3430
|
+
* `embeddingRef` on every record while holding no vectors at all. **A repair
|
|
3431
|
+
* that trusts the field it is repairing is not a repair.**
|
|
3432
|
+
*
|
|
3433
|
+
* It also makes a case *detectable* that an `embeddingRef`-only check cannot
|
|
3434
|
+
* see at all: the index holds the vector but the envelope lost its reference
|
|
3435
|
+
* (a failure swallowed after the vector was committed). That record needs its
|
|
3436
|
+
* reference restamped and **no embedder call**, which is only knowable by
|
|
3437
|
+
* asking the index.
|
|
3438
|
+
*
|
|
3439
|
+
* `Promise<Result<boolean>>`, unlike the synchronous {@link IVectorIndex.size},
|
|
3440
|
+
* because the two are not the same kind of accessor and should not be made to
|
|
3441
|
+
* look alike: `size` is a count both shipped implementations hold or can read
|
|
3442
|
+
* without a failure mode, while `has` on a durable backend is a keyed query
|
|
3443
|
+
* that can fail. Idempotent and side-effect-free; an absent target is
|
|
3444
|
+
* `succeed(false)`, never a failure.
|
|
3445
|
+
*/
|
|
3446
|
+
has(target: IEdgeTarget): Promise<Result<boolean>>;
|
|
2772
3447
|
/**
|
|
2773
3448
|
* The number of vectors currently held.
|
|
2774
3449
|
*
|
|
@@ -2806,8 +3481,36 @@ export declare interface IVectorIndex {
|
|
|
2806
3481
|
*
|
|
2807
3482
|
* See {@link IVectorRebuildReport} for what it reports and
|
|
2808
3483
|
* {@link IVectorRebuildOptions} for the failure mode.
|
|
2809
|
-
|
|
2810
|
-
|
|
3484
|
+
*
|
|
3485
|
+
* **A failure carries the report too, on the `detail`** — coverage is most
|
|
3486
|
+
* wanted exactly when a rebuild did not complete, and withholding it there made
|
|
3487
|
+
* the answer depend on the error-handling mode rather than on the question. The
|
|
3488
|
+
* `'fail'` contract itself is unchanged: it still resets, still aborts, still
|
|
3489
|
+
* returns a failure. It simply also says what it had established before it
|
|
3490
|
+
* stopped. See {@link IVectorRebuildReport} for how to read a report that
|
|
3491
|
+
* arrived on a failure — it describes the attempt, not the surviving index.
|
|
3492
|
+
*
|
|
3493
|
+
* On success the report is the **value** — that is where it belongs, and the
|
|
3494
|
+
* `detail` is not also populated. A failure carries no report when nothing was
|
|
3495
|
+
* attempted: always a `source.list()` failure, and additionally whatever
|
|
3496
|
+
* pre-loop step an implementation needs before it can start (the durable
|
|
3497
|
+
* `SqliteVecVectorIndex` must clear its table, and a failure to do so is such a
|
|
3498
|
+
* case). Those leave the existing index untouched, so an all-zero report would
|
|
3499
|
+
* describe an index the call never disturbed.
|
|
3500
|
+
*
|
|
3501
|
+
* **A rebuild does NOT re-establish the vector dimension on a persistent
|
|
3502
|
+
* index, and this is the one place the two shipped implementations genuinely
|
|
3503
|
+
* differ.** The in-memory indexes forget their dimension when they reset, so a
|
|
3504
|
+
* rebuild with a different-dimension embedder simply re-establishes it. A
|
|
3505
|
+
* `vec0`-backed index cannot: its reset is a `DELETE FROM`, the table's
|
|
3506
|
+
* declared dimension is part of its schema, and `vec0` has no `ALTER TABLE`.
|
|
3507
|
+
* So a rebuild that changes dimension **succeeds in memory and fails on
|
|
3508
|
+
* SQLite**, where it needs the same drop-and-re-index the package README
|
|
3509
|
+
* prescribes for any schema change (drop the table, or point the index at a
|
|
3510
|
+
* fresh `tableName`). Only embedding time is at risk — vectors are derived and
|
|
3511
|
+
* the vault records remain authoritative.
|
|
3512
|
+
*/
|
|
3513
|
+
rebuild(source: IMemoryRecordSource, embed: MemoryEmbedder, options?: IVectorRebuildOptions): Promise<DetailedResult<IVectorRebuildReport, IVectorRebuildReport>>;
|
|
2811
3514
|
}
|
|
2812
3515
|
|
|
2813
3516
|
/**
|
|
@@ -2883,26 +3586,141 @@ export declare interface IVectorRebuildOptions {
|
|
|
2883
3586
|
* What a rebuild actually did — the structural answer to "is this index complete?".
|
|
2884
3587
|
*
|
|
2885
3588
|
* @remarks
|
|
2886
|
-
* A bare count cannot distinguish the
|
|
2887
|
-
*
|
|
2888
|
-
* `skipped` was a fault, and
|
|
2889
|
-
* deriving coverage from a count alone
|
|
2890
|
-
* deliberate policy, which is precisely the
|
|
3589
|
+
* A bare count cannot distinguish the ways a record can be absent from the index,
|
|
3590
|
+
* and that distinction is the entire point: **`declined` was intentional,
|
|
3591
|
+
* `excluded` was never offered, `skipped` was a fault, and none of them is the
|
|
3592
|
+
* same as "never attempted"**. A caller deriving coverage from a count alone
|
|
3593
|
+
* cannot tell an embedder outage from a deliberate policy, which is precisely the
|
|
3594
|
+
* confusion this type exists to end.
|
|
3595
|
+
*
|
|
3596
|
+
* **Every count in this report is resolved by kind.** A coverage report exists to
|
|
3597
|
+
* answer *"is my coverage what I intended?"*, and a bare total cannot:
|
|
3598
|
+
* `indexed: 500` reads identically whether the right kinds were indexed or a
|
|
3599
|
+
* policy drift silently redirected coverage, and the same is true of every other
|
|
3600
|
+
* count here. Totals are derivable by summing; the per-kind breakdown is not
|
|
3601
|
+
* derivable from anything else — {@link IVectorQueryHit} carries no `kind`,
|
|
3602
|
+
* {@link IVectorIndex.query} answers "what is near this" rather than "what is in
|
|
3603
|
+
* here", and {@link IVectorIndex.size} is a scalar, so the index cannot be
|
|
3604
|
+
* interrogated after the fact for any of them. **A new count added to this report
|
|
3605
|
+
* is resolved by kind unless there is a stated reason it cannot be.**
|
|
3606
|
+
*
|
|
3607
|
+
* `indexed` is the count most tempting to leave bare and the most dangerous to,
|
|
3608
|
+
* because it is the number a coverage surface actually renders: 500 bookkeeping
|
|
3609
|
+
* rows and zero knowledge rows is a healthy-looking number for a catastrophically
|
|
3610
|
+
* broken index.
|
|
3611
|
+
*
|
|
3612
|
+
* **Reading a report that arrived on a failure.** Under
|
|
3613
|
+
* {@link VectorRebuildErrorMode | `onRecordError: 'fail'`} the report is handed
|
|
3614
|
+
* back on the failure's `detail` — *after* the rollback has already run. It
|
|
3615
|
+
* describes the attempt, not the surviving index: `indexed` names what had been
|
|
3616
|
+
* established when the rebuild stopped, and the index itself now holds nothing. It
|
|
3617
|
+
* is a diagnostic ("we were 340 knowledge rows in when the embedder died"), not a
|
|
3618
|
+
* coverage statement. Only a report from a **successful** rebuild describes what
|
|
3619
|
+
* the index holds.
|
|
2891
3620
|
* @public
|
|
2892
3621
|
*/
|
|
2893
3622
|
export declare interface IVectorRebuildReport {
|
|
2894
|
-
/**
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
3623
|
+
/**
|
|
3624
|
+
* Records embedded and added to the index, counted by {@link Kind}.
|
|
3625
|
+
*
|
|
3626
|
+
* @remarks
|
|
3627
|
+
* A count of successful `add` calls, so it lines up with its per-record
|
|
3628
|
+
* siblings and the buckets sum back to the listing. It is deliberately **not**
|
|
3629
|
+
* read back off {@link IVectorIndex.size} at the end, which no implementation
|
|
3630
|
+
* could resolve by kind anyway. The trade that makes: a `source` that lists the
|
|
3631
|
+
* same `(scope, id)` twice contributes twice here while the index holds one
|
|
3632
|
+
* vector, where a size read would have self-corrected. A source that does that
|
|
3633
|
+
* is malformed, and a total that silently disagreed with the per-kind
|
|
3634
|
+
* breakdown would be the worse failure.
|
|
3635
|
+
*/
|
|
3636
|
+
readonly indexed: ReadonlyMap<Kind, number>;
|
|
3637
|
+
/**
|
|
3638
|
+
* Records the embedder deliberately declined (resolved `undefined`), counted by
|
|
3639
|
+
* {@link Kind}. The embedder was called and answered — contrast `excluded`,
|
|
3640
|
+
* where it never was.
|
|
3641
|
+
*/
|
|
3642
|
+
readonly declined: ReadonlyMap<Kind, number>;
|
|
3643
|
+
/**
|
|
3644
|
+
* Records the `source` filtered out before the rebuild ever saw them, counted by
|
|
3645
|
+
* {@link Kind} — for a store-backed source, the kinds outside
|
|
3646
|
+
* {@link IMemoryStore.embedsKind | embedsKind}.
|
|
3647
|
+
*
|
|
3648
|
+
* **Optional, and the optionality is semantic rather than cosmetic**: it is the
|
|
3649
|
+
* one count a rebuild genuinely cannot know for itself, because the decision is
|
|
3650
|
+
* made upstream in the source. `undefined` means *this source does not report
|
|
3651
|
+
* exclusions* — distinct from an empty map, which means *this source reports
|
|
3652
|
+
* them and excluded nothing*. `indexed` and `declined` are knowable by
|
|
3653
|
+
* construction (the rebuild either added the vector or the embedder answered)
|
|
3654
|
+
* and so are never optional.
|
|
3655
|
+
*/
|
|
3656
|
+
readonly excluded?: ReadonlyMap<Kind, number>;
|
|
2898
3657
|
/**
|
|
2899
3658
|
* Records whose embedding or add FAILED and were skipped. Non-empty only under
|
|
2900
3659
|
* {@link VectorRebuildErrorMode | `onRecordError: 'skip'`} — under `'fail'` the
|
|
2901
|
-
* first failure aborts the rebuild
|
|
3660
|
+
* first failure aborts the rebuild, so a `'fail'` report names the casualty in
|
|
3661
|
+
* its failure message rather than here.
|
|
3662
|
+
*
|
|
3663
|
+
* Per-record and carrying the error, so it already implies the per-kind
|
|
3664
|
+
* breakdown the counts above spell out; that is the stated reason this one field
|
|
3665
|
+
* is not a `ReadonlyMap<Kind, number>`.
|
|
2902
3666
|
*/
|
|
2903
3667
|
readonly skipped: ReadonlyArray<ISkippedVectorRecord>;
|
|
2904
3668
|
}
|
|
2905
3669
|
|
|
3670
|
+
/**
|
|
3671
|
+
* A record-vector reconcile.
|
|
3672
|
+
* @public
|
|
3673
|
+
*/
|
|
3674
|
+
export declare interface IVectorReconcileReport extends IReconcileReportBase {
|
|
3675
|
+
readonly artifact: 'record-vector';
|
|
3676
|
+
/**
|
|
3677
|
+
* Records the index already held and which needed **no embedder call** — the
|
|
3678
|
+
* whole point of a targeted repair, and the number that shows what it saved
|
|
3679
|
+
* against a `rebuild`.
|
|
3680
|
+
*/
|
|
3681
|
+
readonly alreadyIndexed: number;
|
|
3682
|
+
/**
|
|
3683
|
+
* Records whose vector the index held but whose envelope had **lost its
|
|
3684
|
+
* `embeddingRef`** — repaired by restamping the reference, with no embedder
|
|
3685
|
+
* call.
|
|
3686
|
+
*
|
|
3687
|
+
* @remarks
|
|
3688
|
+
* This case is invisible to an `embeddingRef`-only check, which is one of the
|
|
3689
|
+
* two reasons `IVectorIndex.has` is on the contract: a reference-absent record
|
|
3690
|
+
* looks identical to a never-embedded one until you ask the index.
|
|
3691
|
+
*/
|
|
3692
|
+
readonly restamped: number;
|
|
3693
|
+
/** Records the embedder intentionally declined. Not a failure, not a gap. */
|
|
3694
|
+
readonly declined: number;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
/**
|
|
3698
|
+
* The named, deliberately uncomfortable opt-out from
|
|
3699
|
+
* {@link IMemoryStore.list}'s narrowing requirement — build one with
|
|
3700
|
+
* {@link scanEveryRecord}.
|
|
3701
|
+
* @public
|
|
3702
|
+
*/
|
|
3703
|
+
export declare interface IWholeVaultScan {
|
|
3704
|
+
/** Discriminator. Always `true`; produced only by {@link scanEveryRecord}. */
|
|
3705
|
+
readonly scanEveryRecord: true;
|
|
3706
|
+
/**
|
|
3707
|
+
* Never present on a whole-vault scan — see
|
|
3708
|
+
* {@link IMemoryStoreListFilter.scanEveryRecord} for why these markers exist.
|
|
3709
|
+
* A scan that also carried a narrowing axis would have that axis dropped.
|
|
3710
|
+
*/
|
|
3711
|
+
readonly scope?: never;
|
|
3712
|
+
/** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */
|
|
3713
|
+
readonly kind?: never;
|
|
3714
|
+
/** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */
|
|
3715
|
+
readonly tag?: never;
|
|
3716
|
+
/**
|
|
3717
|
+
* Optional temporal projection, exactly as on {@link IMemoryStoreListFilter}.
|
|
3718
|
+
* NOT excluded, because `asOf` projects rather than narrows and composes with
|
|
3719
|
+
* a whole-vault read exactly as it does with a filtered one.
|
|
3720
|
+
*/
|
|
3721
|
+
readonly asOf?: number;
|
|
3722
|
+
}
|
|
3723
|
+
|
|
2906
3724
|
/**
|
|
2907
3725
|
* A per-kind write policy, injected at store construction. Invoked AFTER
|
|
2908
3726
|
* content-hash dedup (dedup is always pre-policy). The policy decides
|
|
@@ -3074,6 +3892,13 @@ export declare class KnowledgeLwwPolicy implements IWritePolicy {
|
|
|
3074
3892
|
private _rebuild;
|
|
3075
3893
|
}
|
|
3076
3894
|
|
|
3895
|
+
/**
|
|
3896
|
+
* The {@link limitRecords} window, applied to entries — used on the
|
|
3897
|
+
* no-body-filter path so paging happens before anything is read.
|
|
3898
|
+
* @public
|
|
3899
|
+
*/
|
|
3900
|
+
export declare function limitEntries(entries: ReadonlyArray<IIndexedMemoryEntry>, limit?: number, offset?: number): ReadonlyArray<IIndexedMemoryEntry>;
|
|
3901
|
+
|
|
3077
3902
|
/**
|
|
3078
3903
|
* Apply the `{ offset, limit }` page window to an ordered record set. Applied
|
|
3079
3904
|
* last, after ordering, so it always takes a stable window of the ordered
|
|
@@ -3130,22 +3955,16 @@ export declare const LINK_TRAVERSAL_UNWIRED_MESSAGE: string;
|
|
|
3130
3955
|
*/
|
|
3131
3956
|
export declare class LinkTraversalRetriever implements IMemoryRetriever {
|
|
3132
3957
|
private readonly _index;
|
|
3958
|
+
private readonly _resolver;
|
|
3133
3959
|
private constructor();
|
|
3134
3960
|
/** Family-convention factory. */
|
|
3135
|
-
static create(
|
|
3961
|
+
static create(params: IRetrieverCreateParams): Result<LinkTraversalRetriever>;
|
|
3136
3962
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
3137
3963
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
3138
3964
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
3139
3965
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
3140
3966
|
/** Run the bounded, cycle-safe BFS and post-filter the reached records. */
|
|
3141
3967
|
private _traverse;
|
|
3142
|
-
/**
|
|
3143
|
-
* Group the index's entries by their scope-qualified {@link edgeTargetKey}
|
|
3144
|
-
* `(scope, id)` composite. Each composite is the index's primary key, so it maps
|
|
3145
|
-
* to exactly one entry — two records that reuse a filename stem across scopes
|
|
3146
|
-
* (e.g. `turn-0` in two conversations) get distinct keys and never collide.
|
|
3147
|
-
*/
|
|
3148
|
-
private _indexByKey;
|
|
3149
3968
|
/** Outbound neighbors: the scope-qualified targets of every edge on the record at `node`. */
|
|
3150
3969
|
private _outbound;
|
|
3151
3970
|
/** Inbound neighbors: the scope-qualified sources whose edges point AT `node` (the backlinks). */
|
|
@@ -3185,6 +4004,45 @@ export declare class LtmIdentityCodec implements IIdentityCodec {
|
|
|
3185
4004
|
verifyRoundTrip(scope: MemoryScopeKey, stem: string): Result<true>;
|
|
3186
4005
|
}
|
|
3187
4006
|
|
|
4007
|
+
/**
|
|
4008
|
+
* Materialize entries through the resolver, dropping any that have vanished
|
|
4009
|
+
* since selection — a concurrent delete between selecting an envelope and
|
|
4010
|
+
* reading its body is a legitimate race and yields a shorter list, not an error.
|
|
4011
|
+
* A read that FAILS is a real fault and propagates.
|
|
4012
|
+
* @public
|
|
4013
|
+
*/
|
|
4014
|
+
export declare function materializeEntries(entries: ReadonlyArray<IIndexedMemoryEntry>, resolver: IMemoryRecordResolver): Result<ReadonlyArray<IMemoryRecord<unknown>>>;
|
|
4015
|
+
|
|
4016
|
+
/**
|
|
4017
|
+
* Materialize a selected, ordered page — **applying `query.filter` and paging in
|
|
4018
|
+
* the right order**, which is the whole reason this is shared rather than
|
|
4019
|
+
* open-coded per retriever.
|
|
4020
|
+
*
|
|
4021
|
+
* @remarks
|
|
4022
|
+
* Two paths, and the choice is forced by where the predicate can run:
|
|
4023
|
+
*
|
|
4024
|
+
* - **No `filter`** — order and page over *envelopes*, then read only the page.
|
|
4025
|
+
* `limit` bounds the READ, not just the result.
|
|
4026
|
+
* - **With `filter`** — the predicate takes a whole record, so every
|
|
4027
|
+
* envelope-survivor must be read first, then filtered, then paged. Paging
|
|
4028
|
+
* before filtering would return fewer than `limit` rows for no reason a caller
|
|
4029
|
+
* could see.
|
|
4030
|
+
*
|
|
4031
|
+
* **Every retriever must route through this.** `indexedRecordMatchesQuery`
|
|
4032
|
+
* structurally *cannot* apply `filter` — it is handed an envelope — so a
|
|
4033
|
+
* retriever that pre-filters with it and then materializes on its own silently
|
|
4034
|
+
* ignores the predicate. That regression shipped once, in the stream that moved
|
|
4035
|
+
* `filter` out of the pre-filter; this function exists so it cannot recur.
|
|
4036
|
+
*
|
|
4037
|
+
* @param selected - Entries surviving the envelope pre-filter.
|
|
4038
|
+
* @param query - The query whose `filter` / `orderBy` / `limit` / `offset` apply.
|
|
4039
|
+
* @param resolver - Body resolver.
|
|
4040
|
+
* @param order - Applied to whichever collection is paged; identity is legal for
|
|
4041
|
+
* a retriever whose ordering is intrinsic (semantic score, traversal order).
|
|
4042
|
+
* @public
|
|
4043
|
+
*/
|
|
4044
|
+
export declare function materializePage<T extends IIndexedMemoryEntry>(selected: ReadonlyArray<T>, query: IMemoryQuery, resolver: IMemoryRecordResolver, order?: (candidates: ReadonlyArray<T>) => ReadonlyArray<T>): Result<ReadonlyArray<IMemoryRecord<unknown>>>;
|
|
4045
|
+
|
|
3188
4046
|
/**
|
|
3189
4047
|
* Bounded-ring write policy for the experience (memory) kind families.
|
|
3190
4048
|
* Admission accepts until `maxRecords` is reached, then evicts the oldest
|
|
@@ -3344,7 +4202,10 @@ export declare type MemoryId = Brand<string, 'MemoryId'>;
|
|
|
3344
4202
|
* @public
|
|
3345
4203
|
*/
|
|
3346
4204
|
export declare class MemoryIndex implements IMemoryIndex {
|
|
3347
|
-
/**
|
|
4205
|
+
/**
|
|
4206
|
+
* Primary store: `(scope, id)` composite key → indexed entry. Holds the
|
|
4207
|
+
* PROJECTED form, so the index never retains a body.
|
|
4208
|
+
*/
|
|
3348
4209
|
private readonly _byKey;
|
|
3349
4210
|
/** kind → set of composite keys. */
|
|
3350
4211
|
private readonly _byKind;
|
|
@@ -3371,19 +4232,21 @@ export declare class MemoryIndex implements IMemoryIndex {
|
|
|
3371
4232
|
*/
|
|
3372
4233
|
private static _keyOf;
|
|
3373
4234
|
/** {@inheritDoc IMemoryIndex.rebuild} */
|
|
3374
|
-
rebuild(entries: ReadonlyArray<
|
|
4235
|
+
rebuild(entries: ReadonlyArray<IIndexedMemoryEntry>): Result<number>;
|
|
3375
4236
|
/** {@inheritDoc IMemoryIndex.patch} */
|
|
3376
4237
|
patch(op: MemoryIndexPatchOp, entry: IIndexedMemoryRecord): Result<IIndexedMemoryRecord>;
|
|
3377
4238
|
/** {@inheritDoc IMemoryIndex.entries} */
|
|
3378
|
-
entries(): ReadonlyArray<
|
|
4239
|
+
entries(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
4240
|
+
/** {@inheritDoc IMemoryIndex.get} */
|
|
4241
|
+
get(target: IEdgeTarget): IIndexedMemoryEntry | undefined;
|
|
3379
4242
|
/** {@inheritDoc IMemoryIndex.byKind} */
|
|
3380
|
-
byKind(kind: Kind): ReadonlyArray<
|
|
4243
|
+
byKind(kind: Kind): ReadonlyArray<IIndexedMemoryEntry>;
|
|
3381
4244
|
/** {@inheritDoc IMemoryIndex.byTag} */
|
|
3382
|
-
byTag(tag: Tag): ReadonlyArray<
|
|
4245
|
+
byTag(tag: Tag): ReadonlyArray<IIndexedMemoryEntry>;
|
|
3383
4246
|
/** {@inheritDoc IMemoryIndex.byRecency} */
|
|
3384
|
-
byRecency(): ReadonlyArray<
|
|
4247
|
+
byRecency(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
3385
4248
|
/** {@inheritDoc IMemoryIndex.byRank} */
|
|
3386
|
-
byRank(): ReadonlyArray<
|
|
4249
|
+
byRank(): ReadonlyArray<IIndexedMemoryEntry>;
|
|
3387
4250
|
/** {@inheritDoc IMemoryIndex.backlinks} */
|
|
3388
4251
|
backlinks(target: IEdgeTarget): ReadonlyArray<IEdgeTarget>;
|
|
3389
4252
|
/**
|
|
@@ -3401,6 +4264,8 @@ export declare class MemoryIndex implements IMemoryIndex {
|
|
|
3401
4264
|
* approach; the sort is over the in-memory index, never a filesystem walk.
|
|
3402
4265
|
*/
|
|
3403
4266
|
private _rankOrdered;
|
|
4267
|
+
/** Resolve composite keys to their entries, skipping any that are absent. */
|
|
4268
|
+
private static _resolve;
|
|
3404
4269
|
/**
|
|
3405
4270
|
* Rank-descending comparator with an absent-`rank`-last rule and a recency
|
|
3406
4271
|
* (`updated`, then `seq`) tiebreak. Duplicated from the retrieve packlet's
|
|
@@ -3603,6 +4468,13 @@ export declare class MemoryIngestOrchestrator implements IMemoryIngestOrchestrat
|
|
|
3603
4468
|
private static _asStringBody;
|
|
3604
4469
|
}
|
|
3605
4470
|
|
|
4471
|
+
/**
|
|
4472
|
+
* What {@link IMemoryStore.list} accepts: a narrowing filter, or the explicit
|
|
4473
|
+
* whole-vault scan.
|
|
4474
|
+
* @public
|
|
4475
|
+
*/
|
|
4476
|
+
export declare type MemoryListSelection = IMemoryStoreListFilter | IWholeVaultScan;
|
|
4477
|
+
|
|
3606
4478
|
/**
|
|
3607
4479
|
* The outcome of the observed operation.
|
|
3608
4480
|
* @public
|
|
@@ -3812,7 +4684,7 @@ export declare const NON_SEMANTIC_CAPABILITIES: IMemoryRetrieverCapabilities;
|
|
|
3812
4684
|
* default, byte-identical to the pre-`orderBy` behavior).
|
|
3813
4685
|
* @public
|
|
3814
4686
|
*/
|
|
3815
|
-
export declare function orderingCompare(orderBy?: IMemoryQuery['orderBy']): (a:
|
|
4687
|
+
export declare function orderingCompare(orderBy?: IMemoryQuery['orderBy']): (a: IEnvelopeCarrier, b: IEnvelopeCarrier) => number;
|
|
3816
4688
|
|
|
3817
4689
|
/**
|
|
3818
4690
|
* Parse a complete memory file into a typed {@link IMemoryRecord}. Splits the
|
|
@@ -3852,7 +4724,7 @@ export declare type QueryEmbedder = (text: string) => Promise<Result<Float32Arra
|
|
|
3852
4724
|
* index's rank-view ordering.
|
|
3853
4725
|
* @public
|
|
3854
4726
|
*/
|
|
3855
|
-
export declare function rankCompare(a:
|
|
4727
|
+
export declare function rankCompare(a: IEnvelopeCarrier, b: IEnvelopeCarrier): number;
|
|
3856
4728
|
|
|
3857
4729
|
/**
|
|
3858
4730
|
* A per-kind host projection from a fully-resolved (post-merge) memory record
|
|
@@ -3864,7 +4736,7 @@ export declare function rankCompare(a: IMemoryRecord<unknown>, b: IMemoryRecord<
|
|
|
3864
4736
|
* for this record" (logged at `warn`), never failing the write.
|
|
3865
4737
|
*
|
|
3866
4738
|
* Runs on writes only. To apply a newly-registered projector to records that
|
|
3867
|
-
* already exist, call `IMemoryStore.
|
|
4739
|
+
* already exist, call `IMemoryStore.reconcile(kind, 'rank')`.
|
|
3868
4740
|
* @public
|
|
3869
4741
|
*/
|
|
3870
4742
|
export declare type RankProjector = (record: IMemoryRecord<unknown>) => number;
|
|
@@ -3874,7 +4746,7 @@ export declare type RankProjector = (record: IMemoryRecord<unknown>) => number;
|
|
|
3874
4746
|
* equal-`updated` records sort deterministically. Mirrors the B1 index ordering.
|
|
3875
4747
|
* @public
|
|
3876
4748
|
*/
|
|
3877
|
-
export declare function recencyCompare(a:
|
|
4749
|
+
export declare function recencyCompare(a: IEnvelopeCarrier, b: IEnvelopeCarrier): number;
|
|
3878
4750
|
|
|
3879
4751
|
/**
|
|
3880
4752
|
* Returns records matching the query's scope / kind / tag / provenance-source / predicate filters,
|
|
@@ -3884,15 +4756,22 @@ export declare function recencyCompare(a: IMemoryRecord<unknown>, b: IMemoryReco
|
|
|
3884
4756
|
*/
|
|
3885
4757
|
export declare class RecencyRetriever implements IMemoryRetriever {
|
|
3886
4758
|
private readonly _index;
|
|
4759
|
+
private readonly _resolver;
|
|
3887
4760
|
private constructor();
|
|
3888
4761
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
3889
4762
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
3890
4763
|
/** Family-convention factory. */
|
|
3891
|
-
static create(
|
|
4764
|
+
static create(params: IRetrieverCreateParams): Result<RecencyRetriever>;
|
|
3892
4765
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
3893
4766
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
3894
4767
|
}
|
|
3895
4768
|
|
|
4769
|
+
/**
|
|
4770
|
+
* What a {@link IMemoryStore.reconcile} established, discriminated by artifact.
|
|
4771
|
+
* @public
|
|
4772
|
+
*/
|
|
4773
|
+
export declare type ReconcileReport = IRankReconcileReport | IVectorReconcileReport | IFragmentReconcileReport;
|
|
4774
|
+
|
|
3896
4775
|
/**
|
|
3897
4776
|
* The four dedup verdicts a {@link IEntityResolver} (or fgv's exact-match layer)
|
|
3898
4777
|
* returns for a candidate. See the design note §3 for the verdict → write
|
|
@@ -3914,6 +4793,53 @@ export declare type ResolutionVerdict = {
|
|
|
3914
4793
|
readonly target: IEdgeTarget;
|
|
3915
4794
|
};
|
|
3916
4795
|
|
|
4796
|
+
/**
|
|
4797
|
+
* The shared select → order → page → materialize pipeline every non-semantic
|
|
4798
|
+
* retriever runs, and the one place the body-vs-envelope ordering decision lives.
|
|
4799
|
+
*
|
|
4800
|
+
* @public
|
|
4801
|
+
* @remarks
|
|
4802
|
+
* **Without `query.filter`, ordering and paging happen over envelopes and only
|
|
4803
|
+
* the page is materialized** — so `limit` genuinely bounds the number of records
|
|
4804
|
+
* read, not merely the number returned. That is what makes `limit` a legitimate
|
|
4805
|
+
* narrowing axis rather than a loophole, and it is conditional on the ordering
|
|
4806
|
+
* key being an envelope field: both shipped comparators (`recencyCompare`,
|
|
4807
|
+
* `rankCompare`) read `updated` / `seq` / `rank` and qualify. **An ordering that
|
|
4808
|
+
* keyed on a body field could not use this path** and would have to sort after
|
|
4809
|
+
* materialization, at which point `limit` bounds the result and not the read.
|
|
4810
|
+
*
|
|
4811
|
+
* **With `query.filter`, every envelope-survivor must be materialized first**,
|
|
4812
|
+
* because the predicate takes a whole record. Semantics are preserved exactly;
|
|
4813
|
+
* the cost is not. Pair `filter` with an envelope axis when the read cost
|
|
4814
|
+
* matters.
|
|
4815
|
+
*/
|
|
4816
|
+
export declare function resolveQuery(entries: ReadonlyArray<IIndexedMemoryEntry>, query: IMemoryQuery, resolver: IMemoryRecordResolver): Result<ReadonlyArray<IMemoryRecord<unknown>>>;
|
|
4817
|
+
|
|
4818
|
+
/**
|
|
4819
|
+
* Ask {@link IMemoryStore.list} for **every record in the vault**, bodies
|
|
4820
|
+
* included.
|
|
4821
|
+
*
|
|
4822
|
+
* @remarks
|
|
4823
|
+
* `list` requires a selection and rejects one that narrows nothing, so this is
|
|
4824
|
+
* the only way to get the whole vault — and that is the point. Since the index
|
|
4825
|
+
* holds envelopes only, `list` materializes every survivor from storage, so an
|
|
4826
|
+
* unnarrowed call reads one file per record. Making it impossible to write by
|
|
4827
|
+
* accident is worth more than making it fast.
|
|
4828
|
+
*
|
|
4829
|
+
* It is named for what it costs rather than for what it returns, and it is
|
|
4830
|
+
* greppable: `scanEveryRecord` enumerates every whole-vault read in a codebase in
|
|
4831
|
+
* one search. This mirrors `@fgv/ts-extras`' `safer-fetch`, where `addressGuard`
|
|
4832
|
+
* is required with no default and `allowAnyAddress()` is the named opt-out.
|
|
4833
|
+
*
|
|
4834
|
+
* **If you only need to select, you do not need this.** Use
|
|
4835
|
+
* {@link IMemoryStore.listEntries}, which returns every entry's scope and
|
|
4836
|
+
* envelope, reads no files, and needs no selection.
|
|
4837
|
+
* @public
|
|
4838
|
+
*/
|
|
4839
|
+
export declare function scanEveryRecord(options?: {
|
|
4840
|
+
readonly asOf?: number;
|
|
4841
|
+
}): IWholeVaultScan;
|
|
4842
|
+
|
|
3917
4843
|
/**
|
|
3918
4844
|
* The reference {@link IMergeStrategy}: a score-union. Every record is scored by
|
|
3919
4845
|
* the number of composed result sets it appears in (deduplicated by
|
|
@@ -3940,7 +4866,7 @@ export declare class ScoreUnionMergeStrategy implements IMergeStrategy {
|
|
|
3940
4866
|
* unlimited).
|
|
3941
4867
|
* @public
|
|
3942
4868
|
*/
|
|
3943
|
-
export declare function selectByQuery(entries: ReadonlyArray<
|
|
4869
|
+
export declare function selectByQuery(entries: ReadonlyArray<IIndexedMemoryEntry>, query: IMemoryQuery): IIndexedMemoryEntry[];
|
|
3944
4870
|
|
|
3945
4871
|
/**
|
|
3946
4872
|
* Select the current version from a set of an entity's versions: the newest
|
|
@@ -3948,7 +4874,7 @@ export declare function selectByQuery(entries: ReadonlyArray<IIndexedMemoryRecor
|
|
|
3948
4874
|
* entity has no current version (fully invalidated / soft-deleted, or empty).
|
|
3949
4875
|
* @public
|
|
3950
4876
|
*/
|
|
3951
|
-
export declare function selectCurrentVersion(versions: ReadonlyArray<
|
|
4877
|
+
export declare function selectCurrentVersion<T extends IEnvelopeCarrier>(versions: ReadonlyArray<T>): T | undefined;
|
|
3952
4878
|
|
|
3953
4879
|
/**
|
|
3954
4880
|
* Select the version of an entity valid at `asOf` (epoch ms): the newest
|
|
@@ -3956,7 +4882,7 @@ export declare function selectCurrentVersion(versions: ReadonlyArray<IMemoryReco
|
|
|
3956
4882
|
* when no version was valid at that instant.
|
|
3957
4883
|
* @public
|
|
3958
4884
|
*/
|
|
3959
|
-
export declare function selectVersionAsOf(versions: ReadonlyArray<
|
|
4885
|
+
export declare function selectVersionAsOf<T extends IEnvelopeCarrier>(versions: ReadonlyArray<T>, asOf: number): T | undefined;
|
|
3960
4886
|
|
|
3961
4887
|
/**
|
|
3962
4888
|
* The loud-degradation message a retriever returns when `query.semantic` is set
|
|
@@ -3979,6 +4905,7 @@ export declare const SEMANTIC_UNWIRED_MESSAGE: string;
|
|
|
3979
4905
|
*/
|
|
3980
4906
|
export declare class SemanticRetriever implements IMemoryRetriever {
|
|
3981
4907
|
private readonly _index;
|
|
4908
|
+
private readonly _resolver;
|
|
3982
4909
|
private readonly _backend;
|
|
3983
4910
|
private constructor();
|
|
3984
4911
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
@@ -4050,11 +4977,12 @@ export declare type StoreStampedEnvelopeField = 'id' | 'seq' | 'contentHash' | '
|
|
|
4050
4977
|
*/
|
|
4051
4978
|
export declare class StructuredFilterRetriever implements IMemoryRetriever {
|
|
4052
4979
|
private readonly _index;
|
|
4980
|
+
private readonly _resolver;
|
|
4053
4981
|
private constructor();
|
|
4054
4982
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
4055
4983
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
4056
4984
|
/** Family-convention factory. */
|
|
4057
|
-
static create(
|
|
4985
|
+
static create(params: IRetrieverCreateParams): Result<StructuredFilterRetriever>;
|
|
4058
4986
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
4059
4987
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
4060
4988
|
}
|
|
@@ -4074,11 +5002,12 @@ export declare type Tag = Brand<string, 'Tag'>;
|
|
|
4074
5002
|
*/
|
|
4075
5003
|
export declare class TagRetriever implements IMemoryRetriever {
|
|
4076
5004
|
private readonly _index;
|
|
5005
|
+
private readonly _resolver;
|
|
4077
5006
|
private constructor();
|
|
4078
5007
|
/** {@inheritDoc IMemoryRetriever.capabilities} */
|
|
4079
5008
|
get capabilities(): IMemoryRetrieverCapabilities;
|
|
4080
5009
|
/** Family-convention factory. */
|
|
4081
|
-
static create(
|
|
5010
|
+
static create(params: IRetrieverCreateParams): Result<TagRetriever>;
|
|
4082
5011
|
/** {@inheritDoc IMemoryRetriever.retrieve} */
|
|
4083
5012
|
retrieve(query: IMemoryQuery): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
|
|
4084
5013
|
}
|