@dudousxd/nestjs-agent-rag 0.13.0 → 0.14.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/dist/index.js CHANGED
@@ -77,6 +77,16 @@ function chunkByRecord(text, chunkSize, separator) {
77
77
  __name(chunkByRecord, "chunkByRecord");
78
78
 
79
79
  // src/vector-store.ts
80
+ async function replaceDocumentChunks(store, documentId, records) {
81
+ const atomic = store;
82
+ if (typeof atomic.replaceDocument === "function") {
83
+ await atomic.replaceDocument(documentId, records);
84
+ return;
85
+ }
86
+ await store.remove(documentId);
87
+ await store.upsert(records);
88
+ }
89
+ __name(replaceDocumentChunks, "replaceDocumentChunks");
80
90
  function isLexicalVectorStore(store) {
81
91
  return typeof store.searchText === "function";
82
92
  }
@@ -137,12 +147,19 @@ function applyMetadataPatch(metadata, patch) {
137
147
  __name(applyMetadataPatch, "applyMetadataPatch");
138
148
 
139
149
  // src/filter.ts
150
+ function isMissingValue(value) {
151
+ return value === void 0 || Array.isArray(value) && value.includes(void 0);
152
+ }
153
+ __name(isMissingValue, "isMissingValue");
140
154
  function matchesFilter(metadata, filter) {
141
155
  const entries = Object.entries(filter);
142
156
  if (metadata === void 0) {
143
157
  return entries.length === 0;
144
158
  }
145
159
  return entries.every(([key, expected]) => {
160
+ if (isMissingValue(expected)) {
161
+ return false;
162
+ }
146
163
  if (Array.isArray(expected)) {
147
164
  const actual = metadata[key];
148
165
  return Array.isArray(actual) ? actual.some((value) => expected.includes(value)) : expected.includes(actual);
@@ -155,9 +172,18 @@ function filterMatchesNothing(filter) {
155
172
  if (filter === void 0) {
156
173
  return false;
157
174
  }
158
- return Object.values(filter).some((value) => Array.isArray(value) && value.length === 0);
175
+ return Object.values(filter).some((value) => isMissingValue(value) || Array.isArray(value) && value.length === 0);
159
176
  }
160
177
  __name(filterMatchesNothing, "filterMatchesNothing");
178
+ function undefinedFilterKeys(filter) {
179
+ return Object.entries(filter).filter(([, value]) => isMissingValue(value)).map(([key]) => key);
180
+ }
181
+ __name(undefinedFilterKeys, "undefinedFilterKeys");
182
+ function undefinedFilterMessage(keys) {
183
+ const named = keys.map((key) => `"${key}"`).join(", ");
184
+ return `removeWhere() refuses a filter with no value for ${named}: the scope was probably never set.`;
185
+ }
186
+ __name(undefinedFilterMessage, "undefinedFilterMessage");
161
187
 
162
188
  // src/memory-vector-store.ts
163
189
  var MemoryVectorStore = class {
@@ -294,6 +320,10 @@ var MemoryVectorStore = class {
294
320
  if (Object.keys(filter).length === 0) {
295
321
  throw new UnsafeRemovalError("empty-filter", "removeWhere() refuses an empty filter: it would delete every chunk in the store. Pass a filter that scopes the removal, or delete deliberately with removeMany(await store.listDocumentIds()).");
296
322
  }
323
+ const missing = undefinedFilterKeys(filter);
324
+ if (missing.length > 0) {
325
+ throw new UnsafeRemovalError("undefined-value", undefinedFilterMessage(missing));
326
+ }
297
327
  if (filterMatchesNothing(filter)) {
298
328
  return 0;
299
329
  }
@@ -563,6 +593,7 @@ var PgVectorStore = class {
563
593
  dimensions;
564
594
  /** The widths with a partial HNSW index, for a mixed-dimension table. */
565
595
  indexedDimensions;
596
+ vectorType;
566
597
  nullableEmbeddings;
567
598
  iterativeScan;
568
599
  efSearch;
@@ -586,6 +617,10 @@ var PgVectorStore = class {
586
617
  ...new Set(dimensions)
587
618
  ];
588
619
  }
620
+ this.vectorType = options.vectorType ?? "vector";
621
+ if (this.vectorType === "halfvec" && this.dimensions === void 0) {
622
+ throw new Error('PgVectorStore: vectorType "halfvec" needs a single width, not a list');
623
+ }
589
624
  this.nullableEmbeddings = options.nullableEmbeddings ?? false;
590
625
  this.iterativeScan = options.iterativeScan;
591
626
  this.efSearch = options.efSearch;
@@ -604,7 +639,7 @@ var PgVectorStore = class {
604
639
  */
605
640
  schemaStatements() {
606
641
  const mixed = this.dimensions === void 0;
607
- const column = mixed ? "vector" : `vector(${this.dimensions})`;
642
+ const column = mixed ? "vector" : `${this.vectorType}(${this.dimensions})`;
608
643
  const statements = [
609
644
  "CREATE EXTENSION IF NOT EXISTS vector",
610
645
  `CREATE TABLE IF NOT EXISTS ${this.table} (
@@ -623,7 +658,7 @@ var PgVectorStore = class {
623
658
  }
624
659
  } else {
625
660
  statements.push(`CREATE INDEX IF NOT EXISTS ${this.table}_embedding_idx
626
- ON ${this.table} USING hnsw (embedding vector_cosine_ops)`);
661
+ ON ${this.table} USING hnsw (embedding ${this.vectorType}_cosine_ops)`);
627
662
  }
628
663
  return statements;
629
664
  }
@@ -639,6 +674,23 @@ var PgVectorStore = class {
639
674
  * {@link PgVectorStoreOptions.nullableEmbeddings}).
640
675
  */
641
676
  async upsert(records) {
677
+ await this.upsertWith(this.client, records);
678
+ }
679
+ /**
680
+ * Swaps a document's chunks in one transaction, so a crash can't lose it and a search sees the old
681
+ * version or the new one. A client without `transaction` falls back to two statements.
682
+ */
683
+ async replaceDocument(documentId, records) {
684
+ const swap = /* @__PURE__ */ __name(async (client) => {
685
+ await client.query(`DELETE FROM ${this.table} WHERE ${DOCUMENT_ID_FROM_CHUNK} = $1`, [
686
+ stripNulBytes(documentId)
687
+ ]);
688
+ await this.upsertWith(client, records);
689
+ }, "swap");
690
+ const transaction = this.client.transaction?.bind(this.client);
691
+ await (transaction === void 0 ? swap(this.client) : transaction(swap));
692
+ }
693
+ async upsertWith(client, records) {
642
694
  const byId = /* @__PURE__ */ new Map();
643
695
  for (const record of records) {
644
696
  const id = stripNulBytes(record.id);
@@ -660,9 +712,9 @@ var PgVectorStore = class {
660
712
  const metadata = record.metadata !== void 0 ? stripNulBytes(record.metadata) : void 0;
661
713
  const base = params.length;
662
714
  params.push(record.id, text, source ?? null, metadata !== void 0 ? JSON.stringify(metadata) : null, record.embedding.length > 0 ? toVectorLiteral(record.embedding) : null);
663
- return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}::jsonb, $${base + 5}::vector)`;
715
+ return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}::jsonb, $${base + 5}::${this.vectorType})`;
664
716
  });
665
- await this.client.query(`INSERT INTO ${this.table} (id, text, source, metadata, embedding)
717
+ await client.query(`INSERT INTO ${this.table} (id, text, source, metadata, embedding)
666
718
  VALUES ${rows.join(", ")}
667
719
  ON CONFLICT (id) DO UPDATE SET
668
720
  text = EXCLUDED.text,
@@ -786,6 +838,10 @@ var PgVectorStore = class {
786
838
  if (Object.keys(filter).length === 0) {
787
839
  throw new UnsafeRemovalError("empty-filter", "removeWhere() refuses an empty filter: it would delete every chunk in the table. Pass a filter that scopes the removal, or delete deliberately with removeMany(await store.listDocumentIds()).");
788
840
  }
841
+ const missing = undefinedFilterKeys(filter);
842
+ if (missing.length > 0) {
843
+ throw new UnsafeRemovalError("undefined-value", undefinedFilterMessage(missing));
844
+ }
789
845
  if (filterMatchesNothing(filter)) {
790
846
  return 0;
791
847
  }
@@ -817,7 +873,7 @@ var PgVectorStore = class {
817
873
  options.topK
818
874
  ];
819
875
  const conditions = this.whereConditions(options.filter, params);
820
- let vectorType = "vector";
876
+ let vectorType = this.vectorType;
821
877
  if (this.dimensions === void 0) {
822
878
  const width = embedding.length;
823
879
  if (this.indexedDimensions.includes(width)) {
@@ -827,7 +883,7 @@ var PgVectorStore = class {
827
883
  } else if (this.nullableEmbeddings) {
828
884
  conditions.push("embedding IS NOT NULL");
829
885
  }
830
- const column = vectorType === "vector" ? "embedding" : `(embedding::${vectorType})`;
886
+ const column = vectorType === this.vectorType ? "embedding" : `(embedding::${vectorType})`;
831
887
  const sql = `SELECT id, text, source, metadata, 1 - (${column} <=> $1::${vectorType}) AS score
832
888
  FROM ${this.table}
833
889
  ${conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : ""}
@@ -1014,6 +1070,10 @@ function buildWhere(filter, params) {
1014
1070
  const clauses = [];
1015
1071
  const scalar = {};
1016
1072
  for (const [key, value] of Object.entries(stripped)) {
1073
+ if (value === void 0 || Array.isArray(value) && value.includes(void 0)) {
1074
+ clauses.push("false");
1075
+ continue;
1076
+ }
1017
1077
  if (Array.isArray(value)) {
1018
1078
  if (value.length === 0) {
1019
1079
  clauses.push("false");
@@ -1555,6 +1615,10 @@ var RedisVectorStore = class {
1555
1615
  if (keys.length === 0) {
1556
1616
  throw new UnsafeRemovalError("empty-filter", "removeWhere() refuses an empty filter: it would delete every chunk in the index. Pass a filter that scopes the removal, or delete deliberately with removeMany(await store.listDocumentIds()).");
1557
1617
  }
1618
+ const missing = undefinedFilterKeys(filter);
1619
+ if (missing.length > 0) {
1620
+ throw new UnsafeRemovalError("undefined-value", undefinedFilterMessage(missing));
1621
+ }
1558
1622
  const unindexed = keys.filter((key) => !this.filterableFields.includes(key));
1559
1623
  if (unindexed.length > 0) {
1560
1624
  const named = unindexed.map((key) => `"${key}"`).join(", ");
@@ -2105,7 +2169,7 @@ var KeywordRetriever = class {
2105
2169
  }
2106
2170
  };
2107
2171
  function tokenize(text) {
2108
- return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
2172
+ return text.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().match(/[\p{L}\p{N}_]+/gu) ?? [];
2109
2173
  }
2110
2174
  __name(tokenize, "tokenize");
2111
2175
 
@@ -2426,13 +2490,19 @@ function createRetrievalTool(retriever, options = {}) {
2426
2490
  inputSchema: querySchema
2427
2491
  },
2428
2492
  handler: {
2429
- async execute(input) {
2493
+ async execute(input, ctx) {
2430
2494
  if (!isQueryInput(input)) {
2431
2495
  throw new Error("retrieval tool expects { query: string }");
2432
2496
  }
2433
- const passages = await instrumented.retrieve(input.query, topK !== void 0 ? {
2434
- topK
2435
- } : {});
2497
+ const filter = options.filter?.(ctx);
2498
+ const passages = await instrumented.retrieve(input.query, {
2499
+ ...topK !== void 0 ? {
2500
+ topK
2501
+ } : {},
2502
+ ...filter !== void 0 ? {
2503
+ filter
2504
+ } : {}
2505
+ });
2436
2506
  return {
2437
2507
  passages
2438
2508
  };
@@ -2472,7 +2542,7 @@ function openAiEmbeddings(options) {
2472
2542
  const maxInputChars = options.maxInputChars ?? 24e3;
2473
2543
  const timeoutMs = options.timeoutMs ?? 12e4;
2474
2544
  const doFetch = options.fetch ?? fetch;
2475
- const request = /* @__PURE__ */ __name(async (input) => {
2545
+ const request = /* @__PURE__ */ __name(async (input, count) => {
2476
2546
  const response = await doFetch(url, {
2477
2547
  method: "POST",
2478
2548
  headers: {
@@ -2505,19 +2575,20 @@ function openAiEmbeddings(options) {
2505
2575
  const tokens = json2?.usage?.total_tokens ?? json2?.usage?.prompt_tokens;
2506
2576
  if (typeof tokens === "number" && Number.isFinite(tokens)) {
2507
2577
  options.onUsage?.(tokens);
2578
+ count(tokens);
2508
2579
  }
2509
2580
  return items.map((item) => item.embedding);
2510
2581
  }, "request");
2511
- const requestSplitting = /* @__PURE__ */ __name(async (input) => {
2582
+ const requestSplitting = /* @__PURE__ */ __name(async (input, count) => {
2512
2583
  if (input.length > batchSize) {
2513
2584
  const vectors = [];
2514
2585
  for (let start = 0; start < input.length; start += batchSize) {
2515
- vectors.push(...await requestSplitting(input.slice(start, start + batchSize)));
2586
+ vectors.push(...await requestSplitting(input.slice(start, start + batchSize), count));
2516
2587
  }
2517
2588
  return vectors;
2518
2589
  }
2519
2590
  try {
2520
- return await request(input);
2591
+ return await request(input, count);
2521
2592
  } catch (error) {
2522
2593
  if (!isBatchTooLarge(error) || input.length <= 1) {
2523
2594
  throw error;
@@ -2529,20 +2600,37 @@ function openAiEmbeddings(options) {
2529
2600
  options.onWarn?.(`embeddings server ${url} refused a batch of ${input.length} inputs (${error.message}); retrying in batches of ${half}. Raise the server's batch limit (TEI: --max-client-batch-size) or lower batchSize.`);
2530
2601
  }
2531
2602
  return [
2532
- ...await requestSplitting(input.slice(0, half)),
2533
- ...await requestSplitting(input.slice(half))
2603
+ ...await requestSplitting(input.slice(0, half), count),
2604
+ ...await requestSplitting(input.slice(half), count)
2534
2605
  ];
2535
2606
  }
2536
2607
  }, "requestSplitting");
2608
+ const embedAll = /* @__PURE__ */ __name(async (texts, count) => {
2609
+ const vectors = [];
2610
+ for (let start = 0; start < texts.length; ) {
2611
+ const input = texts.slice(start, start + batchSize).map((text) => (text.length > maxInputChars ? text.slice(0, maxInputChars) : text) || " ");
2612
+ vectors.push(...await requestSplitting(input, count));
2613
+ start += input.length;
2614
+ }
2615
+ return vectors;
2616
+ }, "embedAll");
2537
2617
  return {
2538
- async embed(texts) {
2539
- const vectors = [];
2540
- for (let start = 0; start < texts.length; ) {
2541
- const input = texts.slice(start, start + batchSize).map((text) => (text.length > maxInputChars ? text.slice(0, maxInputChars) : text) || " ");
2542
- vectors.push(...await requestSplitting(input));
2543
- start += input.length;
2544
- }
2545
- return vectors;
2618
+ embed: /* @__PURE__ */ __name((texts) => embedAll(texts, () => {
2619
+ }), "embed"),
2620
+ async embedWithUsage(texts) {
2621
+ let inputTokens;
2622
+ const vectors = await embedAll(texts, (tokens) => {
2623
+ inputTokens = (inputTokens ?? 0) + tokens;
2624
+ });
2625
+ return {
2626
+ vectors,
2627
+ ...inputTokens !== void 0 ? {
2628
+ usage: {
2629
+ inputTokens,
2630
+ modelId: options.model
2631
+ }
2632
+ } : {}
2633
+ };
2546
2634
  }
2547
2635
  };
2548
2636
  }
@@ -2647,6 +2735,206 @@ function itemsOf(body) {
2647
2735
  }
2648
2736
  __name(itemsOf, "itemsOf");
2649
2737
 
2738
+ // src/embedding-usage.ts
2739
+ async function embedCountingUsage(provider, texts) {
2740
+ const reporting = provider;
2741
+ return typeof reporting.embedWithUsage === "function" ? reporting.embedWithUsage(texts) : {
2742
+ vectors: await provider.embed(texts)
2743
+ };
2744
+ }
2745
+ __name(embedCountingUsage, "embedCountingUsage");
2746
+
2747
+ // src/rag-index.ts
2748
+ var RAG_ENTITY_KEY = "ragEntity";
2749
+ var RagScopeRequiredError = class extends Error {
2750
+ static {
2751
+ __name(this, "RagScopeRequiredError");
2752
+ }
2753
+ model;
2754
+ key;
2755
+ constructor(model, key) {
2756
+ super(`${model} needs scope.${key}: its chunks are isolated by it`), this.model = model, this.key = key;
2757
+ this.name = "RagScopeRequiredError";
2758
+ }
2759
+ };
2760
+ var ANY_OF = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent-rag/anyOf");
2761
+ function anyOf(values) {
2762
+ return {
2763
+ [ANY_OF]: values
2764
+ };
2765
+ }
2766
+ __name(anyOf, "anyOf");
2767
+ function isScopeValue(value) {
2768
+ return typeof value === "number" ? Number.isFinite(value) : typeof value === "string" && value !== "";
2769
+ }
2770
+ __name(isScopeValue, "isScopeValue");
2771
+ function isAnyOf(value) {
2772
+ return typeof value === "object" && value !== null && ANY_OF in value;
2773
+ }
2774
+ __name(isAnyOf, "isAnyOf");
2775
+ var RagIndex = class {
2776
+ static {
2777
+ __name(this, "RagIndex");
2778
+ }
2779
+ definition;
2780
+ deps;
2781
+ embedder;
2782
+ constructor(definition, deps) {
2783
+ this.definition = definition;
2784
+ this.deps = deps;
2785
+ const { onUsage } = deps;
2786
+ this.embedder = onUsage === void 0 ? deps.embedder : {
2787
+ embed: /* @__PURE__ */ __name(async (texts) => {
2788
+ const { vectors, usage } = await embedCountingUsage(deps.embedder, texts);
2789
+ if (usage !== void 0) {
2790
+ await onUsage(usage);
2791
+ }
2792
+ return vectors;
2793
+ }, "embed")
2794
+ };
2795
+ }
2796
+ /** The id this row's chunks are stored under: `<name>:<id>`. */
2797
+ documentId(id) {
2798
+ if (!isScopeValue(id)) {
2799
+ throw new Error(`${this.definition.name}: a row needs an id to be indexed or removed`);
2800
+ }
2801
+ return `${this.definition.name}:${String(id)}`;
2802
+ }
2803
+ /** A `Retriever` locked to this scope, for `HybridRetriever`, `createRetrievalTool` and so on. */
2804
+ scoped(scope) {
2805
+ return new FilteredRetriever(this.baseRetriever(), this.scopeFilter(scope));
2806
+ }
2807
+ async search(query, options) {
2808
+ const { scope, filter, topK } = options;
2809
+ return this.scoped(scope).retrieve(query, {
2810
+ ...topK !== void 0 ? {
2811
+ topK
2812
+ } : {},
2813
+ ...filter !== void 0 ? {
2814
+ filter
2815
+ } : {}
2816
+ });
2817
+ }
2818
+ /**
2819
+ * Replaces the row's chunks and returns how many were written. Embeddings come first: if the
2820
+ * provider fails, the previous chunks are still there. The swap is one transaction on Postgres; on a
2821
+ * store without `replaceDocument` a crash mid-swap loses the document until the next `index`.
2822
+ */
2823
+ async index(row) {
2824
+ const { definition, deps } = this;
2825
+ const documentId = this.documentId(definition.id(row));
2826
+ const scope = this.scopeFilter(Object.fromEntries(Object.entries(definition.scope).map(([key, read]) => [
2827
+ key,
2828
+ read(row)
2829
+ ])));
2830
+ const text = definition.text(row)?.trim();
2831
+ if (!text) {
2832
+ await deps.store.remove(documentId);
2833
+ return 0;
2834
+ }
2835
+ const pieces = chunkText(text, definition.chunk).slice(0, definition.maxChunks);
2836
+ const embeddings = await this.embedder.embed(pieces);
2837
+ const source = definition.source?.(row) ?? void 0;
2838
+ const metadata = {
2839
+ ...definition.metadata?.(row),
2840
+ ...scope
2841
+ };
2842
+ await replaceDocumentChunks(deps.store, documentId, pieces.map((piece, index) => ({
2843
+ id: `${documentId}#${index}`,
2844
+ text: piece,
2845
+ embedding: embeddings[index] ?? [],
2846
+ ...source !== void 0 ? {
2847
+ source
2848
+ } : {},
2849
+ metadata
2850
+ })));
2851
+ return pieces.length;
2852
+ }
2853
+ /** Takes the id itself once the row is gone. */
2854
+ remove(rowOrId) {
2855
+ const id = typeof rowOrId === "string" || typeof rowOrId === "number" ? rowOrId : this.definition.id(rowOrId);
2856
+ return this.deps.store.remove(this.documentId(id));
2857
+ }
2858
+ /**
2859
+ * Diffs the index against the ids that exist, and removes what no hook could: `ON DELETE CASCADE`,
2860
+ * raw SQL, a crash after a commit. `liveIds` must be complete for the part being compared, because
2861
+ * anything left out is removed. Use `dryRun` to look first.
2862
+ */
2863
+ async reconcile(liveIds, options = {}) {
2864
+ const filter = {
2865
+ [RAG_ENTITY_KEY]: this.definition.name
2866
+ };
2867
+ for (const [key, value] of Object.entries(options.scope ?? {})) {
2868
+ if (!isScopeValue(value)) {
2869
+ throw new RagScopeRequiredError(this.definition.name, key);
2870
+ }
2871
+ filter[key] = String(value);
2872
+ }
2873
+ const live = /* @__PURE__ */ new Set();
2874
+ for await (const id of liveIds) {
2875
+ live.add(this.documentId(id));
2876
+ }
2877
+ const indexed = await this.deps.store.listDocumentIds(filter);
2878
+ const orphans = indexed.filter((id) => !live.has(id));
2879
+ if (options.dryRun !== true) {
2880
+ await this.deps.store.removeMany(orphans);
2881
+ }
2882
+ const known = new Set(indexed);
2883
+ return {
2884
+ orphans,
2885
+ missing: [
2886
+ ...live
2887
+ ].filter((id) => !known.has(id))
2888
+ };
2889
+ }
2890
+ /** A `search_*` tool whose scope comes from the context. Pass it to `provideAgentTool`. */
2891
+ tool(options) {
2892
+ return createRetrievalTool(this.baseRetriever(), {
2893
+ name: options.name,
2894
+ ...options.description !== void 0 ? {
2895
+ description: options.description
2896
+ } : {},
2897
+ ...options.topK !== void 0 ? {
2898
+ topK: options.topK
2899
+ } : {},
2900
+ filter: /* @__PURE__ */ __name((ctx) => this.scopeFilter(options.scope(ctx)), "filter")
2901
+ });
2902
+ }
2903
+ baseRetriever() {
2904
+ const { minScore } = this.definition;
2905
+ return this.deps.retriever ?? new EmbeddingRetriever(this.embedder, this.deps.store, minScore !== void 0 ? {
2906
+ minScore
2907
+ } : {});
2908
+ }
2909
+ /** The filter a scope compiles to. Throws on anything but a usable value, before any paid call. */
2910
+ scopeFilter(scope) {
2911
+ const given = scope ?? {};
2912
+ const filter = {
2913
+ [RAG_ENTITY_KEY]: this.definition.name
2914
+ };
2915
+ for (const key of Object.keys(this.definition.scope)) {
2916
+ const value = given[key];
2917
+ if (isAnyOf(value) && value[ANY_OF].every(isScopeValue)) {
2918
+ filter[key] = value[ANY_OF].map(String);
2919
+ } else if (isScopeValue(value)) {
2920
+ filter[key] = String(value);
2921
+ } else {
2922
+ throw new RagScopeRequiredError(this.definition.name, key);
2923
+ }
2924
+ }
2925
+ return filter;
2926
+ }
2927
+ };
2928
+ function ragFilterableFields(...scopeKeys) {
2929
+ return [
2930
+ .../* @__PURE__ */ new Set([
2931
+ RAG_ENTITY_KEY,
2932
+ ...scopeKeys
2933
+ ])
2934
+ ];
2935
+ }
2936
+ __name(ragFilterableFields, "ragFilterableFields");
2937
+
2650
2938
  // src/tree/types.ts
2651
2939
  function* walkTree(nodes, path = []) {
2652
2940
  for (const node of nodes) {
@@ -4925,8 +5213,11 @@ export {
4925
5213
  PgLexicalVectorStore,
4926
5214
  PgVectorStore,
4927
5215
  RAG_DIAGNOSTIC_LIB,
5216
+ RAG_ENTITY_KEY,
4928
5217
  RAG_RETRIEVAL_CHANNEL,
4929
5218
  RAG_RETRIEVAL_EVENT,
5219
+ RagIndex,
5220
+ RagScopeRequiredError,
4930
5221
  RedisVectorSchemaMismatchError,
4931
5222
  RedisVectorStore,
4932
5223
  RerankingRetriever,
@@ -4934,6 +5225,7 @@ export {
4934
5225
  TreeNavigationRetriever,
4935
5226
  TwoStageRetriever,
4936
5227
  UnsafeRemovalError,
5228
+ anyOf,
4937
5229
  anyTermTsquery,
4938
5230
  applyMetadataPatch,
4939
5231
  buildDocumentTree,
@@ -4949,6 +5241,7 @@ export {
4949
5241
  describesRetrieval,
4950
5242
  detectHeadings,
4951
5243
  documentIdOf,
5244
+ embedCountingUsage,
4952
5245
  emitRagRetrieval,
4953
5246
  estimateTokens,
4954
5247
  hasSearchSyntax,
@@ -4964,6 +5257,8 @@ export {
4964
5257
  openAiChatTreeLlm,
4965
5258
  openAiEmbeddings,
4966
5259
  parseJsonReply,
5260
+ ragFilterableFields,
5261
+ replaceDocumentChunks,
4967
5262
  spanText,
4968
5263
  stableHash,
4969
5264
  toPgClient,