feat: Cross-Context Awareness - Meeting info in email drafts#1149
feat: Cross-Context Awareness - Meeting info in email drafts#1149elie222 merged 7 commits intoelie222:mainfrom
Conversation
|
Warning Rate limit exceeded@elie222 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 42 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughAdds recipient meeting-context collection and formatting, email-address extraction utilities, and threads a formatted Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Draft Flow
participant GenDraft as generate-draft.ts
participant EmailUtil as email.ts
participant CalContext as recipient-context.ts
participant Calendar as Calendar Providers
participant AI as aiDraftWithKnowledge
Client->>GenDraft: generateDraftContent({ emailAccount, lastMessage, ... })
GenDraft->>EmailUtil: extractEmailAddresses(lastMessage.headers.To/CC)
par Parallel data fetch
GenDraft->>CalContext: getMeetingContext({ emailAccountId, recipientEmail, additionalRecipients, logger })
CalContext->>Calendar: fetch events (past & upcoming)
Calendar-->>CalContext: events[]
CalContext-->>GenDraft: MeetingContext[]
and Other context fetch
GenDraft->>GenDraft: gather other prompt context (history, contacts, etc.)
end
GenDraft->>CalContext: formatMeetingContextForPrompt(meetings, timezone)
GenDraft->>AI: aiDraftWithKnowledge({ ..., meetingContext, ... })
AI-->>GenDraft: Generated draft
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@rsnodgrass is attempting to deploy a commit to the Inbox Zero OSS Program Team on Vercel. A member of the Team first needs to authorize it. |
Include meeting context in LLM email draft prompts via
|
When drafting email replies, the AI now considers upcoming meetings scheduled with the recipient. This allows for natural references like "Looking forward to our call on Thursday" or "We can discuss this further in our upcoming meeting." Changes: - Add recipient-context.ts to fetch upcoming meetings with a recipient - Extend aiDraftWithKnowledge to accept meetingContext parameter - Integrate meeting context fetching in generate-draft.ts The feature queries the user's calendar for events within the next 7 days that include the email sender as an attendee, then formats this context for the AI to use when drafting replies.
5ee2465 to
4d940a4
Compare
|
@elie222 I had some extra Claude Code credits expiring December 31 and wanted to donate them to the project by implementing these features as proof of concepts. Feel free to use, modify, or delete/throw out as you see fit! Why Cross-Context Awareness is a great addition: This feature bridges the gap between calendar and email - two tools users constantly context-switch between. When replying to someone you have a meeting scheduled with, the AI can naturally reference it ("Looking forward to discussing this on Thursday" or "Let's save the details for our upcoming call"). This creates more personalized, contextually-aware replies that feel human rather than generic. It's the kind of small touch that makes users think "wow, this tool really gets me" - similar to how a great assistant would naturally mention an upcoming meeting when drafting a response. The implementation is lightweight (queries calendar for next 7 days, max 3 meetings) and integrates cleanly with the existing draft generation pipeline. |
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
There was a problem hiding this comment.
2 issues found across 3 files
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<file name="apps/web/utils/meeting-briefs/recipient-context.ts">
<violation number="1" location="apps/web/utils/meeting-briefs/recipient-context.ts:90">
P2: Date/time formatting uses server timezone instead of user timezone. This could cause the AI to reference incorrect meeting times (e.g., "our call at 3 PM" when the user sees 6 PM). Consider passing the user's timezone preference via the `timeZone` option, or use a relative format (e.g., "later this week") to avoid specific time references.</violation>
</file>
<file name="apps/web/utils/reply-tracker/generate-draft.ts">
<violation number="1" location="apps/web/utils/reply-tracker/generate-draft.ts:167">
P1: The `headers.from` value may contain a display name (e.g., "John Doe <john@example.com>") but is passed directly without extraction. Use `extractEmailAddress()` to extract the actual email address, consistent with the rest of the codebase.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- Pass logger as function parameter instead of file-level creation - Use extractEmailAddress() to properly extract email from headers.from - Use formatInUserTimezone() with user's timezone for meeting dates
|
Fixed all review feedback:
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/utils/meeting-briefs/recipient-context.ts (1)
98-102: Consider escaping special characters in event titles.If an event title contains double quotes (e.g.,
Review "Q4 Budget" draft), the current formatting could produce awkward output like- "Review "Q4 Budget" draft" on Friday.... This is a minor edge case that won't break functionality but could slightly confuse the LLM.🔎 Optional fix to escape quotes in titles
- let details = `- "${meeting.eventTitle}" on ${dateTime}`; + const safeTitle = meeting.eventTitle.replace(/"/g, '\\"'); + let details = `- "${safeTitle}" on ${dateTime}`;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/utils/ai/reply/draft-with-knowledge.tsapps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.ts
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Import specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Do not export types/interfaces that are only used within the same file. Export later if needed
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma'sselectoption. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. AllfindUnique/findFirstcalls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
AllfindManyqueries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g.,emailAccount: { id: emailAccountId }) to validate ownership
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
**/{utils,helpers,lib}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx,js,jsx}: Use@/path aliases for imports from project root
Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments
Add helper functions to the bottom of files, not the top
All imports go at the top of files, no mid-file dynamic imports
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/**/*.{ts,tsx,js,jsx,json,css}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Format code with Prettier
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/**/*.{example,ts,json}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Add environment variables to
.env.example,env.ts, andturbo.json
Files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/{utils/ai,utils/llms,__tests__}/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
LLM-related code must be organized in specific directories:
apps/web/utils/ai/for main implementations,apps/web/utils/llms/for core utilities and configurations, andapps/web/__tests__/for LLM-specific tests
Files:
apps/web/utils/ai/reply/draft-with-knowledge.ts
apps/web/utils/ai/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)
apps/web/utils/ai/**/*.ts: LLM feature functions must import fromzodfor schema validation, usecreateScopedLoggerfrom@/utils/logger,chatCompletionObjectandcreateGenerateObjectfrom@/utils/llms, and importEmailAccountWithAItype from@/utils/llms/types
LLM feature functions must follow a standard structure: accept options withinputDataandemailAccountparameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and usecreateGenerateObjectto execute the LLM call
System prompts must define the LLM's role and task specifications
User prompts must contain the actual data and context, and should be kept separate from system prompts
Always define a Zod schema for LLM response validation and make schemas as specific as possible to guide the LLM output
Use descriptive scoped loggers for each LLM feature, log inputs and outputs with appropriate log levels, and include relevant context in log messages
Implement early returns for invalid LLM inputs, use proper error types and logging, implement fallbacks for AI failures, and add retry logic for transient failures usingwithRetry
Use XML-like tags to structure data in prompts, remove excessive whitespace and truncate long inputs, and format data consistently across similar LLM functions
Use TypeScript types for all LLM function parameters and return values, and define clear interfaces for complex input/output structures
Keep related AI functions in the same file or directory, extract common patterns into utility functions, and document complex AI logic with clear comments
Files:
apps/web/utils/ai/reply/draft-with-knowledge.ts
🧠 Learnings (18)
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Access context (userId, emailAccountId, etc.) via the `ctx` object parameter in the `.action()` handler
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Pass the logger through the request/function chain instead of creating new logger instances at each level
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{utils,helpers,lib}/**/*.{ts,tsx} : Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.{ts,tsx} : Avoid using .with() for global/file-level loggers; only use .with() within specific functions for context enrichment
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use descriptive scoped loggers for each LLM feature, log inputs and outputs with appropriate log levels, and include relevant context in log messages
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{scripts,tests,__tests__}/**/*.{ts,tsx} : Use createScopedLogger only for code that doesn't run within a middleware chain, such as standalone scripts or tests
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.action.{ts,tsx} : Use actionClient context to receive logger automatically in server actions, accessing it via ctx.logger
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must import from `zod` for schema validation, use `createScopedLogger` from `@/utils/logger`, `chatCompletionObject` and `createGenerateObject` from `@/utils/llms`, and import `EmailAccountWithAI` type from `@/utils/llms/types`
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{app,pages}/**/{route,+page}.{ts,tsx} : Enrich logger context within route handlers using logger.with() to add request-specific fields like messageId
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : User prompts must contain the actual data and context, and should be kept separate from system prompts
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Prefer using existing helpers from `@/__tests__/helpers.ts` (`getEmailAccount`, `getEmail`, `getRule`, `getMockMessage`, `getMockExecutedRule`) instead of creating custom test data helpers
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account (reading/writing emails, rules, schedules, etc.) - provides `emailAccountId`, `userId`, and `email` in `request.auth`
Applied to files:
apps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/ai/reply/draft-with-knowledge.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : System prompts must define the LLM's role and task specifications
Applied to files:
apps/web/utils/ai/reply/draft-with-knowledge.ts
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Use `actionClient` when both authenticated user context and a specific emailAccountId are needed, with emailAccountId bound when calling from the client
Applied to files:
apps/web/utils/ai/reply/draft-with-knowledge.ts
📚 Learning: 2025-11-25T14:39:27.909Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:27.909Z
Learning: Applies to **/app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account, including reading/writing emails, rules, schedules, or any operation using `emailAccountId`
Applied to files:
apps/web/utils/ai/reply/draft-with-knowledge.ts
🧬 Code graph analysis (2)
apps/web/utils/meeting-briefs/recipient-context.ts (3)
apps/web/utils/logger.ts (1)
Logger(6-6)apps/web/utils/calendar/event-provider.ts (1)
createCalendarEventProviders(11-74)apps/web/utils/date.ts (1)
formatInUserTimezone(122-143)
apps/web/utils/reply-tracker/generate-draft.ts (2)
apps/web/utils/meeting-briefs/recipient-context.ts (2)
getUpcomingMeetingContext(21-77)formatMeetingContextForPrompt(82-113)apps/web/utils/email.ts (1)
extractEmailAddress(19-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
🔇 Additional comments (8)
apps/web/utils/reply-tracker/generate-draft.ts (2)
166-171: LGTM! Meeting context integration follows established patterns.The implementation correctly:
- Uses
extractEmailAddress()to parse the sender email from headers (addressing prior feedback)- Passes logger as a parameter per project conventions
- Fetches meeting context in parallel with other context operations for efficiency
199-214: Good integration of meeting context into the draft flow.The timezone is properly passed to
formatMeetingContextForPrompt, and themeetingContextis threaded through toaiDraftWithKnowledgeconsistently with other context types (knowledge base, email history, calendar availability, etc.).apps/web/utils/ai/reply/draft-with-knowledge.ts (3)
41-51: Correct extension of the user prompt signature.The
meetingContextparameter is properly typed asstring | nulland positioned consistently with other optional context parameters.
149-159: Meeting context properly integrated into prompt construction.The
upcomingMeetingsContextis added to the template in the same section as other external context types. The empty string fallback (|| "") ensures clean prompt composition when no meetings are found.
186-222: LGTM! aiDraftWithKnowledge correctly threads meeting context through.The function signature and implementation properly accept and pass
meetingContexttogetUserPrompt, maintaining consistency with how other context types are handled.apps/web/utils/meeting-briefs/recipient-context.ts (3)
1-8: LGTM! Clean module setup with sensible defaults.The constants
UPCOMING_DAYS = 7andMAX_MEETINGS = 3are reasonable defaults for cross-context awareness. The imports are appropriate and no file-level logger is created (addressing prior feedback).
21-77: Well-structured meeting context fetcher with proper error handling.Good implementation details:
- Logger is passed as a parameter per project conventions
- Graceful degradation: per-provider errors are caught and logged without failing the entire operation
- Events are sorted and limited after aggregation to get the soonest meetings across all providers
- Outer try/catch ensures failures don't propagate up to break draft generation
82-113: Meeting context formatting correctly uses user timezone.The
formatInUserTimezoneutility properly handles timezone conversion (addressing prior feedback about server vs. user timezone). The XML-like<upcoming_meetings>tags follow the project's established prompt structuring patterns.
- Add recent past meetings (14 days lookback) in addition to upcoming (7 days) - Include meeting descriptions (truncated to 500 chars) for richer context - Increase max meetings per category from 3 to 5 - Add privacy-preserving filtering for CC replies: Only include meetings where ALL recipients were attendees Prevents leaking private calendar info to CC'd recipients - Rename getUpcomingMeetingContext to getMeetingContext (deprecated alias kept) - Add extractEmailAddresses helper for parsing header lists
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/utils/meeting-briefs/recipient-context.ts (1)
82-104: Consider: maxResults applied per-provider, not total.When multiple calendar providers exist (e.g., Google + Microsoft), each provider fetches up to
MAX_MEETINGS_PER_CATEGORYevents, potentially returning more meetings than intended before the finalslice()on lines 128-135 trims them. This is likely acceptable since the final slice enforces the limit, but the over-fetching could be optimized if performance becomes a concern.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/utils/email.tsapps/web/utils/meeting-briefs/recipient-context.tsapps/web/utils/reply-tracker/generate-draft.ts
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Import specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Do not export types/interfaces that are only used within the same file. Export later if needed
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma'sselectoption. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. AllfindUnique/findFirstcalls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
AllfindManyqueries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g.,emailAccount: { id: emailAccountId }) to validate ownership
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/{utils,helpers,lib}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx,js,jsx}: Use@/path aliases for imports from project root
Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments
Add helper functions to the bottom of files, not the top
All imports go at the top of files, no mid-file dynamic imports
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx,js,jsx,json,css}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Format code with Prettier
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{example,ts,json}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Add environment variables to
.env.example,env.ts, andturbo.json
Files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
🧠 Learnings (17)
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to apps/web/utils/gmail/**/*.{ts,tsx} : Keep Gmail provider-specific implementation details isolated within the apps/web/utils/gmail/ directory
Applied to files:
apps/web/utils/email.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Applied to files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must import from `zod` for schema validation, use `createScopedLogger` from `@/utils/logger`, `chatCompletionObject` and `createGenerateObject` from `@/utils/llms`, and import `EmailAccountWithAI` type from `@/utils/llms/types`
Applied to files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.tsapps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Applied to files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:40:00.833Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-11-25T14:40:00.833Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helpers `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for mocking emails, accounts, and rules
Applied to files:
apps/web/utils/email.tsapps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must follow a standard structure: accept options with `inputData` and `emailAccount` parameters, implement input validation with early returns, define separate system and user prompts, create a Zod schema for response validation, and use `createGenerateObject` to execute the LLM call
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Prefer using existing helpers from `@/__tests__/helpers.ts` (`getEmailAccount`, `getEmail`, `getRule`, `getMockMessage`, `getMockExecutedRule`) instead of creating custom test data helpers
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:39:23.326Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:23.326Z
Learning: Applies to app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account (reading/writing emails, rules, schedules, etc.) - provides `emailAccountId`, `userId`, and `email` in `request.auth`
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-11-25T14:39:27.909Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-11-25T14:39:27.909Z
Learning: Applies to **/app/api/**/*.ts : Use `withEmailAccount` middleware for operations scoped to a specific email account, including reading/writing emails, rules, schedules, or any operation using `emailAccountId`
Applied to files:
apps/web/utils/reply-tracker/generate-draft.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Pass the logger through the request/function chain instead of creating new logger instances at each level
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{utils,helpers,lib}/**/*.{ts,tsx} : Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.{ts,tsx} : Avoid using .with() for global/file-level loggers; only use .with() within specific functions for context enrichment
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use descriptive scoped loggers for each LLM feature, log inputs and outputs with appropriate log levels, and include relevant context in log messages
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{scripts,tests,__tests__}/**/*.{ts,tsx} : Use createScopedLogger only for code that doesn't run within a middleware chain, such as standalone scripts or tests
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.action.{ts,tsx} : Use actionClient context to receive logger automatically in server actions, accessing it via ctx.logger
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{app,pages}/**/{route,+page}.{ts,tsx} : Enrich logger context within route handlers using logger.with() to add request-specific fields like messageId
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : User prompts must contain the actual data and context, and should be kept separate from system prompts
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
🧬 Code graph analysis (1)
apps/web/utils/meeting-briefs/recipient-context.ts (3)
apps/web/utils/logger.ts (1)
Logger(6-6)apps/web/utils/calendar/event-provider.ts (1)
createCalendarEventProviders(11-74)apps/web/utils/date.ts (1)
formatInUserTimezone(122-143)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
🔇 Additional comments (14)
apps/web/utils/email.ts (3)
18-29: Well-structured email header parsing.The regex pattern correctly handles commas inside quoted display names, preventing incorrect splits on names like
"Doe, John" <john@example.com>. The delegation toextractEmailAddressand filtering of empty results is clean.
31-65: Robust multi-step email extraction logic.The layered approach (bracket extraction → whole string validation → pattern scanning) handles various header formats gracefully. Each candidate is validated with
isValidEmailbefore returning, preventing invalid addresses from slipping through.
67-69: Clean validation helper.Correctly reuses the existing zod schema and keeps the helper private to this module.
apps/web/utils/reply-tracker/generate-draft.ts (3)
166-178: Good parallel fetching and privacy-aware recipient filtering.The meeting context is fetched concurrently with other context data. The privacy filtering correctly:
- Extracts the sender email using
extractEmailAddress- Extracts all To/CC recipients using
extractEmailAddresses- Filters out the user's own email to avoid self-matching
- Passes additional recipients for the privacy filter in
getMeetingContextThis addresses the previously flagged issue about email extraction from headers.
207-210: Correct timezone handling for meeting context.The user's timezone from
emailAccount.timezoneis properly passed to format meeting times in the user's local timezone, addressing the previously flagged server timezone issue.
212-222: Clean integration with draft generation.The
meetingContextis seamlessly integrated into the existing draft generation flow, following the established pattern for context parameters likecalendarAvailabilityandmcpContext.apps/web/utils/meeting-briefs/recipient-context.ts (8)
1-11: Well-organized imports and constants.Clean separation of concerns with date-fns for date manipulation, calendar providers for event fetching, and the shared
formatInUserTimezoneutility for consistent timezone handling.
24-32: Efficient privacy filter implementation.Uses a Set for O(1) attendee lookups and correctly normalizes emails to lowercase for case-insensitive comparison.
106-135: Privacy filtering and sorting logic is correct.The conditional filtering only applies when additional recipients (CC) exist, preserving all meetings for direct replies while preventing calendar information leakage to CC recipients who weren't invited to those meetings.
137-156: Clean mapping and graceful error handling.The transformation to
MeetingContextis straightforward, and the top-level error handler ensures calendar failures don't break the draft generation flow.
158-161: Good deprecation pattern.The alias with
@deprecatedJSDoc allows for backward compatibility while signaling that callers should migrate togetMeetingContext.
163-169: LGTM!Simple truncation with ellipsis for long descriptions.
171-190: User timezone correctly applied.The
formatInUserTimezoneutility is used with the user's timezone preference, ensuring meeting times display correctly relative to the user's location. This addresses the previously flagged server timezone issue.
195-233: Well-designed prompt formatting.The structured output with
<recent_meetings>and<upcoming_meetings>sections provides clear context for the AI. The instructional text guides natural usage without being overly prescriptive, and the null return for empty meetings prevents unnecessary prompt bloat.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/web/utils/meeting-briefs/recipient-context.ts (1)
24-32: Consider moving helper functions to the bottom of the file.The helper functions
allRecipientsAreAttendees,truncateDescription, andformatMeetingare placed throughout the file. Per coding guidelines, helper functions should be added to the bottom of files, not the top or middle.📝 Suggested organization
Move these helper functions after the main exported functions:
+export async function getMeetingContext({ ... }): Promise<MeetingContext[]> { + // ... main function +} + +export function formatMeetingContextForPrompt( + meetings: MeetingContext[], + timezone?: string | null, +): string | null { + // ... main function +} + +// Helper functions function allRecipientsAreAttendees( event: CalendarEvent, requiredEmails: string[], ): boolean { // ... } + +function truncateDescription( + description: string | undefined, +): string | undefined { + // ... +} + +function formatMeeting( + meeting: MeetingContext, + timezone?: string | null, +): string { + // ... +}As per coding guidelines: "Add helper functions to the bottom of files, not the top"
Also applies to: 158-185
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/data-fetching.mdc)
**/*.{ts,tsx}: For API GET requests to server, use theswrpackage
Useresult?.serverErrorwithtoastErrorfrom@/components/Toastfor error handling in async operations
**/*.{ts,tsx}: Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
**/*.{ts,tsx}: For early access feature flags, create hooks using the naming conventionuse[FeatureName]Enabledthat return a boolean fromuseFeatureFlagEnabled("flag-key")
For A/B test variant flags, create hooks using the naming conventionuse[FeatureName]Variantthat define variant types, useuseFeatureFlagVariantKey()with type casting, and provide a default "control" fallback
Use kebab-case for PostHog feature flag keys (e.g.,inbox-cleaner,pricing-options-2)
Always define types for A/B test variant flags (e.g.,type PricingVariant = "control" | "variant-a" | "variant-b") and provide type safety through type casting
**/*.{ts,tsx}: Don't use primitive type aliases or misleading types
Don't use empty type parameters in type aliases and interfaces
Don't use this and super in static contexts
Don't use any or unknown as type constraints
Don't use the TypeScript directive @ts-ignore
Don't use TypeScript enums
Don't export imported variables
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions
Don't use TypeScript namespaces
Don't use non-null assertions with the!postfix operator
Don't use parameter properties in class constructors
Don't use user-defined types
Useas constinstead of literal types and type annotations
Use eitherT[]orArray<T>consistently
Initialize each enum member value explicitly
Useexport typefor types
Use `impo...
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/prisma-enum-imports.mdc)
Always import Prisma enums from
@/generated/prisma/enumsinstead of@/generated/prisma/clientto avoid Next.js bundling errors in client componentsImport Prisma using the project's centralized utility:
import prisma from '@/utils/prisma'
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)
Import specific lodash functions rather than entire lodash library to minimize bundle size (e.g.,
import groupBy from 'lodash/groupBy')
apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Do not export types/interfaces that are only used within the same file. Export later if needed
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/security.mdc)
**/*.ts: ALL database queries MUST be scoped to the authenticated user/account by including user/account filtering in WHERE clauses to prevent unauthorized data access
Always validate that resources belong to the authenticated user before performing operations, using ownership checks in WHERE clauses or relationships
Always validate all input parameters for type, format, and length before using them in database queries
Use SafeError for error responses to prevent information disclosure. Generic error messages should not reveal internal IDs, logic, or resource ownership details
Only return necessary fields in API responses using Prisma'sselectoption. Never expose sensitive data such as password hashes, private keys, or system flags
Prevent Insecure Direct Object References (IDOR) by validating resource ownership before operations. AllfindUnique/findFirstcalls MUST include ownership filters
Prevent mass assignment vulnerabilities by explicitly whitelisting allowed fields in update operations instead of accepting all user-provided data
Prevent privilege escalation by never allowing users to modify system fields, ownership fields, or admin-only attributes through user input
AllfindManyqueries MUST be scoped to the user's data by including appropriate WHERE filters to prevent returning data from other users
Use Prisma relationships for access control by leveraging nested where clauses (e.g.,emailAccount: { id: emailAccountId }) to validate ownership
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
**/*.{tsx,ts}: Use Shadcn UI and Tailwind for components and styling
Usenext/imagepackage for images
For API GET requests to server, use theswrpackage with hooks likeuseSWRto fetch data
For text inputs, use theInputcomponent withregisterPropsfor form integration and error handling
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{tsx,ts,css}
📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)
Implement responsive design with Tailwind CSS using a mobile-first approach
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{js,jsx,ts,tsx}: Don't useaccessKeyattribute on any HTML element
Don't setaria-hidden="true"on focusable elements
Don't add ARIA roles, states, and properties to elements that don't support them
Don't use distracting elements like<marquee>or<blink>
Only use thescopeprop on<th>elements
Don't assign non-interactive ARIA roles to interactive HTML elements
Make sure label elements have text content and are associated with an input
Don't assign interactive ARIA roles to non-interactive HTML elements
Don't assigntabIndexto non-interactive HTML elements
Don't use positive integers fortabIndexproperty
Don't include "image", "picture", or "photo" in img alt prop
Don't use explicit role property that's the same as the implicit/default role
Make static elements with click handlers use a valid role attribute
Always include atitleelement for SVG elements
Give all elements requiring alt text meaningful information for screen readers
Make sure anchors have content that's accessible to screen readers
AssigntabIndexto non-interactive HTML elements witharia-activedescendant
Include all required ARIA attributes for elements with ARIA roles
Make sure ARIA properties are valid for the element's supported roles
Always include atypeattribute for button elements
Make elements with interactive roles and handlers focusable
Give heading elements content that's accessible to screen readers (not hidden witharia-hidden)
Always include alangattribute on the html element
Always include atitleattribute for iframe elements
AccompanyonClickwith at least one of:onKeyUp,onKeyDown, oronKeyPress
AccompanyonMouseOver/onMouseOutwithonFocus/onBlur
Include caption tracks for audio and video elements
Use semantic elements instead of role attributes in JSX
Make sure all anchors are valid and navigable
Ensure all ARIA properties (aria-*) are valid
Use valid, non-abstract ARIA roles for elements with ARIA roles
Use valid AR...
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{test,spec}.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
**/*.{test,spec}.{js,jsx,ts,tsx}: Don't nest describe() blocks too deeply in test files
Don't use callbacks in asynchronous tests and hooks
Don't have duplicate hooks in describe blocks
Don't use export or module.exports in test files
Don't use focused tests
Make sure the assertion function, like expect, is placed inside an it() function call
Don't use disabled tests
Files:
apps/web/utils/email.test.ts
!(pages/_document).{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)
Don't use the next/head module in pages/_document.js on Next.js projects
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/utilities.mdc)
**/*.{js,ts,jsx,tsx}: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size (e.g.,import groupBy from 'lodash/groupBy')
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/{utils,helpers,lib}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)
Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
apps/web/**/*.{ts,tsx,js,jsx}: Use@/path aliases for imports from project root
Prefer self-documenting code over comments; use descriptive variable and function names instead of explaining intent with comments
Add helper functions to the bottom of files, not the top
All imports go at the top of files, no mid-file dynamic imports
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.{ts,tsx,js,jsx,json,css}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Format code with Prettier
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
apps/web/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Co-locate test files next to source files (e.g.,
utils/example.test.ts). Only E2E and AI tests go in__tests__/
Files:
apps/web/utils/email.test.ts
apps/web/**/*.{example,ts,json}
📄 CodeRabbit inference engine (apps/web/CLAUDE.md)
Add environment variables to
.env.example,env.ts, andturbo.json
Files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
**/*.test.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/notes.mdc)
Co-locate test files next to source files (e.g.,
utils/example.test.ts). Only E2E and AI tests go in__tests__/
Files:
apps/web/utils/email.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)
**/*.test.{ts,tsx}: Usevitestas the testing framework
Colocate test files next to the tested file with.test.tsor.test.tsxnaming convention (e.g.,dir/format.tsanddir/format.test.ts)
Mockserver-onlyusingvi.mock("server-only", () => ({}))
Mock Prisma usingvi.mock("@/utils/prisma")and the provided mock from@/utils/__mocks__/prisma
Use test helper functionsgetEmail,getEmailAccount, andgetRulefrom@/__tests__/helpersfor creating mock data
Clear all mocks between tests usingbeforeEach(() => { vi.clearAllMocks(); })
Use descriptive test names that clearly indicate what is being tested
Do not mock the Logger in tests
Files:
apps/web/utils/email.test.ts
🧠 Learnings (19)
📚 Learning: 2026-01-01T10:42:29.767Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2026-01-01T10:42:29.767Z
Learning: Applies to **/*.test.{ts,tsx} : Use test helper functions `getEmail`, `getEmailAccount`, and `getRule` from `@/__tests__/helpers` for creating mock data
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Prefer using existing helpers from `@/__tests__/helpers.ts` (`getEmailAccount`, `getEmail`, `getRule`, `getMockMessage`, `getMockExecutedRule`) instead of creating custom test data helpers
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to apps/web/utils/gmail/**/*.{ts,tsx} : Keep Gmail provider-specific implementation details isolated within the apps/web/utils/gmail/ directory
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail thread operations from @/utils/gmail/thread.ts instead of direct API calls
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : LLM feature functions must import from `zod` for schema validation, use `createScopedLogger` from `@/utils/logger`, `chatCompletionObject` and `createGenerateObject` from `@/utils/llms`, and import `EmailAccountWithAI` type from `@/utils/llms/types`
Applied to files:
apps/web/utils/email.test.tsapps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail message operations (get, list, batch, etc.) from @/utils/gmail/message.ts instead of direct API calls
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to apps/web/utils/gmail/**/*.{ts,tsx} : Always use wrapper functions from @/utils/gmail/ for Gmail API operations instead of direct provider API calls
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:22.660Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-11-25T14:37:22.660Z
Learning: Applies to **/*.{ts,tsx} : Use wrapper functions for Gmail label operations from @/utils/gmail/label.ts instead of direct API calls
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Use vitest imports (`describe`, `expect`, `test`, `vi`, `beforeEach`) in LLM test files
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:37:56.430Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm-test.mdc:0-0
Timestamp: 2025-11-25T14:37:56.430Z
Learning: Applies to apps/web/__tests__/**/*.test.ts : Place all LLM-related tests in `apps/web/__tests__/` directory
Applied to files:
apps/web/utils/email.test.ts
📚 Learning: 2025-11-25T14:39:49.448Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-11-25T14:39:49.448Z
Learning: Applies to apps/web/utils/actions/*.ts : Access context (userId, emailAccountId, etc.) via the `ctx` object parameter in the `.action()` handler
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Pass the logger through the request/function chain instead of creating new logger instances at each level
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{utils,helpers,lib}/**/*.{ts,tsx} : Logger should be passed as a parameter to helper functions instead of creating their own logger instances
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.{ts,tsx} : Avoid using .with() for global/file-level loggers; only use .with() within specific functions for context enrichment
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : Use descriptive scoped loggers for each LLM feature, log inputs and outputs with appropriate log levels, and include relevant context in log messages
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{scripts,tests,__tests__}/**/*.{ts,tsx} : Use createScopedLogger only for code that doesn't run within a middleware chain, such as standalone scripts or tests
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/*.action.{ts,tsx} : Use actionClient context to receive logger automatically in server actions, accessing it via ctx.logger
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-12-18T16:37:47.972Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/logging.mdc:0-0
Timestamp: 2025-12-18T16:37:47.972Z
Learning: Applies to **/{app,pages}/**/{route,+page}.{ts,tsx} : Enrich logger context within route handlers using logger.with() to add request-specific fields like messageId
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
📚 Learning: 2025-11-25T14:38:07.606Z
Learnt from: CR
Repo: elie222/inbox-zero PR: 0
File: .cursor/rules/llm.mdc:0-0
Timestamp: 2025-11-25T14:38:07.606Z
Learning: Applies to apps/web/utils/ai/**/*.ts : User prompts must contain the actual data and context, and should be kept separate from system prompts
Applied to files:
apps/web/utils/meeting-briefs/recipient-context.ts
🧬 Code graph analysis (2)
apps/web/utils/email.test.ts (1)
apps/web/utils/email.ts (1)
extractEmailAddresses(20-29)
apps/web/utils/meeting-briefs/recipient-context.ts (3)
apps/web/utils/logger.ts (1)
Logger(6-6)apps/web/utils/calendar/event-provider.ts (1)
createCalendarEventProviders(11-74)apps/web/utils/date.ts (1)
formatInUserTimezone(122-143)
🔇 Additional comments (3)
apps/web/utils/email.test.ts (1)
37-153: Excellent test coverage for the newextractEmailAddressesfunction!The test suite is comprehensive and well-structured, covering:
- Basic functionality (empty input, single/multiple emails)
- Various email formats (with/without names, angle brackets)
- Edge cases (whitespace handling, comma variations, empty segments)
- Special characters (plus addressing, hyphens, underscores, numbers)
- Error handling (invalid email filtering)
- Real-world scenarios (complex headers with quoted names containing commas)
The test names are descriptive and follow best practices. This level of coverage is appropriate for a utility function that will be used across the codebase.
apps/web/utils/meeting-briefs/recipient-context.ts (2)
44-156: Excellent implementation with robust error handling and privacy considerations.The
getMeetingContextfunction is well-structured with:
- Proper logger parameter pattern (as per learnings)
- Graceful degradation (continues if individual providers fail, returns empty array on overall failure)
- Privacy-conscious filtering that prevents leaking meeting info to CC recipients who weren't invited
- Appropriate sorting (most recent past first, soonest upcoming first)
- Reasonable limits to prevent overwhelming AI prompts
The logic flow is clean and easy to follow.
190-228: Well-crafted prompt formatting with clear AI guidance.The function properly:
- Returns
nullfor empty input (allows caller to handle gracefully)- Separates past and upcoming meetings with clear XML-like tags
- Uses timezone-aware formatting via
formatInUserTimezone- Provides helpful, natural-sounding instructions to the AI on how to reference meetings
The prompt engineering approach is sound and should produce contextually relevant draft suggestions.
|
thanks! |
Summary
@elie222 This is a feature suggestion, feel free to delete or incorporate.
When drafting email replies, the AI now considers upcoming meetings scheduled with the recipient. This enables natural references like:
Changes
New file:
apps/web/utils/meeting-briefs/recipient-context.tsgetUpcomingMeetingContext()- fetches meetings with a recipient from the next 7 daysformatMeetingContextForPrompt()- formats meeting data for AI consumptionModified:
apps/web/utils/ai/reply/draft-with-knowledge.tsmeetingContextparameter to include upcoming meetings in promptsModified:
apps/web/utils/reply-tracker/generate-draft.tsHow it works
Test plan
fetchEventsWithAttendeereturns correct eventsNote
Introduces upcoming meeting context into AI email drafting.
utils/meeting-briefs/recipient-context.ts:getUpcomingMeetingContext(fetch next 7 days, max 3, by recipient attendee) andformatMeetingContextForPromptfor prompt-ready textutils/reply-tracker/generate-draft.ts: fetch upcoming meetings in parallel with other context and pass formattedmeetingContextto draftingutils/ai/reply/draft-with-knowledge.ts: addmeetingContextparam and inject into composed user promptWritten by Cursor Bugbot for commit 4d940a4. Configure here.
Summary by CodeRabbit
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.