@realtimex/email-automator 2.11.2 → 2.11.3
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/api/src/services/SDKService.ts +18 -7
- package/api/src/services/intelligence.ts +160 -22
- package/api/src/services/processor.ts +9 -2
- package/dist/api/src/services/SDKService.js +18 -7
- package/dist/api/src/services/intelligence.js +153 -21
- package/dist/api/src/services/processor.js +8 -2
- package/dist/assets/{index-BuWrl4UD.js → index-BgMWzGP9.js} +3 -3
- package/dist/index.html +1 -1
- package/package.json +1 -1
|
@@ -161,9 +161,10 @@ export class SDKService {
|
|
|
161
161
|
|
|
162
162
|
this.defaultChatProvider = {
|
|
163
163
|
provider: preferredProvider.provider,
|
|
164
|
-
model: preferredModel.id
|
|
164
|
+
model: preferredModel.id,
|
|
165
|
+
isDefaultFallback: false
|
|
165
166
|
};
|
|
166
|
-
logger.info(`Using preferred
|
|
167
|
+
logger.info(`Using preferred chat provider: ${this.defaultChatProvider.provider}/${this.defaultChatProvider.model}`);
|
|
167
168
|
return this.defaultChatProvider;
|
|
168
169
|
}
|
|
169
170
|
|
|
@@ -172,7 +173,8 @@ export class SDKService {
|
|
|
172
173
|
if (p.models && p.models.length > 0) {
|
|
173
174
|
this.defaultChatProvider = {
|
|
174
175
|
provider: p.provider,
|
|
175
|
-
model: p.models[0].id
|
|
176
|
+
model: p.models[0].id,
|
|
177
|
+
isDefaultFallback: true
|
|
176
178
|
};
|
|
177
179
|
logger.info(`Defaulting to first available chat provider: ${this.defaultChatProvider.provider}/${this.defaultChatProvider.model}`);
|
|
178
180
|
return this.defaultChatProvider;
|
|
@@ -221,9 +223,10 @@ export class SDKService {
|
|
|
221
223
|
if (p.models && p.models.length > 0) {
|
|
222
224
|
this.defaultEmbedProvider = {
|
|
223
225
|
provider: p.provider,
|
|
224
|
-
model: p.models[0].id
|
|
226
|
+
model: p.models[0].id,
|
|
227
|
+
isDefaultFallback: true
|
|
225
228
|
};
|
|
226
|
-
logger.info(`
|
|
229
|
+
logger.info(`Selected embed provider: ${this.defaultEmbedProvider.provider}/${this.defaultEmbedProvider.model}`);
|
|
227
230
|
return this.defaultEmbedProvider;
|
|
228
231
|
}
|
|
229
232
|
}
|
|
@@ -245,7 +248,11 @@ export class SDKService {
|
|
|
245
248
|
static async resolveChatProvider(settings: { llm_provider?: string; llm_model?: string }): Promise<ProviderResult> {
|
|
246
249
|
// If both provider and model are set in settings, use them
|
|
247
250
|
if (settings.llm_provider && settings.llm_model) {
|
|
248
|
-
return {
|
|
251
|
+
return {
|
|
252
|
+
provider: settings.llm_provider,
|
|
253
|
+
model: settings.llm_model,
|
|
254
|
+
isDefaultFallback: false
|
|
255
|
+
};
|
|
249
256
|
}
|
|
250
257
|
|
|
251
258
|
// Try to get from SDK discovery first
|
|
@@ -258,7 +265,11 @@ export class SDKService {
|
|
|
258
265
|
static async resolveEmbedProvider(settings: { embedding_provider?: string; embedding_model?: string }): Promise<ProviderResult> {
|
|
259
266
|
// If both provider and model are set in settings, use them
|
|
260
267
|
if (settings.embedding_provider && settings.embedding_model) {
|
|
261
|
-
return {
|
|
268
|
+
return {
|
|
269
|
+
provider: settings.embedding_provider,
|
|
270
|
+
model: settings.embedding_model,
|
|
271
|
+
isDefaultFallback: false
|
|
272
|
+
};
|
|
262
273
|
}
|
|
263
274
|
|
|
264
275
|
// Try to get from SDK discovery first
|
|
@@ -91,7 +91,7 @@ export class IntelligenceService {
|
|
|
91
91
|
return this.isConfigured && !!SDKService.getSDK();
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
async analyzeEmail(content: string, context: EmailContext, eventLogger?: EventLogger, emailId?: string): Promise<(EmailAnalysis & { _metadata?: any }) | null> {
|
|
94
|
+
async analyzeEmail(content: string, context: EmailContext, eventLogger?: EventLogger, emailId?: string, llmSettings?: { llm_provider?: string; llm_model?: string }): Promise<(EmailAnalysis & { _metadata?: any }) | null> {
|
|
95
95
|
const sdk = SDKService.getSDK();
|
|
96
96
|
if (!sdk) {
|
|
97
97
|
logger.warn('Intelligence service not ready, skipping analysis');
|
|
@@ -101,7 +101,10 @@ export class IntelligenceService {
|
|
|
101
101
|
return null;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const { provider, model, isDefaultFallback } = await SDKService.resolveChatProvider({
|
|
104
|
+
const { provider, model, isDefaultFallback } = await SDKService.resolveChatProvider({
|
|
105
|
+
llm_provider: llmSettings?.llm_provider,
|
|
106
|
+
llm_model: llmSettings?.llm_model
|
|
107
|
+
});
|
|
105
108
|
|
|
106
109
|
const cleanedContent = ContentCleaner.cleanEmailBody(content).substring(0, 2500);
|
|
107
110
|
|
|
@@ -134,10 +137,10 @@ REQUIRED JSON STRUCTURE:
|
|
|
134
137
|
|
|
135
138
|
if (eventLogger) {
|
|
136
139
|
await eventLogger.info('Thinking', `Analyzing email: ${context.subject}`, {
|
|
137
|
-
model
|
|
138
|
-
provider,
|
|
140
|
+
provider: `${provider}/${model}`,
|
|
139
141
|
is_fallback: isDefaultFallback,
|
|
140
|
-
|
|
142
|
+
signals: metadataSignals,
|
|
143
|
+
content_preview: cleanedContent.substring(0, 100) + '...'
|
|
141
144
|
}, emailId);
|
|
142
145
|
}
|
|
143
146
|
|
|
@@ -147,8 +150,27 @@ REQUIRED JSON STRUCTURE:
|
|
|
147
150
|
{ role: 'user', content: cleanedContent || '[Empty body]' }
|
|
148
151
|
], { provider, model });
|
|
149
152
|
|
|
153
|
+
// Check if SDK call failed
|
|
154
|
+
if (!response.success || response.error) {
|
|
155
|
+
const errorMsg = response.error || 'Unknown SDK error';
|
|
156
|
+
logger.error('SDK chat failed for email analysis', {
|
|
157
|
+
provider,
|
|
158
|
+
model,
|
|
159
|
+
error: errorMsg,
|
|
160
|
+
code: response.code
|
|
161
|
+
});
|
|
162
|
+
if (eventLogger) await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
150
166
|
const rawResponse = response.response?.content || '';
|
|
151
|
-
|
|
167
|
+
if (!rawResponse) {
|
|
168
|
+
logger.warn('SDK returned empty response for analysis', { provider, model });
|
|
169
|
+
if (eventLogger) await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const validated = this.parseRobustJSON<EmailAnalysis>(rawResponse, EmailAnalysisSchema, eventLogger, emailId);
|
|
152
174
|
|
|
153
175
|
const result = validated ? {
|
|
154
176
|
...validated,
|
|
@@ -165,6 +187,11 @@ REQUIRED JSON STRUCTURE:
|
|
|
165
187
|
...result,
|
|
166
188
|
_raw_response: rawResponse
|
|
167
189
|
});
|
|
190
|
+
} else if (eventLogger && !result) {
|
|
191
|
+
await eventLogger.error('Malformed Response', {
|
|
192
|
+
message: 'AI returned data that did not match the required schema',
|
|
193
|
+
raw_response: rawResponse.substring(0, 500)
|
|
194
|
+
}, emailId);
|
|
168
195
|
}
|
|
169
196
|
|
|
170
197
|
return result;
|
|
@@ -177,12 +204,16 @@ REQUIRED JSON STRUCTURE:
|
|
|
177
204
|
|
|
178
205
|
async generateDraftReply(
|
|
179
206
|
originalEmail: { subject: string; sender: string; body: string },
|
|
180
|
-
instructions?: string
|
|
207
|
+
instructions?: string,
|
|
208
|
+
llmSettings?: { llm_provider?: string; llm_model?: string }
|
|
181
209
|
): Promise<string | null> {
|
|
182
210
|
const sdk = SDKService.getSDK();
|
|
183
211
|
if (!sdk) return null;
|
|
184
212
|
|
|
185
|
-
const { provider, model } = await SDKService.resolveChatProvider({
|
|
213
|
+
const { provider, model } = await SDKService.resolveChatProvider({
|
|
214
|
+
llm_provider: llmSettings?.llm_provider,
|
|
215
|
+
llm_model: llmSettings?.llm_model
|
|
216
|
+
});
|
|
186
217
|
|
|
187
218
|
try {
|
|
188
219
|
const response = await sdk.llm.chat([
|
|
@@ -196,6 +227,17 @@ REQUIRED JSON STRUCTURE:
|
|
|
196
227
|
},
|
|
197
228
|
], { provider, model });
|
|
198
229
|
|
|
230
|
+
// Check if SDK call failed
|
|
231
|
+
if (!response.success || response.error) {
|
|
232
|
+
logger.error('SDK chat failed for draft generation', {
|
|
233
|
+
provider,
|
|
234
|
+
model,
|
|
235
|
+
error: response.error,
|
|
236
|
+
code: response.code
|
|
237
|
+
});
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
|
|
199
241
|
return response.response?.content || null;
|
|
200
242
|
} catch (error) {
|
|
201
243
|
logger.error('Draft generation failed', error);
|
|
@@ -208,12 +250,16 @@ REQUIRED JSON STRUCTURE:
|
|
|
208
250
|
context: EmailContext,
|
|
209
251
|
compiledRulesContext: string | RuleContext[],
|
|
210
252
|
eventLogger?: EventLogger,
|
|
211
|
-
emailId?: string
|
|
253
|
+
emailId?: string,
|
|
254
|
+
llmSettings?: { llm_provider?: string; llm_model?: string }
|
|
212
255
|
): Promise<(ContextAwareAnalysis & { _metadata?: any }) | null> {
|
|
213
256
|
const sdk = SDKService.getSDK();
|
|
214
257
|
if (!sdk) return null;
|
|
215
258
|
|
|
216
|
-
const { provider, model, isDefaultFallback } = await SDKService.resolveChatProvider({
|
|
259
|
+
const { provider, model, isDefaultFallback } = await SDKService.resolveChatProvider({
|
|
260
|
+
llm_provider: llmSettings?.llm_provider,
|
|
261
|
+
llm_model: llmSettings?.llm_model
|
|
262
|
+
});
|
|
217
263
|
const cleanedContent = ContentCleaner.cleanEmailBody(content).substring(0, 2500);
|
|
218
264
|
|
|
219
265
|
let rulesContext: string;
|
|
@@ -223,24 +269,71 @@ REQUIRED JSON STRUCTURE:
|
|
|
223
269
|
rulesContext = compiledRulesContext.map(r => `- ${r.name}: ${r.intent}`).join('\n');
|
|
224
270
|
}
|
|
225
271
|
|
|
226
|
-
const systemPrompt = `You are an AI Automation Agent.
|
|
272
|
+
const systemPrompt = `You are an AI Automation Agent. Analyze the email and match it against the user's rules.
|
|
273
|
+
|
|
274
|
+
Rules Context:
|
|
275
|
+
${rulesContext}
|
|
276
|
+
|
|
277
|
+
REQUIRED JSON STRUCTURE:
|
|
278
|
+
{
|
|
279
|
+
"summary": "A brief summary of the email content",
|
|
280
|
+
"category": "spam|newsletter|promotional|transactional|social|support|client|internal|personal|other",
|
|
281
|
+
"priority": "High|Medium|Low",
|
|
282
|
+
"matched_rule": {
|
|
283
|
+
"rule_id": "string or null",
|
|
284
|
+
"rule_name": "string or null",
|
|
285
|
+
"confidence": 0.0 to 1.0,
|
|
286
|
+
"reasoning": "Brief explanation"
|
|
287
|
+
},
|
|
288
|
+
"actions_to_execute": ["none"|"delete"|"archive"|"draft"|"read"|"star"],
|
|
289
|
+
"draft_content": "Suggested reply if drafting, otherwise null"
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
IMPORTANT:
|
|
293
|
+
- Use "draft" action only if a rule explicitly requests it or if it's very clear a reply is needed.
|
|
294
|
+
- Categorize accurately.
|
|
295
|
+
- Confidence 0.7+ is required for automatic execution.`;
|
|
227
296
|
|
|
228
297
|
if (eventLogger) {
|
|
229
298
|
await eventLogger.info('Thinking', `Context-aware analysis: ${context.subject}`, {
|
|
230
|
-
model
|
|
231
|
-
|
|
232
|
-
|
|
299
|
+
provider: `${provider}/${model}`,
|
|
300
|
+
is_fallback: isDefaultFallback,
|
|
301
|
+
rules_count: Array.isArray(compiledRulesContext) ? compiledRulesContext.length : 'compiled'
|
|
233
302
|
}, emailId);
|
|
234
303
|
}
|
|
235
304
|
|
|
236
305
|
try {
|
|
306
|
+
logger.debug('Calling SDK chat for rule analysis', { provider, model, promptLength: systemPrompt.length });
|
|
237
307
|
const response = await sdk.llm.chat([
|
|
238
308
|
{ role: 'system', content: systemPrompt },
|
|
239
309
|
{ role: 'user', content: cleanedContent || '[Empty body]' }
|
|
240
310
|
], { provider, model });
|
|
241
311
|
|
|
312
|
+
// Check if SDK call failed
|
|
313
|
+
if (!response.success || response.error) {
|
|
314
|
+
const errorMsg = response.error || 'Unknown SDK error';
|
|
315
|
+
logger.error('SDK chat failed for rule analysis', {
|
|
316
|
+
provider,
|
|
317
|
+
model,
|
|
318
|
+
error: errorMsg,
|
|
319
|
+
code: response.code
|
|
320
|
+
});
|
|
321
|
+
if (eventLogger) await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
|
|
242
325
|
const rawResponse = response.response?.content || '';
|
|
243
|
-
|
|
326
|
+
if (!rawResponse) {
|
|
327
|
+
logger.warn('SDK returned empty response for rule analysis', {
|
|
328
|
+
provider,
|
|
329
|
+
model,
|
|
330
|
+
success: response.success
|
|
331
|
+
});
|
|
332
|
+
if (eventLogger) await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const validated = this.parseRobustJSON<ContextAwareAnalysis>(rawResponse, ContextAwareAnalysisSchema, eventLogger, emailId);
|
|
244
337
|
|
|
245
338
|
const result = validated ? {
|
|
246
339
|
...validated,
|
|
@@ -257,12 +350,23 @@ REQUIRED JSON STRUCTURE:
|
|
|
257
350
|
...result,
|
|
258
351
|
_raw_response: rawResponse
|
|
259
352
|
});
|
|
353
|
+
} else if (eventLogger && !result) {
|
|
354
|
+
await eventLogger.error('Malformed Response', {
|
|
355
|
+
message: 'AI returned rule analysis that did not match the required schema',
|
|
356
|
+
raw_response: rawResponse.substring(0, 500)
|
|
357
|
+
}, emailId);
|
|
260
358
|
}
|
|
261
359
|
|
|
262
360
|
return result;
|
|
263
361
|
} catch (error: any) {
|
|
264
|
-
logger.error('Rule analysis failed',
|
|
265
|
-
|
|
362
|
+
logger.error('Rule analysis failed', {
|
|
363
|
+
error: error.message,
|
|
364
|
+
stack: error.stack,
|
|
365
|
+
provider,
|
|
366
|
+
model,
|
|
367
|
+
errorType: error.constructor.name
|
|
368
|
+
});
|
|
369
|
+
if (eventLogger) await eventLogger.error('Error', `${error.message} (${provider}/${model})`, emailId);
|
|
266
370
|
return null;
|
|
267
371
|
}
|
|
268
372
|
}
|
|
@@ -283,14 +387,48 @@ REQUIRED JSON STRUCTURE:
|
|
|
283
387
|
}
|
|
284
388
|
}
|
|
285
389
|
|
|
286
|
-
private parseRobustJSON<T>(input: string, schema: z.ZodSchema<T
|
|
390
|
+
private parseRobustJSON<T>(input: string, schema: z.ZodSchema<T>, eventLogger?: EventLogger, emailId?: string): T | null {
|
|
287
391
|
try {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
392
|
+
// 1. Remove common LLM artifacts and markdown blocks
|
|
393
|
+
let cleaned = input.trim();
|
|
394
|
+
|
|
395
|
+
// Handle markdown blocks
|
|
396
|
+
if (cleaned.includes('```json')) {
|
|
397
|
+
cleaned = cleaned.split('```json')[1].split('```')[0].trim();
|
|
398
|
+
} else if (cleaned.includes('```')) {
|
|
399
|
+
cleaned = cleaned.split('```')[1].split('```')[0].trim();
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 2. Extract the first { ... } block if visible
|
|
403
|
+
const jsonMatch = cleaned.match(/\{[\s\S]*\}/);
|
|
404
|
+
if (jsonMatch) {
|
|
405
|
+
cleaned = jsonMatch[0];
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 3. Strip aggressive local LLM tokens
|
|
409
|
+
cleaned = cleaned.replace(/<\|[\s\S]*?\|>/g, '').trim();
|
|
410
|
+
|
|
411
|
+
// 4. Parse and Normalize
|
|
291
412
|
const parsed = JSON.parse(cleaned);
|
|
413
|
+
|
|
414
|
+
// Normalize actions_to_execute: convert string to array if needed
|
|
415
|
+
if (parsed && typeof parsed === 'object' && 'actions_to_execute' in parsed) {
|
|
416
|
+
if (typeof parsed.actions_to_execute === 'string') {
|
|
417
|
+
parsed.actions_to_execute = [parsed.actions_to_execute];
|
|
418
|
+
logger.debug('Normalized actions_to_execute from string to array', { original: parsed.actions_to_execute[0] });
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// 5. Validate with Zod
|
|
292
423
|
return schema.parse(parsed);
|
|
293
|
-
} catch (e) {
|
|
424
|
+
} catch (e: any) {
|
|
425
|
+
logger.error('JSON Robust Parsing failed', { error: e.message, input: input.substring(0, 200) });
|
|
426
|
+
if (eventLogger && emailId) {
|
|
427
|
+
eventLogger.error('JSON Parse Error', {
|
|
428
|
+
error: e.message,
|
|
429
|
+
raw_input_preview: input.substring(0, 500)
|
|
430
|
+
}, emailId).catch(() => { });
|
|
431
|
+
}
|
|
294
432
|
return null;
|
|
295
433
|
}
|
|
296
434
|
}
|
|
@@ -651,7 +651,11 @@ export class EmailProcessorService {
|
|
|
651
651
|
},
|
|
652
652
|
compiledContext || '', // Pre-compiled context (fast path)
|
|
653
653
|
eventLogger || undefined,
|
|
654
|
-
email.id
|
|
654
|
+
email.id,
|
|
655
|
+
{
|
|
656
|
+
llm_provider: settings?.llm_provider,
|
|
657
|
+
llm_model: settings?.llm_model
|
|
658
|
+
}
|
|
655
659
|
);
|
|
656
660
|
|
|
657
661
|
if (!analysis) {
|
|
@@ -789,7 +793,10 @@ export class EmailProcessorService {
|
|
|
789
793
|
subject: email.subject || '',
|
|
790
794
|
sender: email.sender || '',
|
|
791
795
|
body: email.body_snippet || ''
|
|
792
|
-
}, rule.instructions
|
|
796
|
+
}, rule.instructions, {
|
|
797
|
+
llm_provider: settings?.llm_provider,
|
|
798
|
+
llm_model: settings?.llm_model
|
|
799
|
+
});
|
|
793
800
|
|
|
794
801
|
if (customizedDraft) {
|
|
795
802
|
draftContent = customizedDraft;
|
|
@@ -133,9 +133,10 @@ export class SDKService {
|
|
|
133
133
|
const preferredModel = preferredProvider.models.find(m => m.id === this.DEFAULT_LLM_MODEL) || preferredProvider.models[0];
|
|
134
134
|
this.defaultChatProvider = {
|
|
135
135
|
provider: preferredProvider.provider,
|
|
136
|
-
model: preferredModel.id
|
|
136
|
+
model: preferredModel.id,
|
|
137
|
+
isDefaultFallback: false
|
|
137
138
|
};
|
|
138
|
-
logger.info(`Using preferred
|
|
139
|
+
logger.info(`Using preferred chat provider: ${this.defaultChatProvider.provider}/${this.defaultChatProvider.model}`);
|
|
139
140
|
return this.defaultChatProvider;
|
|
140
141
|
}
|
|
141
142
|
// 2. Fallback to the first provider with available models
|
|
@@ -143,7 +144,8 @@ export class SDKService {
|
|
|
143
144
|
if (p.models && p.models.length > 0) {
|
|
144
145
|
this.defaultChatProvider = {
|
|
145
146
|
provider: p.provider,
|
|
146
|
-
model: p.models[0].id
|
|
147
|
+
model: p.models[0].id,
|
|
148
|
+
isDefaultFallback: true
|
|
147
149
|
};
|
|
148
150
|
logger.info(`Defaulting to first available chat provider: ${this.defaultChatProvider.provider}/${this.defaultChatProvider.model}`);
|
|
149
151
|
return this.defaultChatProvider;
|
|
@@ -183,9 +185,10 @@ export class SDKService {
|
|
|
183
185
|
if (p.models && p.models.length > 0) {
|
|
184
186
|
this.defaultEmbedProvider = {
|
|
185
187
|
provider: p.provider,
|
|
186
|
-
model: p.models[0].id
|
|
188
|
+
model: p.models[0].id,
|
|
189
|
+
isDefaultFallback: true
|
|
187
190
|
};
|
|
188
|
-
logger.info(`
|
|
191
|
+
logger.info(`Selected embed provider: ${this.defaultEmbedProvider.provider}/${this.defaultEmbedProvider.model}`);
|
|
189
192
|
return this.defaultEmbedProvider;
|
|
190
193
|
}
|
|
191
194
|
}
|
|
@@ -206,7 +209,11 @@ export class SDKService {
|
|
|
206
209
|
static async resolveChatProvider(settings) {
|
|
207
210
|
// If both provider and model are set in settings, use them
|
|
208
211
|
if (settings.llm_provider && settings.llm_model) {
|
|
209
|
-
return {
|
|
212
|
+
return {
|
|
213
|
+
provider: settings.llm_provider,
|
|
214
|
+
model: settings.llm_model,
|
|
215
|
+
isDefaultFallback: false
|
|
216
|
+
};
|
|
210
217
|
}
|
|
211
218
|
// Try to get from SDK discovery first
|
|
212
219
|
return await this.getDefaultChatProvider();
|
|
@@ -217,7 +224,11 @@ export class SDKService {
|
|
|
217
224
|
static async resolveEmbedProvider(settings) {
|
|
218
225
|
// If both provider and model are set in settings, use them
|
|
219
226
|
if (settings.embedding_provider && settings.embedding_model) {
|
|
220
|
-
return {
|
|
227
|
+
return {
|
|
228
|
+
provider: settings.embedding_provider,
|
|
229
|
+
model: settings.embedding_model,
|
|
230
|
+
isDefaultFallback: false
|
|
231
|
+
};
|
|
221
232
|
}
|
|
222
233
|
// Try to get from SDK discovery first
|
|
223
234
|
return await this.getDefaultEmbedProvider();
|