@retrivora-ai/rag-engine 1.0.9 → 1.1.1

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.
@@ -842,20 +842,76 @@ var init_QdrantProvider = __esm({
842
842
  QdrantProvider = class extends BaseVectorProvider {
843
843
  constructor(config) {
844
844
  super(config);
845
+ this.schemaDiscovered = false;
845
846
  const opts = config.options;
846
847
  const baseUrl = opts.baseUrl;
847
848
  if (!baseUrl) throw new Error("[QdrantProvider] baseUrl is required");
849
+ this.contentField = opts.contentField || "content";
850
+ this.metadataField = opts.metadataField || "metadata";
851
+ this.isFlatPayload = !!opts.flatPayload;
848
852
  this.http = import_axios4.default.create({
849
853
  baseURL: baseUrl,
854
+ timeout: 15e3,
855
+ // 15s timeout for vector DB operations
850
856
  headers: __spreadValues({
851
857
  "Content-Type": "application/json"
852
858
  }, opts.apiKey ? { "api-key": opts.apiKey } : {})
853
859
  });
854
860
  }
855
861
  async initialize() {
862
+ if (this.schemaDiscovered) return;
856
863
  await this.ping();
857
864
  await this.ensureCollection();
858
- await this.ensureIndex();
865
+ console.log(`[QdrantProvider] \u{1F50D} Discovering schema for collection "${this.indexName}"...`);
866
+ const discoveredFields = await this.discoverSchema();
867
+ const opts = this.config.options;
868
+ const configFields = opts.filterableFields || [];
869
+ const allFields = [.../* @__PURE__ */ new Set([...discoveredFields, ...configFields])];
870
+ if (allFields.length > 0) {
871
+ console.log(`[QdrantProvider] \u{1F6E0} Ensuring indexes for ${allFields.length} discovered fields...`);
872
+ await Promise.all(
873
+ allFields.map(async (fieldInfo) => {
874
+ const [fieldName, schemaType] = fieldInfo.split(":");
875
+ return this.ensureIndex(fieldName, schemaType || "keyword");
876
+ })
877
+ );
878
+ } else {
879
+ console.log(`[QdrantProvider] \u2139\uFE0F No fields discovered for indexing.`);
880
+ }
881
+ this.schemaDiscovered = true;
882
+ }
883
+ /**
884
+ * Samples points from the collection to discover available payload fields.
885
+ */
886
+ async discoverSchema() {
887
+ var _a;
888
+ try {
889
+ const { data } = await this.http.post(`/collections/${this.indexName}/points/scroll`, {
890
+ limit: 20,
891
+ with_payload: true,
892
+ with_vector: false
893
+ });
894
+ const points = ((_a = data.result) == null ? void 0 : _a.points) || [];
895
+ const keys = /* @__PURE__ */ new Set();
896
+ for (const point of points) {
897
+ const payload = point.payload || {};
898
+ Object.keys(payload).forEach((k) => {
899
+ if (k !== "namespace" && k !== this.contentField && k !== this.metadataField) {
900
+ keys.add(k);
901
+ }
902
+ });
903
+ if (!this.isFlatPayload && payload[this.metadataField]) {
904
+ const meta = payload[this.metadataField];
905
+ if (typeof meta === "object" && meta !== null) {
906
+ Object.keys(meta).forEach((k) => keys.add(k));
907
+ }
908
+ }
909
+ }
910
+ return Array.from(keys);
911
+ } catch (err) {
912
+ console.warn(`[QdrantProvider] \u26A0\uFE0F Schema discovery failed:`, err instanceof Error ? err.message : String(err));
913
+ return [];
914
+ }
859
915
  }
860
916
  /**
861
917
  * Ensures the collection exists. Creates it if missing.
@@ -883,29 +939,25 @@ var init_QdrantProvider = __esm({
883
939
  }
884
940
  }
885
941
  /**
886
- * Ensures that the 'namespace' field has a keyword index for efficient filtering.
887
- * Qdrant requires this for search filters to work in many configurations.
942
+ * Ensures that a payload field has an index.
888
943
  */
889
- async ensureIndex() {
890
- var _a, _b;
944
+ async ensureIndex(fieldName, schema = "keyword") {
945
+ var _a;
946
+ let fullPath = fieldName;
947
+ if (!this.isFlatPayload && !fieldName.includes(".") && fieldName !== "namespace" && fieldName !== this.contentField) {
948
+ fullPath = `${this.metadataField}.${fieldName}`;
949
+ }
891
950
  try {
892
951
  await this.http.put(`/collections/${this.indexName}/index`, {
893
- field_name: "namespace",
894
- field_schema: "keyword"
952
+ field_name: fullPath,
953
+ field_schema: schema
895
954
  });
896
- console.log(`[QdrantProvider] \u2705 Ensured keyword index for "namespace" on collection "${this.indexName}"`);
955
+ console.log(`[QdrantProvider] \u2705 Ensured ${schema} index for "${fullPath}"`);
897
956
  } catch (err) {
898
957
  let status;
899
- let data;
900
- if (import_axios4.default.isAxiosError(err)) {
901
- status = (_a = err.response) == null ? void 0 : _a.status;
902
- data = (_b = err.response) == null ? void 0 : _b.data;
903
- }
904
- if (status === 409) {
905
- return;
906
- }
907
- const errorMessage = err instanceof Error ? err.message : String(err);
908
- console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure namespace index (Status: ${status}):`, JSON.stringify(data || errorMessage));
958
+ if (import_axios4.default.isAxiosError(err)) status = (_a = err.response) == null ? void 0 : _a.status;
959
+ if (status === 409) return;
960
+ console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure index for "${fullPath}":`, err instanceof Error ? err.message : String(err));
909
961
  }
910
962
  }
911
963
  async upsert(doc, namespace) {
@@ -913,14 +965,21 @@ var init_QdrantProvider = __esm({
913
965
  }
914
966
  async batchUpsert(docs, namespace) {
915
967
  const payload = {
916
- points: docs.map((doc) => ({
917
- id: this.normalizeId(doc.id),
918
- vector: doc.vector,
919
- payload: __spreadValues({
920
- content: doc.content,
921
- metadata: doc.metadata || {}
922
- }, namespace ? { namespace } : {})
923
- }))
968
+ points: docs.map((doc) => {
969
+ const pointPayload = __spreadValues({
970
+ [this.contentField]: doc.content
971
+ }, namespace ? { namespace } : {});
972
+ if (this.isFlatPayload) {
973
+ Object.assign(pointPayload, doc.metadata || {});
974
+ } else {
975
+ pointPayload[this.metadataField] = doc.metadata || {};
976
+ }
977
+ return {
978
+ id: this.normalizeId(doc.id),
979
+ vector: doc.vector,
980
+ payload: pointPayload
981
+ };
982
+ })
924
983
  };
925
984
  await this.http.put(`/collections/${this.indexName}/points`, payload);
926
985
  }
@@ -931,7 +990,15 @@ var init_QdrantProvider = __esm({
931
990
  }
932
991
  const sanitizedFilter = this.sanitizeFilter(_filter);
933
992
  for (const [key, value] of Object.entries(sanitizedFilter)) {
934
- must.push({ key: `metadata.${key}`, match: { value } });
993
+ let filterKey = key;
994
+ if (!this.isFlatPayload && !key.includes(".") && key !== "namespace" && key !== this.contentField) {
995
+ filterKey = `${this.metadataField}.${key}`;
996
+ }
997
+ if (Array.isArray(value)) {
998
+ must.push({ key: filterKey, match: { any: value } });
999
+ } else {
1000
+ must.push({ key: filterKey, match: { value } });
1001
+ }
935
1002
  }
936
1003
  const payload = {
937
1004
  vector,
@@ -943,28 +1010,36 @@ var init_QdrantProvider = __esm({
943
1010
  },
944
1011
  filter: must.length > 0 ? { must } : void 0
945
1012
  };
946
- console.log(`[QdrantProvider] \u{1F50D} Searching "${this.indexName}" | Namespace: ${namespace || "default"} | TopK: ${topK}`);
947
- if (must.length > (namespace ? 1 : 0)) {
948
- console.log(`[QdrantProvider] \u{1F6E0} Filters:`, JSON.stringify(must.filter((m) => m.key !== "namespace")));
949
- }
950
1013
  const { data } = await this.http.post(`/collections/${this.indexName}/points/search`, payload);
951
1014
  const results = (data.result || []).map((res) => {
952
- var _a, _b;
1015
+ const p = res.payload || {};
1016
+ let content = p[this.contentField] || "";
1017
+ if (!content) {
1018
+ const stringFields = Object.entries(p).filter(([_, v]) => typeof v === "string").map(([k, v]) => ({ key: k, val: v }));
1019
+ if (stringFields.length > 0) {
1020
+ const bestMatch = stringFields.sort((a, b) => b.val.length - a.val.length)[0];
1021
+ content = bestMatch.val;
1022
+ } else {
1023
+ content = JSON.stringify(p);
1024
+ }
1025
+ }
1026
+ let metadata = {};
1027
+ if (this.isFlatPayload) {
1028
+ metadata = __spreadValues({}, p);
1029
+ delete metadata[this.contentField];
1030
+ delete metadata["namespace"];
1031
+ } else {
1032
+ metadata = p[this.metadataField] || p;
1033
+ }
953
1034
  return {
954
- id: res["id"],
955
- score: res["score"],
956
- content: ((_a = res["payload"]) == null ? void 0 : _a.content) || "",
957
- metadata: ((_b = res["payload"]) == null ? void 0 : _b.metadata) || {}
1035
+ id: res.id,
1036
+ score: res.score,
1037
+ content,
1038
+ metadata
958
1039
  };
959
1040
  });
960
- if (results.length === 0) {
961
- console.warn(`[QdrantProvider] \u26A0\uFE0F Retrieval returned 0 results. Check if data exists in namespace "${namespace}"`);
962
- } else {
963
- console.log(`[QdrantProvider] \u2705 Found ${results.length} results (best score: ${results[0].score.toFixed(4)})`);
964
- }
965
1041
  return results;
966
1042
  }
967
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
968
1043
  async delete(id, _namespace) {
969
1044
  await this.http.post(`/collections/${this.indexName}/points/delete`, {
970
1045
  points: [this.normalizeId(id)]
@@ -985,10 +1060,6 @@ var init_QdrantProvider = __esm({
985
1060
  return false;
986
1061
  }
987
1062
  }
988
- /**
989
- * Normalizes an ID into a format Qdrant accepts (UUID or integer).
990
- * For string IDs that aren't UUIDs, it generates a deterministic UUID v5-like hash.
991
- */
992
1063
  normalizeId(id) {
993
1064
  if (typeof id === "number") return id;
994
1065
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -1868,6 +1939,53 @@ ${context}`
1868
1939
  });
1869
1940
  return (_h = (_g = (_f = completion.choices[0]) == null ? void 0 : _f.message) == null ? void 0 : _g.content) != null ? _h : "";
1870
1941
  }
1942
+ chatStream(messages, context, options) {
1943
+ return __asyncGenerator(this, null, function* () {
1944
+ var _a, _b, _c, _d, _e, _f, _g;
1945
+ const systemContent = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
1946
+
1947
+ Context:
1948
+ ${context}`;
1949
+ const systemMessage = {
1950
+ role: "system",
1951
+ content: systemContent.includes("{{context}}") ? systemContent.replace("{{context}}", context) : `${systemContent}
1952
+
1953
+ Context:
1954
+ ${context}`
1955
+ };
1956
+ const formattedMessages = [
1957
+ systemMessage,
1958
+ ...messages.map((m) => ({
1959
+ role: m.role,
1960
+ content: m.content
1961
+ }))
1962
+ ];
1963
+ const stream = yield new __await(this.client.chat.completions.create({
1964
+ model: this.llmConfig.model,
1965
+ messages: formattedMessages,
1966
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
1967
+ temperature: (_e = (_d = options == null ? void 0 : options.temperature) != null ? _d : this.llmConfig.temperature) != null ? _e : 0.7,
1968
+ stop: options == null ? void 0 : options.stop,
1969
+ stream: true
1970
+ }));
1971
+ try {
1972
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
1973
+ const chunk = temp.value;
1974
+ const content = ((_g = (_f = chunk.choices[0]) == null ? void 0 : _f.delta) == null ? void 0 : _g.content) || "";
1975
+ if (content) yield content;
1976
+ }
1977
+ } catch (temp) {
1978
+ error = [temp];
1979
+ } finally {
1980
+ try {
1981
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
1982
+ } finally {
1983
+ if (error)
1984
+ throw error[0];
1985
+ }
1986
+ }
1987
+ });
1988
+ }
1871
1989
  async embed(text, options) {
1872
1990
  const results = await this.batchEmbed([text], options);
1873
1991
  return results[0];
@@ -1973,6 +2091,47 @@ ${context}`;
1973
2091
  const block = response.content[0];
1974
2092
  return block.type === "text" ? block.text : "";
1975
2093
  }
2094
+ chatStream(messages, context, options) {
2095
+ return __asyncGenerator(this, null, function* () {
2096
+ var _a, _b, _c;
2097
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Use the context below to answer the user's question accurately.
2098
+
2099
+ Context:
2100
+ ${context}`;
2101
+ const system = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2102
+
2103
+ Context:
2104
+ ${context}`;
2105
+ const anthropicMessages = messages.map((m) => ({
2106
+ role: m.role === "assistant" ? "assistant" : "user",
2107
+ content: m.content
2108
+ }));
2109
+ const stream = yield new __await(this.client.messages.create({
2110
+ model: this.llmConfig.model,
2111
+ max_tokens: (_c = (_b = options == null ? void 0 : options.maxTokens) != null ? _b : this.llmConfig.maxTokens) != null ? _c : 1024,
2112
+ system,
2113
+ messages: anthropicMessages,
2114
+ stream: true
2115
+ }));
2116
+ try {
2117
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2118
+ const chunk = temp.value;
2119
+ if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
2120
+ yield chunk.delta.text;
2121
+ }
2122
+ }
2123
+ } catch (temp) {
2124
+ error = [temp];
2125
+ } finally {
2126
+ try {
2127
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2128
+ } finally {
2129
+ if (error)
2130
+ throw error[0];
2131
+ }
2132
+ }
2133
+ });
2134
+ }
1976
2135
  async embed(text, options) {
1977
2136
  void text;
1978
2137
  void options;
@@ -2078,7 +2237,7 @@ var OllamaProvider = class {
2078
2237
  }
2079
2238
  chatStream(messages, context, options) {
2080
2239
  return __asyncGenerator(this, null, function* () {
2081
- var _a, _b, _c, _d, _e;
2240
+ var _a, _b, _c, _d, _e, _f;
2082
2241
  const system = this.buildSystemPrompt(context);
2083
2242
  const response = yield new __await(this.http.post("/api/chat", {
2084
2243
  model: this.llmConfig.model,
@@ -2092,11 +2251,15 @@ var OllamaProvider = class {
2092
2251
  ...messages.map((m) => ({ role: m.role, content: m.content }))
2093
2252
  ]
2094
2253
  }, { responseType: "stream" }));
2254
+ let lineBuffer = "";
2095
2255
  try {
2096
2256
  for (var iter = __forAwait(response.data), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2097
2257
  const chunk = temp.value;
2098
- const lines = chunk.toString().split("\n").filter(Boolean);
2258
+ lineBuffer += chunk.toString();
2259
+ const lines = lineBuffer.split("\n");
2260
+ lineBuffer = lines.pop() || "";
2099
2261
  for (const line of lines) {
2262
+ if (!line.trim()) continue;
2100
2263
  try {
2101
2264
  const json = JSON.parse(line);
2102
2265
  if ((_e = json.message) == null ? void 0 : _e.content) {
@@ -2104,6 +2267,7 @@ var OllamaProvider = class {
2104
2267
  }
2105
2268
  if (json.done) return;
2106
2269
  } catch (e) {
2270
+ console.warn("[OllamaProvider] Failed to parse streaming line:", line);
2107
2271
  }
2108
2272
  }
2109
2273
  }
@@ -2117,6 +2281,13 @@ var OllamaProvider = class {
2117
2281
  throw error[0];
2118
2282
  }
2119
2283
  }
2284
+ if (lineBuffer.trim()) {
2285
+ try {
2286
+ const json = JSON.parse(lineBuffer);
2287
+ if ((_f = json.message) == null ? void 0 : _f.content) yield json.message.content;
2288
+ } catch (e) {
2289
+ }
2290
+ }
2120
2291
  });
2121
2292
  }
2122
2293
  buildSystemPrompt(context) {
@@ -2262,6 +2433,49 @@ ${context}`;
2262
2433
  });
2263
2434
  return (_f = response.text) != null ? _f : "";
2264
2435
  }
2436
+ chatStream(messages, context, options) {
2437
+ return __asyncGenerator(this, null, function* () {
2438
+ var _a, _b, _c, _d, _e;
2439
+ const systemPrompt = (_a = this.llmConfig.systemPrompt) != null ? _a : `You are a helpful assistant. Answer questions based on the provided context.
2440
+
2441
+ Context:
2442
+ ${context}`;
2443
+ const systemInstruction = systemPrompt.includes("{{context}}") ? systemPrompt.replace("{{context}}", context) : `${systemPrompt}
2444
+
2445
+ Context:
2446
+ ${context}`;
2447
+ const geminiMessages = messages.map((m) => ({
2448
+ role: m.role === "assistant" ? "model" : "user",
2449
+ parts: [{ text: m.content }]
2450
+ }));
2451
+ const result = yield new __await(this.client.models.generateContentStream({
2452
+ model: this.llmConfig.model,
2453
+ contents: geminiMessages,
2454
+ config: {
2455
+ systemInstruction,
2456
+ temperature: (_c = (_b = options == null ? void 0 : options.temperature) != null ? _b : this.llmConfig.temperature) != null ? _c : 0.7,
2457
+ maxOutputTokens: (_e = (_d = options == null ? void 0 : options.maxTokens) != null ? _d : this.llmConfig.maxTokens) != null ? _e : 1024,
2458
+ stopSequences: options == null ? void 0 : options.stop
2459
+ }
2460
+ }));
2461
+ try {
2462
+ for (var iter = __forAwait(result.stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2463
+ const chunk = temp.value;
2464
+ const text = chunk.text;
2465
+ if (text) yield text;
2466
+ }
2467
+ } catch (temp) {
2468
+ error = [temp];
2469
+ } finally {
2470
+ try {
2471
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
2472
+ } finally {
2473
+ if (error)
2474
+ throw error[0];
2475
+ }
2476
+ }
2477
+ });
2478
+ }
2265
2479
  async embed(text, options) {
2266
2480
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2267
2481
  const model = this.sanitizeModel(
@@ -3764,6 +3978,7 @@ var Pipeline = class {
3764
3978
  }
3765
3979
  const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
3766
3980
  const filter = QueryProcessor.buildQueryFilter(question, hints);
3981
+ console.log(`[Pipeline] \u{1F9E9} Extracted filters:`, JSON.stringify(filter));
3767
3982
  const { sources: rawSources, graphData } = yield new __await(this.retrieve(searchQuery, {
3768
3983
  namespace: ns,
3769
3984
  topK: topK * 2,
@@ -8,7 +8,7 @@ import {
8
8
  sseFrame,
9
9
  sseMetaFrame,
10
10
  sseTextFrame
11
- } from "../chunk-7S2SRQGL.mjs";
11
+ } from "../chunk-JZ4H7EP6.mjs";
12
12
  import "../chunk-YLTMFW4M.mjs";
13
13
  import "../chunk-X4TOT24V.mjs";
14
14
  export {
package/dist/server.d.mts CHANGED
@@ -731,18 +731,26 @@ declare class MilvusProvider extends BaseVectorProvider {
731
731
 
732
732
  /**
733
733
  * QdrantProvider — implementation for Qdrant using its REST API.
734
+ * Fully dynamic: automatically discovers and indexes schema from available data.
734
735
  */
735
736
  declare class QdrantProvider extends BaseVectorProvider {
736
737
  private http;
738
+ private contentField;
739
+ private metadataField;
740
+ private isFlatPayload;
741
+ private schemaDiscovered;
737
742
  constructor(config: VectorDBConfig);
738
743
  initialize(): Promise<void>;
744
+ /**
745
+ * Samples points from the collection to discover available payload fields.
746
+ */
747
+ private discoverSchema;
739
748
  /**
740
749
  * Ensures the collection exists. Creates it if missing.
741
750
  */
742
751
  private ensureCollection;
743
752
  /**
744
- * Ensures that the 'namespace' field has a keyword index for efficient filtering.
745
- * Qdrant requires this for search filters to work in many configurations.
753
+ * Ensures that a payload field has an index.
746
754
  */
747
755
  private ensureIndex;
748
756
  upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
@@ -751,10 +759,6 @@ declare class QdrantProvider extends BaseVectorProvider {
751
759
  delete(id: string | number, _namespace?: string): Promise<void>;
752
760
  deleteNamespace(_namespace: string): Promise<void>;
753
761
  ping(): Promise<boolean>;
754
- /**
755
- * Normalizes an ID into a format Qdrant accepts (UUID or integer).
756
- * For string IDs that aren't UUIDs, it generates a deterministic UUID v5-like hash.
757
- */
758
762
  private normalizeId;
759
763
  disconnect(): Promise<void>;
760
764
  }
@@ -889,6 +893,7 @@ declare class OpenAIProvider implements ILLMProvider {
889
893
  static getValidator(): IProviderValidator;
890
894
  static getHealthChecker(): IProviderHealthChecker;
891
895
  chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
896
+ chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
892
897
  embed(text: string, options?: EmbedOptions): Promise<number[]>;
893
898
  batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
894
899
  ping(): Promise<boolean>;
@@ -906,6 +911,7 @@ declare class AnthropicProvider implements ILLMProvider {
906
911
  static getValidator(): IProviderValidator;
907
912
  static getHealthChecker(): IProviderHealthChecker;
908
913
  chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
914
+ chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
909
915
  embed(text: string, options?: EmbedOptions): Promise<number[]>;
910
916
  batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
911
917
  ping(): Promise<boolean>;
package/dist/server.d.ts CHANGED
@@ -731,18 +731,26 @@ declare class MilvusProvider extends BaseVectorProvider {
731
731
 
732
732
  /**
733
733
  * QdrantProvider — implementation for Qdrant using its REST API.
734
+ * Fully dynamic: automatically discovers and indexes schema from available data.
734
735
  */
735
736
  declare class QdrantProvider extends BaseVectorProvider {
736
737
  private http;
738
+ private contentField;
739
+ private metadataField;
740
+ private isFlatPayload;
741
+ private schemaDiscovered;
737
742
  constructor(config: VectorDBConfig);
738
743
  initialize(): Promise<void>;
744
+ /**
745
+ * Samples points from the collection to discover available payload fields.
746
+ */
747
+ private discoverSchema;
739
748
  /**
740
749
  * Ensures the collection exists. Creates it if missing.
741
750
  */
742
751
  private ensureCollection;
743
752
  /**
744
- * Ensures that the 'namespace' field has a keyword index for efficient filtering.
745
- * Qdrant requires this for search filters to work in many configurations.
753
+ * Ensures that a payload field has an index.
746
754
  */
747
755
  private ensureIndex;
748
756
  upsert(doc: UpsertDocument, namespace?: string): Promise<void>;
@@ -751,10 +759,6 @@ declare class QdrantProvider extends BaseVectorProvider {
751
759
  delete(id: string | number, _namespace?: string): Promise<void>;
752
760
  deleteNamespace(_namespace: string): Promise<void>;
753
761
  ping(): Promise<boolean>;
754
- /**
755
- * Normalizes an ID into a format Qdrant accepts (UUID or integer).
756
- * For string IDs that aren't UUIDs, it generates a deterministic UUID v5-like hash.
757
- */
758
762
  private normalizeId;
759
763
  disconnect(): Promise<void>;
760
764
  }
@@ -889,6 +893,7 @@ declare class OpenAIProvider implements ILLMProvider {
889
893
  static getValidator(): IProviderValidator;
890
894
  static getHealthChecker(): IProviderHealthChecker;
891
895
  chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
896
+ chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
892
897
  embed(text: string, options?: EmbedOptions): Promise<number[]>;
893
898
  batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
894
899
  ping(): Promise<boolean>;
@@ -906,6 +911,7 @@ declare class AnthropicProvider implements ILLMProvider {
906
911
  static getValidator(): IProviderValidator;
907
912
  static getHealthChecker(): IProviderHealthChecker;
908
913
  chat(messages: ChatMessage[], context: string, options?: ChatOptions): Promise<string>;
914
+ chatStream(messages: ChatMessage[], context: string, options?: ChatOptions): AsyncIterable<string>;
909
915
  embed(text: string, options?: EmbedOptions): Promise<number[]>;
910
916
  batchEmbed(texts: string[], options?: EmbedOptions): Promise<number[][]>;
911
917
  ping(): Promise<boolean>;