Skip to content

Sweetmantech/myc 3794 api email agentgenerate pass in full message history for the - #79

Merged
sweetmantech merged 6 commits into
testfrom
sweetmantech/myc-3794-api-email-agentgenerate-pass-in-full-message-history-for-the
Dec 18, 2025
Merged

Sweetmantech/myc 3794 api email agentgenerate pass in full message history for the#79
sweetmantech merged 6 commits into
testfrom
sweetmantech/myc-3794-api-email-agentgenerate-pass-in-full-message-history-for-the

Conversation

@sweetmantech

@sweetmantechsweetmantech commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features
    • Added inbound email support with automatic response generation
    • Implemented chat system with persistent conversation memory and history
    • Integrated AI-powered conversation routing with context-aware responses
    • Added knowledge base integration for enhanced conversation context
    • Enabled new conversation notifications via email

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel

vercelBot commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentReviewUpdated (UTC)
recoup-apiReadyReadyPreviewDec 18, 2025 8:45pm

@coderabbitai

coderabbitaiBot commented Dec 18, 2025

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR introduces a comprehensive inbound email handling system with automated reply generation. It adds an email ingestion API route, email processing pipeline, chat room orchestration, message persistence, and agent-based reply composition. New utilities support UUID generation, system prompt construction, tool setup, memory tracking, and database schema extensions. The changes integrate Resend email service and MCP-based tool management.

Changes

Cohort / File(s)Summary
Inbound Email API Route
app/api/emails/inbound/route.ts
New POST endpoint delegating to inbound email handler
Email Service Integration
lib/emails/client.ts, lib/emails/sendEmail.ts, lib/emails/isTestEmail.ts
Resend client initialization, email sending with error handling, test email detection
Email Event Validation
lib/emails/validateInboundEmailEvent.ts
Zod schema validation for inbound Resend webhook events with CORS headers
Inbound Email Processing
lib/emails/inbound/getEmailContent.ts, lib/emails/inbound/getEmailRoomId.ts, lib/emails/inbound/getFromWithName.ts, lib/emails/inbound/handleInboundEmail.ts, lib/emails/inbound/respondToInboundEmail.ts
Email content fetching, room lookup, sender formatting, event handling, and reply orchestration
Chat Room Management
lib/chat/createNewRoom.ts, lib/supabase/rooms/insertRoom.ts, lib/supabase/rooms/selectRoom.ts
Room creation with title generation, insertion, and lookup
Message Handling & Validation
lib/messages/getMessages.ts, lib/messages/validateMessages.ts, lib/messages/extractImageUrlsFromMessages.ts, lib/messages/filterMessageContentForMemories.ts
Message construction, validation, image extraction, and filtering
Chat Completion & Persistence
lib/chat/handleChatCompletion.ts, lib/chat/saveNewMessages.ts
Orchestrates room existence checks and saves user/assistant message pairs to memory
Chat Request Schema & Routing
lib/chat/validateChatRequest.ts, lib/chat/types.ts
Request validation enforcing exactly one of messages or prompt; RoutingDecision interface for agent configuration
Agent Orchestration
lib/agents/generalAgent/getGeneralAgent.ts, lib/chat/setupToolsForRequest.ts, lib/chat/filterExcludedTools.ts
General agent construction with account/artist context, MCP tool setup, and tool filtering
System Prompts & AI
lib/chat/const.ts, lib/prompts/getSystemPrompt.ts, lib/chat/buildSystemPromptWithImages.ts, lib/ai/generateText.ts
System prompt constant for music-focused assistant, dynamic prompt building with user/artist context and images, text generation wrapper
Chat Title Generation
lib/chat/generateChatTitle.ts
Generates concise conversation titles via lightweight model inference
Memory & Linkage
lib/supabase/memories/insertMemories.ts, lib/supabase/memories/selectMemories.ts, lib/supabase/memory_emails/insertMemoryEmail.ts, lib/supabase/memory_emails/selectMemoryEmails.ts
Memory insertion/retrieval and email-to-memory association with joined queries
Account & Email Queries
lib/supabase/account_emails/selectAccountEmails.ts, lib/supabase/accounts/getAccountWithDetails.ts
Enhanced account email lookup by accountId, account details with flattened related data
Notifications
lib/telegram/sendNewConversationNotification.ts
Sends Telegram notifications for new conversations, skipping test emails
Utilities
lib/uuid/generateUUID.ts, lib/const.ts, lib/files/getKnowledgeBaseText.ts
UUID v4 generation with fallback, lightweight model constant, knowledge base text fetching from URLs
Database Schema
types/database.types.ts
Added memory_emails table with email_id, message_id, memory reference, and foreign key linkage
Dependencies
package.json
Added @ai-sdk/mcp@^0.0.12 and resend@^6.6.0
Cleanup
lib/coinbase/getAccount.ts, lib/mcp/tools/youtube/registerGetYouTubeRevenueTool.ts, lib/songs/queueRedisSongs.ts, lib/youtube/queryAnalyticsReports.ts
Removed debug logging statements

