@equinor/fusion-framework-cli-plugin-ai-index 2.0.1 → 3.0.0
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/CHANGELOG.md +66 -0
- package/dist/esm/bin/apply-metadata.js +15 -5
- package/dist/esm/bin/apply-metadata.js.map +1 -1
- package/dist/esm/bin/apply-schema.js +64 -0
- package/dist/esm/bin/apply-schema.js.map +1 -0
- package/dist/esm/bin/apply-schema.test.js +143 -0
- package/dist/esm/bin/apply-schema.test.js.map +1 -0
- package/dist/esm/bin/delete-removed-files.js +1 -1
- package/dist/esm/bin/delete-removed-files.js.map +1 -1
- package/dist/esm/bin/embed.js +265 -55
- package/dist/esm/bin/embed.js.map +1 -1
- package/dist/esm/bin/get-diff.js +5 -0
- package/dist/esm/bin/get-diff.js.map +1 -1
- package/dist/esm/create-command.js +186 -0
- package/dist/esm/create-command.js.map +1 -0
- package/dist/esm/delete-command.js +14 -2
- package/dist/esm/delete-command.js.map +1 -1
- package/dist/esm/delete-command.options.js +7 -31
- package/dist/esm/delete-command.options.js.map +1 -1
- package/dist/esm/delete-index-command.js +94 -0
- package/dist/esm/delete-index-command.js.map +1 -0
- package/dist/esm/embed-command.js +30 -0
- package/dist/esm/embed-command.js.map +1 -0
- package/dist/esm/embeddings-command.js +14 -17
- package/dist/esm/embeddings-command.js.map +1 -1
- package/dist/esm/embeddings-command.options.js +12 -43
- package/dist/esm/embeddings-command.options.js.map +1 -1
- package/dist/esm/index.js +12 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/schema.js +41 -0
- package/dist/esm/schema.js.map +1 -0
- package/dist/esm/search-command.js +17 -5
- package/dist/esm/search-command.js.map +1 -1
- package/dist/esm/utils/embedding-dimensions.js +37 -0
- package/dist/esm/utils/embedding-dimensions.js.map +1 -0
- package/dist/esm/utils/zod-to-azure-fields.js +120 -0
- package/dist/esm/utils/zod-to-azure-fields.js.map +1 -0
- package/dist/esm/utils/zod-to-azure-fields.test.js +112 -0
- package/dist/esm/utils/zod-to-azure-fields.test.js.map +1 -0
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/bin/apply-metadata.d.ts +2 -1
- package/dist/types/bin/apply-schema.d.ts +22 -0
- package/dist/types/bin/apply-schema.test.d.ts +1 -0
- package/dist/types/config.d.ts +14 -0
- package/dist/types/create-command.d.ts +6 -0
- package/dist/types/delete-command.options.d.ts +10 -23
- package/dist/types/delete-index-command.d.ts +6 -0
- package/dist/types/embed-command.d.ts +12 -0
- package/dist/types/embeddings-command.options.d.ts +10 -28
- package/dist/types/index.d.ts +1 -0
- package/dist/types/schema.d.ts +137 -0
- package/dist/types/utils/embedding-dimensions.d.ts +13 -0
- package/dist/types/utils/zod-to-azure-fields.d.ts +61 -0
- package/dist/types/utils/zod-to-azure-fields.test.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +5 -5
- package/src/bin/apply-metadata.ts +20 -4
- package/src/bin/apply-schema.test.ts +170 -0
- package/src/bin/apply-schema.ts +86 -0
- package/src/bin/delete-removed-files.ts +1 -1
- package/src/bin/embed.ts +325 -77
- package/src/bin/get-diff.ts +5 -0
- package/src/config.ts +15 -0
- package/src/create-command.ts +218 -0
- package/src/delete-command.options.ts +7 -37
- package/src/delete-command.ts +19 -2
- package/src/delete-index-command.ts +121 -0
- package/src/embed-command.ts +44 -0
- package/src/embeddings-command.options.ts +12 -50
- package/src/embeddings-command.ts +18 -18
- package/src/index.ts +12 -3
- package/src/schema.ts +149 -0
- package/src/search-command.ts +22 -5
- package/src/utils/embedding-dimensions.ts +39 -0
- package/src/utils/zod-to-azure-fields.test.ts +136 -0
- package/src/utils/zod-to-azure-fields.ts +177 -0
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
1
1
|
# @equinor/fusion-framework-cli-plugin-ai-index
|
|
2
2
|
|
|
3
|
+
## 3.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 4711dbc: Add verbose debug logging to the `ai index add` pipeline when `--debug` is active.
|
|
8
|
+
|
|
9
|
+
Debug output includes config/pattern details, skipped files, per-file chunk counts, embedding batch sizes, upsert document IDs, and git diff file listings.
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [4711dbc]
|
|
12
|
+
- Updated dependencies [8d7b8a1]
|
|
13
|
+
- Updated dependencies [4711dbc]
|
|
14
|
+
- @equinor/fusion-framework-cli-plugin-ai-base@4.0.0
|
|
15
|
+
- @equinor/fusion-framework-cli@15.0.0
|
|
16
|
+
|
|
17
|
+
## 2.1.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- ece8f42: Add Zod-based schema promotion for Azure AI Search indexes.
|
|
22
|
+
|
|
23
|
+
New `defineIndexSchema()` factory lets config authors declare which metadata fields should be promoted to top-level Azure AI Search fields, enabling direct OData filtering without `any()` operators.
|
|
24
|
+
|
|
25
|
+
Features:
|
|
26
|
+
- `defineIndexSchema({ shape, prepareAttributes, resolve })` — type-safe schema config with Zod object shape, typed attribute processor, and field resolver
|
|
27
|
+
- `zodToAzureFields()` — converts Zod schemas to Azure EDM field definitions with appropriate capabilities
|
|
28
|
+
- `applySchema` pipeline step — validates resolved values via Zod and moves promoted fields to `metadata.schemaFields`
|
|
29
|
+
- `ffc ai index create --dry-run` — previews the full index schema including promoted fields
|
|
30
|
+
- `resolveEmbeddingDimensions()` — maps known embedding models to vector dimensions, with fallback to `embedding.dimensions` config
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { z } from "zod";
|
|
34
|
+
import { defineIndexSchema } from "@equinor/fusion-framework-cli-plugin-ai-index";
|
|
35
|
+
|
|
36
|
+
// Note: `zod` must be a direct dependency of your project.
|
|
37
|
+
// The CLI plugin uses zod internally but does not re-export it.
|
|
38
|
+
const schema = defineIndexSchema({
|
|
39
|
+
shape: z.object({
|
|
40
|
+
type: z.string(),
|
|
41
|
+
tags: z.array(z.string()).default([]),
|
|
42
|
+
}),
|
|
43
|
+
prepareAttributes: (attrs, doc) => {
|
|
44
|
+
attrs.tags ??= [];
|
|
45
|
+
if (doc.metadata.source.includes("packages/")) attrs.tags.push("package");
|
|
46
|
+
return attrs;
|
|
47
|
+
},
|
|
48
|
+
resolve: (doc) => ({
|
|
49
|
+
type: (doc.metadata.attributes?.type as string) ?? "unknown",
|
|
50
|
+
tags: (doc.metadata.attributes?.tags as string[]) ?? [],
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
ref: equinor/fusion-core-tasks#1011
|
|
56
|
+
|
|
57
|
+
- ece8f42: Internal: update index plugin to use Fusion service discovery and strategy-based AI module. Add `ai index embed` sub-command for standalone embedding operations.
|
|
58
|
+
|
|
59
|
+
Ref: https://github.com/equinor/fusion-framework/issues/1008
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- Updated dependencies [ece8f42]
|
|
64
|
+
- Updated dependencies [ece8f42]
|
|
65
|
+
- Updated dependencies [ece8f42]
|
|
66
|
+
- @equinor/fusion-framework-cli-plugin-ai-base@3.0.0
|
|
67
|
+
- @equinor/fusion-framework-module-ai@4.0.0
|
|
68
|
+
|
|
3
69
|
## 2.0.1
|
|
4
70
|
|
|
5
71
|
### Patch Changes
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { from, mergeMap, map, toArray } from 'rxjs';
|
|
2
|
+
import { from, mergeMap, map, tap, toArray } from 'rxjs';
|
|
3
3
|
import { extractGitMetadata } from '../utils/git/index.js';
|
|
4
4
|
import { resolvePackage } from '../utils/package-resolver.js';
|
|
5
5
|
/**
|
|
6
6
|
* Creates a stream that applies metadata to documents.
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
9
|
-
export function applyMetadata(document$, indexConfig) {
|
|
9
|
+
export function applyMetadata(document$, indexConfig, onProgress) {
|
|
10
10
|
// Resolve packages if enabled
|
|
11
11
|
const shouldResolvePackage = indexConfig?.metadata?.resolvePackage ?? false;
|
|
12
|
+
/** Cap concurrent git subprocess calls to avoid overwhelming the OS process table. */
|
|
13
|
+
const GIT_CONCURRENCY = 20;
|
|
14
|
+
/**
|
|
15
|
+
* Cap the number of file entries processed in parallel.
|
|
16
|
+
* Each entry fans out to GIT_CONCURRENCY inner git calls, so
|
|
17
|
+
* total concurrent git processes ≤ ENTRY_CONCURRENCY × GIT_CONCURRENCY.
|
|
18
|
+
*/
|
|
19
|
+
const ENTRY_CONCURRENCY = 20;
|
|
12
20
|
return document$.pipe(mergeMap((entry) => {
|
|
13
21
|
return from(entry.documents).pipe(
|
|
14
|
-
// Extract git metadata concurrently
|
|
22
|
+
// Extract git metadata concurrently (capped to limit parallel git processes)
|
|
15
23
|
mergeMap(async (document) => {
|
|
16
24
|
const rootPath = document.metadata.rootPath ?? process.cwd();
|
|
17
25
|
const sourcePath = path.join(rootPath, document.metadata.source);
|
|
@@ -42,7 +50,9 @@ export function applyMetadata(document$, indexConfig) {
|
|
|
42
50
|
},
|
|
43
51
|
},
|
|
44
52
|
};
|
|
45
|
-
}),
|
|
53
|
+
}, GIT_CONCURRENCY),
|
|
54
|
+
// Notify caller after each document is enriched
|
|
55
|
+
tap((document) => onProgress?.(document.metadata.source)),
|
|
46
56
|
// Apply custom attribute processor from config
|
|
47
57
|
map((document) => {
|
|
48
58
|
const attributeProcessor = indexConfig?.metadata?.attributeProcessor ||
|
|
@@ -58,6 +68,6 @@ export function applyMetadata(document$, indexConfig) {
|
|
|
58
68
|
}),
|
|
59
69
|
// Group back by file for batch deletion in next step
|
|
60
70
|
toArray());
|
|
61
|
-
}));
|
|
71
|
+
}, ENTRY_CONCURRENCY));
|
|
62
72
|
}
|
|
63
73
|
//# sourceMappingURL=apply-metadata.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-metadata.js","sourceRoot":"","sources":["../../../src/bin/apply-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"apply-metadata.js","sourceRoot":"","sources":["../../../src/bin/apply-metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { map } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an RxJS operator that resolves promoted schema fields for each
|
|
4
|
+
* document and separates them from the generic `attributes` bag.
|
|
5
|
+
*
|
|
6
|
+
* For each document in the batch:
|
|
7
|
+
* 1. Runs the optional `prepareAttributes` callback to enrich attributes
|
|
8
|
+
* with type-safe access to schema-declared fields
|
|
9
|
+
* 2. Calls the schema resolver to compute promoted field values
|
|
10
|
+
* 3. Validates the resolved values against the Zod shape
|
|
11
|
+
* 4. Stores promoted fields on `metadata.schemaFields`
|
|
12
|
+
* 5. Removes promoted keys from `metadata.attributes` to avoid duplication
|
|
13
|
+
*
|
|
14
|
+
* When no schema is configured, the stream passes through unchanged.
|
|
15
|
+
*
|
|
16
|
+
* @param document$ - Stream of document batches from the metadata enrichment step.
|
|
17
|
+
* @param schema - The index schema config, if defined. When `undefined`, documents pass through unchanged.
|
|
18
|
+
* @returns Stream of document batches with promoted fields resolved and stored.
|
|
19
|
+
*/
|
|
20
|
+
export function applySchema(document$, schema) {
|
|
21
|
+
// No schema configured — pass through unchanged (backward compatible)
|
|
22
|
+
if (!schema) {
|
|
23
|
+
return document$;
|
|
24
|
+
}
|
|
25
|
+
const promotedKeys = new Set(Object.keys(schema.shape.shape));
|
|
26
|
+
return document$.pipe(map((documents) => documents.map((document) => {
|
|
27
|
+
// Run typed attribute processor before schema resolution so the
|
|
28
|
+
// resolver receives fully enriched attributes
|
|
29
|
+
let enrichedDocument = document;
|
|
30
|
+
if (schema.prepareAttributes) {
|
|
31
|
+
const enrichedAttributes = schema.prepareAttributes((document.metadata.attributes ?? {}), document);
|
|
32
|
+
enrichedDocument = {
|
|
33
|
+
...document,
|
|
34
|
+
metadata: {
|
|
35
|
+
...document.metadata,
|
|
36
|
+
attributes: enrichedAttributes,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Resolve promoted field values from the fully enriched document
|
|
41
|
+
const resolved = schema.resolve(enrichedDocument);
|
|
42
|
+
// Validate against the Zod shape — throws on invalid data with
|
|
43
|
+
// a clear error message pointing to the offending field
|
|
44
|
+
const validated = schema.shape.parse(resolved);
|
|
45
|
+
// Remove promoted keys from attributes to avoid storing them
|
|
46
|
+
// in both top-level fields and the generic attributes array
|
|
47
|
+
const currentAttributes = (enrichedDocument.metadata.attributes ?? {});
|
|
48
|
+
const remainingAttributes = {};
|
|
49
|
+
for (const [key, value] of Object.entries(currentAttributes)) {
|
|
50
|
+
if (!promotedKeys.has(key)) {
|
|
51
|
+
remainingAttributes[key] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
...enrichedDocument,
|
|
56
|
+
metadata: {
|
|
57
|
+
...enrichedDocument.metadata,
|
|
58
|
+
attributes: remainingAttributes,
|
|
59
|
+
schemaFields: validated,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
})));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=apply-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-schema.js","sourceRoot":"","sources":["../../../src/bin/apply-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAK3B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CACzB,SAA4C,EAC5C,MAAqC;IAErC,sEAAsE;IACtE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAgC,CAAC,CAAC,CAAC;IAEzF,OAAO,SAAS,CAAC,IAAI,CACnB,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAChB,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;QACzB,gEAAgE;QAChE,8CAA8C;QAC9C,IAAI,gBAAgB,GAAG,QAAQ,CAAC;QAChC,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC7B,MAAM,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CACjD,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAA4B,EAC/D,QAAQ,CACT,CAAC;YACF,gBAAgB,GAAG;gBACjB,GAAG,QAAQ;gBACX,QAAQ,EAAE;oBACR,GAAG,QAAQ,CAAC,QAAQ;oBACpB,UAAU,EAAE,kBAA6C;iBAC1D;aACF,CAAC;QACJ,CAAC;QAED,iEAAiE;QACjE,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAElD,+DAA+D;QAC/D,wDAAwD;QACxD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAA4B,CAAC;QAE1E,6DAA6D;QAC7D,4DAA4D;QAC5D,MAAM,iBAAiB,GAAG,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAGpE,CAAC;QACF,MAAM,mBAAmB,GAA4B,EAAE,CAAC;QACxD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,mBAAmB,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YACnC,CAAC;QACH,CAAC;QAED,OAAO;YACL,GAAG,gBAAgB;YACnB,QAAQ,EAAE;gBACR,GAAG,gBAAgB,CAAC,QAAQ;gBAC5B,UAAU,EAAE,mBAAmB;gBAC/B,YAAY,EAAE,SAAS;aACxB;SACF,CAAC;IACJ,CAAC,CAAC,CACH,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { of, lastValueFrom } from 'rxjs';
|
|
4
|
+
import { defineIndexSchema } from '../schema.js';
|
|
5
|
+
import { applySchema } from './apply-schema.js';
|
|
6
|
+
/** Helper to create a minimal VectorStoreDocument for testing. */
|
|
7
|
+
function makeDocument(overrides) {
|
|
8
|
+
return {
|
|
9
|
+
id: 'test-id',
|
|
10
|
+
pageContent: 'test content',
|
|
11
|
+
...overrides,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
describe('defineIndexSchema', () => {
|
|
15
|
+
it('returns the same config object (type-narrowing only)', () => {
|
|
16
|
+
const shape = z.object({ type: z.string() });
|
|
17
|
+
const resolve = () => ({ type: 'tsdoc' });
|
|
18
|
+
const schema = defineIndexSchema({ shape, resolve });
|
|
19
|
+
expect(schema.shape).toBe(shape);
|
|
20
|
+
expect(schema.resolve).toBe(resolve);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('applySchema', () => {
|
|
24
|
+
const schema = defineIndexSchema({
|
|
25
|
+
shape: z.object({
|
|
26
|
+
pkg_name: z.string().optional(),
|
|
27
|
+
type: z.string(),
|
|
28
|
+
tags: z.array(z.string()).default([]),
|
|
29
|
+
source_dir: z.string(),
|
|
30
|
+
}),
|
|
31
|
+
resolve: (doc) => ({
|
|
32
|
+
pkg_name: doc.metadata.attributes?.pkg_name,
|
|
33
|
+
type: doc.metadata.attributes?.type ?? 'unknown',
|
|
34
|
+
tags: doc.metadata.attributes?.tags ?? [],
|
|
35
|
+
source_dir: doc.metadata.source.split('/')[0],
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
it('passes through unchanged when schema is undefined', async () => {
|
|
39
|
+
const doc = makeDocument({
|
|
40
|
+
metadata: { source: 'packages/foo/src/index.ts', attributes: { type: 'tsdoc' } },
|
|
41
|
+
});
|
|
42
|
+
const docs$ = of([doc]);
|
|
43
|
+
const result = await lastValueFrom(applySchema(docs$, undefined));
|
|
44
|
+
expect(result).toEqual([doc]);
|
|
45
|
+
});
|
|
46
|
+
it('resolves promoted fields and stores them on metadata.schemaFields', async () => {
|
|
47
|
+
const doc = makeDocument({
|
|
48
|
+
metadata: {
|
|
49
|
+
source: 'packages/foo/src/index.ts',
|
|
50
|
+
attributes: {
|
|
51
|
+
type: 'tsdoc',
|
|
52
|
+
pkg_name: '@equinor/fusion-framework',
|
|
53
|
+
tags: ['package', 'react'],
|
|
54
|
+
other_attr: 'keep-me',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
const docs$ = of([doc]);
|
|
59
|
+
const result = await lastValueFrom(applySchema(docs$, schema));
|
|
60
|
+
expect(result[0].metadata.schemaFields).toEqual({
|
|
61
|
+
pkg_name: '@equinor/fusion-framework',
|
|
62
|
+
type: 'tsdoc',
|
|
63
|
+
tags: ['package', 'react'],
|
|
64
|
+
source_dir: 'packages',
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
it('removes promoted keys from attributes to avoid duplication', async () => {
|
|
68
|
+
const doc = makeDocument({
|
|
69
|
+
metadata: {
|
|
70
|
+
source: 'packages/foo/src/index.ts',
|
|
71
|
+
attributes: {
|
|
72
|
+
type: 'tsdoc',
|
|
73
|
+
pkg_name: '@equinor/fusion-framework',
|
|
74
|
+
tags: ['package'],
|
|
75
|
+
git_commit_hash: 'abc123',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
const docs$ = of([doc]);
|
|
80
|
+
const result = await lastValueFrom(applySchema(docs$, schema));
|
|
81
|
+
// Promoted keys removed, non-promoted keys preserved
|
|
82
|
+
expect(result[0].metadata.attributes).toEqual({ git_commit_hash: 'abc123' });
|
|
83
|
+
});
|
|
84
|
+
it('handles documents with no attributes gracefully', async () => {
|
|
85
|
+
const doc = makeDocument({
|
|
86
|
+
metadata: { source: 'cookbooks/app-react/src/App.tsx' },
|
|
87
|
+
});
|
|
88
|
+
const docs$ = of([doc]);
|
|
89
|
+
const result = await lastValueFrom(applySchema(docs$, schema));
|
|
90
|
+
expect(result[0].metadata.schemaFields).toEqual({
|
|
91
|
+
pkg_name: undefined,
|
|
92
|
+
type: 'unknown',
|
|
93
|
+
tags: [],
|
|
94
|
+
source_dir: 'cookbooks',
|
|
95
|
+
});
|
|
96
|
+
expect(result[0].metadata.attributes).toEqual({});
|
|
97
|
+
});
|
|
98
|
+
it('throws when resolved values fail Zod validation', async () => {
|
|
99
|
+
const badSchema = defineIndexSchema({
|
|
100
|
+
shape: z.object({ type: z.string().min(1) }),
|
|
101
|
+
resolve: () => ({ type: '' }), // Empty string fails min(1)
|
|
102
|
+
});
|
|
103
|
+
const doc = makeDocument({
|
|
104
|
+
metadata: { source: 'test.ts', attributes: {} },
|
|
105
|
+
});
|
|
106
|
+
const docs$ = of([doc]);
|
|
107
|
+
await expect(lastValueFrom(applySchema(docs$, badSchema))).rejects.toThrow();
|
|
108
|
+
});
|
|
109
|
+
it('runs prepareAttributes before resolve to enrich attributes', async () => {
|
|
110
|
+
const schemaWithPrepare = defineIndexSchema({
|
|
111
|
+
shape: z.object({
|
|
112
|
+
tags: z.array(z.string()).default([]),
|
|
113
|
+
type: z.string(),
|
|
114
|
+
}),
|
|
115
|
+
prepareAttributes: (attrs, doc) => {
|
|
116
|
+
// Type-safe: attrs.tags is string[] | undefined
|
|
117
|
+
attrs.tags ??= [];
|
|
118
|
+
if (doc.metadata.source.includes('packages/')) {
|
|
119
|
+
attrs.tags.push('package');
|
|
120
|
+
}
|
|
121
|
+
return attrs;
|
|
122
|
+
},
|
|
123
|
+
resolve: (doc) => ({
|
|
124
|
+
tags: doc.metadata.attributes?.tags ?? [],
|
|
125
|
+
type: doc.metadata.attributes?.type ?? 'unknown',
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
const doc = makeDocument({
|
|
129
|
+
metadata: {
|
|
130
|
+
source: 'packages/framework/src/index.ts',
|
|
131
|
+
attributes: { type: 'tsdoc' },
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const docs$ = of([doc]);
|
|
135
|
+
const result = await lastValueFrom(applySchema(docs$, schemaWithPrepare));
|
|
136
|
+
// prepareAttributes added 'package' tag before resolve consumed it
|
|
137
|
+
expect(result[0].metadata.schemaFields).toEqual({
|
|
138
|
+
tags: ['package'],
|
|
139
|
+
type: 'tsdoc',
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=apply-schema.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply-schema.test.js","sourceRoot":"","sources":["../../../src/bin/apply-schema.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ export function createDeleteRemovedFilesStream(removedFiles$, framework, options
|
|
|
21
21
|
console.log('Removing entry from vector store', file.relativePath);
|
|
22
22
|
}
|
|
23
23
|
if (!options.dryRun) {
|
|
24
|
-
const vectorStoreService = framework.ai.
|
|
24
|
+
const vectorStoreService = framework.ai.useIndex(options.indexName);
|
|
25
25
|
// Single batch deletion - one file can produce multiple document chunks
|
|
26
26
|
await vectorStoreService.deleteDocuments({
|
|
27
27
|
filter: { filterExpression: filterExpression ?? undefined },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delete-removed-files.js","sourceRoot":"","sources":["../../../src/bin/delete-removed-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMtD;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,aAAwC,EACxC,SAA4B,EAC5B,OAAuB;IAEvB,OAAO,aAAa,CAAC,IAAI,CACvB,OAAO,EAAE,EACT,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACZ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;QAC/C,CAAC;QACD,iFAAiF;QACjF,MAAM,gBAAgB,GAAG,KAAK;aAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,IAAI,CAAC,YAAY,GAAG,CAAC;aAC1D,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,EACF,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,kBAAkB,GAAG,SAAS,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"delete-removed-files.js","sourceRoot":"","sources":["../../../src/bin/delete-removed-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMtD;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,aAAwC,EACxC,SAA4B,EAC5B,OAAuB;IAEvB,OAAO,aAAa,CAAC,IAAI,CACvB,OAAO,EAAE,EACT,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACZ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;QAC/C,CAAC;QACD,iFAAiF;QACjF,MAAM,gBAAgB,GAAG,KAAK;aAC3B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,IAAI,CAAC,YAAY,GAAG,CAAC;aAC1D,IAAI,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IACrC,CAAC,CAAC,EACF,QAAQ,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;QAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,kBAAkB,GAAG,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACpE,wEAAwE;YACxE,MAAM,kBAAkB,CAAC,eAAe,CAAC;gBACvC,MAAM,EAAE,EAAE,gBAAgB,EAAE,gBAAgB,IAAI,SAAS,EAAE;aAC5D,CAAC,CAAC;QACL,CAAC;QACD,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,KAAmC;SAC3C,CAAC;IACJ,CAAC,CAAC,EACF,MAAM,CAAC,CAAC,MAAM,EAAsC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CACxE,CAAC;AACJ,CAAC"}
|