Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/web/app/api/google/webhook/process-history-item.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ describe("processHistoryItem", () => {
expect(runColdEmailBlockerWithProvider).toHaveBeenCalledWith({
email: expect.objectContaining({
from: "sender@example.com",
to: "",
subject: "Test Email",
content: expect.any(String),
id: "123",
Expand All @@ -226,6 +227,7 @@ describe("processHistoryItem", () => {
}),
provider: expect.any(Object),
emailAccount: options.emailAccount,
modelType: "default",
});
});

Expand Down Expand Up @@ -282,6 +284,7 @@ describe("processHistoryItem", () => {
expect(runColdEmailBlockerWithProvider).toHaveBeenCalledWith({
email: expect.objectContaining({
from: "sender@example.com",
to: "",
subject: "Test Email",
content: expect.any(String),
id: "123",
Expand All @@ -290,6 +293,7 @@ describe("processHistoryItem", () => {
}),
provider: expect.any(Object),
emailAccount: options.emailAccount,
modelType: "default",
});

// Verify that cold email is added to digest
Expand Down Expand Up @@ -381,6 +385,7 @@ describe("processHistoryItem", () => {
expect(runColdEmailBlockerWithProvider).toHaveBeenCalledWith({
email: expect.objectContaining({
from: "sender@example.com",
to: "",
subject: "Test Email",
content: expect.any(String),
id: "456",
Expand All @@ -389,6 +394,7 @@ describe("processHistoryItem", () => {
}),
provider: expect.any(Object),
emailAccount: options.emailAccount,
modelType: "default",
});

// Verify that the second email from known cold emailer is added to digest
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/api/google/webhook/process-history-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export async function processHistoryItem(
},
provider,
emailAccount,
modelType: "default",
});

if (response.isColdEmail) {
Expand Down Expand Up @@ -206,6 +207,7 @@ export async function processHistoryItem(
rules,
emailAccount,
isTest: false,
modelType: "default",
});
}
} catch (error: unknown) {
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/api/outlook/webhook/process-history-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export async function processHistoryItem(
},
provider: emailProvider,
emailAccount,
modelType: "default",
});

if (response.isColdEmail) {
Expand Down Expand Up @@ -236,6 +237,7 @@ export async function processHistoryItem(
rules,
emailAccount,
isTest: false,
modelType: "default",
});
}
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions apps/web/utils/actions/ai-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const runRulesAction = actionClient
message,
rules,
emailAccount,
modelType: "chat",
});

return result;
Expand Down Expand Up @@ -152,6 +153,7 @@ export const testAiCustomContentAction = actionClient
},
rules,
emailAccount,
modelType: "chat",
});

return result;
Expand Down
1 change: 1 addition & 0 deletions apps/web/utils/actions/cold-email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export const testColdEmailAction = actionClient
},
emailAccount,
provider: emailProvider,
modelType: "chat",
});

return response;
Expand Down
4 changes: 4 additions & 0 deletions apps/web/utils/ai/choose-rule/ai-choose-args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { createScopedLogger } from "@/utils/logger";
import type { EmailAccountWithAI } from "@/utils/llms/types";
import type { EmailForLLM, RuleWithActions } from "@/utils/types";
import type { ActionType } from "@prisma/client";
import type { ModelType } from "@/utils/llms/model";

