Add Send button → comment_on_lead (Notion comment + local fallback)#8
Add Send button → comment_on_lead (Notion comment + local fallback)#8jerelvelarde wants to merge 1 commit into
Conversation
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.
There was a problem hiding this comment.
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.
| # 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}" |
There was a problem hiding this comment.
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.
| {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 ? ( |
There was a problem hiding this comment.
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.
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:
EmailDraftCardviarenderEmailDraft.injectPromptround-tripslead_id/subject/bodyback to the agent.comment_on_lead, which writes throughLeadStore.add_commentto either Notion (API-create-a-comment) or the local JSON store.What changed
Backend (
agent/)notion_mcp.py— newmcp_create_comment()MCP wrapper (API-create-a-comment).notion_integration.py— newadd_lead_comment()with rich-text chunking for Notion's 2000-char per-block cap.lead_store.py—add_comment()added to theLeadStoreprotocol with implementations on bothNotionStoreandLocalJsonStore(local store appends acomments[]entry on the lead row, keeping the demo flow working without Notion configured).notion_tools.py— new@tool comment_on_lead, registered inload_notion_tools(). ReturnsCommand(update=...)with a one-line confirmation; reports source ascommented on Notion pageorsaved to local store.prompts.py— teaches the agent when to callcomment_on_lead(Send button, or explicit "send / post / deliver / publish") and updatesrenderEmailDraftguidance to forbid calling it in the same turn.Frontend
EmailDraftCard.tsx— newonSendprop. When wired, Send becomes the primary footer action;onQueuestays as a fallback for legacy multi-lead flows.page.tsx(LiveEmailDraft) — wires Send →injectPromptwithlead_id/subject/bodyinline 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
src/app/icon.svg(Next.js App Router favicon convention).Reviewer notes
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 offmain. No content was lost; this branch is one clean commit ahead ofmain.NOTION_TOKEN, Send still completes — the local store appends tocomments[]on the lead row in the JSON file underagent/data/. This is intentional so the demo runs end-to-end offline.Test plan
NOTION_TOKENset: 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)."NOTION_TOKEN: draft + Send, confirm the lead row inagent/data/*.jsongains acomments[]entry and the agent replies "Sent email to<name>(saved to local store)."comment_on_leadin the same turn asrenderEmailDraft./email-draft-review) still renders all four tone variants without runtime errors.