diff --git a/apps/web/__tests__/ai-meeting-briefing.test.ts b/apps/web/__tests__/ai-meeting-briefing.test.ts index 8184569142..81a86430fb 100644 --- a/apps/web/__tests__/ai-meeting-briefing.test.ts +++ b/apps/web/__tests__/ai-meeting-briefing.test.ts @@ -51,9 +51,12 @@ function getMeetingBriefingData( } describe("buildPrompt", () => { + const mockEmailAccount = getEmailAccount({ timezone: "America/New_York" }); + const mockEmailAccountNoTz = getEmailAccount({ timezone: null }); + test("builds prompt with meeting title and description", () => { const data = getMeetingBriefingData(); - const prompt = buildPrompt(data, "America/New_York"); + const prompt = buildPrompt(data, mockEmailAccount); expect(prompt).toContain("Product Discussion"); expect(prompt).toContain("Q1 roadmap"); @@ -63,7 +66,7 @@ describe("buildPrompt", () => { const data = getMeetingBriefingData({ externalGuests: [{ email: "bob@company.com", name: "Bob Smith" }], }); - const prompt = buildPrompt(data, null); + const prompt = buildPrompt(data, mockEmailAccountNoTz); expect(prompt).toContain("bob@company.com"); expect(prompt).toContain("Bob Smith"); @@ -75,7 +78,7 @@ describe("buildPrompt", () => { emailThreads: [], pastMeetings: [], }); - const prompt = buildPrompt(data, null); + const prompt = buildPrompt(data, mockEmailAccountNoTz); expect(prompt).toContain(""); expect(prompt).toContain("New Contact"); @@ -99,7 +102,7 @@ describe("buildPrompt", () => { }, ], }); - const prompt = buildPrompt(data, null); + const prompt = buildPrompt(data, mockEmailAccountNoTz); expect(prompt).toContain(""); expect(prompt).toContain("Partnership proposal"); @@ -121,7 +124,7 @@ describe("buildPrompt", () => { externalGuests: [{ email: "alice@external.com", name: "Alice External" }], pastMeetings: [pastMeeting], }); - const prompt = buildPrompt(data, "America/New_York"); + const prompt = buildPrompt(data, mockEmailAccount); expect(prompt).toContain(""); expect(prompt).toContain("Initial Discussion"); @@ -134,7 +137,7 @@ describe("buildPrompt", () => { { email: "bob@acme.com", name: "Bob Jones" }, ], }); - const prompt = buildPrompt(data, null); + const prompt = buildPrompt(data, mockEmailAccountNoTz); expect(prompt).toContain("alice@acme.com"); expect(prompt).toContain("Alice Smith"); diff --git a/apps/web/utils/ai/meeting-briefs/generate-briefing.test.ts b/apps/web/utils/ai/meeting-briefs/generate-briefing.test.ts index 3415af4a36..aec363135d 100644 --- a/apps/web/utils/ai/meeting-briefs/generate-briefing.test.ts +++ b/apps/web/utils/ai/meeting-briefs/generate-briefing.test.ts @@ -10,6 +10,16 @@ vi.mock("@/env", () => ({ })); vi.mock("@/utils/llms/model", () => ({ getModel: vi.fn() })); vi.mock("@/utils/llms", () => ({ createGenerateObject: vi.fn() })); +vi.mock("@/utils/ai/helpers", () => ({ + getUserInfoPrompt: vi.fn( + ({ emailAccount }) => + `The user you are acting on behalf of is: + +${emailAccount.email} +${emailAccount.about} +`, + ), +})); vi.mock("@/utils/stringify-email", () => ({ stringifyEmailSimple: vi.fn( (email) => @@ -27,12 +37,18 @@ vi.mock("@/utils/get-email-from-message", () => ({ vi.doUnmock("@/utils/date"); import { buildPrompt } from "./generate-briefing"; +import type { EmailAccountWithAI } from "@/utils/llms/types"; beforeEach(() => { vi.clearAllMocks(); }); describe("buildPrompt timezone handling", () => { + const mockEmailAccount = { + email: "user@company.com", + timezone: "America/Sao_Paulo", + about: "I am a product manager at Company Inc.", + } as EmailAccountWithAI; it("formats past meeting times in the user's timezone (not UTC)", () => { // This test documents the timezone bug fix: // - Calendar API stores times in UTC @@ -54,6 +70,7 @@ describe("buildPrompt timezone handling", () => { ], }, externalGuests: [{ email: "client@acme.com", name: "John Smith" }], + internalTeamMembers: [], emailThreads: [], pastMeetings: [ { @@ -67,12 +84,18 @@ describe("buildPrompt timezone handling", () => { ], }; - const prompt = buildPrompt(briefingData, "America/Sao_Paulo"); + const prompt = buildPrompt(briefingData, mockEmailAccount); // The past meeting should show "4:00 PM" (Brazil time), NOT "7:00 PM" (UTC) expect(prompt).toMatchInlineSnapshot(` "Prepare a concise briefing for this upcoming meeting. + The user you are acting on behalf of is: + + user@company.com + I am a product manager at Company Inc. + + Title: Strategy Review Description: Discuss Q1 roadmap @@ -117,15 +140,22 @@ describe("buildPrompt timezone handling", () => { ], }, externalGuests: [{ email: "newcontact@other.com", name: "New Person" }], + internalTeamMembers: [], emailThreads: [], pastMeetings: [], }; - const prompt = buildPrompt(briefingData, "America/Sao_Paulo"); + const prompt = buildPrompt(briefingData, mockEmailAccount); expect(prompt).toMatchInlineSnapshot(` "Prepare a concise briefing for this upcoming meeting. + The user you are acting on behalf of is: + + user@company.com + I am a product manager at Company Inc. + + Title: Intro Meeting diff --git a/apps/web/utils/ai/meeting-briefs/generate-briefing.ts b/apps/web/utils/ai/meeting-briefs/generate-briefing.ts index da80bf6c56..473e624f58 100644 --- a/apps/web/utils/ai/meeting-briefs/generate-briefing.ts +++ b/apps/web/utils/ai/meeting-briefs/generate-briefing.ts @@ -7,6 +7,7 @@ import { env } from "@/env"; import { getModel } from "@/utils/llms/model"; import { createGenerateText } from "@/utils/llms"; import type { EmailAccountWithAI } from "@/utils/llms/types"; +import { getUserInfoPrompt } from "@/utils/ai/helpers"; import type { CalendarEvent } from "@/utils/calendar/event-types"; import type { MeetingBriefingData } from "@/utils/meeting-briefs/gather-context"; import { stringifyEmailSimple } from "@/utils/stringify-email"; @@ -94,7 +95,7 @@ export async function aiGenerateMeetingBriefing({ ); } - const prompt = buildPrompt(briefingData, emailAccount.timezone); + const prompt = buildPrompt(briefingData, emailAccount); const modelOptions = getModel(emailAccount.user); const generateText = createGenerateText({ @@ -342,7 +343,7 @@ function createWebSearchTool({ // Exported for testing export function buildPrompt( briefingData: MeetingBriefingData, - timezone: string | null, + emailAccount: EmailAccountWithAI, ): string { const { event, externalGuests, emailThreads, pastMeetings } = briefingData; @@ -354,7 +355,7 @@ export function buildPrompt( name: guest.name, recentEmails: selectRecentEmailsForGuest(allMessages, guest.email), recentMeetings: selectRecentMeetingsForGuest(pastMeetings, guest.email), - timezone, + timezone: emailAccount.timezone, }), ); @@ -376,6 +377,8 @@ export function buildPrompt( const prompt = `Prepare a concise briefing for this upcoming meeting. +${getUserInfoPrompt({ emailAccount })} + Title: ${event.title} ${event.description ? `Description: ${event.description}` : ""}