human hand off
This commit is contained in:
parent
d0fee5c8f7
commit
7af776196a
34 changed files with 2941 additions and 195 deletions
|
|
@ -1,41 +1,45 @@
|
|||
import pytest
|
||||
|
||||
from app.services.handoff_email_templates import (
|
||||
build_mirror_handoff_html,
|
||||
build_mirror_handoff_text,
|
||||
external_reply_subject,
|
||||
format_sender_line,
|
||||
handoff_email_subject,
|
||||
)
|
||||
from app.services.handoff_mirror import load_mirror_payload
|
||||
from app.services.html_sanitizer import sanitize_email_html
|
||||
from app.services.mime_body_extractor import extract_mirror_content
|
||||
from app.services.mime_body_extractor import (
|
||||
extract_mirror_content,
|
||||
extract_new_reply_mime_content,
|
||||
)
|
||||
from app.services.thread_service import threading_fields_from_parent
|
||||
|
||||
|
||||
def test_mirror_template_is_minimal():
|
||||
html = build_mirror_handoff_html(
|
||||
sender_line="091rabbytes@gmail.com",
|
||||
external_subject="lets try one more time",
|
||||
original_html="<p>one last attempt. i am tired</p>",
|
||||
agent_email="suyash@gentic.email",
|
||||
@pytest.mark.asyncio
|
||||
async def test_mirror_body_is_unchanged_without_gentic_wrapper():
|
||||
payload = await load_mirror_payload(
|
||||
{
|
||||
"body_text": "one last attempt. i am tired",
|
||||
"body_html": "<p><strong>one last attempt.</strong> i am tired</p>",
|
||||
}
|
||||
)
|
||||
assert "LATEST MESSAGE" not in html
|
||||
assert "Why you" not in html
|
||||
assert "gentic-handoff-original" in html
|
||||
assert "one last attempt. i am tired" in html
|
||||
assert "✦ Human Handoff" in html
|
||||
assert "091rabbytes@gmail.com" in html
|
||||
assert "lets try one more time" in html
|
||||
assert payload.body_text == "one last attempt. i am tired"
|
||||
assert payload.body_html == (
|
||||
"<p><strong>one last attempt.</strong> i am tired</p>"
|
||||
)
|
||||
assert "Human Handoff" not in payload.body_text
|
||||
assert "gentic-handoff" not in (payload.body_html or "")
|
||||
|
||||
|
||||
def test_mirror_plain_text_template():
|
||||
text = build_mirror_handoff_text(
|
||||
sender_line="091rabbytes@gmail.com",
|
||||
external_subject="lets try one more time",
|
||||
original_body_text="one last attempt. i am tired",
|
||||
agent_email="suyash@gentic.email",
|
||||
@pytest.mark.asyncio
|
||||
async def test_mirror_plain_text_fallback_is_unchanged():
|
||||
payload = await load_mirror_payload(
|
||||
{
|
||||
"body_text": "one last attempt. i am tired",
|
||||
"body_html": None,
|
||||
}
|
||||
)
|
||||
assert "one last attempt. i am tired" in text
|
||||
assert "LATEST MESSAGE" not in text
|
||||
assert "Reply normally" in text
|
||||
assert payload.body_text == "one last attempt. i am tired"
|
||||
assert payload.body_html is None
|
||||
|
||||
|
||||
def test_format_sender_with_name():
|
||||
|
|
@ -83,3 +87,42 @@ def test_extract_html_from_multipart():
|
|||
extracted = extract_mirror_content(raw)
|
||||
assert "Invoice" in (extracted.body_html or "")
|
||||
assert "<table>" in (extracted.body_html or "")
|
||||
|
||||
|
||||
def test_rich_human_reply_keeps_new_html_and_removes_private_quote():
|
||||
raw = (
|
||||
b"From: owner@example.com\r\n"
|
||||
b"To: agent@gentic.email\r\n"
|
||||
b"Subject: Re: Finance handoff\r\n"
|
||||
b'MIME-Version: 1.0\r\nContent-Type: multipart/alternative; boundary="b"\r\n\r\n'
|
||||
b"--b\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n"
|
||||
b"Approved with urgency.\r\n\r\n"
|
||||
b"On Tue, Oct 6, 2026 at 6:00 AM agent@gentic.email wrote:\r\n"
|
||||
b"> private mirror\r\n"
|
||||
b"--b\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
|
||||
b'<div><strong>Approved</strong> with <em>urgency</em>.</div>'
|
||||
b'<div class="gmail_quote">private mirror</div>\r\n'
|
||||
b"--b--\r\n"
|
||||
)
|
||||
extracted = extract_new_reply_mime_content(raw)
|
||||
assert extracted.body_text == "Approved with urgency."
|
||||
assert "<strong>Approved</strong>" in (extracted.body_html or "")
|
||||
assert "private mirror" not in (extracted.body_html or "")
|
||||
|
||||
|
||||
def test_rich_human_reply_keeps_new_attachment():
|
||||
raw = (
|
||||
b"From: owner@example.com\r\n"
|
||||
b"To: agent@gentic.email\r\n"
|
||||
b"MIME-Version: 1.0\r\n"
|
||||
b'Content-Type: multipart/mixed; boundary="m"\r\n\r\n'
|
||||
b"--m\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nApproved\r\n"
|
||||
b"--m\r\nContent-Type: application/pdf\r\n"
|
||||
b'Content-Disposition: attachment; filename="approval.pdf"\r\n\r\nPDF\r\n'
|
||||
b"--m--\r\n"
|
||||
)
|
||||
extracted = extract_new_reply_mime_content(raw)
|
||||
assert extracted.body_text == "Approved"
|
||||
assert [part.filename for part in extracted.file_attachments] == [
|
||||
"approval.pdf"
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue