@retrivora-ai/rag-engine 1.0.4 → 1.0.5

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 (39) hide show
  1. package/dist/DocumentChunker-Dh9TvmGG.d.mts +45 -0
  2. package/dist/DocumentChunker-Dh9TvmGG.d.ts +45 -0
  3. package/dist/{RagConfig-DRJO4hGU.d.mts → RagConfig-BEmz4hVP.d.mts} +58 -1
  4. package/dist/{RagConfig-DRJO4hGU.d.ts → RagConfig-BEmz4hVP.d.ts} +58 -1
  5. package/dist/{chunk-6MLZHQZT.mjs → chunk-MWL4AGQI.mjs} +189 -98
  6. package/dist/handlers/index.d.mts +2 -2
  7. package/dist/handlers/index.d.ts +2 -2
  8. package/dist/handlers/index.js +191 -100
  9. package/dist/handlers/index.mjs +11 -3
  10. package/dist/index-CSfaCeux.d.ts +206 -0
  11. package/dist/index-DFSy0CG6.d.mts +206 -0
  12. package/dist/index.d.mts +3 -4
  13. package/dist/index.d.ts +3 -4
  14. package/dist/index.js +103 -89
  15. package/dist/index.mjs +91 -95
  16. package/dist/server.d.mts +45 -97
  17. package/dist/server.d.ts +45 -97
  18. package/dist/server.js +271 -215
  19. package/dist/server.mjs +78 -167
  20. package/package.json +12 -10
  21. package/src/components/ChatWindow.tsx +2 -2
  22. package/src/components/ConfigProvider.tsx +2 -2
  23. package/src/components/MessageBubble.tsx +2 -2
  24. package/src/components/SourceCard.tsx +1 -1
  25. package/src/components/ThemeToggle.tsx +1 -1
  26. package/src/config/ConfigBuilder.ts +86 -211
  27. package/src/config/uiConstants.ts +23 -0
  28. package/src/core/ConfigResolver.ts +57 -29
  29. package/src/core/LangChainAgent.ts +73 -40
  30. package/src/core/Pipeline.ts +63 -7
  31. package/src/core/ProviderRegistry.ts +2 -2
  32. package/src/core/QueryProcessor.ts +9 -8
  33. package/src/handlers/index.ts +138 -49
  34. package/src/hooks/useRagChat.ts +71 -32
  35. package/src/server.ts +12 -2
  36. package/dist/DocumentChunker-C-sCZPhi.d.mts +0 -102
  37. package/dist/DocumentChunker-C-sCZPhi.d.ts +0 -102
  38. package/dist/index-B2mutkgp.d.ts +0 -116
  39. package/dist/index-Bjy0es5a.d.mts +0 -116
@@ -8,7 +8,7 @@
8
8
  * - Fluent API for easy configuration
9
9
  * - Type-safe provider selection
10
10
  * - Automatic environment variable resolution
11
- * - Built-in validation
11
+ * - Built-in validation at build() time
12
12
  * - Support for presets
13
13
  *
14
14
  * @example
@@ -22,23 +22,31 @@
22
22
  * const plugin = new VectorPlugin(config);
23
23
  */
24
24
 
25
- import { RagConfig, VectorDBConfig, LLMConfig, EmbeddingConfig, VectorDBProvider, LLMProvider, EmbeddingProvider } from './RagConfig';
25
+ import {
26
+ RagConfig,
27
+ VectorDBConfig,
28
+ LLMConfig,
29
+ EmbeddingConfig,
30
+ UIConfig,
31
+ RAGConfig,
32
+ VectorDBProvider,
33
+ LLMProvider,
34
+ EmbeddingProvider,
35
+ } from './RagConfig';
26
36
 
27
37
  export class ConfigBuilder {
28
- private config: Partial<RagConfig> = {
29
- projectId: 'default-project',
30
- rag: {
31
- chunkSize: 1000,
32
- chunkOverlap: 200,
33
- topK: 5,
34
- },
35
- };
38
+ private _projectId?: string;
39
+ private _vectorDb?: VectorDBConfig;
40
+ private _llm?: LLMConfig;
41
+ private _embedding?: EmbeddingConfig;
42
+ private _ui?: UIConfig;
43
+ private _rag?: RAGConfig;
36
44
 
37
45
  /**
38
46
  * Set the project/application ID for namespacing
39
47
  */
40
48
  projectId(id: string): this {
41
- this.config.projectId = id;
49
+ this._projectId = id;
42
50
  return this;
43
51
  }
44
52
 
@@ -50,15 +58,12 @@ export class ConfigBuilder {
50
58
  options?: Record<string, unknown>
51
59
  ): this {
52
60
  if (provider === 'auto') {
53
- // Auto-detect from environment
54
- this.config.vectorDb = this.autoDetectVectorDb();
61
+ this._vectorDb = this._autoDetectVectorDb();
55
62
  } else {
56
- this.config.vectorDb = {
63
+ this._vectorDb = {
57
64
  provider: provider as VectorDBProvider,
58
65
  indexName: (options?.indexName as string) ?? 'default',
59
- options: {
60
- ...options,
61
- },
66
+ options: { ...options },
62
67
  };
63
68
  }
64
69
  return this;
@@ -74,9 +79,9 @@ export class ConfigBuilder {
74
79
  options?: Record<string, unknown>
75
80
  ): this {
76
81
  if (provider === 'auto') {
77
- this.config.llm = this.autoDetectLLM();
82
+ this._llm = this._autoDetectLLM();
78
83
  } else {
79
- this.config.llm = {
84
+ this._llm = {
80
85
  provider: provider as LLMProvider,
81
86
  model: model ?? 'default-model',
82
87
  apiKey,
@@ -100,9 +105,9 @@ export class ConfigBuilder {
100
105
  options?: Record<string, unknown>
101
106
  ): this {
102
107
  if (provider === 'auto') {
103
- this.config.embedding = this.autoDetectEmbedding();
108
+ this._embedding = this._autoDetectEmbedding();
104
109
  } else {
105
- this.config.embedding = {
110
+ this._embedding = {
106
111
  provider: provider as EmbeddingProvider,
107
112
  model: model ?? 'default-embedding',
108
113
  apiKey,
@@ -114,40 +119,48 @@ export class ConfigBuilder {
114
119
  }
115
120
 
116
121
  /**
117
- * Set RAG-specific parameters
122
+ * Set RAG-specific pipeline parameters
118
123
  */
119
- rag(options: {
120
- chunkSize?: number;
121
- chunkOverlap?: number;
122
- topK?: number;
123
- }): this {
124
- this.config.rag = {
125
- ...(this.config.rag ?? {}),
126
- ...options,
127
- };
124
+ rag(options: RAGConfig): this {
125
+ this._rag = { ...(this._rag ?? {}), ...options };
128
126
  return this;
129
127
  }
130
128
 
131
129
  /**
132
- * Set UI/UX parameters
130
+ * Set UI branding and appearance options.
131
+ * Accepts the full UIConfig interface.
133
132
  */
134
- ui(options: {
135
- branding?: string;
136
- primaryColor?: string;
137
- darkMode?: boolean;
138
- }): this {
139
- this.config.ui = options;
133
+ ui(options: UIConfig): this {
134
+ this._ui = options;
140
135
  return this;
141
136
  }
142
137
 
143
-
144
-
145
138
  /**
146
- * Build and return the configuration
139
+ * Build and return the final RagConfig.
140
+ * Throws if required fields (projectId, vectorDb, llm, embedding) are not set.
147
141
  */
148
142
  build(): RagConfig {
149
- const finalConfig = this.config as RagConfig;
150
- return finalConfig;
143
+ const missing: string[] = [];
144
+ if (!this._projectId) missing.push('projectId (call .projectId("my-app"))');
145
+ if (!this._vectorDb) missing.push('vectorDb (call .vectorDb("pinecone", { ... }))');
146
+ if (!this._llm) missing.push('llm (call .llm("openai", "gpt-4o", apiKey))');
147
+ if (!this._embedding) missing.push('embedding (call .embedding("openai", "text-embedding-3-small"))');
148
+
149
+ if (missing.length > 0) {
150
+ throw new Error(
151
+ `[ConfigBuilder] Cannot build — required fields are missing:\n ${missing.join('\n ')}`
152
+ );
153
+ }
154
+
155
+ return {
156
+ projectId: this._projectId!,
157
+ vectorDb: this._vectorDb!,
158
+ llm: this._llm!,
159
+ embedding: this._embedding!,
160
+ ui: this._rag ? this._ui : undefined,
161
+ rag: this._rag ?? { chunkSize: 1000, chunkOverlap: 200, topK: 5 },
162
+ ...(this._ui ? { ui: this._ui } : {}),
163
+ };
151
164
  }
152
165
 
153
166
  /**
@@ -161,133 +174,43 @@ export class ConfigBuilder {
161
174
  // Private helper methods for auto-detection
162
175
  // ============================================================================
163
176
 
164
- private autoDetectVectorDb(): VectorDBConfig {
165
- // Check for Pinecone
177
+ private _autoDetectVectorDb(): VectorDBConfig {
166
178
  if (process.env.PINECONE_API_KEY && process.env.PINECONE_INDEX) {
167
- return {
168
- provider: 'pinecone',
169
- indexName: process.env.PINECONE_INDEX,
170
- options: { apiKey: process.env.PINECONE_API_KEY },
171
- };
179
+ return { provider: 'pinecone', indexName: process.env.PINECONE_INDEX, options: { apiKey: process.env.PINECONE_API_KEY } };
172
180
  }
173
-
174
- // Check for Qdrant
175
181
  if (process.env.QDRANT_URL) {
176
- return {
177
- provider: 'qdrant',
178
- indexName: process.env.QDRANT_COLLECTION || 'documents',
179
- options: {
180
- url: process.env.QDRANT_URL,
181
- apiKey: process.env.QDRANT_API_KEY,
182
- },
183
- };
182
+ return { provider: 'qdrant', indexName: process.env.QDRANT_COLLECTION || 'documents', options: { url: process.env.QDRANT_URL, apiKey: process.env.QDRANT_API_KEY } };
184
183
  }
185
-
186
- // Check for PostgreSQL/pgvector
187
184
  if (process.env.DATABASE_URL) {
188
- return {
189
- provider: 'postgresql',
190
- indexName: process.env.PG_TABLE || 'documents',
191
- options: {
192
- connectionString: process.env.DATABASE_URL,
193
- },
194
- };
185
+ return { provider: 'postgresql', indexName: process.env.PG_TABLE || 'documents', options: { connectionString: process.env.DATABASE_URL } };
195
186
  }
196
-
197
- // Check for MongoDB
198
187
  if (process.env.MONGODB_URI) {
199
- return {
200
- provider: 'mongodb',
201
- indexName: process.env.MONGODB_COLLECTION || 'documents',
202
- options: {
203
- uri: process.env.MONGODB_URI,
204
- database: process.env.MONGODB_DB || 'ai_db',
205
- collection: process.env.MONGODB_COLLECTION || 'documents',
206
- },
207
- };
188
+ return { provider: 'mongodb', indexName: process.env.MONGODB_COLLECTION || 'documents', options: { uri: process.env.MONGODB_URI, database: process.env.MONGODB_DB || 'ai_db', collection: process.env.MONGODB_COLLECTION || 'documents' } };
208
189
  }
209
-
210
- // Check for Redis
211
190
  if (process.env.REDIS_URL) {
212
- return {
213
- provider: 'redis',
214
- indexName: process.env.REDIS_INDEX || 'documents',
215
- options: {
216
- url: process.env.REDIS_URL,
217
- },
218
- };
191
+ return { provider: 'redis', indexName: process.env.REDIS_INDEX || 'documents', options: { url: process.env.REDIS_URL } };
219
192
  }
220
-
221
- // Default to Qdrant localhost
222
- return {
223
- provider: 'qdrant',
224
- indexName: 'documents',
225
- options: {
226
- url: process.env.QDRANT_URL || 'http://localhost:6333',
227
- },
228
- };
193
+ return { provider: 'qdrant', indexName: 'documents', options: { url: process.env.QDRANT_URL || 'http://localhost:6333' } };
229
194
  }
230
195
 
231
- private autoDetectLLM(): LLMConfig {
232
- // Check for OpenAI
196
+ private _autoDetectLLM(): LLMConfig {
233
197
  if (process.env.OPENAI_API_KEY) {
234
- return {
235
- provider: 'openai',
236
- model: process.env.OPENAI_MODEL || 'gpt-4o-mini',
237
- apiKey: process.env.OPENAI_API_KEY,
238
- maxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || '1024'),
239
- temperature: parseFloat(process.env.OPENAI_TEMPERATURE || '0.7'),
240
- };
198
+ return { provider: 'openai', model: process.env.OPENAI_MODEL || 'gpt-4o-mini', apiKey: process.env.OPENAI_API_KEY, maxTokens: parseInt(process.env.OPENAI_MAX_TOKENS || '1024'), temperature: parseFloat(process.env.OPENAI_TEMPERATURE || '0.7') };
241
199
  }
242
-
243
- // Check for Anthropic
244
200
  if (process.env.ANTHROPIC_API_KEY) {
245
- return {
246
- provider: 'anthropic',
247
- model: process.env.ANTHROPIC_MODEL || 'claude-3-haiku-20240307',
248
- apiKey: process.env.ANTHROPIC_API_KEY,
249
- maxTokens: parseInt(process.env.ANTHROPIC_MAX_TOKENS || '1024'),
250
- temperature: parseFloat(process.env.ANTHROPIC_TEMPERATURE || '0.7'),
251
- };
201
+ return { provider: 'anthropic', model: process.env.ANTHROPIC_MODEL || 'claude-3-haiku-20240307', apiKey: process.env.ANTHROPIC_API_KEY, maxTokens: parseInt(process.env.ANTHROPIC_MAX_TOKENS || '1024'), temperature: parseFloat(process.env.ANTHROPIC_TEMPERATURE || '0.7') };
252
202
  }
253
-
254
- // Check for Ollama
255
203
  if (process.env.OLLAMA_BASE_URL) {
256
- return {
257
- provider: 'ollama',
258
- model: process.env.OLLAMA_MODEL || 'mistral',
259
- baseUrl: process.env.OLLAMA_BASE_URL,
260
- maxTokens: parseInt(process.env.OLLAMA_MAX_TOKENS || '1024'),
261
- temperature: parseFloat(process.env.OLLAMA_TEMPERATURE || '0.7'),
262
- };
204
+ return { provider: 'ollama', model: process.env.OLLAMA_MODEL || 'mistral', baseUrl: process.env.OLLAMA_BASE_URL, maxTokens: parseInt(process.env.OLLAMA_MAX_TOKENS || '1024'), temperature: parseFloat(process.env.OLLAMA_TEMPERATURE || '0.7') };
263
205
  }
264
-
265
- // Default to OpenAI (requires API key at runtime)
266
- return {
267
- provider: 'openai',
268
- model: 'gpt-4o-mini',
269
- apiKey: process.env.OPENAI_API_KEY,
270
- };
206
+ return { provider: 'openai', model: 'gpt-4o-mini', apiKey: process.env.OPENAI_API_KEY };
271
207
  }
272
208
 
273
- private autoDetectEmbedding(): EmbeddingConfig {
274
- // Check for dedicated embedding provider
209
+ private _autoDetectEmbedding(): EmbeddingConfig {
275
210
  if (process.env.EMBEDDING_PROVIDER) {
276
- const provider = process.env.EMBEDDING_PROVIDER as EmbeddingProvider;
277
- return {
278
- provider,
279
- model: process.env.EMBEDDING_MODEL || 'default',
280
- apiKey: process.env.EMBEDDING_API_KEY,
281
- baseUrl: process.env.EMBEDDING_BASE_URL,
282
- };
211
+ return { provider: process.env.EMBEDDING_PROVIDER as EmbeddingProvider, model: process.env.EMBEDDING_MODEL || 'default', apiKey: process.env.EMBEDDING_API_KEY, baseUrl: process.env.EMBEDDING_BASE_URL };
283
212
  }
284
-
285
- // Default to OpenAI embeddings
286
- return {
287
- provider: 'openai',
288
- model: 'text-embedding-3-small',
289
- apiKey: process.env.OPENAI_API_KEY,
290
- };
213
+ return { provider: 'openai', model: 'text-embedding-3-small', apiKey: process.env.OPENAI_API_KEY };
291
214
  }
292
215
  }
293
216
 
@@ -295,74 +218,26 @@ export class ConfigBuilder {
295
218
  * Preset configurations for common provider combinations
296
219
  */
297
220
  export const PRESETS = {
298
- /**
299
- * OpenAI + Pinecone: Production-ready cloud setup
300
- */
301
- 'openai-pinecone': {
302
- vectorDb: 'pinecone' as const,
303
- llm: 'openai' as const,
304
- embedding: 'openai' as const,
305
- },
306
-
307
- /**
308
- * Claude + Qdrant: Open-source vector DB + proprietary LLM
309
- */
310
- 'claude-qdrant': {
311
- vectorDb: 'qdrant' as const,
312
- llm: 'anthropic' as const,
313
- embedding: 'openai' as const,
314
- },
315
-
316
- /**
317
- * Local development: Ollama + local Qdrant
318
- */
319
- 'local-dev': {
320
- vectorDb: 'qdrant' as const,
321
- llm: 'ollama' as const,
322
- embedding: 'ollama' as const,
323
- },
324
-
325
- /**
326
- * Fully open-source: Ollama LLM + Qdrant vector DB + Ollama embeddings
327
- */
328
- 'fully-open-source': {
329
- vectorDb: 'qdrant' as const,
330
- llm: 'ollama' as const,
331
- embedding: 'ollama' as const,
332
- },
333
-
334
- /**
335
- * PostgreSQL stack: pgvector + OpenAI
336
- */
337
- 'postgres-openai': {
338
- vectorDb: 'postgresql' as const,
339
- llm: 'openai' as const,
340
- embedding: 'openai' as const,
341
- },
342
-
343
- /**
344
- * Enterprise MongoDB: MongoDB Atlas with OpenAI
345
- */
346
- 'mongodb-openai': {
347
- vectorDb: 'mongodb' as const,
348
- llm: 'openai' as const,
349
- embedding: 'openai' as const,
350
- },
351
-
352
- /**
353
- * Redis stack for caching + search
354
- */
355
- 'redis-openai': {
356
- vectorDb: 'redis' as const,
357
- llm: 'openai' as const,
358
- embedding: 'openai' as const,
359
- },
221
+ /** OpenAI + Pinecone: Production-ready cloud setup */
222
+ 'openai-pinecone': { vectorDb: 'pinecone' as const, llm: 'openai' as const, embedding: 'openai' as const },
223
+ /** Claude + Qdrant: Open-source vector DB + proprietary LLM */
224
+ 'claude-qdrant': { vectorDb: 'qdrant' as const, llm: 'anthropic' as const, embedding: 'openai' as const },
225
+ /** Local development: Ollama + local Qdrant */
226
+ 'local-dev': { vectorDb: 'qdrant' as const, llm: 'ollama' as const, embedding: 'ollama' as const },
227
+ /** Fully open-source: Ollama LLM + Qdrant + Ollama embeddings */
228
+ 'fully-open-source': { vectorDb: 'qdrant' as const, llm: 'ollama' as const, embedding: 'ollama' as const },
229
+ /** PostgreSQL stack: pgvector + OpenAI */
230
+ 'postgres-openai': { vectorDb: 'postgresql' as const, llm: 'openai' as const, embedding: 'openai' as const },
231
+ /** Enterprise MongoDB: MongoDB Atlas with OpenAI */
232
+ 'mongodb-openai': { vectorDb: 'mongodb' as const, llm: 'openai' as const, embedding: 'openai' as const },
233
+ /** Redis stack for caching + search */
234
+ 'redis-openai': { vectorDb: 'redis' as const, llm: 'openai' as const, embedding: 'openai' as const },
360
235
  } as const;
361
236
 
362
237
  export type PresetName = keyof typeof PRESETS;
363
238
 
364
239
  /**
365
- * Helper to create config from preset
240
+ * Helper to create a ConfigBuilder pre-seeded with a named preset.
366
241
  */
367
242
  export function createFromPreset(presetName: PresetName): ConfigBuilder {
368
243
  const preset = PRESETS[presetName];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * uiConstants.ts — UI-specific constants for the package's React components.
3
+ *
4
+ * Kept inside the package src so they resolve correctly when the package
5
+ * is consumed via npm without Next.js path-alias configuration.
6
+ */
7
+
8
+ /** Maps the `borderRadius` config value to a Tailwind class. */
9
+ export const BORDER_RADIUS_MAP: Record<string, string> = {
10
+ none: 'rounded-none',
11
+ sm: 'rounded-sm',
12
+ md: 'rounded-md',
13
+ lg: 'rounded-lg',
14
+ xl: 'rounded-xl',
15
+ full: 'rounded-3xl',
16
+ };
17
+
18
+ /** Default suggested prompts shown on the chat welcome screen. */
19
+ export const CHAT_SUGGESTIONS: string[] = [
20
+ 'What can you help me with?',
21
+ 'Summarise the key topics',
22
+ 'Show me an example',
23
+ ];
@@ -1,52 +1,80 @@
1
+ /**
2
+ * ConfigResolver — validates and normalizes host configuration.
3
+ * It merges host-provided config with environment defaults.
4
+ *
5
+ * The `getRagConfig()` result is memoized at module level so that
6
+ * environment variables are only parsed once per process, avoiding
7
+ * repeated work in serverless cold starts and per-request handler calls.
8
+ */
1
9
  import { RagConfig } from '../config/RagConfig';
2
10
  import { mergeDefined } from '../utils/templateUtils';
3
11
  import { getRagConfig as getEnvConfig } from '../config/serverConfig';
4
12
 
13
+ /** Module-level cache: populated on first use, shared across all VectorPlugin instances. */
14
+ let _cachedEnvConfig: RagConfig | null = null;
15
+
16
+ function getCachedEnvConfig(): RagConfig {
17
+ if (!_cachedEnvConfig) {
18
+ _cachedEnvConfig = getEnvConfig();
19
+ }
20
+ return _cachedEnvConfig;
21
+ }
22
+
5
23
  /**
6
- * ConfigResolver validates and normalizes host configuration.
7
- * It merges host-provided config with environment defaults.
24
+ * Reset the cached env config. Useful in tests where environment variables
25
+ * change between test cases.
8
26
  */
27
+ export function resetConfigCache(): void {
28
+ _cachedEnvConfig = null;
29
+ }
30
+
9
31
  export class ConfigResolver {
10
32
  /**
11
- * Resolves the final configuration by merging host-provided config with defaults.
33
+ * Resolves the final configuration by merging host-provided config with environment defaults.
12
34
  * @param hostConfig - Partial configuration passed from the host application.
13
35
  */
14
36
  static resolve(hostConfig?: Partial<RagConfig>): RagConfig {
15
- const envConfig = getEnvConfig();
37
+ const envConfig = getCachedEnvConfig();
16
38
 
17
39
  if (!hostConfig) {
18
40
  return envConfig;
19
41
  }
20
42
 
21
- // Deep merge or specific merging logic
43
+ // Deep merge: host config wins over env config at every level
22
44
  return {
23
45
  ...envConfig,
24
46
  ...hostConfig,
25
47
  projectId: hostConfig.projectId || envConfig.projectId,
26
- vectorDb: hostConfig.vectorDb ? {
27
- ...envConfig.vectorDb,
28
- ...hostConfig.vectorDb,
29
- options: {
30
- ...envConfig.vectorDb.options,
31
- ...(hostConfig.vectorDb.options || {})
32
- }
33
- } : envConfig.vectorDb,
34
- llm: hostConfig.llm ? {
35
- ...envConfig.llm,
36
- ...hostConfig.llm,
37
- options: {
38
- ...(envConfig.llm.options || {}),
39
- ...(hostConfig.llm.options || {})
40
- }
41
- } : envConfig.llm,
42
- embedding: hostConfig.embedding ? {
43
- ...envConfig.embedding,
44
- ...hostConfig.embedding,
45
- options: {
46
- ...(envConfig.embedding.options || {}),
47
- ...(hostConfig.embedding.options || {})
48
- }
49
- } : envConfig.embedding,
48
+ vectorDb: hostConfig.vectorDb
49
+ ? {
50
+ ...envConfig.vectorDb,
51
+ ...hostConfig.vectorDb,
52
+ options: {
53
+ ...envConfig.vectorDb.options,
54
+ ...(hostConfig.vectorDb.options || {}),
55
+ },
56
+ }
57
+ : envConfig.vectorDb,
58
+ llm: hostConfig.llm
59
+ ? {
60
+ ...envConfig.llm,
61
+ ...hostConfig.llm,
62
+ options: {
63
+ ...(envConfig.llm.options || {}),
64
+ ...(hostConfig.llm.options || {}),
65
+ },
66
+ }
67
+ : envConfig.llm,
68
+ embedding: hostConfig.embedding
69
+ ? {
70
+ ...envConfig.embedding,
71
+ ...hostConfig.embedding,
72
+ options: {
73
+ ...(envConfig.embedding.options || {}),
74
+ ...(hostConfig.embedding.options || {}),
75
+ },
76
+ }
77
+ : envConfig.embedding,
50
78
  ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
51
79
  rag: hostConfig.rag ? { ...envConfig.rag, ...hostConfig.rag } : envConfig.rag,
52
80
  };