human hand off

This commit is contained in:
debu-2 2026-10-06 07:12:55 +05:30
parent d0fee5c8f7
commit 7af776196a
34 changed files with 2941 additions and 195 deletions

View file

@ -10,7 +10,16 @@ from app.config import get_settings
from app.database import SessionFactory, mongo_db
from app.models import Account
from app.services.external_reply_service import log_original_external_message
from app.services.handoff_mirror_policy import (
GENERATED_BY_CUSTOMER,
MESSAGE_ORIGIN_EXTERNAL_CUSTOMER,
)
from app.services.human_handoff_service import MESSAGE_SCOPE_EXTERNAL
from app.services.human_handoff_service import (
maybe_trigger_handoff,
process_human_reply,
resolve_handoff_from_inbound,
)
from app.services.message_ids import canonical_message_id, message_id_fields
from app.services.mime_parser import parse_mime
from app.services.reply_extractor import build_reply_display
@ -121,26 +130,65 @@ class InboundHandler:
body_text = parsed.pop("body_text")
body_html = parsed.pop("body_html")
stored = await get_raw_mime_storage().put(raw, delivery_key)
raw_mime = {
"bucket": stored.bucket,
"name": stored.name,
"generation": stored.generation,
"size": stored.size,
"crc32c": stored.crc32c,
}
now = datetime.now(timezone.utc)
sender_address = (parsed.get("sender") or {}).get("address", "").lower()
internet_message_id = canonical_message_id(parsed.get("message_id"))
id_fields = message_id_fields(internet_message_id)
external_recipients: list[str] = []
for recipient in recipients:
account_id = envelope.account_ids[recipient]
handoff = await resolve_handoff_from_inbound(
mongo_db,
account_id=account_id,
agent_email=recipient,
sender_address=sender_address,
in_reply_to=parsed.get("in_reply_to"),
references=parsed.get("references", []),
)
if handoff is None:
external_recipients.append(recipient)
continue
await process_human_reply(
mongo_db,
account_id=account_id,
agent_email=recipient,
handoff=handoff,
parsed=parsed,
body_text=body_text,
body_html=body_html,
raw_mime=raw_mime,
delivery_key=delivery_key,
)
logger.info(
"handoff_reply_received account_id=%s handoff_id=%s message_id=%s",
account_id,
handoff["_id"],
internet_message_id,
)
if not external_recipients:
return f"250 2.0.0 Handoff message accepted as {delivery_key}"
recipients = external_recipients
message = {
**parsed,
"direction": "inbound",
"message_scope": MESSAGE_SCOPE_EXTERNAL,
"message_origin": MESSAGE_ORIGIN_EXTERNAL_CUSTOMER,
"generated_by": GENERATED_BY_CUSTOMER,
"envelope_sender": envelope.mail_from.lower(),
"envelope_recipients": recipients,
"delivery_key": delivery_key,
**id_fields,
"raw_mime": {
"bucket": stored.bucket,
"name": stored.name,
"generation": stored.generation,
"size": stored.size,
"crc32c": stored.crc32c,
},
"raw_mime": raw_mime,
"received_at": now,
"created_at": now,
"has_text_body": bool(body_text),
@ -275,6 +323,21 @@ class InboundHandler:
thread_id,
mailbox_result.upserted_id is not None or mailbox_result.modified_count > 0,
)
try:
await maybe_trigger_handoff(
mongo_db,
account_id=account_id,
agent_email=recipient,
external_message=persisted,
external_thread_id=thread_id,
)
except Exception:
logger.exception(
"handoff_trigger_failed account_id=%s thread_id=%s message_id=%s",
account_id,
thread_id,
persisted["_id"],
)
except Exception:
logger.exception("Temporary failure accepting inbound message")
return "451 4.3.0 Temporary server failure; please retry"