@retrivora-ai/rag-engine 1.8.1 → 1.8.2

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.
Files changed (55) hide show
  1. package/dist/{ILLMProvider-BfRgI1Xh.d.mts → ILLMProvider-BOJFz3Na.d.mts} +47 -1
  2. package/dist/{ILLMProvider-BfRgI1Xh.d.ts → ILLMProvider-BOJFz3Na.d.ts} +47 -1
  3. package/dist/{MultiTablePostgresProvider-YY7LPNJK.mjs → MultiTablePostgresProvider-ZLGSKTJR.mjs} +1 -1
  4. package/dist/chunk-ICKRMZQK.mjs +76 -0
  5. package/dist/{chunk-BFYLQYQU.mjs → chunk-LZVVLSDN.mjs} +192 -100
  6. package/dist/{chunk-R3RGUMHE.mjs → chunk-OZFBG4BA.mjs} +121 -48
  7. package/dist/handlers/index.d.mts +2 -2
  8. package/dist/handlers/index.d.ts +2 -2
  9. package/dist/handlers/index.js +368 -147
  10. package/dist/handlers/index.mjs +4 -1
  11. package/dist/{index-BV0z5mb6.d.mts → index-BwpcaziY.d.ts} +4 -2
  12. package/dist/{index-1Z4GuYBi.d.ts → index-D3V9Et2M.d.mts} +4 -2
  13. package/dist/index.d.mts +23 -3
  14. package/dist/index.d.ts +23 -3
  15. package/dist/index.js +1143 -790
  16. package/dist/index.mjs +1065 -770
  17. package/dist/server.d.mts +15 -25
  18. package/dist/server.d.ts +15 -25
  19. package/dist/server.js +366 -147
  20. package/dist/server.mjs +3 -2
  21. package/package.json +4 -2
  22. package/src/app/api/upload/route.ts +4 -0
  23. package/src/app/constants.tsx +2 -2
  24. package/src/app/page.tsx +12 -321
  25. package/src/components/AmbientBackground.tsx +29 -0
  26. package/src/components/ArchitectureCard.tsx +17 -0
  27. package/src/components/ArchitectureCardsSection.tsx +15 -0
  28. package/src/components/ChatWindow.tsx +32 -0
  29. package/src/components/CodeViewer.tsx +51 -0
  30. package/src/components/ConfigProvider.tsx +1 -0
  31. package/src/components/DocViewer.tsx +37 -0
  32. package/src/components/DocumentUpload.tsx +44 -1
  33. package/src/components/Documentation.tsx +58 -0
  34. package/src/components/DynamicChart.tsx +27 -2
  35. package/src/components/Hero.tsx +59 -0
  36. package/src/components/HourglassLoader.tsx +87 -0
  37. package/src/components/Lifecycle.tsx +37 -0
  38. package/src/components/MarkdownComponents.tsx +140 -0
  39. package/src/components/MessageBubble.tsx +88 -1010
  40. package/src/components/Navbar.tsx +55 -0
  41. package/src/components/ObservabilityPanel.tsx +374 -0
  42. package/src/components/ProductCard.tsx +3 -1
  43. package/src/components/UIDispatcher.tsx +344 -0
  44. package/src/components/VisualizationRenderer.tsx +48 -26
  45. package/src/core/Pipeline.ts +186 -76
  46. package/src/handlers/index.ts +72 -12
  47. package/src/hooks/useRagChat.ts +19 -9
  48. package/src/index.ts +9 -1
  49. package/src/providers/vectordb/MultiTablePostgresProvider.ts +150 -64
  50. package/src/types/chat.ts +2 -0
  51. package/src/types/index.ts +52 -0
  52. package/src/types/props.ts +9 -1
  53. package/src/utils/ProductExtractor.ts +347 -0
  54. package/src/utils/UITransformer.ts +4 -53
  55. package/src/utils/synonyms.ts +78 -0
@@ -19,16 +19,17 @@
19
19
  */
20
20
 
21
21
  import { useState, useCallback, useRef, useEffect } from 'react';
22
- import { VectorMatch, RagMessage, UseRagChatOptions, UseRagChatReturn } from '../types';
22
+ import { VectorMatch, RagMessage, UseRagChatOptions, UseRagChatReturn, ObservabilityTrace } from '../types';
23
23
  import { useStoredMessages } from './useStoredMessages';
