@realtimex/email-automator 2.21.1 → 2.21.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/routes/drafts.ts +1 -33
- package/api/src/services/processor.ts +30 -1
- package/api/src/services/supabase.ts +2 -2
- package/dist/api/src/routes/drafts.js +1 -29
- package/dist/api/src/services/processor.js +27 -1
- package/dist/api/src/services/supabase.js +2 -2
- package/dist/assets/{index-CP8zE58U.js → index-L-bedZY8.js} +3 -3
- package/dist/index.html +1 -1
- package/package.json +1 -1
package/api/src/routes/drafts.ts
CHANGED
|
@@ -45,44 +45,12 @@ router.get('/',
|
|
|
45
45
|
|
|
46
46
|
if (error) throw error;
|
|
47
47
|
|
|
48
|
-
// Debug: Log draft content structure for first few emails
|
|
49
|
-
if (data && data.length > 0) {
|
|
50
|
-
logger.info(`Found ${data.length} drafts with draft_status='${status}'`);
|
|
51
|
-
data.slice(0, 3).forEach((email, idx) => {
|
|
52
|
-
const aiAnalysis = email.ai_analysis as any;
|
|
53
|
-
logger.debug(`Draft ${idx + 1} content check`, {
|
|
54
|
-
emailId: email.id,
|
|
55
|
-
hasDraftContent: !!email.draft_content,
|
|
56
|
-
hasAiAnalysis: !!email.ai_analysis,
|
|
57
|
-
aiAnalysisKeys: email.ai_analysis ? Object.keys(email.ai_analysis) : [],
|
|
58
|
-
hasDraftResponse: !!aiAnalysis?.draft_response,
|
|
59
|
-
hasDraftContentInAi: !!aiAnalysis?.draft_content,
|
|
60
|
-
draftResponseLength: aiAnalysis?.draft_response?.length || 0,
|
|
61
|
-
draftContentLength: aiAnalysis?.draft_content?.length || 0,
|
|
62
|
-
persistedDraftLength: email.draft_content?.length || 0
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
48
|
// Filter out drafts without content (these can't be sent)
|
|
68
49
|
const validDrafts = (data || []).filter(email => {
|
|
69
50
|
const aiAnalysis = email.ai_analysis as any;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!hasContent) {
|
|
73
|
-
logger.debug('Draft without content filtered out', {
|
|
74
|
-
emailId: email.id,
|
|
75
|
-
subject: email.subject,
|
|
76
|
-
hasAiAnalysis: !!email.ai_analysis,
|
|
77
|
-
aiAnalysisKeys: email.ai_analysis ? Object.keys(email.ai_analysis) : []
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return hasContent;
|
|
51
|
+
return email.draft_content || aiAnalysis?.draft_response || aiAnalysis?.draft_content;
|
|
82
52
|
});
|
|
83
53
|
|
|
84
|
-
logger.info(`Returning ${validDrafts.length} valid drafts out of ${data?.length || 0} total`);
|
|
85
|
-
|
|
86
54
|
res.json({
|
|
87
55
|
drafts: validDrafts,
|
|
88
56
|
total: validDrafts.length
|
|
@@ -736,8 +736,36 @@ export class EmailProcessorService {
|
|
|
736
736
|
let conditionText = '';
|
|
737
737
|
if (r.condition) {
|
|
738
738
|
const cond = r.condition as any;
|
|
739
|
+
|
|
740
|
+
// Handle new simple condition format: {"category": "news"}
|
|
741
|
+
if (cond.category) {
|
|
742
|
+
conditionText = `When category is "${cond.category}"`;
|
|
743
|
+
}
|
|
744
|
+
if (cond.sentiment) {
|
|
745
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sentiment is "${cond.sentiment}"`;
|
|
746
|
+
}
|
|
747
|
+
if (cond.priority) {
|
|
748
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `priority is "${cond.priority}"`;
|
|
749
|
+
}
|
|
750
|
+
if (cond.sender_email) {
|
|
751
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender is "${cond.sender_email}"`;
|
|
752
|
+
}
|
|
753
|
+
if (cond.sender_domain) {
|
|
754
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender domain is "${cond.sender_domain}"`;
|
|
755
|
+
}
|
|
756
|
+
if (cond.sender_contains) {
|
|
757
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender contains "${cond.sender_contains}"`;
|
|
758
|
+
}
|
|
759
|
+
if (cond.subject_contains) {
|
|
760
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `subject contains "${cond.subject_contains}"`;
|
|
761
|
+
}
|
|
762
|
+
if (cond.body_contains) {
|
|
763
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `body contains "${cond.body_contains}"`;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Handle legacy format with field/operator/value
|
|
739
767
|
if (cond.field) {
|
|
740
|
-
conditionText
|
|
768
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + cond.field;
|
|
741
769
|
if (cond.operator === 'equals') {
|
|
742
770
|
conditionText += ` equals "${cond.value}"`;
|
|
743
771
|
} else if (cond.operator === 'contains') {
|
|
@@ -748,6 +776,7 @@ export class EmailProcessorService {
|
|
|
748
776
|
conditionText += ` ${cond.operator} "${cond.value}"`;
|
|
749
777
|
}
|
|
750
778
|
}
|
|
779
|
+
|
|
751
780
|
if (cond.is_useless === true) {
|
|
752
781
|
conditionText += (conditionText ? ' AND ' : 'When ') + 'email is useless/low-value';
|
|
753
782
|
}
|
|
@@ -30,7 +30,7 @@ export function getServerSupabase(forceRefresh = false): SupabaseClient | null {
|
|
|
30
30
|
const key = config.supabase.anonKey;
|
|
31
31
|
|
|
32
32
|
if (!url || !key || !isValidUrl(url)) {
|
|
33
|
-
|
|
33
|
+
// BYOK mode: Supabase configured via UI, not .env - this is expected
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -56,7 +56,7 @@ export function getServiceRoleSupabase(): SupabaseClient | null {
|
|
|
56
56
|
const key = config.supabase.serviceRoleKey;
|
|
57
57
|
|
|
58
58
|
if (!url || !key || !isValidUrl(url)) {
|
|
59
|
-
|
|
59
|
+
// BYOK mode: Service role Supabase configured via UI, not .env - this is expected
|
|
60
60
|
return null;
|
|
61
61
|
}
|
|
62
62
|
|
|
@@ -28,39 +28,11 @@ router.get('/', apiRateLimit, authMiddleware, asyncHandler(async (req, res) => {
|
|
|
28
28
|
const { data, error, count } = await query;
|
|
29
29
|
if (error)
|
|
30
30
|
throw error;
|
|
31
|
-
// Debug: Log draft content structure for first few emails
|
|
32
|
-
if (data && data.length > 0) {
|
|
33
|
-
logger.info(`Found ${data.length} drafts with draft_status='${status}'`);
|
|
34
|
-
data.slice(0, 3).forEach((email, idx) => {
|
|
35
|
-
const aiAnalysis = email.ai_analysis;
|
|
36
|
-
logger.debug(`Draft ${idx + 1} content check`, {
|
|
37
|
-
emailId: email.id,
|
|
38
|
-
hasDraftContent: !!email.draft_content,
|
|
39
|
-
hasAiAnalysis: !!email.ai_analysis,
|
|
40
|
-
aiAnalysisKeys: email.ai_analysis ? Object.keys(email.ai_analysis) : [],
|
|
41
|
-
hasDraftResponse: !!aiAnalysis?.draft_response,
|
|
42
|
-
hasDraftContentInAi: !!aiAnalysis?.draft_content,
|
|
43
|
-
draftResponseLength: aiAnalysis?.draft_response?.length || 0,
|
|
44
|
-
draftContentLength: aiAnalysis?.draft_content?.length || 0,
|
|
45
|
-
persistedDraftLength: email.draft_content?.length || 0
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
31
|
// Filter out drafts without content (these can't be sent)
|
|
50
32
|
const validDrafts = (data || []).filter(email => {
|
|
51
33
|
const aiAnalysis = email.ai_analysis;
|
|
52
|
-
|
|
53
|
-
if (!hasContent) {
|
|
54
|
-
logger.debug('Draft without content filtered out', {
|
|
55
|
-
emailId: email.id,
|
|
56
|
-
subject: email.subject,
|
|
57
|
-
hasAiAnalysis: !!email.ai_analysis,
|
|
58
|
-
aiAnalysisKeys: email.ai_analysis ? Object.keys(email.ai_analysis) : []
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
return hasContent;
|
|
34
|
+
return email.draft_content || aiAnalysis?.draft_response || aiAnalysis?.draft_content;
|
|
62
35
|
});
|
|
63
|
-
logger.info(`Returning ${validDrafts.length} valid drafts out of ${data?.length || 0} total`);
|
|
64
36
|
res.json({
|
|
65
37
|
drafts: validDrafts,
|
|
66
38
|
total: validDrafts.length
|
|
@@ -612,8 +612,34 @@ export class EmailProcessorService {
|
|
|
612
612
|
let conditionText = '';
|
|
613
613
|
if (r.condition) {
|
|
614
614
|
const cond = r.condition;
|
|
615
|
+
// Handle new simple condition format: {"category": "news"}
|
|
616
|
+
if (cond.category) {
|
|
617
|
+
conditionText = `When category is "${cond.category}"`;
|
|
618
|
+
}
|
|
619
|
+
if (cond.sentiment) {
|
|
620
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sentiment is "${cond.sentiment}"`;
|
|
621
|
+
}
|
|
622
|
+
if (cond.priority) {
|
|
623
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `priority is "${cond.priority}"`;
|
|
624
|
+
}
|
|
625
|
+
if (cond.sender_email) {
|
|
626
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender is "${cond.sender_email}"`;
|
|
627
|
+
}
|
|
628
|
+
if (cond.sender_domain) {
|
|
629
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender domain is "${cond.sender_domain}"`;
|
|
630
|
+
}
|
|
631
|
+
if (cond.sender_contains) {
|
|
632
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `sender contains "${cond.sender_contains}"`;
|
|
633
|
+
}
|
|
634
|
+
if (cond.subject_contains) {
|
|
635
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `subject contains "${cond.subject_contains}"`;
|
|
636
|
+
}
|
|
637
|
+
if (cond.body_contains) {
|
|
638
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + `body contains "${cond.body_contains}"`;
|
|
639
|
+
}
|
|
640
|
+
// Handle legacy format with field/operator/value
|
|
615
641
|
if (cond.field) {
|
|
616
|
-
conditionText
|
|
642
|
+
conditionText += (conditionText ? ' AND ' : 'When ') + cond.field;
|
|
617
643
|
if (cond.operator === 'equals') {
|
|
618
644
|
conditionText += ` equals "${cond.value}"`;
|
|
619
645
|
}
|
|
@@ -23,7 +23,7 @@ export function getServerSupabase(forceRefresh = false) {
|
|
|
23
23
|
const url = config.supabase.url;
|
|
24
24
|
const key = config.supabase.anonKey;
|
|
25
25
|
if (!url || !key || !isValidUrl(url)) {
|
|
26
|
-
|
|
26
|
+
// BYOK mode: Supabase configured via UI, not .env - this is expected
|
|
27
27
|
return null;
|
|
28
28
|
}
|
|
29
29
|
try {
|
|
@@ -46,7 +46,7 @@ export function getServiceRoleSupabase() {
|
|
|
46
46
|
const url = config.supabase.url;
|
|
47
47
|
const key = config.supabase.serviceRoleKey;
|
|
48
48
|
if (!url || !key || !isValidUrl(url)) {
|
|
49
|
-
|
|
49
|
+
// BYOK mode: Service role Supabase configured via UI, not .env - this is expected
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
try {
|