Examples
diff --git a/apps/web/app/(app)/[emailAccountId]/assistant/examples.ts b/apps/web/app/(app)/[emailAccountId]/assistant/examples.ts
index 473bc4945b..8c73b0c248 100644
--- a/apps/web/app/(app)/[emailAccountId]/assistant/examples.ts
+++ b/apps/web/app/(app)/[emailAccountId]/assistant/examples.ts
@@ -1,3 +1,7 @@
+import { getEmailTerminology } from "@/utils/terminology";
+
+export type Personas = ReturnType;
+
// NOTE: some users save the example rules when trying out the platform, and start auto sending emails
// to people without realising it. This is a simple check to avoid that.
// This needs changing when the examples change. But it works for now.
@@ -21,12 +25,29 @@ function formatPromptArray(promptArray: string[]): string {
return `${promptArray.map((item) => `* ${item}`).join(".\n")}.`;
}
+function processPromptsWithTerminology(
+ prompts: string[],
+ provider: string,
+): string[] {
+ const terminology = getEmailTerminology(provider);
+ return prompts.map((prompt) => {
+ // Replace "Label" at the beginning of sentences or after punctuation
+ let processed = prompt.replace(/\bLabel\b/g, terminology.label.action);
+ // Replace lowercase "label" in the middle of sentences
+ processed = processed.replace(
+ /\blabel\b/g,
+ terminology.label.action.toLowerCase(),
+ );
+ return processed;
+ });
+}
+
const commonPrompts = [
"Label urgent emails as @[Urgent]",
"Label emails from @mycompany.com addresses as @[Team]",
];
-export const examplePrompts = [
+const examplePromptsBase = [
...commonPrompts,
"Forward receipts to jane@accounting.com and label them @[Receipt]",
"Forward pitch decks to john@investing.com and label them @[Pitch Deck]",
@@ -46,6 +67,10 @@ export const examplePrompts = [
"Label Stripe emails as @[Stripe]",
];
+export function getExamplePrompts(provider: string): string[] {
+ return processPromptsWithTerminology(examplePromptsBase, provider);
+}
+
const founderPromptArray = [
...commonPrompts,
"If someone asks to set up a call, draft a reply with my calendar link: https://cal.com/example",
@@ -57,232 +82,267 @@ const founderPromptArray = [
"Label recruitment related emails as @[Hiring]",
];
-export const personas = {
- founder: {
- label: "🚀 Founder",
- promptArray: founderPromptArray,
- get prompt() {
- return formatPromptArray(this.promptArray);
+export function getPersonas(provider: string) {
+ return {
+ founder: {
+ label: "🚀 Founder",
+ promptArray: processPromptsWithTerminology(founderPromptArray, provider),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- influencer: {
- label: "📹 Influencer",
- promptArray: [
- ...commonPrompts,
- `Label sponsorship inquiries as @[Sponsorship] and draft a reply as follows:
+ influencer: {
+ label: "📹 Influencer",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ `Label sponsorship inquiries as @[Sponsorship] and draft a reply as follows:
> Hey NAME,
>
> I've attached my media kit and pricing`,
- "Label emails about affiliate programs as @[Affiliate] and archive them",
- "Label collaboration requests as @[Collab] and draft a reply asking about their audience size and engagement rates",
- "Label brand partnership emails as @[Brand Deal] and forward to manager@example.com",
- "Label media inquiries as @[Press] and draft a reply a polite reply",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ "Label emails about affiliate programs as @[Affiliate] and archive them",
+ "Label collaboration requests as @[Collab] and draft a reply asking about their audience size and engagement rates",
+ "Label brand partnership emails as @[Brand Deal] and forward to manager@example.com",
+ "Label media inquiries as @[Press] and draft a reply a polite reply",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- realtor: {
- label: "🏠 Realtor",
- promptArray: [
- ...commonPrompts,
- "Label emails from potential buyers as @[Buyer Lead] and draft a reply asking about their budget and preferred neighborhoods",
- "Label emails from potential sellers as @[Seller Lead] and draft a reply with my calendar link to schedule a home evaluation: https://cal.com/example",
- "If someone asks about home prices in a specific area, label as @[Market Inquiry] and draft a reply with recent comparable sales data",
- "Label emails from mortgage brokers and lenders as @[Lender] and archive them",
- "If someone asks to schedule a showing, label as @[Showing Request] and draft a reply with available time slots",
- "Label emails about closing documents as @[Closing] and forward to transactions@realty.com",
- "If someone asks about the home buying process, draft a reply with our buyer's guide link: https://realty.com/buyers-guide",
- "Label emails from home inspectors as @[Inspector] and forward to scheduling@realty.com",
- "If someone refers a client to me, label as @[Referral] and draft a thank you reply with my calendar link to schedule a consultation",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ realtor: {
+ label: "🏠 Realtor",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label emails from potential buyers as @[Buyer Lead] and draft a reply asking about their budget and preferred neighborhoods",
+ "Label emails from potential sellers as @[Seller Lead] and draft a reply with my calendar link to schedule a home evaluation: https://cal.com/example",
+ "If someone asks about home prices in a specific area, label as @[Market Inquiry] and draft a reply with recent comparable sales data",
+ "Label emails from mortgage brokers and lenders as @[Lender] and archive them",
+ "If someone asks to schedule a showing, label as @[Showing Request] and draft a reply with available time slots",
+ "Label emails about closing documents as @[Closing] and forward to transactions@realty.com",
+ "If someone asks about the home buying process, draft a reply with our buyer's guide link: https://realty.com/buyers-guide",
+ "Label emails from home inspectors as @[Inspector] and forward to scheduling@realty.com",
+ "If someone refers a client to me, label as @[Referral] and draft a thank you reply with my calendar link to schedule a consultation",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- investor: {
- label: "💰 Investor",
- promptArray: [
- ...commonPrompts,
- "If a founder asks to set up a call, draft a reply with my calendar link: https://cal.com/example",
- "If a founder sends me an investor update, label it @[Investor Update] and archive it",
- "Forward pitch decks to analyst@vc.com that asks them to review it and label them @[Pitch Deck]",
- "Label emails from LPs as @[LP]",
- "Label legal documents as @[Legal]",
- "Label emails about travel as @[Travel]",
- "Label emails about portfolio company exits as @[Exit Opportunity]",
- "Label emails containing term sheets as @[Term Sheet]",
- "If a portfolio company reports bad news, label as @[Portfolio Alert] and draft a reply to schedule an emergency call",
- "Label due diligence related emails as @[Due Diligence]",
- "Forward emails about industry research reports to research@vc.com",
- "If someone asks for a warm intro to a portfolio company, draft a reply asking for more context about why they want to connect",
- "Label emails about fund administration as @[Fund Admin]",
- "Label emails about speaking at investment conferences as @[Speaking Opportunity]",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ investor: {
+ label: "💰 Investor",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "If a founder asks to set up a call, draft a reply with my calendar link: https://cal.com/example",
+ "If a founder sends me an investor update, label it @[Investor Update] and archive it",
+ "Forward pitch decks to analyst@vc.com that asks them to review it and label them @[Pitch Deck]",
+ "Label emails from LPs as @[LP]",
+ "Label legal documents as @[Legal]",
+ "Label emails about travel as @[Travel]",
+ "Label emails about portfolio company exits as @[Exit Opportunity]",
+ "Label emails containing term sheets as @[Term Sheet]",
+ "If a portfolio company reports bad news, label as @[Portfolio Alert] and draft a reply to schedule an emergency call",
+ "Label due diligence related emails as @[Due Diligence]",
+ "Forward emails about industry research reports to research@vc.com",
+ "If someone asks for a warm intro to a portfolio company, draft a reply asking for more context about why they want to connect",
+ "Label emails about fund administration as @[Fund Admin]",
+ "Label emails about speaking at investment conferences as @[Speaking Opportunity]",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- assistant: {
- label: "📋 Assistant",
- promptArray: founderPromptArray,
- get prompt() {
- return formatPromptArray(this.promptArray);
+ assistant: {
+ label: "📋 Assistant",
+ promptArray: processPromptsWithTerminology(founderPromptArray, provider),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- developer: {
- label: "👨💻 Developer",
- promptArray: [
- ...commonPrompts,
- "Label server errors, deployment failures, and other server alerts as @[Alert] and forward to oncall@company.com",
- "Label emails from GitHub as @[GitHub] and archive them",
- "Label emails from Figma as @[Design] and archive them",
- "Label emails from Stripe as @[Stripe] and archive them",
- "Label emails from Slack as @[Slack] and archive them",
- "Label emails about bug reports as @[Bug]",
- "If someone reports a security vulnerability, label as @[Security] and forward to security@company.com",
- "Label emails about job interviews as @[Job Search]",
- "Label emails from recruiters as @[Recruiter] and archive them",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ developer: {
+ label: "👨💻 Developer",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label server errors, deployment failures, and other server alerts as @[Alert] and forward to oncall@company.com",
+ "Label emails from GitHub as @[GitHub] and archive them",
+ "Label emails from Figma as @[Design] and archive them",
+ "Label emails from Stripe as @[Stripe] and archive them",
+ "Label emails from Slack as @[Slack] and archive them",
+ "Label emails about bug reports as @[Bug]",
+ "If someone reports a security vulnerability, label as @[Security] and forward to security@company.com",
+ "Label emails about job interviews as @[Job Search]",
+ "Label emails from recruiters as @[Recruiter] and archive them",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- designer: {
- label: "🎨 Designer",
- promptArray: [
- ...commonPrompts,
- "Label emails from Figma, Adobe, Sketch, and other design tools as @[Design] and archive them",
- "Label emails from clients as @[Client]",
- "If someone sends design assets, label as @[Design Assets] and forward to assets@company.com",
- "Label emails from Dribbble, Behance, and other design inspiration sites as @[Inspiration] and archive them",
- "Label emails about design conferences as @[Conference]",
- "If someone requests brand assets, draft a reply with a link to our brand portal: https://brand.company.com",
- "Label emails about user research as @[Research]",
- "Label emails about job interviews as @[Job Search]",
- "Label emails from recruiters as @[Recruiter] and archive them",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ designer: {
+ label: "🎨 Designer",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label emails from Figma, Adobe, Sketch, and other design tools as @[Design] and archive them",
+ "Label emails from clients as @[Client]",
+ "If someone sends design assets, label as @[Design Assets] and forward to assets@company.com",
+ "Label emails from Dribbble, Behance, and other design inspiration sites as @[Inspiration] and archive them",
+ "Label emails about design conferences as @[Conference]",
+ "If someone requests brand assets, draft a reply with a link to our brand portal: https://brand.company.com",
+ "Label emails about user research as @[Research]",
+ "Label emails about job interviews as @[Job Search]",
+ "Label emails from recruiters as @[Recruiter] and archive them",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- sales: {
- label: "🤝 Sales",
- promptArray: [
- ...commonPrompts,
- "Label emails from prospects as @[Prospect]",
- "Label emails from customers as @[Customer]",
- "Label emails about deal negotiations as @[Deal Discussion]",
- "Label emails from sales tools as @[Sales Tool] and archive them",
- "Label emails about sales opportunities as @[Sales Opportunity]",
- "If someone asks for pricing, draft a reply with our pricing page link: https://company.com/pricing",
- "Label emails containing signed contracts as @[Signed Contract] and forward to legal@company.com",
- "If someone requests a demo, draft a reply with my calendar link: https://cal.com/example",
- "If someone asks about product features, draft a reply with relevant feature documentation links",
- "If someone reports implementation issues, label as @[Support Need] and forward to support@company.com",
- "If someone asks about enterprise pricing, draft a reply asking about their company size and requirements",
- "If a customer mentions churn risk, label as @[Churn Risk] and draft an urgent notification to the customer success team",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ sales: {
+ label: "🤝 Sales",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label emails from prospects as @[Prospect]",
+ "Label emails from customers as @[Customer]",
+ "Label emails about deal negotiations as @[Deal Discussion]",
+ "Label emails from sales tools as @[Sales Tool] and archive them",
+ "Label emails about sales opportunities as @[Sales Opportunity]",
+ "If someone asks for pricing, draft a reply with our pricing page link: https://company.com/pricing",
+ "Label emails containing signed contracts as @[Signed Contract] and forward to legal@company.com",
+ "If someone requests a demo, draft a reply with my calendar link: https://cal.com/example",
+ "If someone asks about product features, draft a reply with relevant feature documentation links",
+ "If someone reports implementation issues, label as @[Support Need] and forward to support@company.com",
+ "If someone asks about enterprise pricing, draft a reply asking about their company size and requirements",
+ "If a customer mentions churn risk, label as @[Churn Risk] and draft an urgent notification to the customer success team",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- marketer: {
- label: "📢 Marketer",
- promptArray: [
- ...commonPrompts,
- "Label emails from influencers as @[Influencer]",
- "Label emails from ad platforms (Google, Meta, LinkedIn) as @[Advertising]",
- "Label press inquiries as @[Press] and forward to pr@company.com",
- "Label emails about content marketing as @[Content]",
- "If someone asks about sponsorship, label as @[Sponsorship] and draft a reply asking about their audience size",
- "If someone requests to guest post, label as @[Guest Post] and draft a reply with our guidelines",
- "If someone asks about partnership opportunities, label as @[Partnership] and draft a reply asking for their media kit",
- "If someone reports broken marketing links, label as @[Bug] and forward to tech@company.com",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ marketer: {
+ label: "📢 Marketer",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label emails from influencers as @[Influencer]",
+ "Label emails from ad platforms (Google, Meta, LinkedIn) as @[Advertising]",
+ "Label press inquiries as @[Press] and forward to pr@company.com",
+ "Label emails about content marketing as @[Content]",
+ "If someone asks about sponsorship, label as @[Sponsorship] and draft a reply asking about their audience size",
+ "If someone requests to guest post, label as @[Guest Post] and draft a reply with our guidelines",
+ "If someone asks about partnership opportunities, label as @[Partnership] and draft a reply asking for their media kit",
+ "If someone reports broken marketing links, label as @[Bug] and forward to tech@company.com",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- support: {
- label: "🛠️ Support",
- promptArray: [
- ...commonPrompts,
- "Label customer support tickets as @[Support Ticket]",
- "If someone reports a critical issue, label as @[Urgent Support] and forward to urgent@company.com",
- "Label bug reports as @[Bug] and forward to engineering@company.com",
- "Label feature requests as @[Feature Request] and forward to product@company.com",
- "If someone asks for refund, draft a reply with our refund policy link: https://company.com/refund-policy",
- "Label emails about account access issues as @[Access Issue] and draft a reply asking for their account details",
- "If someone asks for product documentation, draft a reply with our help center link: https://help.company.com",
- "Label emails about service outages as @[Service Issue] and forward to status@company.com",
- "If someone needs technical assistance, draft a reply asking for their account details and specific error messages",
- "Label positive feedback as @[Testimonial] and forward to marketing@company.com",
- "Label emails about API integration issues as @[API Support]",
- "If someone reports data privacy concerns, label as @[Privacy], and draft a reply with our privacy policy link: https://company.com/privacy-policy",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ support: {
+ label: "🛠️ Support",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label customer support tickets as @[Support Ticket]",
+ "If someone reports a critical issue, label as @[Urgent Support] and forward to urgent@company.com",
+ "Label bug reports as @[Bug] and forward to engineering@company.com",
+ "Label feature requests as @[Feature Request] and forward to product@company.com",
+ "If someone asks for refund, draft a reply with our refund policy link: https://company.com/refund-policy",
+ "Label emails about account access issues as @[Access Issue] and draft a reply asking for their account details",
+ "If someone asks for product documentation, draft a reply with our help center link: https://help.company.com",
+ "Label emails about service outages as @[Service Issue] and forward to status@company.com",
+ "If someone needs technical assistance, draft a reply asking for their account details and specific error messages",
+ "Label positive feedback as @[Testimonial] and forward to marketing@company.com",
+ "Label emails about API integration issues as @[API Support]",
+ "If someone reports data privacy concerns, label as @[Privacy], and draft a reply with our privacy policy link: https://company.com/privacy-policy",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- recruiter: {
- label: "👥 Recruiter",
- promptArray: [
- ...commonPrompts,
- "Label emails from candidates as @[Candidate]",
- "Label emails from hiring managers as @[Hiring Manager]",
- "Label emails from recruiters as @[Recruiter] and draft a reply with our hiring process overview link: https://company.com/hiring-process",
- "Label emails from job boards as @[Job Board] and archive them",
- "Label emails from LinkedIn as @[LinkedIn] and archive them",
- "If someone applies for a job, label as @[New Application] and draft a reply acknowledging their application",
- "Label emails containing resumes or CVs as @[Resume]",
- "If a candidate asks about application status, label as @[Status Update] and draft a reply asking for their position and date applied",
- "Label emails about interview scheduling as @[Interview Scheduling]",
- "If someone accepts an interview invite, label as @[Interview Confirmed] and forward to calendar@company.com",
- "If someone declines a job offer, label as @[Offer Declined] and forward to hiring-updates@company.com",
- "If someone accepts a job offer, label as @[Offer Accepted] and forward to onboarding@company.com",
- "Label emails about salary negotiations as @[Compensation]",
- "Label emails about reference checks as @[References]",
- "If someone asks about benefits, draft a reply with our benefits overview link: https://company.com/benefits",
- "Label emails about background checks as @[Background Check]",
- "If an internal employee refers someone, label as @[Employee Referral]",
- "Label emails about recruitment events or job fairs as @[Recruiting Event]",
- "If someone withdraws their application, label as @[Withdrawn]",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ recruiter: {
+ label: "👥 Recruiter",
+ promptArray: processPromptsWithTerminology(
+ [
+ ...commonPrompts,
+ "Label emails from candidates as @[Candidate]",
+ "Label emails from hiring managers as @[Hiring Manager]",
+ "Label emails from recruiters as @[Recruiter] and draft a reply with our hiring process overview link: https://company.com/hiring-process",
+ "Label emails from job boards as @[Job Board] and archive them",
+ "Label emails from LinkedIn as @[LinkedIn] and archive them",
+ "If someone applies for a job, label as @[New Application] and draft a reply acknowledging their application",
+ "Label emails containing resumes or CVs as @[Resume]",
+ "If a candidate asks about application status, label as @[Status Update] and draft a reply asking for their position and date applied",
+ "Label emails about interview scheduling as @[Interview Scheduling]",
+ "If someone accepts an interview invite, label as @[Interview Confirmed] and forward to calendar@company.com",
+ "If someone declines a job offer, label as @[Offer Declined] and forward to hiring-updates@company.com",
+ "If someone accepts a job offer, label as @[Offer Accepted] and forward to onboarding@company.com",
+ "Label emails about salary negotiations as @[Compensation]",
+ "Label emails about reference checks as @[References]",
+ "If someone asks about benefits, draft a reply with our benefits overview link: https://company.com/benefits",
+ "Label emails about background checks as @[Background Check]",
+ "If an internal employee refers someone, label as @[Employee Referral]",
+ "Label emails about recruitment events or job fairs as @[Recruiting Event]",
+ "If someone withdraws their application, label as @[Withdrawn]",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- student: {
- label: "👩🎓 Student",
- promptArray: [
- "Label emails from professors and teaching assistants as @[School]",
- "Label emails about assignments and homework as @[Assignment]",
- "If someone sends class notes or study materials, label as @[Study Materials]",
- "Label emails about internships as @[Internship] and forward to my personal email me@example.com",
- "Label emails about exam schedules as @[Exam]",
- "Label emails about campus events as @[Event] and archive them",
- "If someone asks for class notes, draft a reply with our shared Google Drive folder link: https://drive.google.com/drive/u/0/folders/1234567890",
- "Label emails about tutoring opportunities as @[Tutoring] and draft a reply with that my rate is $70/hour or $40/hour for group tutoring",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ student: {
+ label: "👩🎓 Student",
+ promptArray: processPromptsWithTerminology(
+ [
+ "Label emails from professors and teaching assistants as @[School]",
+ "Label emails about assignments and homework as @[Assignment]",
+ "If someone sends class notes or study materials, label as @[Study Materials]",
+ "Label emails about internships as @[Internship] and forward to my personal email me@example.com",
+ "Label emails about exam schedules as @[Exam]",
+ "Label emails about campus events as @[Event] and archive them",
+ "If someone asks for class notes, draft a reply with our shared Google Drive folder link: https://drive.google.com/drive/u/0/folders/1234567890",
+ "Label emails about tutoring opportunities as @[Tutoring] and draft a reply with that my rate is $70/hour or $40/hour for group tutoring",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- reachout: {
- label: "💬 Outreach",
- promptArray: [
- "If someone replies to me that they're interested, label it @[Interested] and draft a reply with my calendar link: https://cal.com/example",
- ],
- get prompt() {
- return formatPromptArray(this.promptArray);
+ reachout: {
+ label: "💬 Outreach",
+ promptArray: processPromptsWithTerminology(
+ [
+ "If someone replies to me that they're interested, label it @[Interested] and draft a reply with my calendar link: https://cal.com/example",
+ ],
+ provider,
+ ),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
- other: {
- label: "🤖 Other",
- promptArray: examplePrompts,
- get prompt() {
- return formatPromptArray(this.promptArray);
+ other: {
+ label: "🤖 Other",
+ promptArray: getExamplePrompts(provider),
+ get prompt() {
+ return formatPromptArray(this.promptArray);
+ },
},
- },
-};
+ };
+}
diff --git a/apps/web/components/assistant-chat/examples-dialog.tsx b/apps/web/components/assistant-chat/examples-dialog.tsx
index 31d5a838ea..461133089e 100644
--- a/apps/web/components/assistant-chat/examples-dialog.tsx
+++ b/apps/web/components/assistant-chat/examples-dialog.tsx
@@ -16,7 +16,7 @@ import {
PlusIcon,
CheckCircle2Icon,
} from "lucide-react";
-import { personas } from "@/app/(app)/[emailAccountId]/assistant/examples";
+import { getPersonas } from "@/app/(app)/[emailAccountId]/assistant/examples";
import {
convertLabelsToDisplay,
convertMentionsToLabels,
@@ -25,6 +25,7 @@ import { Tooltip } from "@/components/Tooltip";
import { ButtonList } from "@/components/ButtonList";
import { parseAsStringEnum, useQueryState } from "nuqs";
import { cn } from "@/utils";
+import { useAccount } from "@/providers/EmailAccountProvider";
interface ExamplesDialogProps {
setInput: (input: string) => void;
@@ -39,6 +40,8 @@ export function ExamplesDialog({
open,
onOpenChange,
}: ExamplesDialogProps) {
+ const { provider } = useAccount();
+ const personas = getPersonas(provider);
const [internalOpen, setInternalOpen] = useState(false);
const [selectedExamples, setSelectedExamples] = useState([]);
diff --git a/apps/web/utils/actions/rule.ts b/apps/web/utils/actions/rule.ts
index 9af3705273..fbe5629275 100644
--- a/apps/web/utils/actions/rule.ts
+++ b/apps/web/utils/actions/rule.ts
@@ -56,7 +56,7 @@ export const createRuleAction = actionClient
.schema(createRuleBody)
.action(
async ({
- ctx: { emailAccountId },
+ ctx: { emailAccountId, provider },
parsedInput: {
name,
automate,
@@ -133,7 +133,13 @@ export const createRuleAction = actionClient
createRuleHistory({ rule, triggerType: "manual_creation" }),
);
- after(() => updatePromptFileOnRuleCreated({ emailAccountId, rule }));
+ after(() =>
+ updatePromptFileOnRuleCreated({
+ emailAccountId,
+ provider,
+ rule,
+ }),
+ );
return { rule };
} catch (error) {
diff --git a/apps/web/utils/ai/assistant/process-user-request.ts b/apps/web/utils/ai/assistant/process-user-request.ts
index 14d481cdfc..f1bc04abfa 100644
--- a/apps/web/utils/ai/assistant/process-user-request.ts
+++ b/apps/web/utils/ai/assistant/process-user-request.ts
@@ -648,6 +648,7 @@ ${senderCategory || "No category"}
for (const rule of createdRules.values()) {
await updatePromptFileOnRuleCreated({
emailAccountId: emailAccount.id,
+ provider: emailAccount.account.provider,
rule,
});
}
diff --git a/apps/web/utils/ai/rule/create-prompt-from-rule.test.ts b/apps/web/utils/ai/rule/create-prompt-from-rule.test.ts
index 764197b73c..b815e5bf17 100644
--- a/apps/web/utils/ai/rule/create-prompt-from-rule.test.ts
+++ b/apps/web/utils/ai/rule/create-prompt-from-rule.test.ts
@@ -9,7 +9,7 @@ describe("generatePromptFromRule", () => {
actions: [{ type: "ARCHIVE" }] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "newsletter@example.com", archive',
);
});
@@ -25,7 +25,7 @@ describe("generatePromptFromRule", () => {
],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "support@company.com" and with subject containing "urgent" and with body containing "priority", label as "Important" and forward to manager@company.com',
);
});
@@ -40,7 +40,7 @@ describe("generatePromptFromRule", () => {
actions: [{ type: "LABEL", label: "Priority" }] as Action[],
} as Rule & { actions: Action[]; categoryFilters: Category[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from senders in categories: Finance, Important, label as "Priority"',
);
});
@@ -52,7 +52,7 @@ describe("generatePromptFromRule", () => {
actions: [{ type: "ARCHIVE" }] as Action[],
} as Rule & { actions: Action[]; categoryFilters: Category[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
"For emails from senders not in categories: Spam, archive",
);
});
@@ -66,7 +66,7 @@ describe("generatePromptFromRule", () => {
] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails matching AI criteria: "contains a meeting request", create a draft and label as "Meeting"',
);
});
@@ -86,7 +86,7 @@ describe("generatePromptFromRule", () => {
],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "test@example.com", archive and label as "Test" and send a reply and send email to other@example.com and forward to forward@example.com and create a draft and mark as spam and call webhook at https://example.com/webhook',
);
});
@@ -96,7 +96,9 @@ describe("generatePromptFromRule", () => {
actions: [{ type: "ARCHIVE" }] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe("For all emails, archive");
+ expect(createPromptFromRule(rule, "google")).toBe(
+ "For all emails, archive",
+ );
});
it("handles templated reply", () => {
@@ -114,7 +116,7 @@ Alice`,
] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "job@company.com", send a templated reply: "Hi {{name}},\n{{personalized reply}}\n\nI\'d love to set up a time to chat.\nAlice"',
);
});
@@ -130,7 +132,7 @@ Alice`,
] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails with subject containing "newsletter", send a static reply: "Please unsubscribe me from your mailing list."',
);
});
@@ -141,7 +143,7 @@ Alice`,
actions: [{ type: "REPLY" }] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails matching AI criteria: "is a meeting request", send a reply',
);
});
@@ -154,7 +156,7 @@ Alice`,
actions: [{ type: "LABEL", label: "Sales" }] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "sales@company.com" or with subject containing "invoice", label as "Sales"',
);
});
@@ -166,7 +168,7 @@ Alice`,
actions: [{ type: "LABEL", label: "Sales" }] as Action[],
} as Rule & { actions: Action[] };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails from "sales@company.com" and with subject containing "invoice", label as "Sales"',
);
});
@@ -180,7 +182,7 @@ Alice`,
] as Action[],
} as Rule & { actions: Action[]; group: Group };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For all emails, label as "Receipt" and archive',
);
});
@@ -192,7 +194,7 @@ Alice`,
actions: [{ type: "ARCHIVE" }] as Action[],
} as Rule & { actions: Action[]; group: Group };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails with subject containing "order", archive',
);
});
@@ -205,7 +207,7 @@ Alice`,
actions: [{ type: "ARCHIVE" }] as Action[],
} as Rule & { actions: Action[]; group: Group };
- expect(createPromptFromRule(rule)).toBe(
+ expect(createPromptFromRule(rule, "google")).toBe(
'For emails with subject containing "order", archive',
);
});
diff --git a/apps/web/utils/ai/rule/create-prompt-from-rule.ts b/apps/web/utils/ai/rule/create-prompt-from-rule.ts
index b2eadb8726..187fbf277d 100644
--- a/apps/web/utils/ai/rule/create-prompt-from-rule.ts
+++ b/apps/web/utils/ai/rule/create-prompt-from-rule.ts
@@ -6,6 +6,7 @@ import {
type Prisma,
} from "@prisma/client";
import { createScopedLogger } from "@/utils/logger";
+import { getEmailTerminology } from "@/utils/terminology";
const logger = createScopedLogger("ai/rule/create-prompt-from-rule");
@@ -25,7 +26,11 @@ export type RuleWithRelations = Rule & {
| null;
};
-export function createPromptFromRule(rule: RuleWithRelations): string {
+export function createPromptFromRule(
+ rule: RuleWithRelations,
+ provider: string,
+): string {
+ const terminology = getEmailTerminology(provider);
const conditions: string[] = [];
const actions: string[] = [];
@@ -55,7 +60,10 @@ export function createPromptFromRule(rule: RuleWithRelations): string {
actions.push("archive");
break;
case ActionType.LABEL:
- if (action.label) actions.push(`label as "${action.label}"`);
+ if (action.label)
+ actions.push(
+ `${terminology.label.action.toLowerCase()} as "${action.label}"`,
+ );
break;
case ActionType.REPLY:
if (action.content) {
diff --git a/apps/web/utils/ai/rule/generate-prompt-on-delete-rule.ts b/apps/web/utils/ai/rule/generate-prompt-on-delete-rule.ts
index b2c32d12c9..f2e41cb4f7 100644
--- a/apps/web/utils/ai/rule/generate-prompt-on-delete-rule.ts
+++ b/apps/web/utils/ai/rule/generate-prompt-on-delete-rule.ts
@@ -20,7 +20,10 @@ export async function generatePromptOnDeleteRule({
existingPrompt: string;
deletedRule: RuleWithRelations;
}): Promise {
- const deletedRulePrompt = createPromptFromRule(deletedRule);
+ const deletedRulePrompt = createPromptFromRule(
+ deletedRule,
+ emailAccount.account.provider,
+ );
if (!existingPrompt) return "";
if (!deletedRulePrompt) return "";
diff --git a/apps/web/utils/ai/rule/generate-prompt-on-update-rule.ts b/apps/web/utils/ai/rule/generate-prompt-on-update-rule.ts
index a2153ebe89..ecca1e7498 100644
--- a/apps/web/utils/ai/rule/generate-prompt-on-update-rule.ts
+++ b/apps/web/utils/ai/rule/generate-prompt-on-update-rule.ts
@@ -16,8 +16,14 @@ export async function generatePromptOnUpdateRule({
currentRule: RuleWithRelations;
updatedRule: RuleWithRelations;
}): Promise {
- const currentRulePrompt = createPromptFromRule(currentRule);
- const updatedRulePrompt = createPromptFromRule(updatedRule);
+ const currentRulePrompt = createPromptFromRule(
+ currentRule,
+ emailAccount.account.provider,
+ );
+ const updatedRulePrompt = createPromptFromRule(
+ updatedRule,
+ emailAccount.account.provider,
+ );
if (!existingPrompt) return "";
if (!updatedRulePrompt) return "";
diff --git a/apps/web/utils/rule/prompt-file.ts b/apps/web/utils/rule/prompt-file.ts
index 18e270c050..d19834b926 100644
--- a/apps/web/utils/rule/prompt-file.ts
+++ b/apps/web/utils/rule/prompt-file.ts
@@ -7,12 +7,14 @@ import prisma from "@/utils/prisma";
export async function updatePromptFileOnRuleCreated({
emailAccountId,
+ provider,
rule,
}: {
emailAccountId: string;
+ provider: string;
rule: RuleWithRelations;
}) {
- const prompt = createPromptFromRule(rule);
+ const prompt = createPromptFromRule(rule, provider);
await appendRulePrompt({ emailAccountId, rulePrompt: prompt });
}
From 94a41864427722ac219fa98d1e52b614e9b009ed Mon Sep 17 00:00:00 2001
From: Eliezer Steinbock <3090527+elie222@users.noreply.github.com>
Date: Wed, 20 Aug 2025 07:49:33 +0300
Subject: [PATCH 4/6] fix build
---
.../[emailAccountId]/assistant/ExecutedRulesTable.tsx | 4 +++-
apps/web/app/(app)/[emailAccountId]/assistant/Pending.tsx | 7 +++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/apps/web/app/(app)/[emailAccountId]/assistant/ExecutedRulesTable.tsx b/apps/web/app/(app)/[emailAccountId]/assistant/ExecutedRulesTable.tsx
index 2a408dc07d..89b8233f1b 100644
--- a/apps/web/app/(app)/[emailAccountId]/assistant/ExecutedRulesTable.tsx
+++ b/apps/web/app/(app)/[emailAccountId]/assistant/ExecutedRulesTable.tsx
@@ -148,13 +148,15 @@ export function RuleCell({
export function ActionItemsCell({
actionItems,
+ provider,
}: {
actionItems: PendingExecutedRules["executedRules"][number]["actionItems"];
+ provider: string;
}) {
return (