24
24
 
25
25
  // ─── SSE Frame Parser ──────────────────────────────────────────────────────────
26
26
 
27
- interface SseTextFrame { type: 'text'; text: string }
28
- interface SseMetaFrame { type: 'metadata'; sources?: VectorMatch[] }
29
- interface SseErrorFrame { type: 'error'; error: string }
30
- interface SseUiFrame { type: 'ui_transformation'; data: unknown }
31
- type SseFrame = SseTextFrame | SseMetaFrame | SseErrorFrame | SseUiFrame;
27
+ interface SseTextFrame { type: 'text'; text: string }
28
+ interface SseMetaFrame { type: 'metadata'; sources?: VectorMatch[] }
29
+ interface SseErrorFrame { type: 'error'; error: string }
30
+ interface SseUiFrame { type: 'ui_transformation'; data: unknown }
31
+ interface SseObservabilityFrame { type: 'observability'; data: ObservabilityTrace }
32
+ type SseFrame = SseTextFrame | SseMetaFrame | SseErrorFrame | SseUiFrame | SseObservabilityFrame;
32
33
 
33
34
  /**
34
35
  * Parse all complete SSE frames from a raw chunk string.
@@ -126,6 +127,7 @@ export function useRagChat(
126
127
  let assistantContent = '';
127
128
  let sources: VectorMatch[] = [];
128
129
  let uiTransformation: unknown = null;
130
+ let trace: ObservabilityTrace | undefined;
129
131
  // Buffer for partial SSE frames that arrive split across reads
130
132
  let buffer = '';
131
133
 
@@ -161,6 +163,8 @@ export function useRagChat(
161
163
  sources = frame.sources ?? [];
162
164
  } else if (frame.type === 'ui_transformation') {
163
165
  uiTransformation = frame.data;
166
+ } else if (frame.type === 'observability') {
167
+ trace = (frame as SseObservabilityFrame).data;
164
168
  } else if (frame.type === 'error') {
165
169
  setError(frame.error || 'Stream error');
166
170
  }
@@ -186,18 +190,24 @@ export function useRagChat(
186
190
  for (const frame of parseSseChunk(buffer)) {
187
191
  if (frame.type === 'text' && frame.text) assistantContent += frame.text;
188
192
  else if (frame.type === 'metadata') sources = frame.sources ?? [];
193
+ else if (frame.type === 'observability') trace = (frame as SseObservabilityFrame).data;
189
194
  }
190
195
  }
191
196
 
192
- const finalAssistantMessage: RagMessage = {
197
+ // Final message with all accumulated data
198
+ const finalMsg: RagMessage = {
193
199
  id: assistantMessageId,
194
200
  role: 'assistant',
195
201
  content: assistantContent,
196
202
  sources: sources.length > 0 ? sources : undefined,
197
- uiTransformation: uiTransformation || undefined,
203
+ uiTransformation: uiTransformation ?? undefined,
204
+ trace,
198
205
  createdAt: new Date().toISOString(),
199
206
  };
200
- onReply?.(finalAssistantMessage);
207
+ setMessages((prev) =>
208
+ prev.map((msg) => (msg.id === assistantMessageId ? finalMsg : msg))
209
+ );
210
+ onReply?.(finalMsg);
201
211
  } catch (err) {
202
212
  const msg = err instanceof Error ? err.message : 'Something went wrong. Please try again.';
203
213
  setError(msg);
package/src/index.ts CHANGED
@@ -9,11 +9,15 @@ export { ChatWindow } from './components/ChatWindow';
9
9
  export { DocumentUpload } from './components/DocumentUpload';
10
10
  export { MessageBubble } from './components/MessageBubble';
11
11
  export { SourceCard } from './components/SourceCard';
12
+ export { ObservabilityPanel } from './components/ObservabilityPanel';
12
13
  export { ConfigProvider, useConfig } from './components/ConfigProvider';
13
14
 
14
15
  // ── Headless Hooks ────────────────────────────────────────────
15
16
  export { useRagChat } from './hooks/useRagChat';
16
17
 
18
+ // ── Utils ─────────────────────────────────────────────────────
19
+ export { addSynonyms } from './utils/synonyms';
20
+
17
21
  // ── Types (Interfaces/Types only, no Node.js deps) ─────────────
18
22
  export type { RagConfig, VectorDBConfig, VectorDBProvider, LLMConfig, LLMProvider, EmbeddingConfig, EmbeddingProvider, UIConfig, RAGConfig } from './config/RagConfig';
19
23
  export type { ILLMProvider, EmbedOptions } from './llm/ILLMProvider';
@@ -35,5 +39,9 @@ export type {
35
39
  ProductCardProps,
36
40
  ProductCarouselProps,
37
41
  DocumentUploadProps,
38
- SourceCardProps
42
+ SourceCardProps,
43
+ ObservabilityTrace,
44
+ LatencyBreakdown,
45
+ TokenUsage,
46
+ RetrievedChunk
39
47
  } from './types';
@@ -21,6 +21,7 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
21
21
  private readonly connectionString: string;
22
22
  private tables: string[];
23
23
  private searchFields: string[];
24
+ private readonly uploadTable: string;
24
25
 
25
26
  constructor(config: VectorDBConfig) {
26
27
  super(config);
@@ -31,22 +32,8 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
31
32
  this.connectionString = opts.connectionString as string;
32
33
  this.dimensions = (opts.dimensions as number) ?? 768;
33
34
 
34
- // Tables can come from options.tables (custom key) or be derived from VECTOR_DB_TABLES env var
35
- const rawTables: string | string[] =
36
- (opts.tables as string | string[]) ??
37
- process.env.VECTOR_DB_TABLES ??
38
- '';
39
-
40
- this.tables = typeof rawTables === 'string'
41
- ? rawTables.split(',').map((t) => t.trim()).filter(Boolean)
42
- : rawTables;
43
-
44
- if (this.tables.length === 0) {
45
- console.warn(
46
- '[MultiTablePostgresProvider] No tables configured. ' +
47
- 'Set VECTOR_DB_TABLES as a comma-separated list of table names or pass options.tables.'
48
- );
49
- }
35
+ // The provider will dynamically discover tables during initialize().
36
+ this.tables = [];
50
37
 
51
38
  // Exact match fields can come from options.searchFields or be derived from VECTOR_DB_SEARCH_FIELDS env var
52
39
  const rawSearchFields: string | string[] =
@@ -57,6 +44,8 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
57
44
  this.searchFields = typeof rawSearchFields === 'string'
58
45
  ? rawSearchFields.split(',').map((f) => f.trim()).filter(Boolean)
59
46
  : rawSearchFields;
47
+
48
+ this.uploadTable = (opts.uploadTable as string) || 'document_chunks';
60
49
  }
61
50
 
62
51
  async initialize(): Promise<void> {
@@ -65,6 +54,24 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
65
54
  // Dynamically discover all tables that have an 'embedding' column
66
55
  const client: PoolClient = await this.pool.connect();
67
56
  try {
57
+ await client.query('CREATE EXTENSION IF NOT EXISTS vector');
58
+
59
+ // Ensure the upload table exists
60
+ await client.query(`
61
+ CREATE TABLE IF NOT EXISTS ${this.uploadTable} (
62
+ id TEXT PRIMARY KEY,
63
+ namespace TEXT NOT NULL DEFAULT '',
64
+ content TEXT NOT NULL,
65
+ metadata JSONB,
66
+ embedding VECTOR(${this.dimensions})
67
+ )
68
+ `);
69
+ await client.query(`
70
+ CREATE INDEX IF NOT EXISTS ${this.uploadTable}_embedding_idx
71
+ ON ${this.uploadTable}
72
+ USING hnsw (embedding vector_cosine_ops)
73
+ `);
74
+
68
75
  const res = await client.query(`
69
76
  SELECT table_name
70
77
  FROM information_schema.columns
@@ -72,21 +79,8 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
72
79
  AND table_schema = 'public'
73
80
  `);
74
81
 
75
- const discoveredTables = res.rows.map(r => r.table_name);
76
-
77
- if (this.tables.length === 0) {
78
- // No static tables configured, use everything discovered
79
- this.tables = discoveredTables;
80
- } else {
81
- // Filter configured tables to ensure they actually exist with embeddings
82
- const staticTables = [...this.tables];
83
- this.tables = staticTables.filter(t => discoveredTables.includes(t));
84
-
85
- if (this.tables.length < staticTables.length) {
86
- const missing = staticTables.filter(t => !discoveredTables.includes(t));
87
- console.warn(`[MultiTablePostgresProvider] Some configured tables were skipped (missing 'embedding' column): ${missing.join(', ')}`);
88
- }
89
- }
82
+ // Dynamically use all tables that have an embedding column
83
+ this.tables = res.rows.map(r => r.table_name);
90
84
 
91
85
  if (this.tables.length === 0) {
92
86
  console.warn('[MultiTablePostgresProvider] No tables with "embedding" columns found in the database.');
@@ -101,23 +95,125 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
101
95
  }
102
96
 
103
97
  /**
104
- * Upsert is not supported for MultiTablePostgresProvider as it's designed for
105
- * searching across pre-existing tables with varying schemas.
98
+ * Upsert a document by dynamically provisioning a table and columns.
106
99
  */
