Conversation
WalkthroughThis update introduces a new "Open in New Tab" action to the email thread context menu and updates icon styling. It also refines draft and reply handling, improves thread data retrieval, adjusts event handling, and removes or simplifies asynchronous state updates and cache management. Minor localization and formatting changes are included. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant ThreadContextMenu
participant Browser
User->>ThreadContextMenu: Right-clicks thread, selects "Open in New Tab"
ThreadContextMenu->>Browser: Opens new tab with constructed thread URL
sequenceDiagram
participant User
participant EmailComposer
participant DraftManager
participant Server
User->>EmailComposer: Clicks "Send"
EmailComposer->>DraftManager: Checks for unsaved changes
alt Unsaved changes
DraftManager->>Server: saveDraft()
end
EmailComposer->>Server: sendEmail (with draftId if available)
Possibly related PRs
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
PR Summary
Comprehensive improvements to email handling and UI functionality across multiple components, focusing on draft management, thread organization, and performance optimizations.
- Enhanced draft handling in
apps/mail/components/create/email-composer.tsxto properly save draft state before sending emails - Improved thread message filtering in
apps/server/src/routes/chat.tsto correctly handle draft messages in thread counts and latest message calculations - Added 'Open in New Tab' functionality in
apps/mail/components/context/thread-context.tsxwith corresponding i18n support - Optimized performance by removing unnecessary async/await operations in multiple components including
app-sidebar.tsx,nav-user.tsx, andai-sidebar.tsx - Enhanced web search flexibility in
apps/server/src/routes/agent/tools.tsby adding support for both streaming and non-streaming responses
13 files reviewed, 2 comments
Edit PR Review Bot Settings | Greptile
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
apps/server/src/routes/agent/tools.ts (1)
341-368: Refactor to eliminate code duplication and improve type safety.The conditional logic correctly handles streaming vs non-streaming responses, but there are areas for improvement:
- Code duplication: The system messages are duplicated in both branches
- Type safety: The function returns different types (
{type: 'streaming_response', query}vsstring), which could cause runtime issuesConsider this refactoring to eliminate duplication and improve type safety:
execute: async ({ query }) => { try { + const systemMessages = [ + { role: 'system', content: 'Be precise and concise.' }, + { role: 'system', content: 'Do not include sources in your response.' }, + { role: 'system', content: 'Do not use markdown formatting in your response.' }, + { role: 'user', content: query }, + ] as const; + if (dataStream) { const response = streamText({ model: perplexity('sonar'), - messages: [ - { role: 'system', content: 'Be precise and concise.' }, - { role: 'system', content: 'Do not include sources in your response.' }, - { role: 'system', content: 'Do not use markdown formatting in your response.' }, - { role: 'user', content: query }, - ], + messages: systemMessages, maxTokens: 1024, }); response.mergeIntoDataStream(dataStream); - return { type: 'streaming_response', query }; + return `Streaming web search results for: ${query}`; } const response = await generateText({ model: perplexity('sonar'), - messages: [ - { role: 'system', content: 'Be precise and concise.' }, - { role: 'system', content: 'Do not include sources in your response.' }, - { role: 'system', content: 'Do not use markdown formatting in your response.' }, - { role: 'user', content: query }, - ], + messages: systemMessages, maxTokens: 1024, }); return response.text;
🧹 Nitpick comments (2)
apps/server/src/routes/agent/tools.ts (1)
333-374: Consider potential naming conflict with other webSearch implementations.There's another
webSearchfunction inapps/server/src/trpc/routes/ai/webSearch.tsthat serves a different purpose (TRPC mutation vs tool). This could lead to confusion and potential import conflicts.Consider renaming this function to
webSearchToolto clearly distinguish it from the TRPC procedure:-export const webSearch = (dataStream?: DataStreamWriter) => +export const webSearchTool = (dataStream?: DataStreamWriter) =>And update the usage in the tools object:
- [Tools.WebSearch]: webSearch(dataStream), + [Tools.WebSearch]: webSearchTool(dataStream),apps/mail/components/create/email-composer.tsx (1)
468-469: Consider error handling for draft saving before send.The conditional draft save before sending is a good improvement that ensures consistency. However, consider what should happen if
saveDraft()fails - should the send operation continue or be aborted?You might want to add explicit error handling:
// Save draft before sending, we want to send drafts instead of sending new emails -if (hasUnsavedChanges) await saveDraft(); +if (hasUnsavedChanges) { + try { + await saveDraft(); + } catch (error) { + console.error('Failed to save draft before sending:', error); + toast.error('Failed to save draft before sending'); + return; // or continue based on your preference + } +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
apps/mail/components/context/thread-context.tsx(3 hunks)apps/mail/components/create/create-email.tsx(4 hunks)apps/mail/components/create/email-composer.tsx(1 hunks)apps/mail/components/mail/mail-display.tsx(6 hunks)apps/mail/components/mail/reply-composer.tsx(2 hunks)apps/mail/components/ui/ai-sidebar.tsx(1 hunks)apps/mail/components/ui/app-sidebar.tsx(2 hunks)apps/mail/components/ui/nav-user.tsx(1 hunks)apps/mail/messages/en.json(1 hunks)apps/mail/providers/query-provider.tsx(0 hunks)apps/server/src/lib/driver/google.ts(4 hunks)apps/server/src/routes/agent/tools.ts(2 hunks)apps/server/src/routes/chat.ts(1 hunks)apps/server/src/trpc/routes/ai/compose.ts(3 hunks)
💤 Files with no reviewable changes (1)
- apps/mail/providers/query-provider.tsx
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: danteissaias
PR: Mail-0/Zero#618
File: apps/mail/components/mail/mail-iframe.tsx:12-12
Timestamp: 2025-04-07T20:46:11.697Z
Learning: In the Mail-0/Zero application, sender emails are guaranteed to be non-empty when passed to components that handle them, making additional empty string validation unnecessary.
apps/mail/components/ui/nav-user.tsx (2)
Learnt from: dakdevs
PR: Mail-0/Zero#764
File: apps/mail/lib/ai.ts:50-51
Timestamp: 2025-04-25T08:33:16.956Z
Learning: In Next.js 15, the `headers()` function from 'next/headers' is asynchronous and requires using `await` when called, which is a breaking change from previous versions where it was synchronous.
Learnt from: dakdevs
PR: Mail-0/Zero#764
File: apps/mail/lib/ai.ts:50-51
Timestamp: 2025-04-25T08:33:16.956Z
Learning: In Next.js 15, the `headers()` function from 'next/headers' is asynchronous and requires using `await` when called, which is a breaking change from previous versions where it was synchronous.
apps/mail/components/ui/ai-sidebar.tsx (2)
Learnt from: dakdevs
PR: Mail-0/Zero#764
File: apps/mail/lib/ai.ts:50-51
Timestamp: 2025-04-25T08:33:16.956Z
Learning: In Next.js 15, the `headers()` function from 'next/headers' is asynchronous and requires using `await` when called, which is a breaking change from previous versions where it was synchronous.
Learnt from: dakdevs
PR: Mail-0/Zero#764
File: apps/mail/lib/ai.ts:50-51
Timestamp: 2025-04-25T08:33:16.956Z
Learning: In Next.js 15, the `headers()` function from 'next/headers' is asynchronous and requires using `await` when called, which is a breaking change from previous versions where it was synchronous.
apps/mail/components/create/create-email.tsx (3)
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.
apps/mail/components/create/email-composer.tsx (2)
Learnt from: retrogtx
PR: Mail-0/Zero#1622
File: apps/server/src/lib/email-verification.ts:189-189
Timestamp: 2025-07-05T05:27:24.592Z
Learning: During testing phases, debug logging should be kept active in apps/server/src/lib/email-verification.ts for BIMI validation and email verification debugging, even if it's verbose.
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.
apps/mail/components/ui/app-sidebar.tsx (2)
Learnt from: danteissaias
PR: Mail-0/Zero#902
File: apps/mail/components/connection/add.tsx:77-77
Timestamp: 2025-05-07T16:55:46.513Z
Learning: For the "Upgrade" link in AddConnectionDialog, using a proper <button> element instead of a <span> with onClick is recognized as an accessibility improvement but was deferred as out of scope in PR #902 (CSS variables PR).
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.
apps/mail/components/context/thread-context.tsx (1)
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.
apps/server/src/lib/driver/google.ts (2)
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.
apps/mail/components/mail/mail-display.tsx (1)
Learnt from: retrogtx
PR: Mail-0/Zero#1328
File: apps/mail/lib/hotkeys/mail-list-hotkeys.tsx:202-209
Timestamp: 2025-06-18T17:26:50.918Z
Learning: In apps/mail/lib/hotkeys/mail-list-hotkeys.tsx, the switchCategoryByIndex function using hardcoded indices for category hotkeys does not break when users reorder categories, contrary to the theoretical index-shifting issue. The actual implementation has constraints or mechanisms that prevent hotkey targeting issues.
🧬 Code Graph Analysis (3)
apps/mail/components/create/create-email.tsx (2)
apps/server/src/types.ts (1)
Attachment(152-159)apps/mail/types/index.ts (1)
Attachment(98-105)
apps/server/src/routes/agent/tools.ts (1)
apps/server/src/trpc/routes/ai/webSearch.ts (1)
webSearch(6-17)
apps/mail/components/context/thread-context.tsx (1)
apps/mail/components/icons/icons.tsx (1)
ExclamationCircle(415-432)
⏰ 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). (2)
- GitHub Check: Cursor BugBot
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (24)
apps/server/src/trpc/routes/ai/compose.ts (3)
6-11: Import reordering improves code organization.The reordering of imports creates better logical grouping by placing related imports together. This enhances code readability and follows good practices.
40-41: Trailing commas enhance code consistency.Adding trailing commas is a good practice that makes future diffs cleaner and follows modern JavaScript/TypeScript conventions.
107-107: Function invocation aligns with updated signature.The change from
webSearchtowebSearch()correctly adapts to the updated function signature that now accepts an optionaldataStreamparameter. Since no dataStream is provided here, the function will use the non-streaming branch.apps/server/src/routes/agent/tools.ts (1)
333-333: Function signature change enables flexible usage.Making the
dataStreamparameter optional allows the function to work in both streaming and non-streaming contexts, which improves its reusability across different parts of the application.apps/mail/components/ui/nav-user.tsx (1)
96-96: LGTM - Fire-and-forget mutation pattern applied consistently.The removal of
awaitfrom the mutation call aligns with the broader pattern in this PR to simplify state updates. The mutation now fires without blocking the rest of the function execution, which can improve perceived performance.apps/mail/components/ui/ai-sidebar.tsx (1)
282-284: LGTM - Consistent async simplification.The removal of
asyncandawaitkeywords simplifies the function while maintaining the same functionality. The query state update is now fire-and-forget, which is appropriate for this use case.apps/mail/components/ui/app-sidebar.tsx (2)
160-160: Minor CSS class reordering - no functional impact.The CSS classes have been reordered without affecting the visual appearance or functionality.
187-197: LGTM - Removed unnecessary await from state setters.React state setters are synchronous operations that don't need to be awaited. This change simplifies the code while maintaining the same functionality.
apps/mail/components/mail/reply-composer.tsx (2)
194-194: LGTM - Enhanced draft handling.Adding
draftIdto the email payload allows proper association between sent emails and their corresponding drafts, improving the draft workflow.
257-259: LGTM - Consistent removal of unnecessary await.React state setters don't need to be awaited. This change aligns with the consistent pattern applied throughout the codebase.
apps/mail/messages/en.json (1)
373-374: LGTM - New localization key for "Open in new tab" feature.The new localization key follows the established naming convention and supports the new context menu action.
apps/mail/components/create/create-email.tsx (2)
117-117: LGTM: Correctly removed unnecessaryawaitfrom state setter.State setters from
useQueryStateare synchronous functions that don't return promises, so removing theawaitis correct and improves code clarity.
15-15: LGTM: Good formatting and style improvements.The changes include:
- Moving the
Attachmentimport to an earlier position for better organization- Adding consistent semicolons
- Reformatting the attachment conversion logic for better readability
These changes improve code consistency and readability without affecting functionality.
Also applies to: 31-31, 165-165, 168-168, 172-173
apps/server/src/routes/chat.ts (2)
1212-1212: LGTM! Improved draft exclusion logic.The explicit check
e.isDraft !== trueis more robust than!e.isDraftas it specifically excludes only messages that are explicitly marked as drafts, properly handling cases whereisDraftmight be undefined or null.
1214-1214: LGTM! Consistent draft exclusion for reply count.The change aligns with the latest message selection logic and ensures that draft messages are consistently excluded from the total replies count.
apps/mail/components/context/thread-context.tsx (4)
15-15: LGTM! Proper import for new feature.The
ExternalLinkimport is correctly added to support the new "Open in New Tab" functionality.
268-270: LGTM! Clean implementation of new tab functionality.The
handleOpenInNewTabfunction correctly constructs the URL using the current folder and thread ID, and properly opens it in a new tab.
274-280: LGTM! Well-structured context menu action.The new "Open in New Tab" action follows the existing pattern with proper localization, icon, and handler function. The placement as the first action in the primary actions array makes sense from a UX perspective.
443-443: LGTM! Consistent icon styling approach.The change from opacity-based styling to explicit fill colors for light and dark modes aligns with the pattern used for other icons in the same actions array (like the Mail icon on line 431).
apps/server/src/lib/driver/google.ts (2)
392-392: LGTM! Consistent draft exclusion logic.The explicit check
e.isDraft !== truealigns with the similar change inapps/server/src/routes/chat.tsand ensures consistent draft handling across the server-side components.
127-127: LGTM! Minor formatting improvements.The formatting changes in the
parseDraftmethod improve code readability without affecting functionality. The changes include better line breaks for async operations and filtering logic.Also applies to: 132-132, 153-153, 159-162, 178-179
apps/mail/components/mail/mail-display.tsx (3)
49-49: LGTM!The import of
useThreadhook is correctly added to support the new thread data functionality.
82-85: Good defensive programming with event handling.The addition of
preventDefault()andstopPropagation()calls with explicitMouseEventparameter improves event handling by preventing unwanted default behaviors and event bubbling during text selection.
783-783: ThreadData.latest.id is reliably the most recent non-draft message—no further action needed.
- In GoogleDriver.get,
messagesis populated from Gmail’s API (which returns messages in chronological order), andlatestis set viamessages.findLast(e ⇒ !e.isDraft).- The
useThreadhook preserves thislatestvalue unaltered inthreadData.latest.Change to ID-based last-email detection is safe and can be approved.
| <> | ||
| {searchQuery && ( |
There was a problem hiding this comment.
Critical: Text selection functionality is broken.
The TextSelectionPopover wrapper has been completely removed and replaced with a React fragment, which breaks the text selection functionality entirely. The TextSelectionPopover component provides essential event listeners and selection logic that enables users to select text and get search/copy options.
The TextSelectionPopover component should wrap the main content to maintain text selection functionality:
- <>
+ <TextSelectionPopover onSearch={setSearchQuery}>
{searchQuery && (
<MoreAboutQuery
query={searchQuery}
open={!!searchQuery}
onOpenChange={(open) => (open ? void 0 : setSearchQuery(null))}
/>
)}
{/* ... rest of content ... */}
- </>
+ </TextSelectionPopover>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <> | |
| {searchQuery && ( | |
| <TextSelectionPopover onSearch={setSearchQuery}> | |
| {searchQuery && ( | |
| <MoreAboutQuery | |
| query={searchQuery} | |
| open={!!searchQuery} | |
| onOpenChange={(open) => (open ? void 0 : setSearchQuery(null))} | |
| /> | |
| )} | |
| {/* ... rest of content ... */} | |
| </TextSelectionPopover> |
🤖 Prompt for AI Agents
In apps/mail/components/mail/mail-display.tsx around lines 1361 to 1362, the
TextSelectionPopover component was removed and replaced with a React fragment,
breaking text selection functionality. To fix this, wrap the main content inside
the TextSelectionPopover component again to restore the event listeners and
selection logic needed for text selection and related options.
1c9c239 to
9ba3ac8
Compare
There was a problem hiding this comment.
Bug: Removed UI Breaks Text Selection
The TextSelectionPopover component was removed, but its associated handleSelectionChange function continues to prevent default browser text selection behavior by calling e.preventDefault() and e.stopPropagation() when text is selected. This results in text selection being intercepted without any visible UI or intended functionality, breaking normal text selection and potentially copy/paste.
apps/mail/components/mail/mail-display.tsx#L81-L87
Zero/apps/mail/components/mail/mail-display.tsx
Lines 81 to 87 in 9ba3ac8
apps/mail/components/mail/mail-display.tsx#L1362-L1864
Zero/apps/mail/components/mail/mail-display.tsx
Lines 1362 to 1864 in 9ba3ac8
Bug: Undefined Folder Parameter Causes Malformed URL
The handleOpenInNewTab function constructs a URL using the folder variable from useParams. If the current route does not include a folder parameter, folder will be undefined, leading to a malformed URL (e.g., /mail/undefined?threadId=...).
apps/mail/components/context/thread-context.tsx#L267-L270
Zero/apps/mail/components/context/thread-context.tsx
Lines 267 to 270 in 9ba3ac8
Was this report helpful? Give feedback by reacting with 👍 or 👎
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
apps/server/src/routes/ai.ts (1)
70-80: Fix variable declaration scope issue in switch statement.The static analysis tool correctly identifies that variable declarations in switch clauses should be wrapped in blocks to prevent access from other clauses.
case Tools.SendEmail: + { const result = await agent.create({ to: body.to.map((to: any) => ({ name: to.name ?? to.email, email: to.email ?? 'founders@0.email', })), subject: body.subject, message: body.message, attachments: [], headers: {}, }); return c.json({ success: true, result }); + }
🧹 Nitpick comments (1)
apps/server/src/lib/driver/microsoft.ts (1)
1300-1302: LGTM! Consider adding documentation for the placeholder implementation.The method correctly implements the interface requirement and maintains type safety. Since this returns an empty history array, consider adding a comment to clarify whether this is a temporary placeholder or if history functionality is not applicable for Microsoft Graph API.
+ // TODO: Implement history functionality for Microsoft Graph API or document if not applicable listHistory<T>(historyId: string): Promise<{ history: T[]; historyId: string }> { return Promise.resolve({ history: [], historyId }); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
apps/mail/components/context/thread-context.tsx(3 hunks)apps/mail/components/create/create-email.tsx(4 hunks)apps/mail/components/create/email-composer.tsx(1 hunks)apps/mail/components/mail/mail-display.tsx(6 hunks)apps/mail/components/mail/reply-composer.tsx(2 hunks)apps/mail/components/ui/ai-sidebar.tsx(1 hunks)apps/mail/components/ui/app-sidebar.tsx(2 hunks)apps/mail/components/ui/nav-user.tsx(1 hunks)apps/mail/messages/en.json(1 hunks)apps/mail/providers/query-provider.tsx(1 hunks)apps/server/src/lib/driver/google.ts(4 hunks)apps/server/src/lib/driver/microsoft.ts(1 hunks)apps/server/src/lib/driver/types.ts(1 hunks)apps/server/src/lib/server-utils.ts(0 hunks)apps/server/src/pipelines.effect.ts(1 hunks)apps/server/src/routes/agent/tools.ts(2 hunks)apps/server/src/routes/ai.ts(14 hunks)apps/server/src/routes/chat.ts(13 hunks)apps/server/src/services/mcp-service/mcp.ts(0 hunks)apps/server/src/trpc/routes/ai/compose.ts(3 hunks)apps/server/src/trpc/trpc.ts(1 hunks)
💤 Files with no reviewable changes (2)
- apps/server/src/lib/server-utils.ts
- apps/server/src/services/mcp-service/mcp.ts
✅ Files skipped from review due to trivial changes (2)
- apps/server/src/pipelines.effect.ts
- apps/server/src/trpc/trpc.ts
🚧 Files skipped from review as they are similar to previous changes (14)
- apps/server/src/trpc/routes/ai/compose.ts
- apps/mail/components/create/email-composer.tsx
- apps/mail/messages/en.json
- apps/mail/components/ui/ai-sidebar.tsx
- apps/mail/components/ui/app-sidebar.tsx
- apps/mail/components/create/create-email.tsx
- apps/mail/components/context/thread-context.tsx
- apps/mail/components/ui/nav-user.tsx
- apps/server/src/routes/agent/tools.ts
- apps/server/src/lib/driver/google.ts
- apps/server/src/routes/chat.ts
- apps/mail/providers/query-provider.tsx
- apps/mail/components/mail/reply-composer.tsx
- apps/mail/components/mail/mail-display.tsx
🧰 Additional context used
🧠 Learnings (2)
apps/server/src/lib/driver/types.ts (1)
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:331-331
Timestamp: 2025-06-28T03:56:09.376Z
Learning: In apps/server/src/trpc/routes/mail.ts, the user indicated they are not using ISO format for the scheduleAt parameter, despite the frontend code showing toISOString() usage in the ScheduleSendPicker component.
apps/server/src/routes/ai.ts (1)
Learnt from: retrogtx
PR: Mail-0/Zero#1468
File: apps/server/src/trpc/routes/mail.ts:386-391
Timestamp: 2025-06-27T04:59:29.731Z
Learning: In apps/server/src/trpc/routes/mail.ts, the attachment processing logic conditionally handles mixed attachment types - it preserves existing File-like objects with arrayBuffer methods while only converting serialized attachments that need processing through toAttachmentFiles.
🪛 Biome (1.9.4)
apps/server/src/routes/ai.ts
[error] 70-79: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
⏰ 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). (2)
- GitHub Check: Cursor BugBot
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
apps/server/src/lib/driver/types.ts (1)
28-28: LGTM! Improved type safety for draft handling.The type change from
stringtostring | nullproperly reflects the reality that draft messages may not have an internal date or that some email providers may return null for this field. This improves type safety and aligns with the broader draft handling improvements mentioned in the PR.apps/server/src/routes/ai.ts (8)
4-4: LGTM! Appropriate import change for the agent-based refactoring.The import change from driver utilities to
getZeroAgentaligns with the systematic refactoring from driver-based to agent-based email operations.
42-42: LGTM! Consistent with the agent-based architecture.The replacement of driver instantiation with agent instantiation is appropriate for this refactoring.
47-60: LGTM! Method name changes align with agent interface.The changes from
driver.listtoagent.listThreadsanddriver.gettoagent.getThreadare consistent with the new agent-based architecture. The functionality and response handling remain intact.
147-147: LGTM! Consistent agent instantiation.The replacement of driver with agent is consistent throughout the file.
193-199: LGTM! Agent method calls are correctly updated.The method calls have been properly updated to use the agent interface with the new method names.
232-232: LGTM! Consistent agent method usage.The
getThreadmethod call is correctly updated to use the agent interface.
265-265: LGTM! Consistent modifyLabels method usage.All
modifyLabelscalls have been correctly updated to use the agent interface while maintaining the same functionality.Also applies to: 284-284, 305-305, 426-426, 458-458
338-338: LGTM! Label management methods correctly updated.The label management methods (
getUserLabels,getLabel,createLabel) have been consistently updated to use the agent interface.Also applies to: 359-359, 385-385

Add "Open in New Tab" Feature and Fix Email Handling
Description
This PR adds an "Open in New Tab" feature to the thread context menu, allowing users to open email threads in a new browser tab. It also fixes several issues with email handling:
Type of Change
Areas Affected
Testing Done
Checklist
Additional Notes
The "Open in New Tab" feature improves workflow for users who need to reference multiple email threads simultaneously. The draft handling improvements ensure that emails are properly saved before sending, preventing data loss.
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Style
Chores