@fgv/ts-agent-memory 5.1.0-45 → 5.1.0-46
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 → 6e1299d1cebb080772163a532c221cd181b54f9f.tar.log} +20 -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 +79 -4
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js +10 -7
- package/dist/packlets/retrieve/fragmentSemanticRetriever.js.map +1 -1
- package/dist/packlets/store/fileTreeMemoryStore.js +20 -4
- 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/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/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 +240 -37
- package/etc/ts-agent-memory.api.md +10 -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 +65 -3
- package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
- package/lib/packlets/store/fileTreeMemoryStore.js +20 -4
- 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/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/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/retrieve/fragmentSemanticRetriever.ts +10 -7
- package/src/packlets/store/fileTreeMemoryStore.ts +74 -4
- 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/store/fileTreeMemoryStore.test.ts +75 -0
- package/src/test/unit/store/indexInjection.test.ts +550 -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 +23 -11
- package/temp/build/typescript/ts_8nwakTlr.json +1 -1
- package/temp/ts-agent-memory.api.json +177 -21
- package/temp/ts-agent-memory.api.md +10 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inMemoryFragmentCosineIndex.test.js","sourceRoot":"","sources":["../../../../src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport '@fgv/ts-utils-jest';\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport {\n IEdgeTarget,\n IEmbeddedFragment,\n IFragmentLocator,\n IMemoryRecord,\n IMemoryRecordSource,\n IScopedMemoryRecord,\n IVectorQueryHit,\n InMemoryFragmentCosineIndex,\n MemoryId,\n MemoryScopeKey\n} from '../../../index';\n\n/** A scope-qualified target from a `(scope, id)` pair. */\nfunction target(scope: string, id: string): IEdgeTarget {\n return { scope: scope as MemoryScopeKey, id: id as MemoryId };\n}\n\n/** A locator over an arbitrary `[start, end)` span (opaque to the index). */\nfunction loc(start: number, end: number): IFragmentLocator {\n return { start, end };\n}\n\n/** An embedded fragment from a locator + a raw vector. */\nfunction frag(start: number, end: number, vector: number[]): IEmbeddedFragment {\n return { locator: loc(start, end), vector: Float32Array.from(vector) };\n}\n\n/** A trivial record carrying just the id + a marker body, for rebuild tests. */\nfunction record(id: string, body: string = `body-${id}`): IMemoryRecord<unknown> {\n return {\n envelope: { id: id as MemoryId } as IMemoryRecord<unknown>['envelope'],\n body\n };\n}\n\n/** A scope-qualified record entry for a rebuild source. */\nfunction scoped(scope: string, id: string, body?: string): IScopedMemoryRecord {\n return { target: target(scope, id), record: record(id, body) };\n}\n\n/** A scripted record source for `rebuild`. */\nclass FakeSource implements IMemoryRecordSource {\n private readonly _result: Result<ReadonlyArray<IScopedMemoryRecord>>;\n public constructor(result: Result<ReadonlyArray<IScopedMemoryRecord>>) {\n this._result = result;\n }\n public list(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>> {\n return Promise.resolve(this._result);\n }\n}\n\ndescribe('InMemoryFragmentCosineIndex', () => {\n describe('addFragments', () => {\n test('stores every fragment and reports the count; tracks record/fragment counts', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])).toSucceedWith(2);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(2);\n });\n\n test('whole-record replace — a second addFragments drops the prior fragments', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])).toSucceedWith(2);\n // Re-author with a single fragment: the old two must be gone.\n expect(await index.addFragments(t, [frag(0, 3, [1, 1])])).toSucceedWith(1);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(1);\n expect(await index.query(Float32Array.from([1, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(1);\n expect(hits[0].locator).toEqual(loc(0, 3));\n }\n );\n });\n\n test('an empty fragments array drops the record entirely', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0])])).toSucceedWith(1);\n expect(await index.addFragments(t, [])).toSucceedWith(0);\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n });\n\n test('same stem in different scopes are distinct entries', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('conv-a', 'turn-3');\n const b = target('conv-b', 'turn-3');\n expect(await index.addFragments(a, [frag(0, 5, [1, 0])])).toSucceedWith(1);\n expect(await index.addFragments(b, [frag(0, 5, [0, 1])])).toSucceedWith(1);\n expect(index.recordCount).toBe(2);\n expect(await index.query(Float32Array.from([1, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.target)).toEqual(expect.arrayContaining([a, b]));\n }\n );\n });\n\n test('fails loudly on an empty fragment vector — and does not partially store', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n // First fragment is fine, second is empty: whole-record-replace must be all-or-nothing.\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [])])).toFailWith(\n /empty fragment vector/i\n );\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n });\n\n test('fails loudly on a fragment-dimension mismatch against the established dimension', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(await index.addFragments(target('knowledge', 'a'), [frag(0, 5, [1, 0])])).toSucceed();\n expect(await index.addFragments(target('knowledge', 'b'), [frag(0, 5, [1, 0, 0])])).toFailWith(\n /fragment dimension 3 does not match index dimension 2/i\n );\n });\n\n test('a failed multi-fragment add on a fresh index does not establish a dimension (all-or-nothing)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n // Batch: first fragment (dim 2) would set the dimension, second (dim 3) fails\n // the check. The failed add must leave the index wholly dimensionless — not\n // half-committed to dim 2 — so a later legitimate dim-3 add still succeeds.\n expect(\n await index.addFragments(target('knowledge', 'doc-1'), [frag(0, 5, [1, 0]), frag(5, 10, [1, 0, 0])])\n ).toFailWith(/fragment dimension 3 does not match index dimension 2/i);\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n // The dimension was never committed: a fresh dim-3 record indexes cleanly.\n expect(await index.addFragments(target('knowledge', 'doc-2'), [frag(0, 5, [1, 0, 0])])).toSucceedWith(\n 1\n );\n expect(await index.query(Float32Array.from([1, 0, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].target.id).toBe('doc-2');\n expect(hits[0].score).toBeCloseTo(1);\n }\n );\n });\n\n test('stores a defensive copy — mutating the caller buffer after add does not corrupt the index', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const buffer = Float32Array.from([1, 0]);\n (\n await index.addFragments(target('knowledge', 'doc-1'), [{ locator: loc(0, 5), vector: buffer }])\n ).orThrow();\n buffer[0] = 0;\n buffer[1] = 1;\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].score).toBeCloseTo(1);\n }\n );\n });\n });\n\n describe('query', () => {\n async function seeded(): Promise<InMemoryFragmentCosineIndex> {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc-a'), [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])\n ).orThrow();\n (await index.addFragments(target('knowledge', 'doc-b'), [frag(0, 5, [1, 1])])).orThrow();\n return index;\n }\n\n test('returns fragment hits in descending cosine-similarity order, each carrying its locator', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 3)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n // doc-a[0,5] matches [1,0] best (score 1), then doc-b (1/sqrt2), then doc-a[5,10] (0).\n expect(hits[0].target.id).toBe('doc-a');\n expect(hits[0].locator).toEqual(loc(0, 5));\n expect(hits[0].score).toBeCloseTo(1);\n expect(hits[1].target.id).toBe('doc-b');\n expect(hits[1].score).toBeCloseTo(1 / Math.sqrt(2));\n expect(hits[2].target.id).toBe('doc-a');\n expect(hits[2].locator).toEqual(loc(5, 10));\n expect(hits[2].score).toBeCloseTo(0);\n }\n );\n });\n\n test('truncates to topK', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.locator)).toEqual([loc(0, 5), loc(0, 5)]);\n expect(hits[0].target.id).toBe('doc-a');\n expect(hits[1].target.id).toBe('doc-b');\n }\n );\n });\n\n test('maxPerRecord caps fragments per record during selection (before the topK cut)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n // doc-a has three fragments that all beat doc-b's single fragment.\n (\n await index.addFragments(target('knowledge', 'doc-a'), [\n frag(0, 5, [1, 0]),\n frag(5, 10, [0.9, 0.1]),\n frag(10, 15, [0.8, 0.2])\n ])\n ).orThrow();\n (await index.addFragments(target('knowledge', 'doc-b'), [frag(0, 5, [0.7, 0.3])])).orThrow();\n // Without a cap, top-2 would be doc-a twice. With maxPerRecord=1, doc-b surfaces.\n expect(await index.query(Float32Array.from([1, 0]), 2, 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.target.id)).toEqual(['doc-a', 'doc-b']);\n expect(hits[0].locator).toEqual(loc(0, 5));\n }\n );\n });\n\n test('maxPerRecord=0 yields no hits', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 5, 0)).toSucceedWith([]);\n });\n\n test('maxPerRecord larger than any record leaves the ranking unchanged', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 5, 10)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(3);\n expect(hits[0].target.id).toBe('doc-a');\n }\n );\n });\n\n test('returns empty for a non-positive topK', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 0)).toSucceedWith([]);\n expect(await index.query(Float32Array.from([1, 0]), -1)).toSucceedWith([]);\n });\n\n test('returns empty when the index is empty (no dimension check)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(await index.query(Float32Array.from([1, 2, 3, 4]), 5)).toSucceedWith([]);\n });\n\n test('fails loudly on a query-dimension mismatch', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0, 0]), 3)).toFailWith(\n /query dimension 3 does not match index dimension 2/i\n );\n });\n\n test('scores a degenerate (zero-magnitude) stored fragment as 0 rather than NaN', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc'), [frag(0, 5, [0, 0]), frag(5, 10, [1, 0])])\n ).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits.map((h) => h.locator)).toEqual([loc(5, 10), loc(0, 5)]);\n expect(hits[1].score).toBe(0);\n }\n );\n });\n\n test('scores against a degenerate (zero-magnitude) query as 0 rather than NaN', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'doc'), [frag(0, 5, [1, 0])])).orThrow();\n expect(await index.query(Float32Array.from([0, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].score).toBe(0);\n }\n );\n });\n });\n\n describe('remove', () => {\n test('removes every fragment of a record and is reflected in subsequent queries', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('knowledge', 'doc-a');\n const b = target('knowledge', 'doc-b');\n (await index.addFragments(a, [frag(0, 5, [1, 0]), frag(5, 10, [1, 0])])).orThrow();\n (await index.addFragments(b, [frag(0, 5, [0, 1])])).orThrow();\n expect(await index.remove(a)).toSucceedWith(a);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(1);\n expect(await index.query(Float32Array.from([1, 0]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits.map((h) => h.target.id)).toEqual(['doc-b']);\n }\n );\n });\n\n test('removes only the scoped target — a same-stem record in another scope is left intact', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('conv-a', 'turn-3');\n const b = target('conv-b', 'turn-3');\n (await index.addFragments(a, [frag(0, 5, [1, 0])])).orThrow();\n (await index.addFragments(b, [frag(0, 5, [0, 1])])).orThrow();\n expect(await index.remove(a)).toSucceedWith(a);\n expect(index.recordCount).toBe(1);\n expect(await index.query(Float32Array.from([0, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(1);\n expect(hits[0].target).toEqual(b);\n }\n );\n });\n\n test('is idempotent — removing an absent target still succeeds', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'missing');\n expect(await index.remove(t)).toSucceedWith(t);\n });\n });\n\n describe('rebuild', () => {\n // Deterministic: each record yields two fragments encoding the id's first char code.\n const embed = (r: IMemoryRecord<unknown>): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> => {\n const code: number = (r.envelope.id as string).charCodeAt(0);\n return Promise.resolve(succeed([frag(0, 5, [code, 1]), frag(5, 10, [1, code])]));\n };\n\n test('re-embeds every scoped record and reports the total fragment count', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a'), scoped('knowledge', 'b')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(4);\n expect(index.recordCount).toBe(2);\n expect(index.fragmentCount).toBe(4);\n });\n\n test('keeps same-stem records under different scopes distinct across a rebuild', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('conv-a', 'turn-3'), scoped('conv-b', 'turn-3')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(4);\n expect(index.recordCount).toBe(2);\n });\n\n test('clears prior contents and re-establishes the dimension', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'old'), [frag(0, 5, [1, 2, 3])])).orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(2);\n expect(index.recordCount).toBe(1);\n expect(await index.query(Float32Array.from([97, 1]), 1)).toSucceed();\n });\n\n test('fails loudly when the source list fails and rolls back to empty', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'seed'), [frag(0, 5, [1, 1])])).orThrow();\n const source = new FakeSource(fail('disk gone'));\n expect(await index.rebuild(source, embed)).toFailWith(/failed to list records: disk gone/i);\n expect(index.recordCount).toBe(0);\n });\n\n test('fails loudly and rolls back to empty when an embedding fails mid-rebuild', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'seed'), [frag(0, 5, [1, 1])])).orThrow();\n let calls: number = 0;\n const flakyEmbed = (): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> => {\n calls += 1;\n return Promise.resolve(calls === 1 ? succeed([frag(0, 5, [1, 1])]) : fail('no model'));\n };\n const source = new FakeSource(succeed([scoped('conv-a', 'turn-1'), scoped('conv-b', 'turn-1')]));\n expect(await index.rebuild(source, flakyEmbed)).toFailWith(\n /embedding 'conv-b\\0turn-1' failed: no model/i\n );\n expect(index.recordCount).toBe(0);\n });\n\n test('fails loudly and rolls back to empty when adding an embedded fragment fails', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a')]));\n const emptyEmbed = (): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> =>\n Promise.resolve(succeed([frag(0, 5, [])]));\n expect(await index.rebuild(source, emptyEmbed)).toFailWith(/empty fragment vector/i);\n expect(index.recordCount).toBe(0);\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"inMemoryFragmentCosineIndex.test.js","sourceRoot":"","sources":["../../../../src/test/unit/vector/inMemoryFragmentCosineIndex.test.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport '@fgv/ts-utils-jest';\nimport { Result, fail, succeed } from '@fgv/ts-utils';\nimport {\n IEdgeTarget,\n IEmbeddedFragment,\n IFragmentLocator,\n IMemoryRecord,\n IMemoryRecordSource,\n IScopedMemoryRecord,\n IVectorQueryHit,\n InMemoryFragmentCosineIndex,\n MemoryId,\n MemoryScopeKey\n} from '../../../index';\n\n/** A scope-qualified target from a `(scope, id)` pair. */\nfunction target(scope: string, id: string): IEdgeTarget {\n return { scope: scope as MemoryScopeKey, id: id as MemoryId };\n}\n\n/** A locator over an arbitrary `[start, end)` span (opaque to the index). */\nfunction loc(start: number, end: number): IFragmentLocator {\n return { start, end };\n}\n\n/** An embedded fragment from a locator + a raw vector. */\nfunction frag(start: number, end: number, vector: number[]): IEmbeddedFragment {\n return { locator: loc(start, end), vector: Float32Array.from(vector) };\n}\n\n/** A trivial record carrying just the id + a marker body, for rebuild tests. */\nfunction record(id: string, body: string = `body-${id}`): IMemoryRecord<unknown> {\n return {\n envelope: { id: id as MemoryId } as IMemoryRecord<unknown>['envelope'],\n body\n };\n}\n\n/** A scope-qualified record entry for a rebuild source. */\nfunction scoped(scope: string, id: string, body?: string): IScopedMemoryRecord {\n return { target: target(scope, id), record: record(id, body) };\n}\n\n/** A scripted record source for `rebuild`. */\nclass FakeSource implements IMemoryRecordSource {\n private readonly _result: Result<ReadonlyArray<IScopedMemoryRecord>>;\n public constructor(result: Result<ReadonlyArray<IScopedMemoryRecord>>) {\n this._result = result;\n }\n public list(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>> {\n return Promise.resolve(this._result);\n }\n}\n\ndescribe('InMemoryFragmentCosineIndex', () => {\n describe('addFragments', () => {\n test('stores every fragment and reports the count; tracks record/fragment counts', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])).toSucceedWith(2);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(2);\n });\n\n test('whole-record replace — a second addFragments drops the prior fragments', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])).toSucceedWith(2);\n // Re-author with a single fragment: the old two must be gone.\n expect(await index.addFragments(t, [frag(0, 3, [1, 1])])).toSucceedWith(1);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(1);\n expect(await index.query(Float32Array.from([1, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(1);\n expect(hits[0].locator).toEqual(loc(0, 3));\n }\n );\n });\n\n test('an empty fragments array drops the record entirely', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n expect(await index.addFragments(t, [frag(0, 5, [1, 0])])).toSucceedWith(1);\n expect(await index.addFragments(t, [])).toSucceedWith(0);\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n });\n\n test('same stem in different scopes are distinct entries', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('conv-a', 'turn-3');\n const b = target('conv-b', 'turn-3');\n expect(await index.addFragments(a, [frag(0, 5, [1, 0])])).toSucceedWith(1);\n expect(await index.addFragments(b, [frag(0, 5, [0, 1])])).toSucceedWith(1);\n expect(index.recordCount).toBe(2);\n expect(await index.query(Float32Array.from([1, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.target)).toEqual(expect.arrayContaining([a, b]));\n }\n );\n });\n\n test('fails loudly on an empty fragment vector — and does not partially store', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'doc-1');\n // First fragment is fine, second is empty: whole-record-replace must be all-or-nothing.\n expect(await index.addFragments(t, [frag(0, 5, [1, 0]), frag(5, 10, [])])).toFailWith(\n /empty fragment vector/i\n );\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n });\n\n test('fails loudly on a fragment-dimension mismatch against the established dimension', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(await index.addFragments(target('knowledge', 'a'), [frag(0, 5, [1, 0])])).toSucceed();\n expect(await index.addFragments(target('knowledge', 'b'), [frag(0, 5, [1, 0, 0])])).toFailWith(\n /fragment dimension 3 does not match index dimension 2/i\n );\n });\n\n test('a failed multi-fragment add on a fresh index does not establish a dimension (all-or-nothing)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n // Batch: first fragment (dim 2) would set the dimension, second (dim 3) fails\n // the check. The failed add must leave the index wholly dimensionless — not\n // half-committed to dim 2 — so a later legitimate dim-3 add still succeeds.\n expect(\n await index.addFragments(target('knowledge', 'doc-1'), [frag(0, 5, [1, 0]), frag(5, 10, [1, 0, 0])])\n ).toFailWith(/fragment dimension 3 does not match index dimension 2/i);\n expect(index.recordCount).toBe(0);\n expect(index.fragmentCount).toBe(0);\n // The dimension was never committed: a fresh dim-3 record indexes cleanly.\n expect(await index.addFragments(target('knowledge', 'doc-2'), [frag(0, 5, [1, 0, 0])])).toSucceedWith(\n 1\n );\n expect(await index.query(Float32Array.from([1, 0, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].target.id).toBe('doc-2');\n expect(hits[0].score).toBeCloseTo(1);\n }\n );\n });\n\n test('stores a defensive copy — mutating the caller buffer after add does not corrupt the index', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const buffer = Float32Array.from([1, 0]);\n (\n await index.addFragments(target('knowledge', 'doc-1'), [{ locator: loc(0, 5), vector: buffer }])\n ).orThrow();\n buffer[0] = 0;\n buffer[1] = 1;\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].score).toBeCloseTo(1);\n }\n );\n });\n });\n\n describe('query', () => {\n async function seeded(): Promise<InMemoryFragmentCosineIndex> {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc-a'), [frag(0, 5, [1, 0]), frag(5, 10, [0, 1])])\n ).orThrow();\n (await index.addFragments(target('knowledge', 'doc-b'), [frag(0, 5, [1, 1])])).orThrow();\n return index;\n }\n\n test('returns fragment hits in descending cosine-similarity order, each carrying its locator', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 3)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n // doc-a[0,5] matches [1,0] best (score 1), then doc-b (1/sqrt2), then doc-a[5,10] (0).\n expect(hits[0].target.id).toBe('doc-a');\n expect(hits[0].locator).toEqual(loc(0, 5));\n expect(hits[0].score).toBeCloseTo(1);\n expect(hits[1].target.id).toBe('doc-b');\n expect(hits[1].score).toBeCloseTo(1 / Math.sqrt(2));\n expect(hits[2].target.id).toBe('doc-a');\n expect(hits[2].locator).toEqual(loc(5, 10));\n expect(hits[2].score).toBeCloseTo(0);\n }\n );\n });\n\n test('truncates to topK', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.locator)).toEqual([loc(0, 5), loc(0, 5)]);\n expect(hits[0].target.id).toBe('doc-a');\n expect(hits[1].target.id).toBe('doc-b');\n }\n );\n });\n\n test('maxPerRecord caps fragments per record during selection (before the topK cut)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n // doc-a has three fragments that all beat doc-b's single fragment.\n (\n await index.addFragments(target('knowledge', 'doc-a'), [\n frag(0, 5, [1, 0]),\n frag(5, 10, [0.9, 0.1]),\n frag(10, 15, [0.8, 0.2])\n ])\n ).orThrow();\n (await index.addFragments(target('knowledge', 'doc-b'), [frag(0, 5, [0.7, 0.3])])).orThrow();\n // Without a cap, top-2 would be doc-a twice. With maxPerRecord=1, doc-b surfaces.\n expect(await index.query(Float32Array.from([1, 0]), 2, 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(2);\n expect(hits.map((h) => h.target.id)).toEqual(['doc-a', 'doc-b']);\n expect(hits[0].locator).toEqual(loc(0, 5));\n }\n );\n });\n\n test('maxPerRecord=0 yields no hits', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 5, 0)).toSucceedWith([]);\n });\n\n test('maxPerRecord larger than any record leaves the ranking unchanged', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 5, 10)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(3);\n expect(hits[0].target.id).toBe('doc-a');\n }\n );\n });\n\n test('returns empty for a non-positive topK', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0]), 0)).toSucceedWith([]);\n expect(await index.query(Float32Array.from([1, 0]), -1)).toSucceedWith([]);\n });\n\n test('returns empty when the index is empty (no dimension check)', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(await index.query(Float32Array.from([1, 2, 3, 4]), 5)).toSucceedWith([]);\n });\n\n test('fails loudly on a query-dimension mismatch', async () => {\n const index = await seeded();\n expect(await index.query(Float32Array.from([1, 0, 0]), 3)).toFailWith(\n /query dimension 3 does not match index dimension 2/i\n );\n });\n\n test('scores a degenerate (zero-magnitude) stored fragment as 0 rather than NaN', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc'), [frag(0, 5, [0, 0]), frag(5, 10, [1, 0])])\n ).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits.map((h) => h.locator)).toEqual([loc(5, 10), loc(0, 5)]);\n expect(hits[1].score).toBe(0);\n }\n );\n });\n\n test('scores against a degenerate (zero-magnitude) query as 0 rather than NaN', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'doc'), [frag(0, 5, [1, 0])])).orThrow();\n expect(await index.query(Float32Array.from([0, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].score).toBe(0);\n }\n );\n });\n });\n\n describe('remove', () => {\n test('removes every fragment of a record and is reflected in subsequent queries', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('knowledge', 'doc-a');\n const b = target('knowledge', 'doc-b');\n (await index.addFragments(a, [frag(0, 5, [1, 0]), frag(5, 10, [1, 0])])).orThrow();\n (await index.addFragments(b, [frag(0, 5, [0, 1])])).orThrow();\n expect(await index.remove(a)).toSucceedWith(a);\n expect(index.recordCount).toBe(1);\n expect(index.fragmentCount).toBe(1);\n expect(await index.query(Float32Array.from([1, 0]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits.map((h) => h.target.id)).toEqual(['doc-b']);\n }\n );\n });\n\n test('removes only the scoped target — a same-stem record in another scope is left intact', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const a = target('conv-a', 'turn-3');\n const b = target('conv-b', 'turn-3');\n (await index.addFragments(a, [frag(0, 5, [1, 0])])).orThrow();\n (await index.addFragments(b, [frag(0, 5, [0, 1])])).orThrow();\n expect(await index.remove(a)).toSucceedWith(a);\n expect(index.recordCount).toBe(1);\n expect(await index.query(Float32Array.from([0, 1]), 5)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits).toHaveLength(1);\n expect(hits[0].target).toEqual(b);\n }\n );\n });\n\n test('is idempotent — removing an absent target still succeeds', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const t = target('knowledge', 'missing');\n expect(await index.remove(t)).toSucceedWith(t);\n });\n });\n\n describe('rebuild', () => {\n // Deterministic: each record yields two fragments encoding the id's first char code.\n const embed = (r: IMemoryRecord<unknown>): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> => {\n const code: number = (r.envelope.id as string).charCodeAt(0);\n return Promise.resolve(succeed([frag(0, 5, [code, 1]), frag(5, 10, [1, code])]));\n };\n\n test('re-embeds every scoped record and reports the total fragment count', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a'), scoped('knowledge', 'b')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(4);\n expect(index.recordCount).toBe(2);\n expect(index.fragmentCount).toBe(4);\n });\n\n test('keeps same-stem records under different scopes distinct across a rebuild', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('conv-a', 'turn-3'), scoped('conv-b', 'turn-3')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(4);\n expect(index.recordCount).toBe(2);\n });\n\n test('clears prior contents and re-establishes the dimension', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'old'), [frag(0, 5, [1, 2, 3])])).orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a')]));\n expect(await index.rebuild(source, embed)).toSucceedWith(2);\n expect(index.recordCount).toBe(1);\n expect(await index.query(Float32Array.from([97, 1]), 1)).toSucceed();\n });\n\n test('fails loudly when the source list fails and rolls back to empty', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'seed'), [frag(0, 5, [1, 1])])).orThrow();\n const source = new FakeSource(fail('disk gone'));\n expect(await index.rebuild(source, embed)).toFailWith(/failed to list records: disk gone/i);\n expect(index.recordCount).toBe(0);\n });\n\n test('fails loudly and rolls back to empty when an embedding fails mid-rebuild', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'seed'), [frag(0, 5, [1, 1])])).orThrow();\n let calls: number = 0;\n const flakyEmbed = (): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> => {\n calls += 1;\n return Promise.resolve(calls === 1 ? succeed([frag(0, 5, [1, 1])]) : fail('no model'));\n };\n const source = new FakeSource(succeed([scoped('conv-a', 'turn-1'), scoped('conv-b', 'turn-1')]));\n expect(await index.rebuild(source, flakyEmbed)).toFailWith(\n /embedding 'conv-b\\0turn-1' failed: no model/i\n );\n expect(index.recordCount).toBe(0);\n });\n\n test('fails loudly and rolls back to empty when adding an embedded fragment fails', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const source = new FakeSource(succeed([scoped('knowledge', 'a')]));\n const emptyEmbed = (): Promise<Result<ReadonlyArray<IEmbeddedFragment>>> =>\n Promise.resolve(succeed([frag(0, 5, [])]));\n expect(await index.rebuild(source, emptyEmbed)).toFailWith(/empty fragment vector/i);\n expect(index.recordCount).toBe(0);\n });\n });\n\n describe('fragment identity', () => {\n /** A fragment identified only by an opaque id — no honest body span. */\n function idFrag(fragmentId: string, vector: number[]): IEmbeddedFragment {\n return { fragmentId, vector: Float32Array.from(vector) };\n }\n\n test('rejects a fragment carrying neither a locator nor a fragmentId', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n expect(\n await index.addFragments(target('knowledge', 'doc-a'), [{ vector: Float32Array.from([1, 0]) }])\n ).toFailWith(/at least one of 'locator' or 'fragmentId'/i);\n expect(index.recordCount).toBe(0);\n });\n\n test('carries an opaque fragmentId through to the query hit verbatim', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n const opaque = 'urn:frag:9f8e::{not-parsed}';\n (await index.addFragments(target('knowledge', 'doc-a'), [idFrag(opaque, [1, 0])])).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].fragmentId).toBe(opaque);\n expect(hits[0].locator).toBeUndefined();\n }\n );\n });\n\n test('carries both identities when a fragment supplies both', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc-a'), [\n { ...frag(2, 8, [1, 0]), fragmentId: 'frag-1' }\n ])\n ).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].locator).toEqual(loc(2, 8));\n expect(hits[0].fragmentId).toBe('frag-1');\n }\n );\n });\n\n test('a locator-only fragment produces a hit with no fragmentId key at all', async () => {\n // Byte-identical to what the index produced before `fragmentId` existed: the key\n // is absent, not present-and-undefined, so an existing caller's structural\n // comparisons are unaffected by the addition.\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'doc-a'), [frag(0, 5, [1, 0])])).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(Object.keys(hits[0]).sort()).toEqual(['locator', 'score', 'target']);\n expect(hits[0]).toStrictEqual({\n target: target('knowledge', 'doc-a'),\n score: hits[0].score,\n locator: loc(0, 5)\n });\n }\n );\n });\n\n test('an id-only fragment produces a hit with no locator key at all', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (await index.addFragments(target('knowledge', 'doc-a'), [idFrag('frag-1', [1, 0])])).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 1)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(Object.keys(hits[0]).sort()).toEqual(['fragmentId', 'score', 'target']);\n }\n );\n });\n\n test('mixes identity shapes within one record and within one query', async () => {\n const index = InMemoryFragmentCosineIndex.create().orThrow();\n (\n await index.addFragments(target('knowledge', 'doc-a'), [\n frag(0, 5, [1, 0]),\n idFrag('frag-rewritten', [0, 1])\n ])\n ).orThrow();\n expect(await index.query(Float32Array.from([1, 0]), 2)).toSucceedAndSatisfy(\n (hits: ReadonlyArray<IVectorQueryHit>) => {\n expect(hits[0].locator).toEqual(loc(0, 5));\n expect(hits[0].fragmentId).toBeUndefined();\n expect(hits[1].fragmentId).toBe('frag-rewritten');\n expect(hits[1].locator).toBeUndefined();\n }\n );\n });\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-agent-memory",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-46",
|
|
4
4
|
"description": "FileTree-backed storage and retrieval substrate for agent memory and knowledge",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "dist/ts-agent-memory.d.ts",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"tslib": "^2.8.1",
|
|
38
|
-
"@fgv/ts-json
|
|
39
|
-
"@fgv/ts-
|
|
40
|
-
"@fgv/ts-utils": "5.1.0-
|
|
41
|
-
"@fgv/ts-
|
|
38
|
+
"@fgv/ts-json": "5.1.0-46",
|
|
39
|
+
"@fgv/ts-json-base": "5.1.0-46",
|
|
40
|
+
"@fgv/ts-utils": "5.1.0-46",
|
|
41
|
+
"@fgv/ts-extras": "5.1.0-46"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@microsoft/api-extractor": "^7.55.2",
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"@rushstack/heft-node-rig": "2.11.27",
|
|
66
66
|
"@types/heft-jest": "1.0.6",
|
|
67
67
|
"eslint-plugin-tsdoc": "~0.5.2",
|
|
68
|
-
"@fgv/heft-dual-rig": "5.1.0-
|
|
69
|
-
"@fgv/ts-utils-jest": "5.1.0-
|
|
68
|
+
"@fgv/heft-dual-rig": "5.1.0-46",
|
|
69
|
+
"@fgv/ts-utils-jest": "5.1.0-46"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "heft build --clean",
|
|
@@ -5,5 +5,5 @@ Invoking: heft build --clean
|
|
|
5
5
|
[build:lint] Using ESLint version 9.39.5
|
|
6
6
|
[build:api-extractor] Using API Extractor version 7.58.9
|
|
7
7
|
[build:api-extractor] Analysis will use the bundled TypeScript version 5.9.3
|
|
8
|
-
---- build finished (
|
|
9
|
-
-------------------- Finished (
|
|
8
|
+
---- build finished (28.708s) ----
|
|
9
|
+
-------------------- Finished (28.714s) --------------------
|
|
@@ -60,16 +60,19 @@ export interface IFragmentRetrieverCapabilities {
|
|
|
60
60
|
* The sub-document semantic-search retriever — the "discovery" half of a
|
|
61
61
|
* search-then-read contract. It embeds a fragment query, queries the
|
|
62
62
|
* {@link IFragmentVectorIndex}, and returns the raw per-fragment
|
|
63
|
-
* {@link IVectorQueryHit | hits} (each carrying a record `target` AND
|
|
64
|
-
* `locator`
|
|
65
|
-
*
|
|
63
|
+
* {@link IVectorQueryHit | hits} (each carrying a record `target` AND whichever of
|
|
64
|
+
* `locator` / `fragmentId` the stored fragment was indexed with), NOT resolved
|
|
65
|
+
* records: the consumer re-reads each record and resolves the fragment on its own
|
|
66
|
+
* read side. Note the `locator` span is advisory — see {@link IFragmentLocator}; it
|
|
67
|
+
* is not a slice guaranteed to reproduce the fragment's text.
|
|
66
68
|
*
|
|
67
69
|
* @remarks
|
|
68
70
|
* Deliberately NOT an {@link IMemoryRetriever}: memory recall is record-granular and
|
|
69
|
-
* returns records; fragment discovery is
|
|
70
|
-
* it a distinct surface matches the consumer contract (memory
|
|
71
|
-
* sub-document knowledge uses a separate fragment index) and
|
|
72
|
-
* record retriever's return type with
|
|
71
|
+
* returns records; fragment discovery is fragment-granular and returns fragment
|
|
72
|
+
* identities. Keeping it a distinct surface matches the consumer contract (memory
|
|
73
|
+
* stays record-granular; sub-document knowledge uses a separate fragment index) and
|
|
74
|
+
* avoids overloading the record retriever's return type with identity fields that
|
|
75
|
+
* only make sense here.
|
|
73
76
|
*
|
|
74
77
|
* When no backend is wired, `supportsFragmentRecall` is `false` and any fragment
|
|
75
78
|
* query degrades loudly ({@link FRAGMENT_SEMANTIC_UNWIRED_MESSAGE}) — it NEVER
|
|
@@ -194,6 +194,59 @@ export interface IFileTreeMemoryStoreCreateParams {
|
|
|
194
194
|
readonly rankProjectors?: ReadonlyMap<Kind, RankProjector>;
|
|
195
195
|
/** Default codec for kinds without an explicit entry. */
|
|
196
196
|
readonly defaultCodec?: IIdentityCodec;
|
|
197
|
+
/**
|
|
198
|
+
* Optional derived-index implementation. Defaults to a fresh {@link MemoryIndex} —
|
|
199
|
+
* omitting this parameter is byte-identical to the store's behavior before the
|
|
200
|
+
* parameter existed. When supplied, the store uses it for EVERY index operation
|
|
201
|
+
* it performs and never holds a second index, so an injected index is the store's
|
|
202
|
+
* only view of its own records:
|
|
203
|
+
*
|
|
204
|
+
* - `rebuild` — once, from the initial vault walk in `create()`.
|
|
205
|
+
* - `patch` — on every persisted write, delete, version invalidation, and
|
|
206
|
+
* cap-cull eviction.
|
|
207
|
+
* - `entries` — behind {@link IMemoryStore.list | list} /
|
|
208
|
+
* {@link IMemoryStore.listScoped | listScoped}, the keyed temporal reads, the
|
|
209
|
+
* write path's content-hash dedup and write-policy admission cohort, AND the
|
|
210
|
+
* temporal (versioned) write and delete paths, which resolve an entity's
|
|
211
|
+
* version history entirely from the index.
|
|
212
|
+
*
|
|
213
|
+
* That last group is the one to weigh before injecting anything other than a
|
|
214
|
+
* pass-through decorator: an index that filters, reorders, or otherwise reshapes
|
|
215
|
+
* `entries()` changes WRITE semantics, not just what reads return. Concretely,
|
|
216
|
+
* on a versioned kind the store derives an entity's whole version history from
|
|
217
|
+
* `entries()` filtered by scope, and that derivation decides which version a
|
|
218
|
+
* `put` treats as current (so what it dedups against and what it merges its
|
|
219
|
+
* patch over), which prior versions it stamps `invalid_at` on, what the
|
|
220
|
+
* admission cohort is, and which versions a `delete` tombstones. An index that
|
|
221
|
+
* hides a version makes it invisible to all of those — the FileTree still holds
|
|
222
|
+
* it, but the store will not supersede, invalidate, or tombstone it. On flat
|
|
223
|
+
* kinds the same reshaping changes what dedups and what a cap-cull policy
|
|
224
|
+
* evicts. A faithful delegating decorator — the intended use below — has no such
|
|
225
|
+
* effect. Note the store's keyed reads ({@link IMemoryStore.get | get} on a flat
|
|
226
|
+
* kind, and {@link IMemoryStore.getById | getById}) go to the FileTree, not the
|
|
227
|
+
* index; the FileTree remains the source of truth and the index stays a derived
|
|
228
|
+
* view.
|
|
229
|
+
*
|
|
230
|
+
* @remarks
|
|
231
|
+
* **This is an instrumentation seam, NOT a resident-memory fix.** The intended
|
|
232
|
+
* use is wrapping the shipped {@link MemoryIndex} in a decorator that counts and
|
|
233
|
+
* times the calls the store makes — resident bytes by kind, open cost against
|
|
234
|
+
* vault size, where the curve actually bends — so a decision about a partial-read
|
|
235
|
+
* redesign can be driven by measurements instead of estimates.
|
|
236
|
+
*
|
|
237
|
+
* It does NOT lower the store's resident-memory ceiling, and injecting a
|
|
238
|
+
* "persisted" or "lazy" index will not change that. {@link IMemoryIndex}'s read
|
|
239
|
+
* surface returns whole records by construction: `entries()` yields
|
|
240
|
+
* {@link IIndexedMemoryRecord}s and `byKind` / `byTag` / `byRecency` / `byRank`
|
|
241
|
+
* yield `IMemoryRecord<unknown>` — `{ envelope, body }` pairs with the body
|
|
242
|
+
* materialized. Any implementation satisfying the current contract must therefore
|
|
243
|
+
* be able to produce every body on demand. An injected index changes WHERE records
|
|
244
|
+
* come from; it does not change WHETHER bodies are held. Lowering the ceiling
|
|
245
|
+
* requires a partial-read (id-or-envelope-only) redesign of `IMemoryIndex` itself,
|
|
246
|
+
* which is separate, breaking, design-first work and is deliberately not part of
|
|
247
|
+
* this seam.
|
|
248
|
+
*/
|
|
249
|
+
readonly index?: IMemoryIndex;
|
|
197
250
|
/** Scope encoding. Defaults to {@link defaultMemoryScopeEncoding}. */
|
|
198
251
|
readonly scopeEncoding?: (scope: MemoryScopeKey) => Result<string>;
|
|
199
252
|
/**
|
|
@@ -412,13 +465,15 @@ export class FileTreeMemoryStore implements IMemoryStore {
|
|
|
412
465
|
}
|
|
413
466
|
|
|
414
467
|
/**
|
|
415
|
-
* Family-convention factory.
|
|
416
|
-
*
|
|
417
|
-
*
|
|
468
|
+
* Family-convention factory. Resolves the derived index (the caller's
|
|
469
|
+
* {@link IFileTreeMemoryStoreCreateParams.index | index} when supplied, a fresh
|
|
470
|
+
* {@link MemoryIndex} otherwise) and a default LWW policy, then performs an
|
|
471
|
+
* initial FileTree walk so an existing vault is indexed (and the `seq` counter
|
|
472
|
+
* resumes past the highest persisted `seq`).
|
|
418
473
|
*/
|
|
419
474
|
public static create(params: IFileTreeMemoryStoreCreateParams): Result<FileTreeMemoryStore> {
|
|
420
475
|
return KnowledgeLwwPolicy.create().onSuccess((defaultPolicy) =>
|
|
421
|
-
|
|
476
|
+
FileTreeMemoryStore._resolveIndex(params.index).onSuccess((index) => {
|
|
422
477
|
const store: FileTreeMemoryStore = new FileTreeMemoryStore({
|
|
423
478
|
root: params.root,
|
|
424
479
|
registry: params.registry,
|
|
@@ -442,6 +497,21 @@ export class FileTreeMemoryStore implements IMemoryStore {
|
|
|
442
497
|
);
|
|
443
498
|
}
|
|
444
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Resolve the derived index for a `create()`: the caller's injected
|
|
502
|
+
* {@link IMemoryIndex} verbatim, or a fresh {@link MemoryIndex} when none was
|
|
503
|
+
* supplied (the default that keeps an omitting caller byte-identical).
|
|
504
|
+
*/
|
|
505
|
+
private static _resolveIndex(index: IMemoryIndex | undefined): Result<IMemoryIndex> {
|
|
506
|
+
// Nullish rather than strictly-undefined, matching how every sibling optional
|
|
507
|
+
// param in `create()` handles absence (`params.codecs ?? new Map()`, and so on).
|
|
508
|
+
// A JS caller — or a TS caller arriving through an `unknown` escape hatch —
|
|
509
|
+
// passing `null` otherwise gets `null` installed as the store's index and fails
|
|
510
|
+
// later inside `entries()` with a message that names neither the param nor the
|
|
511
|
+
// cause.
|
|
512
|
+
return index ? succeed(index) : MemoryIndex.create();
|
|
513
|
+
}
|
|
514
|
+
|
|
445
515
|
/** {@inheritDoc IMemoryStore.get} */
|
|
446
516
|
public async get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>> {
|
|
447
517
|
const result: Result<IMemoryRecord<unknown> | undefined> = this._codecFor(kind).onSuccess((codec) =>
|
|
@@ -90,6 +90,27 @@ export interface IWritePolicy {
|
|
|
90
90
|
* record. Called when admission is `accept` AND a record with the same
|
|
91
91
|
* `entityId` already exists (an update, not a first write).
|
|
92
92
|
*
|
|
93
|
+
* @remarks
|
|
94
|
+
* **RFC-7386 semantics are the contract here, not an artifact of the shipped
|
|
95
|
+
* policies' merge configuration.** Implementations are expected to honor them,
|
|
96
|
+
* and consumers may rely on them:
|
|
97
|
+
*
|
|
98
|
+
* - **Objects merge per key.** A supplied key overwrites; an omitted key is
|
|
99
|
+
* PRESERVED, not dropped. Patching one key of a nested object (e.g. one
|
|
100
|
+
* field of `provenance`) leaves its siblings intact.
|
|
101
|
+
* - **An explicit `null` on a sub-key clears exactly that sub-key.** This is
|
|
102
|
+
* the sanctioned way to remove a single key from a nested object.
|
|
103
|
+
* - **Arrays replace wholesale** — `tags` / `links` are never element-merged.
|
|
104
|
+
* - **A whole-block `null` that would delete a REQUIRED field is rejected
|
|
105
|
+
* loudly** (`Result.fail`), never silently accepted. `body` / `tags` /
|
|
106
|
+
* `links` / `provenance` are required; `embeddingRef` is optional and a
|
|
107
|
+
* `null` restores it to absent (NOT to `null`), so it stays hash-stable.
|
|
108
|
+
*
|
|
109
|
+
* Which fields these guarantees cover is **policy-dependent**: they apply to
|
|
110
|
+
* the fields the policy declares in {@link IWritePolicy.mutableFields}, and a
|
|
111
|
+
* field outside that list is inert — its patch key is dropped before the merge,
|
|
112
|
+
* so a `null` on it neither clears the value nor raises an error.
|
|
113
|
+
*
|
|
93
114
|
* @param existing - The current persisted record.
|
|
94
115
|
* @param patch - A partial JSON object in Merge Patch format. `null`
|
|
95
116
|
* deletes the corresponding key; arrays replace wholesale; nested objects
|
|
@@ -133,13 +154,21 @@ const MERGE_PATCH_OPTIONS: Partial<IJsonEditorOptions> = {
|
|
|
133
154
|
* view, runs the merge over that view, then rebuilds a coherent record. The
|
|
134
155
|
* identity and transaction-time envelope fields (`id`, `entityId`, `kind`,
|
|
135
156
|
* `created`, `updated`, `seq`, `contentHash`) are NOT mutable and are
|
|
136
|
-
* preserved verbatim; the store stamps `updated` / `seq` on write.
|
|
157
|
+
* preserved verbatim; the store stamps `updated` / `seq` / `contentHash` on write.
|
|
158
|
+
*
|
|
159
|
+
* Because the surface is pinned rather than caller-supplied, the RFC-7386
|
|
160
|
+
* guarantees documented on {@link IWritePolicy.applyUpdate} apply to every field
|
|
161
|
+
* listed above — in particular to `provenance`, whose keys merge individually, a
|
|
162
|
+
* `null` on any one of which clears that key alone, and a `null` on the whole
|
|
163
|
+
* block of which is rejected loudly (it is a required field). Consumers may
|
|
164
|
+
* depend on this; it is covered by tests.
|
|
137
165
|
* @public
|
|
138
166
|
*/
|
|
139
167
|
export class KnowledgeLwwPolicy implements IWritePolicy {
|
|
140
168
|
/**
|
|
141
169
|
* The knowledge mutable surface: the body plus the envelope metadata a
|
|
142
|
-
* consumer may revise without minting a new entity.
|
|
170
|
+
* consumer may revise without minting a new entity. Pinned, not
|
|
171
|
+
* caller-supplied — see the class remarks for what that guarantees.
|
|
143
172
|
*/
|
|
144
173
|
public readonly mutableFields: ReadonlyArray<string> = [
|
|
145
174
|
'body',
|
|
@@ -271,6 +300,15 @@ export interface IMemoryCapCullPolicyParams {
|
|
|
271
300
|
* The fields a merge-patch update may touch (drawn from the record-level
|
|
272
301
|
* mutable vocabulary: `body` / `tags` / `links` / `provenance` /
|
|
273
302
|
* `embeddingRef`). Fields outside this list are immutable.
|
|
303
|
+
*
|
|
304
|
+
* @remarks
|
|
305
|
+
* This list — unlike {@link KnowledgeLwwPolicy}'s pinned surface — is
|
|
306
|
+
* caller-supplied, so it is what decides which fields get the RFC-7386
|
|
307
|
+
* guarantees documented on {@link IWritePolicy.applyUpdate}. Declare
|
|
308
|
+
* `provenance` here to get per-key provenance merging and `null` sub-key
|
|
309
|
+
* clearing; omit it and every provenance patch key is inert (dropped before
|
|
310
|
+
* the merge, so the existing value is preserved verbatim and even a
|
|
311
|
+
* whole-block `null` is a silent no-op rather than an error).
|
|
274
312
|
*/
|
|
275
313
|
readonly mutableFields: ReadonlyArray<string>;
|
|
276
314
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Erik Fortune
|
|
3
|
+
* SPDX-License-Identifier: MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Converter, Converters, Result, fail, succeed } from '@fgv/ts-utils';
|
|
7
|
+
import { IEmbeddedFragment, IFragmentLocator } from './vectorIndex';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converter for an {@link IFragmentLocator}. Validates the two offsets only — the
|
|
11
|
+
* span's *meaning* (character / byte / token unit) is the consumer's, and the index
|
|
12
|
+
* never interprets it. Note the span is advisory: see {@link IFragmentLocator}.
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
export const fragmentLocatorConverter: Converter<IFragmentLocator> = Converters.object<IFragmentLocator>({
|
|
16
|
+
start: Converters.number,
|
|
17
|
+
end: Converters.number
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
/** Validates an already-constructed `Float32Array` embedding vector in place. */
|
|
21
|
+
const embeddingVectorConverter: Converter<Float32Array> = Converters.generic<Float32Array>(
|
|
22
|
+
(from: unknown): Result<Float32Array> =>
|
|
23
|
+
from instanceof Float32Array ? succeed(from) : fail('embedded fragment: vector must be a Float32Array')
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
/** The field-shape half of {@link embeddedFragmentConverter}; the invariant is layered on top. */
|
|
27
|
+
const embeddedFragmentFieldsConverter: Converter<IEmbeddedFragment> = Converters.object<IEmbeddedFragment>(
|
|
28
|
+
{
|
|
29
|
+
locator: fragmentLocatorConverter.optional(),
|
|
30
|
+
fragmentId: Converters.string.optional(),
|
|
31
|
+
vector: embeddingVectorConverter
|
|
32
|
+
},
|
|
33
|
+
{ optionalFields: ['locator', 'fragmentId'] }
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Converter for an {@link IEmbeddedFragment}, and the boundary that enforces the
|
|
38
|
+
* fragment-identifiability invariant: **at least one of `locator` / `fragmentId`
|
|
39
|
+
* must be present.**
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* The invariant lives here rather than in the type. A conditional-required union
|
|
43
|
+
* (`{ locator; fragmentId? } | { locator?; fragmentId }`) was considered and
|
|
44
|
+
* declined: it costs at every construction site and buys nothing at the read site,
|
|
45
|
+
* where each field reads as `… | undefined` either way. What it must not cost is
|
|
46
|
+
* identifiability — a fragment carrying neither identity cannot be resolved back to
|
|
47
|
+
* anything by a consumer holding the query hit, so it is rejected here.
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export const embeddedFragmentConverter: Converter<IEmbeddedFragment> =
|
|
51
|
+
embeddedFragmentFieldsConverter.withConstraint((fragment: IEmbeddedFragment) =>
|
|
52
|
+
fragment.locator === undefined && fragment.fragmentId === undefined
|
|
53
|
+
? fail('embedded fragment: at least one of `locator` or `fragmentId` is required')
|
|
54
|
+
: succeed(fragment)
|
|
55
|
+
);
|
|
@@ -8,16 +8,31 @@ import { IEdgeTarget, edgeTargetKey } from '../types';
|
|
|
8
8
|
import {
|
|
9
9
|
FragmentEmbedder,
|
|
10
10
|
IEmbeddedFragment,
|
|
11
|
-
IFragmentLocator,
|
|
12
11
|
IFragmentVectorIndex,
|
|
13
12
|
IMemoryRecordSource,
|
|
14
13
|
IScopedMemoryRecord,
|
|
15
14
|
IVectorQueryHit
|
|
16
15
|
} from './vectorIndex';
|
|
17
16
|
|
|
18
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* The identity fields a fragment was added with, already in query-hit shape: a field
|
|
19
|
+
* the fragment did not carry is *absent*, never present-but-`undefined`, so a hit
|
|
20
|
+
* for a fragment added without a `fragmentId` is structurally identical to one
|
|
21
|
+
* produced before `fragmentId` existed.
|
|
22
|
+
*/
|
|
23
|
+
type FragmentIdentity = Pick<IVectorQueryHit, 'locator' | 'fragmentId'>;
|
|
24
|
+
|
|
25
|
+
/** Project an incoming fragment's identity fields, dropping the ones it did not carry. */
|
|
26
|
+
function fragmentIdentity(fragment: IEmbeddedFragment): FragmentIdentity {
|
|
27
|
+
return {
|
|
28
|
+
...(fragment.locator !== undefined ? { locator: fragment.locator } : {}),
|
|
29
|
+
...(fragment.fragmentId !== undefined ? { fragmentId: fragment.fragmentId } : {})
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** One stored fragment: the identity it was added with plus its vector. */
|
|
19
34
|
interface IStoredFragment {
|
|
20
|
-
readonly
|
|
35
|
+
readonly identity: FragmentIdentity;
|
|
21
36
|
readonly vector: Float32Array;
|
|
22
37
|
}
|
|
23
38
|
|
|
@@ -36,9 +51,11 @@ interface IScoredFragment {
|
|
|
36
51
|
/**
|
|
37
52
|
* The brute-force, in-memory cosine {@link IFragmentVectorIndex} — the
|
|
38
53
|
* fragment-granular sibling of {@link InMemoryCosineIndex}. Stores many
|
|
39
|
-
* `Float32Array`s per record (one per
|
|
40
|
-
*
|
|
41
|
-
*
|
|
54
|
+
* `Float32Array`s per record (one per {@link IEmbeddedFragment | fragment}) and
|
|
55
|
+
* answers a query by computing cosine similarity against every stored fragment,
|
|
56
|
+
* returning the top-k fragment hits by descending score. Each hit carries back
|
|
57
|
+
* whichever of {@link IFragmentLocator | locator} / `fragmentId` its fragment was
|
|
58
|
+
* added with; a fragment must carry at least one of the two.
|
|
42
59
|
*
|
|
43
60
|
* @remarks
|
|
44
61
|
* Same regime and same non-goals as {@link InMemoryCosineIndex}: no external
|
|
@@ -108,6 +125,16 @@ export class InMemoryFragmentCosineIndex implements IFragmentVectorIndex {
|
|
|
108
125
|
if (fragment.vector.length === 0) {
|
|
109
126
|
return Promise.resolve(fail(`fragment index: cannot add '${key}': empty fragment vector`));
|
|
110
127
|
}
|
|
128
|
+
// A fragment carrying neither identity cannot be resolved back to anything by a
|
|
129
|
+
// consumer holding the hit — the same invariant `embeddedFragmentConverter`
|
|
130
|
+
// enforces at the untyped boundary, re-checked here at the index seam.
|
|
131
|
+
if (fragment.locator === undefined && fragment.fragmentId === undefined) {
|
|
132
|
+
return Promise.resolve(
|
|
133
|
+
fail(
|
|
134
|
+
`fragment index: cannot add '${key}': fragment requires at least one of 'locator' or 'fragmentId'`
|
|
135
|
+
)
|
|
136
|
+
);
|
|
137
|
+
}
|
|
111
138
|
if (dimension === undefined) {
|
|
112
139
|
dimension = fragment.vector.length;
|
|
113
140
|
} else if (fragment.vector.length !== dimension) {
|
|
@@ -118,7 +145,7 @@ export class InMemoryFragmentCosineIndex implements IFragmentVectorIndex {
|
|
|
118
145
|
);
|
|
119
146
|
}
|
|
120
147
|
// Defensive copy: the caller may reuse or mutate the buffer after `addFragments`.
|
|
121
|
-
stored.push({
|
|
148
|
+
stored.push({ identity: fragmentIdentity(fragment), vector: Float32Array.from(fragment.vector) });
|
|
122
149
|
}
|
|
123
150
|
// Whole-record replace: an empty `fragments` array drops the record entirely
|
|
124
151
|
// rather than leaving an empty shell behind. Commit the (possibly newly-derived)
|
|
@@ -163,7 +190,7 @@ export class InMemoryFragmentCosineIndex implements IFragmentVectorIndex {
|
|
|
163
190
|
hit: {
|
|
164
191
|
target: record.target,
|
|
165
192
|
score: InMemoryFragmentCosineIndex._cosine(vector, queryMagnitude, fragment.vector),
|
|
166
|
-
|
|
193
|
+
...fragment.identity
|
|
167
194
|
}
|
|
168
195
|
});
|
|
169
196
|
}
|