107
- async upsert(_doc: UpsertDocument, _namespace?: string): Promise<void> { // eslint-disable-line @typescript-eslint/no-unused-vars
108
- throw new Error(
109
- '[MultiTablePostgresProvider] upsert() is not supported in multi-table mode. ' +
110
- 'Please use the standard PostgreSQLProvider for single-table managed indices.'
111
- );
100
+ async upsert(doc: UpsertDocument, namespace = ''): Promise<void> {
101
+ await this.batchUpsert([doc], namespace);
112
102
  }
113
103
 
114
104
  /**
115
- * Batch upsert is not supported for MultiTablePostgresProvider.
105
+ * Batch upsert documents by dynamically provisioning tables and columns based on CSV headers.
116
106
  */
117
- async batchUpsert(_docs: UpsertDocument[], _namespace?: string): Promise<void> { // eslint-disable-line @typescript-eslint/no-unused-vars
118
- throw new Error(
119
- '[MultiTablePostgresProvider] batchUpsert() is not supported in multi-table mode.'
120
- );
107
+ async batchUpsert(docs: UpsertDocument[], namespace = ''): Promise<void> {
108
+ if (docs.length === 0) return;
109
+
110
+ // Group docs by fileName to support dynamic table creation per CSV
111
+ const docsByFile: Record<string, UpsertDocument[]> = {};
112
+ for (const doc of docs) {
113
+ const fileName = (doc.metadata?.fileName as string) || this.uploadTable;
114
+ if (!docsByFile[fileName]) docsByFile[fileName] = [];
115
+ docsByFile[fileName].push(doc);
116
+ }
117
+
118
+ const client = await this.pool.connect();
119
+ try {
120
+ await client.query('BEGIN');
121
+
122
+ for (const [fileName, fileDocs] of Object.entries(docsByFile)) {
123
+ // Sanitize table name (e.g., "jewelery.csv" -> "jewelery")
124
+ let tableName = fileName;
125
+ if (tableName.toLowerCase().endsWith('.csv')) {
126
+ tableName = tableName.slice(0, -4);
127
+ }
128
+ tableName = tableName.replace(/[^a-z0-9_]/gi, '_').toLowerCase() || this.uploadTable;
129
+
130
+ // Extract headers from the first doc's metadata
131
+ const firstMeta = fileDocs[0].metadata || {};
132
+ const systemKeys = ['fileName', 'fileSize', 'fileType', 'uploadedAt', 'dimension', 'chunkIndex', 'id', 'namespace', 'content', 'metadata', 'embedding'];
133
+ const csvHeaders = Object.keys(firstMeta).filter(k => !systemKeys.includes(k) && !systemKeys.includes(k.toLowerCase()));
134
+
135
+ // 1. Create Table Dynamically
136
+ const columnDefs = csvHeaders.map(h => `"${h}" TEXT`).join(',\n ');
137
+ const createTableSql = `
138
+ CREATE TABLE IF NOT EXISTS "${tableName}" (
139
+ id TEXT PRIMARY KEY,
140
+ ${columnDefs ? columnDefs + ',' : ''}
141
+ namespace TEXT NOT NULL DEFAULT '',
142
+ content TEXT NOT NULL,
143
+ metadata JSONB,
144
+ embedding VECTOR(${this.dimensions})
145
+ )
146
+ `;
147
+ await client.query(createTableSql);
148
+
149
+ // Create Index
150
+ await client.query(`
151
+ CREATE INDEX IF NOT EXISTS "${tableName}_embedding_idx"
152
+ ON "${tableName}"
153
+ USING hnsw (embedding vector_cosine_ops)
154
+ `);
155
+
156
+ // Ensure this new table is added to our search scope
157
+ if (!this.tables.includes(tableName)) {
158
+ this.tables.push(tableName);
159
+ }
160
+
161
+ // 2. Insert Data
162
+ const BATCH_SIZE = 50;
163
+ for (let i = 0; i < fileDocs.length; i += BATCH_SIZE) {
164
+ const batch = fileDocs.slice(i, i + BATCH_SIZE);
165
+ const values: unknown[] = [];
166
+
167
+ const headerColumns = csvHeaders.map(h => `"${h}"`).join(', ');
168
+ const allColumns = `id, ${headerColumns ? headerColumns + ', ' : ''}namespace, content, metadata, embedding`;
169
+
170
+ const valuePlaceholders = batch.map((doc, idx) => {
171
+ const offset = idx * (5 + csvHeaders.length);
172
+
173
+ values.push(doc.id);
174
+ // Push header values
175
+ for (const h of csvHeaders) {
176
+ values.push(String(doc.metadata?.[h] || ''));
177
+ }
178
+
179
+ values.push(namespace, doc.content, JSON.stringify(doc.metadata ?? {}), `[${doc.vector.join(',')}]`);
180
+
181
+ const docPlaceholders = [];
182
+ for (let j = 1; j <= 5 + csvHeaders.length; j++) {
183
+ if (j === 5 + csvHeaders.length) {
184
+ docPlaceholders.push(`$${offset + j}::vector`);
185
+ } else {
186
+ docPlaceholders.push(`$${offset + j}`);
187
+ }
188
+ }
189
+
190
+ return `(${docPlaceholders.join(', ')})`;
191
+ }).join(', ');
192
+
193
+ const conflictUpdates = csvHeaders.map(h => `"${h}" = EXCLUDED."${h}"`).join(',\n ');
194
+
195
+ const query = `
196
+ INSERT INTO "${tableName}" (${allColumns})
197
+ VALUES ${valuePlaceholders}
198
+ ON CONFLICT (id) DO UPDATE
199
+ SET ${conflictUpdates ? conflictUpdates + ',' : ''}
200
+ namespace = EXCLUDED.namespace,
201
+ content = EXCLUDED.content,
202
+ metadata = EXCLUDED.metadata,
203
+ embedding = EXCLUDED.embedding
204
+ `;
205
+
206
+ await client.query(query, values);
207
+ }
208
+ }
209
+
210
+ await client.query('COMMIT');
211
+ } catch (error) {
212
+ await client.query('ROLLBACK');
213
+ throw error;
214
+ } finally {
215
+ client.release();
216
+ }
121
217
  }
122
218
 
123
219
  /**
@@ -258,30 +354,20 @@ export class MultiTablePostgresProvider extends BaseVectorProvider {
258
354
  allResults.push(...tableResults);
259
355
  }
260
356
 
261
- // 1. Group results by table to ensure we take the top ones from each
262
- const resultsByTable: Record<string, VectorMatch[]> = {};
263
- for (const res of allResults) {
264
- const table = res.metadata?.source_table as string;
265
- if (!resultsByTable[table]) resultsByTable[table] = [];
266
- resultsByTable[table].push(res);
267
- }
268
-
269
- // 2. Take top 3 from EACH table guaranteed, then fill the rest with overall best
270
- const balancedResults: VectorMatch[] = [];
271
- const tables = Object.keys(resultsByTable);
357
+ // 1. Sort all results globally by semantic similarity score
358
+ allResults.sort((a, b) => b.score - a.score);
272
359
 
273
- // First, ensure every table's best match is included
274
- for (const table of tables) {
275
- balancedResults.push(...resultsByTable[table].slice(0, 3));
276
- }
360
+ if (allResults.length === 0) return [];
277
361
 
278
- // 3. Sort the balanced list by score
279
- const finalSorted = balancedResults.sort((a, b) => b.score - a.score);
362
+ // 2. Identify the "Active Table Context" from the absolute highest scoring match
363
+ const bestMatchTable = allResults[0].metadata?.source_table as string;
364
+
365
+ // 3. Filter out all results that don't belong to the active table to prevent cross-contamination
366
+ const finalSorted = allResults.filter(res => res.metadata?.source_table === bestMatchTable);
280
367
 
281
- if (finalSorted.length > 0) {
282
- console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
283
- console.log(`[MultiTablePostgresProvider] Final top match from "${finalSorted[0].metadata?.source_table ?? 'unknown'}" with score ${finalSorted[0].score.toFixed(4)}`);
284
- }
368
+ console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
369
+ console.log(`[MultiTablePostgresProvider] Final top match from "${bestMatchTable}" with score ${finalSorted[0].score.toFixed(4)}`);
370
+ console.log(`[MultiTablePostgresProvider] Restricting recommendations strictly to table: "${bestMatchTable}"`);
285
371
 
286
372
  return finalSorted.slice(0, Math.max(topK, 15));
287
373
  }
package/src/types/chat.ts CHANGED
@@ -11,6 +11,8 @@ export interface RagMessage extends ChatMessage {
11
11
  id: string;
12
12
  sources?: VectorMatch[];
13
13
  uiTransformation?: unknown;
14
+ /** Full observability trace emitted by the backend. Only present on assistant messages. */
15
+ trace?: import('./index').ObservabilityTrace;
14
16
  createdAt: string;
15
17
  }
16
18
 
@@ -1,3 +1,53 @@
1
+ // ─── Observability ────────────────────────────────────────────────────────────
2
+
3
+ /** Per-stage latency breakdown for a single RAG request. */
4
+ export interface LatencyBreakdown {
5
+ embedMs: number;
6
+ retrieveMs: number;
7
+ rerankMs?: number;
8
+ generateMs: number;
9
+ totalMs: number;
10
+ }
11
+
12
+ /** Token usage reported by the LLM (or estimated when the provider doesn't expose it). */
13
+ export interface TokenUsage {
14
+ promptTokens: number;
15
+ completionTokens: number;
16
+ totalTokens: number;
17
+ /** Rough cost in USD — estimated from token counts and model pricing. */
18
+ estimatedCostUsd?: number;
19
+ }
20
+
21
+ /** A single retrieved chunk annotated with its retrieval context. */
22
+ export interface RetrievedChunk {
23
+ id: string | number;
24
+ score: number;
25
+ content: string;
26
+ metadata: Record<string, unknown>;
27
+ namespace: string;
28
+ }
29
+
30
+ /**
31
+ * Full observability trace for one RAG request.
32
+ * Emitted by the backend as an SSE frame and stored on each RagMessage.
33
+ */
34
+ export interface ObservabilityTrace {
35
+ requestId: string;
36
+ query: string;
37
+ rewrittenQuery?: string;
38
+ systemPrompt: string;
39
+ userPrompt: string;
40
+ chunks: RetrievedChunk[];
41
+ latency: LatencyBreakdown;
42
+ tokens?: TokenUsage;
43
+ /** 0 = fully grounded, 1 = likely hallucinated. */
44
+ hallucinationScore?: number;
45
+ hallucinationReason?: string;
46
+ timestamp: string;
47
+ }
48
+
49
+ // ─── Vector / RAG ─────────────────────────────────────────────────────────────
50
+
1
51
  export interface VectorMatch {
2
52
  id: string | number;
3
53
  score: number;
@@ -23,6 +73,8 @@ export interface ChatResponse {
23
73
  sources: VectorMatch[];
24
74
  graphData?: GraphSearchResult;
25
75
  ui_transformation?: unknown;
76
+ /** Observability trace — populated by the instrumented Pipeline. */
77
+ trace?: ObservabilityTrace;
26
78
  }
27
79
 
28
80
  export interface GraphNode {
@@ -74,9 +74,17 @@ export interface SourceCardProps {
74
74
  export interface ClientConfig {
75
75
  projectId: string;
76
76
  ui: Required<UIConfig>;
77
+ embedding?: {
78
+ model?: string;
79
+ dimensions?: number;
80
+ };
77
81
  }
78
82
 
79
83
  export interface ConfigProviderProps {
80
- config?: { projectId?: string; ui?: Partial<UIConfig> };
84
+ config?: {
85
+ projectId?: string;
86
+ ui?: Partial<UIConfig>;
87
+ embedding?: { model?: string; dimensions?: number }
88
+ };
81
89
  children: ReactNode;
82
90
  }