Sequence Diagram(s)

sequenceDiagram
participant Client as HTTP Client
participant APIRoute as API Route<br/>(POST /inbound)
participant Validator as validateInboundEmailEvent
participant EmailHandler as handleInboundEmail
participant Responder as respondToInboundEmail
participant Resend as Resend API
participant Agent as getGeneralAgent
participant Memory as Supabase Memories
Client->>APIRoute: POST with email event
APIRoute->>Validator: Validate event payload
alt Invalid Event
Validator->>APIRoute: 400 error response
APIRoute->>Client: Return error
else Valid Event
Validator->>APIRoute: Parsed event
APIRoute->>EmailHandler: handleInboundEmail(request)
rect rgb(200, 220, 240)
note over EmailHandler: Process email.received event
EmailHandler->>Responder: respondToInboundEmail(event)
Responder->>Resend: getEmailContent(emailId)
Resend-->>Responder: Email with headers
Responder->>Responder: Extract room_id from references
Responder->>Responder: Build chat request with message history
Responder->>Agent: getGeneralAgent(chatRequest)
Agent-->>Responder: Agent + tools + instructions
Responder->>Agent: Generate reply via ToolLoopAgent
Agent-->>Responder: Reply text
Responder->>Resend: sendEmailWithResend(reply payload)
Resend-->>Responder: Email sent confirmation
Responder->>Memory: insertMemoryEmail(linkage)
Memory-->>Responder: Saved reference
end
Responder-->>EmailHandler: Response
EmailHandler-->>APIRoute: Response
APIRoute-->>Client: 200 OK
end
Loading
sequenceDiagram
participant App as Application
participant Validator as validateChatRequest
participant Completion as handleChatCompletion
participant RoomSvc as Room Service
participant MsgSvc as Message Service
participant Memory as Supabase
App->>Validator: Validate chat request<br/>(messages or prompt)
alt Invalid
Validator->>App: Error
else Valid
Validator-->>Completion: Proceed
Completion->>MsgSvc: validateMessages(messages)
MsgSvc-->>Completion: lastMessage + validMessages
alt Room exists
Completion->>RoomSvc: selectRoom(roomId)
RoomSvc-->>Completion: Room data
else Room missing
Completion->>RoomSvc: createNewRoom(accountId, roomId)
RoomSvc->>Memory: insertRoom + notify
Memory-->>RoomSvc: Confirmed
end
Completion->>MsgSvc: saveNewMessages(roomId, messages)
MsgSvc->>Memory: insertMemories (user + assistant)
Memory-->>MsgSvc: Saved records
MsgSvc-->>Completion: Memory array
Completion-->>App: Memory records
end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • lib/emails/inbound/respondToInboundEmail.ts — Multi-step orchestration with agent invocation, email composition, memory linkage, and error handling across external services (Resend, Supabase); dense control flow
  • lib/agents/generalAgent/getGeneralAgent.ts — Wires multiple data fetchers and context builders; requires understanding of account/artist resolution, image augmentation, and tool setup
  • lib/supabase/accounts/getAccountWithDetails.ts — Type structure changed significantly from explicit interface to composite type alias; verify flattening logic aligns with related table semantics
  • lib/prompts/getSystemPrompt.ts — Complex conditional prompt assembly with multiple context sections (user, artist, knowledge base); ensure conditional logic and formatting are correct
  • lib/chat/setupToolsForRequest.ts — MCP client initialization and tool merging; verify transport configuration and tool retrieval logic
  • lib/supabase/memory_emails/selectMemoryEmails.ts — Join logic with memories table; verify foreign key resolution and null-safety in nested access patterns
  • types/database.types.ts — New memory_emails table schema; confirm relationships and field optionality match migration/schema expectations

