@realtimex/email-automator 2.23.9 → 2.23.10

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.
@@ -252,21 +252,27 @@ REQUIRED JSON STRUCTURE:
252
252
  // Check if SDK call failed
253
253
  if (!response.success || response.error) {
254
254
  const errorMsg = response.error || 'Unknown SDK error';
255
- logger.error('SDK chat failed for email analysis', {
255
+ logger.error('SDK chat failed for email analysis, using fallback', {
256
256
  provider,
257
257
  model,
258
258
  error: errorMsg,
259
259
  code: response.code
260
260
  });
261
- if (eventLogger) await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
262
- return null;
261
+ if (eventLogger) {
262
+ await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
263
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to SDK error', undefined, emailId);
264
+ }
265
+ return this.createFallbackAnalysis(context, cleanedContent);
263
266
  }
264
267
 
265
268
  const rawResponse = response.response?.content || '';
266
269
  if (!rawResponse) {
267
- logger.warn('SDK returned empty response for analysis', { provider, model });
268
- if (eventLogger) await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
269
- return null;
270
+ logger.warn('SDK returned empty response for analysis, using fallback', { provider, model });
271
+ if (eventLogger) {
272
+ await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
273
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to empty response', undefined, emailId);
274
+ }
275
+ return this.createFallbackAnalysis(context, cleanedContent);
270
276
  }
271
277
 
272
278
  const validated = this.parseRobustJSON<EmailAnalysis>(rawResponse, EmailAnalysisSchema, eventLogger, emailId);
@@ -585,30 +591,89 @@ CRITICAL INSTRUCTIONS:
585
591
  // Check if SDK call failed
586
592
  if (!response.success || response.error) {
587
593
  const errorMsg = response.error || 'Unknown SDK error';
588
- logger.error('SDK chat failed for rule analysis', {
594
+ logger.error('SDK chat failed for rule analysis, using fallback', {
589
595
  provider,
590
596
  model,
591
597
  error: errorMsg,
592
598
  code: response.code
593
599
  });
594
- if (eventLogger) await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
595
- return null;
600
+ if (eventLogger) {
601
+ await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
602
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to SDK error', undefined, emailId);
603
+ }
604
+ // Return fallback analysis wrapped in ContextAwareAnalysis structure
605
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
606
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive' as const] : [];
607
+ return {
608
+ ...fallbackAnalysis,
609
+ matched_rules: [],
610
+ actions_to_execute: actions,
611
+ _metadata: {
612
+ provider,
613
+ model,
614
+ is_fallback: true,
615
+ timestamp: new Date().toISOString()
616
+ }
617
+ };
596
618
  }
597
619
 
598
620
  const rawResponse = response.response?.content || '';
599
621
  if (!rawResponse) {
600
- logger.warn('SDK returned empty response for rule analysis', {
622
+ logger.warn('SDK returned empty response for rule analysis, using fallback', {
601
623
  provider,
602
624
  model,
603
625
  success: response.success
604
626
  });
605
- if (eventLogger) await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
606
- return null;
627
+ if (eventLogger) {
628
+ await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
629
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to empty response', undefined, emailId);
630
+ }
631
+ // Return fallback analysis wrapped in ContextAwareAnalysis structure
632
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
633
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive' as const] : [];
634
+ return {
635
+ ...fallbackAnalysis,
636
+ matched_rules: [],
637
+ actions_to_execute: actions,
638
+ _metadata: {
639
+ provider,
640
+ model,
641
+ is_fallback: true,
642
+ timestamp: new Date().toISOString()
643
+ }
644
+ };
607
645
  }
608
646
 
609
647
  const validated = this.parseRobustJSON<ContextAwareAnalysis>(rawResponse, ContextAwareAnalysisSchema, eventLogger, emailId);
610
648
 
611
- const result = validated ? {
649
+ if (!validated) {
650
+ // JSON parsing failed - use fallback
651
+ logger.warn('JSON parsing failed for rule analysis, using fallback', { provider, model });
652
+ if (eventLogger) {
653
+ await eventLogger.error('Malformed Response', {
654
+ message: 'AI returned rule analysis that did not match the required schema',
655
+ raw_response: rawResponse.substring(0, 500),
656
+ system_prompt: systemPrompt,
657
+ content_preview: cleanedContent?.substring(0, 500) || '[Empty]'
658
+ }, emailId);
659
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to malformed response', undefined, emailId);
660
+ }
661
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
662
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive' as const] : [];
663
+ return {
664
+ ...fallbackAnalysis,
665
+ matched_rules: [],
666
+ actions_to_execute: actions,
667
+ _metadata: {
668
+ provider,
669
+ model,
670
+ is_fallback: true,
671
+ timestamp: new Date().toISOString()
672
+ }
673
+ };
674
+ }
675
+
676
+ const result = {
612
677
  ...validated,
613
678
  _metadata: {
614
679
  provider,
@@ -616,9 +681,9 @@ CRITICAL INSTRUCTIONS:
616
681
  is_fallback: isDefaultFallback,
617
682
  timestamp: new Date().toISOString()
618
683
  }
619
- } : null;
684
+ };
620
685
 
621
- if (eventLogger && emailId && result) {
686
+ if (eventLogger && emailId) {
622
687
  // Clean raw response for logging (remove markdown code fences)
623
688
  let cleanedRawResponse = rawResponse.trim();
624
689
  if (cleanedRawResponse.includes('```json')) {
@@ -633,13 +698,6 @@ CRITICAL INSTRUCTIONS:
633
698
  content_preview: cleanedContent?.substring(0, 500) || '[Empty]',
634
699
  _raw_response: cleanedRawResponse
635
700
  });
636
- } else if (eventLogger && !result) {
637
- await eventLogger.error('Malformed Response', {
638
- message: 'AI returned rule analysis that did not match the required schema',
639
- raw_response: rawResponse.substring(0, 500),
640
- system_prompt: systemPrompt,
641
- content_preview: cleanedContent?.substring(0, 500) || '[Empty]'
642
- }, emailId);
643
701
  }
644
702
 
645
703
  return result;
@@ -203,22 +203,26 @@ REQUIRED JSON STRUCTURE:
203
203
  // Check if SDK call failed
204
204
  if (!response.success || response.error) {
205
205
  const errorMsg = response.error || 'Unknown SDK error';
206
- logger.error('SDK chat failed for email analysis', {
206
+ logger.error('SDK chat failed for email analysis, using fallback', {
207
207
  provider,
208
208
  model,
209
209
  error: errorMsg,
210
210
  code: response.code
211
211
  });
212
- if (eventLogger)
212
+ if (eventLogger) {
213
213
  await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
214
- return null;
214
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to SDK error', undefined, emailId);
215
+ }
216
+ return this.createFallbackAnalysis(context, cleanedContent);
215
217
  }
216
218
  const rawResponse = response.response?.content || '';
217
219
  if (!rawResponse) {
218
- logger.warn('SDK returned empty response for analysis', { provider, model });
219
- if (eventLogger)
220
+ logger.warn('SDK returned empty response for analysis, using fallback', { provider, model });
221
+ if (eventLogger) {
220
222
  await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
221
- return null;
223
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to empty response', undefined, emailId);
224
+ }
225
+ return this.createFallbackAnalysis(context, cleanedContent);
222
226
  }
223
227
  const validated = this.parseRobustJSON(rawResponse, EmailAnalysisSchema, eventLogger, emailId);
224
228
  const result = validated ? {
@@ -472,29 +476,85 @@ CRITICAL INSTRUCTIONS:
472
476
  // Check if SDK call failed
473
477
  if (!response.success || response.error) {
474
478
  const errorMsg = response.error || 'Unknown SDK error';
475
- logger.error('SDK chat failed for rule analysis', {
479
+ logger.error('SDK chat failed for rule analysis, using fallback', {
476
480
  provider,
477
481
  model,
478
482
  error: errorMsg,
479
483
  code: response.code
480
484
  });
481
- if (eventLogger)
485
+ if (eventLogger) {
482
486
  await eventLogger.error('SDK Error', `${errorMsg} (${provider}/${model})`, emailId);
483
- return null;
487
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to SDK error', undefined, emailId);
488
+ }
489
+ // Return fallback analysis wrapped in ContextAwareAnalysis structure
490
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
491
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive'] : [];
492
+ return {
493
+ ...fallbackAnalysis,
494
+ matched_rules: [],
495
+ actions_to_execute: actions,
496
+ _metadata: {
497
+ provider,
498
+ model,
499
+ is_fallback: true,
500
+ timestamp: new Date().toISOString()
501
+ }
502
+ };
484
503
  }
485
504
  const rawResponse = response.response?.content || '';
486
505
  if (!rawResponse) {
487
- logger.warn('SDK returned empty response for rule analysis', {
506
+ logger.warn('SDK returned empty response for rule analysis, using fallback', {
488
507
  provider,
489
508
  model,
490
509
  success: response.success
491
510
  });
492
- if (eventLogger)
511
+ if (eventLogger) {
493
512
  await eventLogger.error('Empty Response', `LLM (${provider}/${model}) returned no content`, emailId);
494
- return null;
513
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to empty response', undefined, emailId);
514
+ }
515
+ // Return fallback analysis wrapped in ContextAwareAnalysis structure
516
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
517
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive'] : [];
518
+ return {
519
+ ...fallbackAnalysis,
520
+ matched_rules: [],
521
+ actions_to_execute: actions,
522
+ _metadata: {
523
+ provider,
524
+ model,
525
+ is_fallback: true,
526
+ timestamp: new Date().toISOString()
527
+ }
528
+ };
495
529
  }
496
530
  const validated = this.parseRobustJSON(rawResponse, ContextAwareAnalysisSchema, eventLogger, emailId);
497
- const result = validated ? {
531
+ if (!validated) {
532
+ // JSON parsing failed - use fallback
533
+ logger.warn('JSON parsing failed for rule analysis, using fallback', { provider, model });
534
+ if (eventLogger) {
535
+ await eventLogger.error('Malformed Response', {
536
+ message: 'AI returned rule analysis that did not match the required schema',
537
+ raw_response: rawResponse.substring(0, 500),
538
+ system_prompt: systemPrompt,
539
+ content_preview: cleanedContent?.substring(0, 500) || '[Empty]'
540
+ }, emailId);
541
+ await eventLogger.info('Fallback', 'Using heuristic analysis due to malformed response', undefined, emailId);
542
+ }
543
+ const fallbackAnalysis = this.createFallbackAnalysis(context, cleanedContent);
544
+ const actions = fallbackAnalysis.suggested_actions?.includes('archive') ? ['archive'] : [];
545
+ return {
546
+ ...fallbackAnalysis,
547
+ matched_rules: [],
548
+ actions_to_execute: actions,
549
+ _metadata: {
550
+ provider,
551
+ model,
552
+ is_fallback: true,
553
+ timestamp: new Date().toISOString()
554
+ }
555
+ };
556
+ }
557
+ const result = {
498
558
  ...validated,
499
559
  _metadata: {
500
560
  provider,
@@ -502,8 +562,8 @@ CRITICAL INSTRUCTIONS:
502
562
  is_fallback: isDefaultFallback,
503
563
  timestamp: new Date().toISOString()
504
564
  }
505
- } : null;
506
- if (eventLogger && emailId && result) {
565
+ };
566
+ if (eventLogger && emailId) {
507
567
  // Clean raw response for logging (remove markdown code fences)
508
568
  let cleanedRawResponse = rawResponse.trim();
509
569
  if (cleanedRawResponse.includes('```json')) {
@@ -519,14 +579,6 @@ CRITICAL INSTRUCTIONS:
519
579
  _raw_response: cleanedRawResponse
520
580
  });
521
581
  }
522
- else if (eventLogger && !result) {
523
- await eventLogger.error('Malformed Response', {
524
- message: 'AI returned rule analysis that did not match the required schema',
525
- raw_response: rawResponse.substring(0, 500),
526
- system_prompt: systemPrompt,
527
- content_preview: cleanedContent?.substring(0, 500) || '[Empty]'
528
- }, emailId);
529
- }
530
582
  return result;
531
583
  }
532
584
  catch (error) {