@fgv/ts-agent-memory 5.1.0-45 → 5.1.0-47
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/.rush/temp/{bc5b0f2098f7df2a5c498ea77b0de13316349b96.tar.log → 5667e36f1c0cc503a5c20a3ebff76e7b9a702d41.tar.log} +26 -2
- package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +2 -2
- package/.rush/temp/operation/build/all.log +2 -2
- package/.rush/temp/operation/build/log-chunks.jsonl +2 -2
- package/.rush/temp/operation/build/state.json +1 -1
- package/README.md +134 -4
- package/dist/packlets/ingest/orchestrator.js +104 -19
- package/dist/packlets/ingest/orchestrator.js.map +1 -1
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js +10 -7
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js.map +1 -1
- package/dist/packlets/store/fileTreeMemoryStore.js +31 -8
- package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/dist/packlets/types/writePolicy.js +10 -2
- package/dist/packlets/types/writePolicy.js.map +1 -1
- package/dist/packlets/vector/fragmentConverters.js +41 -0
- package/dist/packlets/vector/fragmentConverters.js.map +1 -0
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +17 -9
- package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/dist/packlets/vector/index.js +1 -0
- package/dist/packlets/vector/index.js.map +1 -1
- package/dist/packlets/vector/vectorIndex.js.map +1 -1
- package/dist/test/unit/ingest/dedupScope.test.js +434 -0
- package/dist/test/unit/ingest/dedupScope.test.js.map +1 -0
- package/dist/test/unit/ingest/orchestrator.test.js +7 -4
- package/dist/test/unit/ingest/orchestrator.test.js.map +1 -1
- package/dist/test/unit/store/fileTreeMemoryStore.test.js +64 -0
- package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +1 -1
- package/dist/test/unit/store/indexInjection.test.js +432 -0
- package/dist/test/unit/store/indexInjection.test.js.map +1 -0
- package/dist/test/unit/tools/memoryTools.test.js +1 -0
- package/dist/test/unit/tools/memoryTools.test.js.map +1 -1
- package/dist/test/unit/types/temporalPolicy.test.js +21 -0
- package/dist/test/unit/types/temporalPolicy.test.js.map +1 -1
- package/dist/test/unit/types/writePolicy.test.js +83 -0
- package/dist/test/unit/types/writePolicy.test.js.map +1 -1
- package/dist/test/unit/vector/fragmentConverters.test.js +58 -0
- package/dist/test/unit/vector/fragmentConverters.test.js.map +1 -0
- package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js +65 -0
- package/dist/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +1 -1
- package/dist/ts-agent-memory.d.ts +332 -42
- package/etc/ts-agent-memory.api.md +12 -1
- package/lib/packlets/ingest/orchestrator.d.ts +62 -5
- package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
- package/lib/packlets/ingest/orchestrator.js +104 -19
- package/lib/packlets/ingest/orchestrator.js.map +1 -1
- package/lib/packlets/retrieve/fragmentSemanticRetriever.d.ts +10 -7
- package/lib/packlets/retrieve/fragmentSemanticRetriever.d.ts.map +1 -1
- package/lib/packlets/retrieve/fragmentSemanticRetriever.js +10 -7
- package/lib/packlets/retrieve/fragmentSemanticRetriever.js.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.d.ts +96 -4
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +31 -8
- package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
- package/lib/packlets/types/writePolicy.d.ts +40 -2
- package/lib/packlets/types/writePolicy.d.ts.map +1 -1
- package/lib/packlets/types/writePolicy.js +10 -2
- package/lib/packlets/types/writePolicy.js.map +1 -1
- package/lib/packlets/vector/fragmentConverters.d.ts +25 -0
- package/lib/packlets/vector/fragmentConverters.d.ts.map +1 -0
- package/lib/packlets/vector/fragmentConverters.js +44 -0
- package/lib/packlets/vector/fragmentConverters.js.map +1 -0
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +5 -3
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +17 -9
- package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
- package/lib/packlets/vector/index.d.ts +1 -0
- package/lib/packlets/vector/index.d.ts.map +1 -1
- package/lib/packlets/vector/index.js +1 -0
- package/lib/packlets/vector/index.js.map +1 -1
- package/lib/packlets/vector/vectorIndex.d.ts +97 -22
- package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
- package/lib/packlets/vector/vectorIndex.js.map +1 -1
- package/lib/test/unit/ingest/dedupScope.test.d.ts +2 -0
- package/lib/test/unit/ingest/dedupScope.test.d.ts.map +1 -0
- package/lib/test/unit/ingest/dedupScope.test.js +436 -0
- package/lib/test/unit/ingest/dedupScope.test.js.map +1 -0
- package/lib/test/unit/ingest/orchestrator.test.js +7 -4
- package/lib/test/unit/ingest/orchestrator.test.js.map +1 -1
- package/lib/test/unit/store/fileTreeMemoryStore.test.js +64 -0
- package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +1 -1
- package/lib/test/unit/store/indexInjection.test.d.ts +2 -0
- package/lib/test/unit/store/indexInjection.test.d.ts.map +1 -0
- package/lib/test/unit/store/indexInjection.test.js +434 -0
- package/lib/test/unit/store/indexInjection.test.js.map +1 -0
- package/lib/test/unit/tools/memoryTools.test.js +1 -0
- package/lib/test/unit/tools/memoryTools.test.js.map +1 -1
- package/lib/test/unit/types/temporalPolicy.test.js +21 -0
- package/lib/test/unit/types/temporalPolicy.test.js.map +1 -1
- package/lib/test/unit/types/writePolicy.test.js +83 -0
- package/lib/test/unit/types/writePolicy.test.js.map +1 -1
- package/lib/test/unit/vector/fragmentConverters.test.d.ts +2 -0
- package/lib/test/unit/vector/fragmentConverters.test.d.ts.map +1 -0
- package/lib/test/unit/vector/fragmentConverters.test.js +60 -0
- package/lib/test/unit/vector/fragmentConverters.test.js.map +1 -0
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js +65 -0
- package/lib/test/unit/vector/inMemoryFragmentCosineIndex.test.js.map +1 -1
- package/package.json +7 -7
- package/rush-logs/ts-agent-memory.build.cache.log +1 -1
- package/rush-logs/ts-agent-memory.build.log +2 -2
- package/src/packlets/ingest/orchestrator.ts +116 -21
- package/src/packlets/retrieve/fragmentSemanticRetriever.ts +10 -7
- package/src/packlets/store/fileTreeMemoryStore.ts +114 -6
- package/src/packlets/types/writePolicy.ts +40 -2
- package/src/packlets/vector/fragmentConverters.ts +55 -0
- package/src/packlets/vector/inMemoryFragmentCosineIndex.ts +35 -8
- package/src/packlets/vector/index.ts +1 -0
- package/src/packlets/vector/vectorIndex.ts +97 -22
- package/src/test/unit/ingest/dedupScope.test.ts +542 -0
- package/src/test/unit/ingest/orchestrator.test.ts +4 -0
- package/src/test/unit/store/fileTreeMemoryStore.test.ts +75 -0
- package/src/test/unit/store/indexInjection.test.ts +550 -0
- package/src/test/unit/tools/memoryTools.test.ts +1 -0
- package/src/test/unit/types/temporalPolicy.test.ts +28 -0
- package/src/test/unit/types/writePolicy.test.ts +112 -0
- package/src/test/unit/vector/fragmentConverters.test.ts +80 -0
- package/src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts +88 -0
- package/temp/build/lint/_eslint-5eVG3S6w.json +30 -14
- package/temp/build/typescript/ts_8nwakTlr.json +1 -1
- package/temp/ts-agent-memory.api.json +274 -21
- package/temp/ts-agent-memory.api.md +12 -1
|
@@ -149,6 +149,68 @@ describe('KnowledgeLwwPolicy', () => {
|
|
|
149
149
|
);
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Pins the provenance merge contract documented in the package README
|
|
155
|
+
* (§ "Record updates — the merge contract"). `provenance` is on this policy's
|
|
156
|
+
* PINNED mutable surface, so these four behaviors are guarantees a consumer
|
|
157
|
+
* may depend on — not incidental consequences of the merge configuration. If
|
|
158
|
+
* one of these ever changes, the README claim is wrong and must move with it.
|
|
159
|
+
*/
|
|
160
|
+
describe('provenance merge contract (README-pinned)', () => {
|
|
161
|
+
/** `provenance` with one key to clear, one to revise, and one to leave alone. */
|
|
162
|
+
function provenanceRecord(): IMemoryRecord<unknown> {
|
|
163
|
+
return makeRecord({
|
|
164
|
+
provenance: { source: 'agent', confidence: 0.9, note: 'stale' } as IProvenance
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
test('an explicit null on a sub-key clears that key and preserves its siblings', () => {
|
|
169
|
+
expect(policy.applyUpdate(provenanceRecord(), { provenance: { note: null } })).toSucceedAndSatisfy(
|
|
170
|
+
(updated) => {
|
|
171
|
+
expect(updated.envelope.provenance).toEqual({ source: 'agent', confidence: 0.9 });
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test('a sub-key revision merges per key and preserves untouched siblings', () => {
|
|
177
|
+
expect(policy.applyUpdate(provenanceRecord(), { provenance: { confidence: 0.5 } })).toSucceedAndSatisfy(
|
|
178
|
+
(updated) => {
|
|
179
|
+
expect(updated.envelope.provenance).toEqual({
|
|
180
|
+
source: 'agent',
|
|
181
|
+
confidence: 0.5,
|
|
182
|
+
note: 'stale'
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
test('a whole-block null is rejected loudly rather than silently accepted', () => {
|
|
189
|
+
expect(policy.applyUpdate(provenanceRecord(), { provenance: null })).toFailWith(
|
|
190
|
+
/may not delete required field\(s\): provenance/i
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test('a patch that does not mention provenance leaves it untouched', () => {
|
|
195
|
+
expect(policy.applyUpdate(provenanceRecord(), { tags: ['x'] })).toSucceedAndSatisfy((updated) => {
|
|
196
|
+
expect(updated.envelope.provenance).toEqual({
|
|
197
|
+
source: 'agent',
|
|
198
|
+
confidence: 0.9,
|
|
199
|
+
note: 'stale'
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('the existing record is not mutated in place', () => {
|
|
205
|
+
const existing = provenanceRecord();
|
|
206
|
+
expect(policy.applyUpdate(existing, { provenance: { note: null } })).toSucceed();
|
|
207
|
+
expect(existing.envelope.provenance).toEqual({
|
|
208
|
+
source: 'agent',
|
|
209
|
+
confidence: 0.9,
|
|
210
|
+
note: 'stale'
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
});
|
|
152
214
|
});
|
|
153
215
|
|
|
154
216
|
describe('MemoryCapCullPolicy', () => {
|
|
@@ -330,5 +392,55 @@ describe('MemoryCapCullPolicy', () => {
|
|
|
330
392
|
expect(updated.envelope.embeddingRef).toBe('vec-keep');
|
|
331
393
|
});
|
|
332
394
|
});
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Pins the policy-dependence caveat the README states alongside the
|
|
398
|
+
* provenance merge contract: unlike {@link KnowledgeLwwPolicy}'s pinned
|
|
399
|
+
* surface, this policy's surface is caller-supplied, so a consumer who does
|
|
400
|
+
* not declare `provenance` mutable gets NEITHER the sub-key clear NOR the
|
|
401
|
+
* loud whole-block rejection — every provenance patch key is simply inert.
|
|
402
|
+
*/
|
|
403
|
+
describe('provenance guarantees are policy-dependent (README-pinned)', () => {
|
|
404
|
+
const bodyOnly = (): MemoryCapCullPolicy =>
|
|
405
|
+
MemoryCapCullPolicy.create({ maxRecords: 5, mutableFields: ['body'] }).orThrow();
|
|
406
|
+
|
|
407
|
+
function undeclaredProvenanceRecord(): IMemoryRecord<unknown> {
|
|
408
|
+
return makeRecord(
|
|
409
|
+
{
|
|
410
|
+
id: 'turn-0' as MemoryId,
|
|
411
|
+
kind: 'summarized-turn' as Kind,
|
|
412
|
+
provenance: { source: 'agent', note: 'stale' } as IProvenance
|
|
413
|
+
},
|
|
414
|
+
{ summary: 'old' }
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
test('a sub-key null is inert when provenance is not declared mutable', () => {
|
|
419
|
+
expect(
|
|
420
|
+
bodyOnly().applyUpdate(undeclaredProvenanceRecord(), { provenance: { note: null } })
|
|
421
|
+
).toSucceedAndSatisfy((updated) => {
|
|
422
|
+
expect(updated.envelope.provenance).toEqual({ source: 'agent', note: 'stale' });
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test('a whole-block null is a silent no-op, not an error, when provenance is not declared mutable', () => {
|
|
427
|
+
expect(
|
|
428
|
+
bodyOnly().applyUpdate(undeclaredProvenanceRecord(), { provenance: null })
|
|
429
|
+
).toSucceedAndSatisfy((updated) => {
|
|
430
|
+
expect(updated.envelope.provenance).toEqual({ source: 'agent', note: 'stale' });
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test('declaring provenance mutable restores both guarantees', () => {
|
|
435
|
+
expect(
|
|
436
|
+
policy.applyUpdate(undeclaredProvenanceRecord(), { provenance: { note: null } })
|
|
437
|
+
).toSucceedAndSatisfy((updated) => {
|
|
438
|
+
expect(updated.envelope.provenance).toEqual({ source: 'agent' });
|
|
439
|
+
});
|
|
440
|
+
expect(policy.applyUpdate(undeclaredProvenanceRecord(), { provenance: null })).toFailWith(
|
|
441
|
+
/may not delete required field\(s\): provenance/i
|
|
442
|
+
);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
333
445
|
});
|
|
334
446
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Erik Fortune
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import '@fgv/ts-utils-jest';
|
|
7
|
+
import { IEmbeddedFragment, embeddedFragmentConverter, fragmentLocatorConverter } from '../../../index';
|
|
8
|
+
|
|
9
|
+
describe('fragmentLocatorConverter', () => {
|
|
10
|
+
test('converts a well-formed span', () => {
|
|
11
|
+
expect(fragmentLocatorConverter.convert({ start: 3, end: 11 })).toSucceedWith({ start: 3, end: 11 });
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('rejects a non-numeric offset', () => {
|
|
15
|
+
expect(fragmentLocatorConverter.convert({ start: 'nope', end: 11 })).toFailWith(/start/i);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('rejects a span missing an offset', () => {
|
|
19
|
+
expect(fragmentLocatorConverter.convert({ start: 3 })).toFailWith(/end/i);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('embeddedFragmentConverter', () => {
|
|
24
|
+
const vector: Float32Array = Float32Array.from([1, 0, 0]);
|
|
25
|
+
|
|
26
|
+
describe('identity invariant', () => {
|
|
27
|
+
test('accepts a fragment identified only by its locator', () => {
|
|
28
|
+
expect(
|
|
29
|
+
embeddedFragmentConverter.convert({ locator: { start: 0, end: 4 }, vector })
|
|
30
|
+
).toSucceedAndSatisfy((fragment: IEmbeddedFragment) => {
|
|
31
|
+
expect(fragment.locator).toEqual({ start: 0, end: 4 });
|
|
32
|
+
expect(fragment.fragmentId).toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('accepts a fragment identified only by its fragmentId', () => {
|
|
37
|
+
expect(embeddedFragmentConverter.convert({ fragmentId: 'frag-7', vector })).toSucceedAndSatisfy(
|
|
38
|
+
(fragment: IEmbeddedFragment) => {
|
|
39
|
+
expect(fragment.fragmentId).toBe('frag-7');
|
|
40
|
+
expect(fragment.locator).toBeUndefined();
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('accepts a fragment carrying both identities', () => {
|
|
46
|
+
expect(
|
|
47
|
+
embeddedFragmentConverter.convert({ locator: { start: 0, end: 4 }, fragmentId: 'frag-7', vector })
|
|
48
|
+
).toSucceedAndSatisfy((fragment: IEmbeddedFragment) => {
|
|
49
|
+
expect(fragment.locator).toEqual({ start: 0, end: 4 });
|
|
50
|
+
expect(fragment.fragmentId).toBe('frag-7');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('rejects a fragment carrying neither identity', () => {
|
|
55
|
+
expect(embeddedFragmentConverter.convert({ vector })).toFailWith(
|
|
56
|
+
/at least one of .locator. or .fragmentId./i
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('field validation', () => {
|
|
62
|
+
test('rejects a vector that is not a Float32Array', () => {
|
|
63
|
+
expect(embeddedFragmentConverter.convert({ fragmentId: 'frag-7', vector: [1, 0, 0] })).toFailWith(
|
|
64
|
+
/Float32Array/i
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('rejects a missing vector', () => {
|
|
69
|
+
expect(embeddedFragmentConverter.convert({ fragmentId: 'frag-7' })).toFailWith(/vector/i);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('rejects a non-string fragmentId', () => {
|
|
73
|
+
expect(embeddedFragmentConverter.convert({ fragmentId: 7, vector })).toFailWith(/fragmentId/i);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('rejects a malformed locator', () => {
|
|
77
|
+
expect(embeddedFragmentConverter.convert({ locator: { start: 0 }, vector })).toFailWith(/locator/i);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -386,4 +386,92 @@ describe('InMemoryFragmentCosineIndex', () => {
|
|
|
386
386
|
expect(index.recordCount).toBe(0);
|
|
387
387
|
});
|
|
388
388
|
});
|
|
389
|
+
|
|
390
|
+
describe('fragment identity', () => {
|
|
391
|
+
/** A fragment identified only by an opaque id — no honest body span. */
|
|
392
|
+
function idFrag(fragmentId: string, vector: number[]): IEmbeddedFragment {
|
|
393
|
+
return { fragmentId, vector: Float32Array.from(vector) };
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
test('rejects a fragment carrying neither a locator nor a fragmentId', async () => {
|
|
397
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
398
|
+
expect(
|
|
399
|
+
await index.addFragments(target('knowledge', 'doc-a'), [{ vector: Float32Array.from([1, 0]) }])
|
|
400
|
+
).toFailWith(/at least one of 'locator' or 'fragmentId'/i);
|
|
401
|
+
expect(index.recordCount).toBe(0);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
test('carries an opaque fragmentId through to the query hit verbatim', async () => {
|
|
405
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
406
|
+
const opaque = 'urn:frag:9f8e::{not-parsed}';
|
|
407
|
+
(await index.addFragments(target('knowledge', 'doc-a'), [idFrag(opaque, [1, 0])])).orThrow();
|
|
408
|
+
expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(
|
|
409
|
+
(hits: ReadonlyArray<IVectorQueryHit>) => {
|
|
410
|
+
expect(hits[0].fragmentId).toBe(opaque);
|
|
411
|
+
expect(hits[0].locator).toBeUndefined();
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
test('carries both identities when a fragment supplies both', async () => {
|
|
417
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
418
|
+
(
|
|
419
|
+
await index.addFragments(target('knowledge', 'doc-a'), [
|
|
420
|
+
{ ...frag(2, 8, [1, 0]), fragmentId: 'frag-1' }
|
|
421
|
+
])
|
|
422
|
+
).orThrow();
|
|
423
|
+
expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(
|
|
424
|
+
(hits: ReadonlyArray<IVectorQueryHit>) => {
|
|
425
|
+
expect(hits[0].locator).toEqual(loc(2, 8));
|
|
426
|
+
expect(hits[0].fragmentId).toBe('frag-1');
|
|
427
|
+
}
|
|
428
|
+
);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
test('a locator-only fragment produces a hit with no fragmentId key at all', async () => {
|
|
432
|
+
// Byte-identical to what the index produced before `fragmentId` existed: the key
|
|
433
|
+
// is absent, not present-and-undefined, so an existing caller's structural
|
|
434
|
+
// comparisons are unaffected by the addition.
|
|
435
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
436
|
+
(await index.addFragments(target('knowledge', 'doc-a'), [frag(0, 5, [1, 0])])).orThrow();
|
|
437
|
+
expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(
|
|
438
|
+
(hits: ReadonlyArray<IVectorQueryHit>) => {
|
|
439
|
+
expect(Object.keys(hits[0]).sort()).toEqual(['locator', 'score', 'target']);
|
|
440
|
+
expect(hits[0]).toStrictEqual({
|
|
441
|
+
target: target('knowledge', 'doc-a'),
|
|
442
|
+
score: hits[0].score,
|
|
443
|
+
locator: loc(0, 5)
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test('an id-only fragment produces a hit with no locator key at all', async () => {
|
|
450
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
451
|
+
(await index.addFragments(target('knowledge', 'doc-a'), [idFrag('frag-1', [1, 0])])).orThrow();
|
|
452
|
+
expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(
|
|
453
|
+
(hits: ReadonlyArray<IVectorQueryHit>) => {
|
|
454
|
+
expect(Object.keys(hits[0]).sort()).toEqual(['fragmentId', 'score', 'target']);
|
|
455
|
+
}
|
|
456
|
+
);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
test('mixes identity shapes within one record and within one query', async () => {
|
|
460
|
+
const index = InMemoryFragmentCosineIndex.create().orThrow();
|
|
461
|
+
(
|
|
462
|
+
await index.addFragments(target('knowledge', 'doc-a'), [
|
|
463
|
+
frag(0, 5, [1, 0]),
|
|
464
|
+
idFrag('frag-rewritten', [0, 1])
|
|
465
|
+
])
|
|
466
|
+
).orThrow();
|
|
467
|
+
expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(
|
|
468
|
+
(hits: ReadonlyArray<IVectorQueryHit>) => {
|
|
469
|
+
expect(hits[0].locator).toEqual(loc(0, 5));
|
|
470
|
+
expect(hits[0].fragmentId).toBeUndefined();
|
|
471
|
+
expect(hits[1].fragmentId).toBe('frag-rewritten');
|
|
472
|
+
expect(hits[1].locator).toBeUndefined();
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
389
477
|
});
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
[
|
|
25
25
|
"packlets/types/writePolicy.ts",
|
|
26
|
-
"
|
|
26
|
+
"239707437000bfeaaa44dd6ca0f6a582a55dc149a567ceedec2b9be42b8f6f46_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
27
27
|
],
|
|
28
28
|
[
|
|
29
29
|
"packlets/types/index.ts",
|
|
@@ -63,7 +63,11 @@
|
|
|
63
63
|
],
|
|
64
64
|
[
|
|
65
65
|
"packlets/vector/vectorIndex.ts",
|
|
66
|
-
"
|
|
66
|
+
"fa4879a08b8cb1631f6a8e968d0df8fb803a0a33db6265cd03f5e566de8f0f82_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
67
|
+
],
|
|
68
|
+
[
|
|
69
|
+
"packlets/vector/fragmentConverters.ts",
|
|
70
|
+
"7253c019d02c288dec21314579f63d40af7db6fb08fe9f4af09cfb6a8cdb71f6_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
67
71
|
],
|
|
68
72
|
[
|
|
69
73
|
"packlets/vector/inMemoryCosineIndex.ts",
|
|
@@ -71,11 +75,11 @@
|
|
|
71
75
|
],
|
|
72
76
|
[
|
|
73
77
|
"packlets/vector/inMemoryFragmentCosineIndex.ts",
|
|
74
|
-
"
|
|
78
|
+
"8e2464ba6c1f87551b7588fadb5fc92cd1a5e4f5e5714171759073c8c1cc9b3b_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
75
79
|
],
|
|
76
80
|
[
|
|
77
81
|
"packlets/vector/index.ts",
|
|
78
|
-
"
|
|
82
|
+
"8049e688c06aadd87e7ef453e0307662b49ba2f2c245d6ea59c6cabe3a53bc14_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
79
83
|
],
|
|
80
84
|
[
|
|
81
85
|
"packlets/store/scopeEncoding.ts",
|
|
@@ -83,7 +87,7 @@
|
|
|
83
87
|
],
|
|
84
88
|
[
|
|
85
89
|
"packlets/store/fileTreeMemoryStore.ts",
|
|
86
|
-
"
|
|
90
|
+
"91d6847b70a5d8b8eb47b56b5970c0abf68bd205d936a2af6951892694f25d21_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
87
91
|
],
|
|
88
92
|
[
|
|
89
93
|
"packlets/store/index.ts",
|
|
@@ -115,7 +119,7 @@
|
|
|
115
119
|
],
|
|
116
120
|
[
|
|
117
121
|
"packlets/retrieve/fragmentSemanticRetriever.ts",
|
|
118
|
-
"
|
|
122
|
+
"06a4d99730c38e8430f3aaf5472530d54110cd17f48d57585b7d6ea5548157eb_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
119
123
|
],
|
|
120
124
|
[
|
|
121
125
|
"packlets/retrieve/temporalRetrievers.ts",
|
|
@@ -151,7 +155,7 @@
|
|
|
151
155
|
],
|
|
152
156
|
[
|
|
153
157
|
"packlets/ingest/orchestrator.ts",
|
|
154
|
-
"
|
|
158
|
+
"eda2f50e1a6753e19002bb060fa24e395e43ba4ea496469dfa65651a56048dfe_5FxNr7n+qjkV58wA2j2YZUqKABE="
|
|
155
159
|
],
|
|
156
160
|
[
|
|
157
161
|
"packlets/ingest/index.ts",
|
|
@@ -185,9 +189,13 @@
|
|
|
185
189
|
"test/unit/ingest/cycleGuard.test.ts",
|
|
186
190
|
"f0096fa558b1ab01e2b291b826dc413086a83530e033828133e2e231f055d14c_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
187
191
|
],
|
|
192
|
+
[
|
|
193
|
+
"test/unit/ingest/dedupScope.test.ts",
|
|
194
|
+
"0d8d34dd8a09bb56ed2d0400930b230e1a3a5f62c36f63646b742203385fe4f1_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
195
|
+
],
|
|
188
196
|
[
|
|
189
197
|
"test/unit/ingest/orchestrator.test.ts",
|
|
190
|
-
"
|
|
198
|
+
"3a7c53e84bb37043edc0cf0d64eb217fcb106fd18e4c9f675be293a180aa0de3_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
191
199
|
],
|
|
192
200
|
[
|
|
193
201
|
"test/unit/observe/memoryObservationStore.test.ts",
|
|
@@ -219,12 +227,16 @@
|
|
|
219
227
|
],
|
|
220
228
|
[
|
|
221
229
|
"test/unit/store/fileTreeMemoryStore.test.ts",
|
|
222
|
-
"
|
|
230
|
+
"7ab5f3104461c232d0c37c7f8519a1dbb7a75df0f6f186fd324846321ca146ff_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
223
231
|
],
|
|
224
232
|
[
|
|
225
233
|
"test/unit/store/fragmentEmbedOnWrite.test.ts",
|
|
226
234
|
"70969bc20e808fc082eaad736072e783314b6d245c12f9db2d69caf942588a8b_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
227
235
|
],
|
|
236
|
+
[
|
|
237
|
+
"test/unit/store/indexInjection.test.ts",
|
|
238
|
+
"b521f5197e59f488e39a7620c53088776a69f7c31cf3b451bb9f089230e83ec9_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
239
|
+
],
|
|
228
240
|
[
|
|
229
241
|
"test/unit/store/lenientOpen.test.ts",
|
|
230
242
|
"f7051e2e38e4a195585e3fa4e36c373f909032141da7f77043bbd8d0a9808d75_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
@@ -251,7 +263,7 @@
|
|
|
251
263
|
],
|
|
252
264
|
[
|
|
253
265
|
"test/unit/tools/memoryTools.test.ts",
|
|
254
|
-
"
|
|
266
|
+
"86537c3f7ba5a99bc2de7e89de677b249b352604d7d064a8762c8e6c864531a2_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
255
267
|
],
|
|
256
268
|
[
|
|
257
269
|
"test/unit/types/identityCodec.test.ts",
|
|
@@ -267,11 +279,15 @@
|
|
|
267
279
|
],
|
|
268
280
|
[
|
|
269
281
|
"test/unit/types/temporalPolicy.test.ts",
|
|
270
|
-
"
|
|
282
|
+
"5f757ea55ba1e2fc3a9e5ec3027a03a186f69cb8388dc2cd57241ecd9ac453f3_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
271
283
|
],
|
|
272
284
|
[
|
|
273
285
|
"test/unit/types/writePolicy.test.ts",
|
|
274
|
-
"
|
|
286
|
+
"55d66cedb5ee43e0692df8351f4c19039d32c71fb24ba7ce803d8657f27b95b5_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
287
|
+
],
|
|
288
|
+
[
|
|
289
|
+
"test/unit/vector/fragmentConverters.test.ts",
|
|
290
|
+
"2871bb0b9ba94d131c4b34464de85627ecf54cbb71319037b88132c05b2eb594_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
275
291
|
],
|
|
276
292
|
[
|
|
277
293
|
"test/unit/vector/inMemoryCosineIndex.test.ts",
|
|
@@ -279,12 +295,12 @@
|
|
|
279
295
|
],
|
|
280
296
|
[
|
|
281
297
|
"test/unit/vector/inMemoryFragmentCosineIndex.test.ts",
|
|
282
|
-
"
|
|
298
|
+
"bd4b7312b74ab15ae7ca45c8c8701a984fddbd668364329912fefdf7ee54fe89_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
283
299
|
],
|
|
284
300
|
[
|
|
285
301
|
"test/unit/vector/vectorIndex.test.ts",
|
|
286
302
|
"ee46f9a64127b829fea5ce21e63481d2ad757cfc9d04b389bd27e146b6a0c136_fnTnCS8rja7DE6jB0bKRna1pZAg="
|
|
287
303
|
]
|
|
288
304
|
],
|
|
289
|
-
"filesHash": "
|
|
305
|
+
"filesHash": "d6xwZmXvrL_zWYf2GJYlVw"
|
|
290
306
|
}
|