Possibly related PRs

Poem

🐰 Emails hop in through the door,
Rooms get birthed, memories store,
Agents chat with flair and wit,
Replies sent with perfect fit!
AI dreams made automat',
Recoup runs smooth—and that is that! 🎵

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check nameStatusExplanationResolution
Title check❓ InconclusiveThe title is incomplete and vague. It cuts off mid-sentence ('for the') and does not clearly convey the main change despite referencing a ticket number and general topic of email/agent/message history.Complete the title with clear, specific language describing the primary change. For example: 'Pass full message history to email agent for context' or similar concise completion.
✅ Passed checks (2 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage✅ PassedDocstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercelvercelBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

If the AI agent's response text is empty or falsy, the code will crash when trying to save the assistant's message to the database.

View Details
📝 Patch Details
diff --git a/lib/chat/saveNewMessages.ts b/lib/chat/saveNewMessages.ts
index 8bd8262..46878ca 100644
--- a/lib/chat/saveNewMessages.ts+++ b/lib/chat/saveNewMessages.ts@@ -34,6 +34,11 @@ export async function saveNewMessages({
content: filterMessageContentForMemories(lastMessage),
});
+ // Only save assistant message if response messages exist (e.g., not empty from AI agent)+ if (responseMessages.length === 0) {+ return [userMemory].filter((m): m is Memory => m !== null);+ }+
const assistantMemory = await insertMemories({
id: responseMessages[responseMessages.length - 1].id,
room_id: roomId,
diff --git a/lib/emails/inbound/respondToInboundEmail.ts b/lib/emails/inbound/respondToInboundEmail.ts
index 7f831bf..95d8e05 100644
--- a/lib/emails/inbound/respondToInboundEmail.ts+++ b/lib/emails/inbound/respondToInboundEmail.ts@@ -52,6 +52,15 @@ export async function respondToInboundEmail(
const chatResponse = await agent.generate({
messages,
});
++ // Skip email and database save if the assistant response is empty+ if (!chatResponse.text) {+ return NextResponse.json(+ { error: "No response generated from AI agent" },+ { status: 400 },+ );+ }+
const payload = {
from,
to: toArray,

Analysis

Crash when AI agent returns empty text in respondToInboundEmail

What fails:saveNewMessages() crashes with TypeError: Cannot read property 'id' of undefined when ToolLoopAgent.generate() returns an empty text string, which causes getMessages() to return an empty array and accessing responseMessages[-1] throws.

How to reproduce:

  1. Trigger inbound email processing via respondToInboundEmail() endpoint
  2. Configure the AI agent to invoke tools that produce only tool results without generating text (empty text field)
  3. Per AI SDK GitHub issue #1831, this is a known scenario where tool-only responses return empty text

Result: The code crashes at lib/chat/saveNewMessages.ts:40 when trying to access responseMessages[responseMessages.length - 1].id on an empty array, resulting in a TypeError: Cannot read property 'id' of undefined

Expected: Should handle empty AI responses gracefully without crashing. Per Vercel AI SDK documentation, the text field is always a string but can be empty when models prioritize tool invocation over text generation.

Root cause: The code does not validate that chatResponse.text is non-empty before passing it to getMessages(), which returns an empty array for falsy input. The empty array is then passed to saveNewMessages() which attempts to access the last element without checking if the array is empty.

Fix: Added defensive checks at two levels:

  1. In respondToInboundEmail.ts: Return error response if chatResponse.text is falsy before sending empty email
  2. In saveNewMessages.ts: Check if responseMessages array is empty before accessing the last element

@sweetmantech
sweetmantech merged commit f982f48 into testDec 18, 2025
3 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@sweetmantech