/**
* AI Argument Generator for Email Actions
Expand Down Expand Up @@ -43,6 +44,7 @@ export async function aiGenerateArgs({
emailAccount,
selectedRule,
parameters,
modelType,
}: {
email: EmailForLLM;
emailAccount: EmailAccountWithAI;
Expand All @@ -54,6 +56,7 @@ export async function aiGenerateArgs({
Record<string, z.ZodObject<Record<string, z.ZodString>>>
>;
}[];
modelType: ModelType;
}) {
const loggerOptions = {
email: emailAccount.email,
Expand All @@ -79,6 +82,7 @@ export async function aiGenerateArgs({
() =>
chatCompletionObject({
userAi: emailAccount.user,
modelType,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
prompt,
system,
schemaName: "Apply rule",
Expand Down
8 changes: 7 additions & 1 deletion apps/web/utils/ai/choose-rule/ai-choose-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { chatCompletionObject } from "@/utils/llms";
import { stringifyEmail } from "@/utils/stringify-email";
import type { EmailForLLM } from "@/utils/types";
import { createScopedLogger } from "@/utils/logger";
import type { ModelType } from "@/utils/llms/model";
// import { Braintrust } from "@/utils/braintrust";

const logger = createScopedLogger("ai-choose-rule");
Expand All @@ -14,10 +15,11 @@ type GetAiResponseOptions = {
email: EmailForLLM;
emailAccount: EmailAccountWithAI;
rules: { name: string; instructions: string }[];
modelType?: ModelType;
};

async function getAiResponse(options: GetAiResponseOptions) {
const { email, emailAccount, rules } = options;
const { email, emailAccount, rules, modelType = "default" } = options;

const emailSection = stringifyEmail(email, 500);

Expand Down Expand Up @@ -80,6 +82,7 @@ ${emailSection}

const aiResponse = await chatCompletionObject({
userAi: emailAccount.user,
modelType,
messages: [
{
role: "system",
Expand Down Expand Up @@ -133,17 +136,20 @@ export async function aiChooseRule<
email,
rules,
emailAccount,
modelType,
}: {
email: EmailForLLM;
rules: T[];
emailAccount: EmailAccountWithAI;
modelType?: ModelType;
}) {
if (!rules.length) return { reason: "No rules" };

const aiResponse = await getAiResponse({
email,
rules,
emailAccount,
modelType,
});

if (aiResponse.noMatchFound)
Expand Down
4 changes: 4 additions & 0 deletions apps/web/utils/ai/choose-rule/choose-args.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from "zod";
import type { EmailAccountWithAI } from "@/utils/llms/types";
import type { ModelType } from "@/utils/llms/model";
import { ActionType, type Action } from "@prisma/client";
import {
type RuleWithActions,
Expand Down Expand Up @@ -27,11 +28,13 @@ export async function getActionItemsWithAiArgs({
emailAccount,
selectedRule,
client,
modelType,
}: {
message: ParsedMessage;
emailAccount: EmailAccountWithAI;
selectedRule: RuleWithActions;
client: EmailProvider;
modelType: ModelType;
}): Promise<Action[]> {
// Draft content is handled via its own AI call
// We provide a lot more context to the AI to draft the content
Expand Down Expand Up @@ -64,6 +67,7 @@ export async function getActionItemsWithAiArgs({
emailAccount,
selectedRule,
parameters,
modelType,
});

return combineActionsWithAiArgs(selectedRule.actions, result, draft);
Expand Down
6 changes: 6 additions & 0 deletions apps/web/utils/ai/choose-rule/match-rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { extractEmailAddress } from "@/utils/email";
import { hasIcsAttachment } from "@/utils/parse/calender-event";
import { checkSenderReplyHistory } from "@/utils/reply-tracker/check-sender-reply-history";
import type { EmailProvider } from "@/utils/email/provider";
import type { ModelType } from "@/utils/llms/model";

const logger = createScopedLogger("match-rules");

Expand Down Expand Up @@ -203,17 +204,20 @@ export async function findMatchingRule({
message,
emailAccount,
client,
modelType,
}: {
rules: RuleWithActionsAndCategories[];
message: ParsedMessage;
emailAccount: EmailAccountWithAI;
client: EmailProvider;
modelType: ModelType;
}) {
const result = await findMatchingRuleWithReasons(
rules,
message,
emailAccount,
client,
modelType,
);
return {
...result,
Expand All @@ -226,6 +230,7 @@ async function findMatchingRuleWithReasons(
message: ParsedMessage,
emailAccount: EmailAccountWithAI,
client: EmailProvider,
modelType: ModelType,
): Promise<{
rule?: RuleWithActionsAndCategories;
matchReasons?: MatchReason[];
Expand All @@ -248,6 +253,7 @@ async function findMatchingRuleWithReasons(
email: getEmailForLLM(message),
rules: potentialMatches,
emailAccount,
modelType,
});

return result;
Expand Down
7 changes: 7 additions & 0 deletions apps/web/utils/ai/choose-rule/run-rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from "@/utils/scheduled-actions/scheduler";
import groupBy from "lodash/groupBy";
import type { EmailProvider } from "@/utils/email/provider";
import type { ModelType } from "@/utils/llms/model";

const logger = createScopedLogger("ai-run-rules");

Expand All @@ -39,18 +40,21 @@ export async function runRules({
rules,
emailAccount,
isTest,
modelType,
}: {
client: EmailProvider;
message: ParsedMessage;
rules: RuleWithActionsAndCategories[];
emailAccount: EmailAccountWithAI;
isTest: boolean;
modelType: ModelType;
}): Promise<RunRulesResult> {
const result = await findMatchingRule({
rules,
message,
emailAccount,
client,
modelType,
});

analyzeSenderPatternIfAiMatch({
Expand All @@ -71,6 +75,7 @@ export async function runRules({
result.reason,
result.matchReasons,
isTest,
modelType,
);
} else {
await saveSkippedExecutedRule({
Expand All @@ -91,13 +96,15 @@ async function executeMatchedRule(
reason: string | undefined,
matchReasons: MatchReason[] | undefined,
isTest: boolean,
modelType: ModelType,
) {
// get action items with args
const actionItems = await getActionItemsWithAiArgs({
message,
emailAccount,
selectedRule: rule,
client,
modelType,
});

if (!isTest) {
Expand Down
1 change: 1 addition & 0 deletions apps/web/utils/ai/reply/generate-nudge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ IMPORTANT: The person you're writing an email for is: ${messages.at(-1)?.from}.`
system,
prompt,
userEmail: emailAccount.email,
modelType: "chat",
usageLabel: "Reply",
});

Expand Down
Loading
Loading