-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fixes for AI generated responses #258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f8f9306
8c87b8a
4910a1b
77f5a7e
f4105c4
26e99bc
bec7cbf
a889a7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,9 @@ import { runRulesOnMessage } from "@/utils/ai/choose-rule/run-rules"; | |
| import { blockUnsubscribedEmails } from "@/app/api/google/webhook/block-unsubscribed-emails"; | ||
| import { categorizeSender } from "@/utils/actions/categorize"; | ||
| import { unwatchEmails } from "@/app/api/google/watch/controller"; | ||
| import { createScopedLogger } from "@/utils/logger"; | ||
|
|
||
| const logger = createScopedLogger("Process History"); | ||
|
|
||
| export async function processHistoryForUser( | ||
| decodedData: { | ||
|
|
@@ -70,7 +73,7 @@ export async function processHistoryForUser( | |
| }); | ||
|
|
||
| if (!account) { | ||
| console.error(`Google webhook: Account not found. email: ${email}`); | ||
| logger.error(`Account not found. email: ${email}`); | ||
| return NextResponse.json({ ok: true }); | ||
| } | ||
|
|
||
|
|
@@ -79,7 +82,7 @@ export async function processHistoryForUser( | |
| : undefined; | ||
|
|
||
| if (!premium) { | ||
| console.log(`Google webhook: Account not premium. email: ${email}`); | ||
| logger.log(`Account not premium. email: ${email}`); | ||
| await unwatchEmails(account); | ||
| return NextResponse.json({ ok: true }); | ||
| } | ||
|
|
@@ -94,9 +97,7 @@ export async function processHistoryForUser( | |
| ); | ||
|
|
||
| if (!userHasAiAccess && !userHasColdEmailAccess) { | ||
| console.debug( | ||
| `Google webhook: does not have hasAiOrColdEmailAccess. email: ${email}`, | ||
| ); | ||
| console.debug(`does not have hasAiOrColdEmailAccess. email: ${email}`); | ||
| await unwatchEmails(account); | ||
| return NextResponse.json({ ok: true }); | ||
|
Comment on lines
+100
to
102
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace console.debug with logger.debug for consistency There's a remaining console.debug call that should be updated to use the scoped logger. - console.debug(`does not have hasAiOrColdEmailAccess. email: ${email}`);
+ logger.debug(`does not have hasAiOrColdEmailAccess. email: ${email}`);
|
||
| } | ||
|
|
@@ -107,21 +108,21 @@ export async function processHistoryForUser( | |
| account.user.coldEmailBlocker !== ColdEmailSetting.DISABLED; | ||
| if (!hasAutomationRules && !shouldBlockColdEmails) { | ||
| console.debug( | ||
| `Google webhook: has no rules set and cold email blocker disabled. email: ${email}`, | ||
| `has no rules set and cold email blocker disabled. email: ${email}`, | ||
| ); | ||
| return NextResponse.json({ ok: true }); | ||
| } | ||
|
|
||
| if (!account.access_token || !account.refresh_token) { | ||
| console.error( | ||
| logger.error( | ||
| `Missing access or refresh token. User needs to re-authenticate. email: ${email}`, | ||
| ); | ||
| return NextResponse.json({ ok: true }); | ||
| } | ||
|
|
||
| if (!account.user.email) { | ||
| // shouldn't ever happen | ||
| console.error("Missing user email.", email); | ||
| logger.error(`Missing user email: ${email}`); | ||
| return NextResponse.json({ ok: true }); | ||
| } | ||
|
|
||
|
|
@@ -145,8 +146,8 @@ export async function processHistoryForUser( | |
| historyId - 500, // avoid going too far back | ||
| ).toString(); | ||
|
|
||
| console.log( | ||
| `Webhook: Listing history... Start: ${startHistoryId} lastSyncedHistoryId: ${account.user.lastSyncedHistoryId} gmailHistoryId: ${startHistoryId} email: ${email}`, | ||
| logger.log( | ||
| `Listing history... Start: ${startHistoryId} lastSyncedHistoryId: ${account.user.lastSyncedHistoryId} gmailHistoryId: ${startHistoryId} email: ${email}`, | ||
| ); | ||
|
|
||
| const history = await gmail.users.history.list({ | ||
|
|
@@ -160,8 +161,8 @@ export async function processHistoryForUser( | |
| }); | ||
|
|
||
| if (history.data.history) { | ||
| console.log( | ||
| `Webhook: Processing... email: ${email} startHistoryId: ${startHistoryId} historyId: ${history.data.historyId}`, | ||
| logger.log( | ||
| `Processing... email: ${email} startHistoryId: ${startHistoryId} historyId: ${history.data.historyId}`, | ||
| ); | ||
|
|
||
| await processHistory({ | ||
|
|
@@ -186,8 +187,8 @@ export async function processHistoryForUser( | |
| }, | ||
| }); | ||
| } else { | ||
| console.log( | ||
| `Webhook: No history. startHistoryId: ${startHistoryId}. ${JSON.stringify(decodedData)}`, | ||
| logger.log( | ||
| `No history. startHistoryId: ${startHistoryId}. ${JSON.stringify(decodedData)}`, | ||
| ); | ||
|
|
||
| // important to save this or we can get into a loop with never receiving history | ||
|
|
@@ -197,12 +198,12 @@ export async function processHistoryForUser( | |
| }); | ||
| } | ||
|
|
||
| console.log(`Webhook: Completed. ${JSON.stringify(decodedData)}`); | ||
| logger.log(`Completed. ${JSON.stringify(decodedData)}`); | ||
|
|
||
| return NextResponse.json({ ok: true }); | ||
| } catch (error) { | ||
| captureException(error, { extra: { decodedData } }, email); | ||
| console.error("Error processing webhook", error, decodedData); | ||
| logger.error("Error processing webhook", error, decodedData); | ||
| return NextResponse.json({ error: true }); | ||
| // be careful about calling an error here with the wrong settings, as otherwise PubSub will call the webhook over and over | ||
| // return NextResponse.error(); | ||
|
|
@@ -260,7 +261,7 @@ async function processHistory(options: ProcessHistoryOptions) { | |
| { extra: { email, messageId: m.message?.id } }, | ||
| email, | ||
| ); | ||
| console.error(`Error processing history item. email: ${email}`, error); | ||
| logger.error(`Error processing history item. email: ${email}`, error); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -292,7 +293,7 @@ async function processHistoryItem( | |
| if (!messageId) return; | ||
| if (!threadId) return; | ||
|
|
||
| console.log( | ||
| logger.log( | ||
| `Getting message... email: ${user.email} messageId: ${messageId} threadId: ${threadId}`, | ||
| ); | ||
|
|
||
|
|
@@ -309,7 +310,7 @@ async function processHistoryItem( | |
|
|
||
| // if the rule has already been executed, skip | ||
| if (hasExistingRule) { | ||
| console.log("Skipping. Rule already exists."); | ||
| logger.log("Skipping. Rule already exists."); | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -326,7 +327,7 @@ async function processHistoryItem( | |
| }); | ||
|
|
||
| if (blocked) { | ||
| console.log( | ||
| logger.log( | ||
| `Skipping. Blocked unsubscribed email. email: ${user.email} messageId: ${messageId} threadId: ${threadId}`, | ||
| ); | ||
| return; | ||
|
|
@@ -341,7 +342,7 @@ async function processHistoryItem( | |
| ); | ||
|
|
||
| if (shouldRunBlocker) { | ||
| console.log("Running cold email blocker..."); | ||
| logger.log("Running cold email blocker..."); | ||
|
|
||
| const hasPreviousEmail = await hasPreviousEmailsFromSenderOrDomain( | ||
| gmail, | ||
|
|
@@ -386,7 +387,7 @@ async function processHistoryItem( | |
| } | ||
|
|
||
| if (hasAutomationRules && hasAiAutomationAccess) { | ||
| console.log("Running rules..."); | ||
| logger.log("Running rules..."); | ||
|
|
||
| await runRulesOnMessage({ | ||
| gmail, | ||
|
|
@@ -399,7 +400,7 @@ async function processHistoryItem( | |
| } catch (error: any) { | ||
| // gmail bug or snoozed email: https://stackoverflow.com/questions/65290987/gmail-api-getmessage-method-returns-404-for-message-gotten-from-listhistory-meth | ||
| if (error.message === "Requested entity was not found.") { | ||
| console.log( | ||
| logger.log( | ||
| `Message not found. email: ${user.email} messageId: ${messageId} threadId: ${threadId}`, | ||
| ); | ||
| return; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,9 @@ import { | |
| } from "@/utils/gmail/label"; | ||
| import { markSpam } from "@/utils/gmail/spam"; | ||
| import type { Attachment } from "@/utils/types/mail"; | ||
| import { createScopedLogger } from "@/utils/logger"; | ||
|
|
||
| const logger = createScopedLogger("ai-actions"); | ||
|
|
||
| export type EmailForAction = { | ||
| threadId: string; | ||
|
|
@@ -369,7 +372,8 @@ export const runActionFunction = async ( | |
| action: ActionItem, | ||
| userEmail: string, | ||
| ) => { | ||
| console.log("Running action", { actionType: action.type, userEmail }); | ||
| logger.log("Running action", { actionType: action.type, userEmail }); | ||
| logger.trace("Running action:", action); | ||
|
Comment on lines
+375
to
+376
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider security and performance implications of logging. A few concerns about the current logging implementation:
Consider applying these improvements: - logger.log("Running action", { actionType: action.type, userEmail });
- logger.trace("Running action:", action);
+ logger.log("Running action", {
+ actionType: action.type,
+ userEmail: userEmail.replace(/(.{2}).*@/, '$1***@') // Mask email
+ });
+ if (logger.isTraceEnabled()) {
+ const sanitizedAction = {
+ ...action,
+ content: action.content ? '[REDACTED]' : undefined,
+ to: action.to ? '[REDACTED]' : undefined,
+ cc: action.cc ? '[REDACTED]' : undefined,
+ bcc: action.bcc ? '[REDACTED]' : undefined
+ };
+ logger.trace("Running action details:", sanitizedAction);
+ }
|
||
|
|
||
| const { type, ...args } = action; | ||
| switch (type) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding error handling for AI operations.
The AI operation could fail due to various reasons (API limits, network issues, invalid responses). Consider adding proper error handling to ensure graceful degradation.
💡 Codebase verification
Migration to consolidated AI function needs attention
The verification shows that while the new
getActionItemsWithAiArgsfunction is properly used across multiple files, the oldgetArgsAiResponsefunction still exists and is being used inapps/web/utils/ai/choose-rule/ai-choose-args.ts. This indicates an incomplete migration:apps/web/utils/ai/choose-rule/ai-choose-args.ts: Contains both the old and new implementation, with the oldgetArgsAiResponsefunction still being actively used.🔗 Analysis chain
Verify complete migration to consolidated AI function.
Let's ensure all previous AI argument handling code has been properly migrated to use the new consolidated function.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 199
Script:
Length of output: 494
Script:
Length of output: 2513