Skip to content

Add Send button → comment_on_lead (Notion comment + local fallback)#8

Open
jerelvelarde wants to merge 1 commit into
mainfrom
email-send-comment-on-lead
Open

Add Send button → comment_on_lead (Notion comment + local fallback)#8
jerelvelarde wants to merge 1 commit into
mainfrom
email-send-comment-on-lead

Conversation

@jerelvelarde

Copy link
Copy Markdown
Owner

Summary

Replaces the email-draft card's Queue button with Send, which posts the drafted outreach email as a comment on the lead's Notion page (with local-JSON-store fallback when Notion isn't configured).

End-to-end flow:

  1. Agent renders an inline EmailDraftCard via renderEmailDraft.
  2. User clicks SendinjectPrompt round-trips lead_id / subject / body back to the agent.
  3. Agent calls the new backend tool comment_on_lead, which writes through LeadStore.add_comment to either Notion (API-create-a-comment) or the local JSON store.

What changed

Backend (agent/)

  • notion_mcp.py — new mcp_create_comment() MCP wrapper (API-create-a-comment).
  • notion_integration.py — new add_lead_comment() with rich-text chunking for Notion's 2000-char per-block cap.
  • lead_store.pyadd_comment() added to the LeadStore protocol with implementations on both NotionStore and LocalJsonStore (local store appends a comments[] entry on the lead row, keeping the demo flow working without Notion configured).
  • notion_tools.py — new @tool comment_on_lead, registered in load_notion_tools(). Returns Command(update=...) with a one-line confirmation; reports source as commented on Notion page or saved to local store.
  • prompts.py — teaches the agent when to call comment_on_lead (Send button, or explicit "send / post / deliver / publish") and updates renderEmailDraft guidance to forbid calling it in the same turn.

Frontend

  • EmailDraftCard.tsx — new onSend prop. When wired, Send becomes the primary footer action; onQueue stays as a fallback for legacy multi-lead flows.
  • page.tsx (LiveEmailDraft) — wires Send → injectPrompt with lead_id / subject / body inline as JSON, mirroring the canvas's existing "Update lead <id> in Notion: { ... }" pattern.
  • email-draft-review.tsx — showcase mirrors the live wiring + updates the prompt-review code block.

Misc

  • Adds src/app/icon.svg (Next.js App Router favicon convention).

Reviewer notes

  • The original commit was first pushed to mcp-widget-card-surface (a branch already merged via Wrap MCP widgets in card surface, drop view toggle #7), then moved to this fresh branch off main. No content was lost; this branch is one clean commit ahead of main.
  • Without NOTION_TOKEN, Send still completes — the local store appends to comments[] on the lead row in the JSON file under agent/data/. This is intentional so the demo runs end-to-end offline.
  • Notion's rich-text blocks cap at 2000 chars; multi-paragraph email bodies are chunked at 1900 to stay safely under it.

Test plan

  • With NOTION_TOKEN set: draft an email via chat, click Send, confirm a comment appears on the lead's Notion page and the agent replies "Sent email to <name> (commented on Notion page)."
  • Without NOTION_TOKEN: draft + Send, confirm the lead row in agent/data/*.json gains a comments[] entry and the agent replies "Sent email to <name> (saved to local store)."
  • Send a long body (>2000 chars) and confirm chunking lands without truncation/error.
  • Confirm the agent does not call comment_on_lead in the same turn as renderEmailDraft.
  • Showcase page (/email-draft-review) still renders all four tone variants without runtime errors.

Replaces the email-draft card's Queue button with Send, which posts
the drafted outreach email as a comment on the lead's Notion page
(falling back to the local JSON store when Notion isn't configured).

Backend: new mcp_create_comment wrapper, add_lead_comment helper with
rich-text chunking for Notion's 2000-char cap, add_comment on the
LeadStore protocol (NotionStore + LocalJsonStore), and the
comment_on_lead @tool wired into load_notion_tools. Prompts updated
so the agent calls comment_on_lead on Send and not in the same turn
as renderEmailDraft.

Frontend: onSend prop on EmailDraftCard, LiveEmailDraft + showcase
both inject a prompt that passes lead_id/subject/body verbatim. Also
adds the App Router icon.svg.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the ability to send outreach email drafts by posting them as comments on Notion lead pages or saving them to a local store. Key additions include the comment_on_lead tool, text chunking for Notion's character limits, and UI updates to the EmailDraftCard. Feedback identifies that the subject line is not bolded as documented and that the 'Send' and 'Queue' buttons are mutually exclusive in the UI, which contradicts the component's documentation.

Comment thread agent/src/notion_tools.py
Comment on lines +563 to +567
# Compose the comment text. Subject as a bold-prefix-style first line
# makes the comment readable at a glance in the Notion sidebar.
text = f"📨 {subject}".strip() if subject else "📨 (no subject)"
if body:
text = f"{text}\n\n{body}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The implementation of the comment text does not match the description in the docstring and parameter annotations. The docstring states the subject is rendered as a 'bold-prefixed' first line, but the code only prepends an emoji and concatenates the strings without applying any Notion rich-text formatting (like bold: true). If the intention is to have a bold subject, the _chunk_rich_text utility in notion_integration.py would need to be updated to support annotations.

Comment on lines +241 to +251
{onSend ? (
<button
type="button"
onClick={onSend}
title="Post this email as a comment on the lead's Notion page"
className="ml-auto inline-flex items-center gap-1 rounded-md border border-secondary/30 bg-secondary/10 px-2.5 py-1 text-[11px] font-medium text-secondary hover:bg-secondary/15"
>
<Send className="size-3" />
Send
</button>
) : onQueue ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The implementation makes the 'Send' and 'Queue' buttons mutually exclusive in the UI. If onSend is provided, the onQueue button is completely hidden. However, the prop documentation at line 58 suggests that onQueue should become a 'secondary action' when onSend is wired, implying both might be visible. If the intention is to replace 'Queue' with 'Send' entirely for this flow, the documentation should be updated to reflect that they are mutually exclusive in the compact footer.

Sign up for free to 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