feat: enrich handover notification with phone + chat link - #2
Conversation
Owner notifications now include a normalized customer phone number and a clickable platform-specific link (wa.me/<phone> for WhatsApp, tg://user?id=<id> for Telegram, raw chat_id elsewhere). LIDs are canonicalized via gateway.whatsapp_identity, so the previous "Kong (122299244130458@lid)" message becomes "Kong (whatsapp 60173380115)" with a clickable wa.me link. Also bundles a fix for a session_id vs session_key cache lookup mismatch that caused trigger_handover to return no_active_chat when the runtime forwards task_id=session_id (the file-style id) rather than the routing session_key. Tests: 22 -> 34 passed (added helper coverage + regression tests for the session_id lookup path).
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
WalkthroughThe PR enhances handover notifications by adding context caching for sessions and enriching owner-facing messages with customer contact information. It introduces utilities to format customer phone numbers and chat links across platforms (WhatsApp, Telegram, others), and updates configuration templates and test coverage accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Dispatch as Dispatch Pipeline
participant Hook as Pre-Dispatch Hook
participant Active as state.active_sessions
participant Store as session_store
Dispatch->>Hook: trigger pre-dispatch
Hook->>Hook: construct cached tuple<br/>(platform, chat_id, user_name, gateway)
Hook->>Active: write cached to<br/>active_sessions[session_key]
Hook->>Store: _ensure_loaded()
Store-->>Hook: store ready (errors suppressed)
Hook->>Store: lookup entry for session_key
Store-->>Hook: entry with session_id (if present)
Hook->>Active: write cached to<br/>active_sessions[session_id]
Hook-->>Dispatch: pre-dispatch complete
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Summary
Owner notifications for the handover flow now include a normalized customer phone number and a platform-aware clickable link, so the owner can jump straight from Telegram into the customer's chat instead of pasting an opaque
@lidinto WhatsApp search.Notification template tokens
Two new tokens, alongside the existing
{customer_name},{chat_id},{platform},{reason},{activated_by}(preserved):{customer_phone}gateway.whatsapp_identity(LID → phone vialid-mapping-*.json)chat_idchat_id{customer_link}https://wa.me/<phone>tg://user?id=<id>chat_idResolution lives in a single helper,
notify.format_chat_link(platform, chat_id) -> (phone, link), used from bothtools/trigger_handover.pyand the/takebackpath inrules/handover.py. Failure paths (canonical helper unavailable, LID with no mapping) fall back to a last-resort suffix strip — never raises.Default template upgrade
HandoverConfig.notify_on_activatedefault changes fromto
Old templates that only reference
{chat_id}still render correctly — extra format kwargs are ignored.config.example.yamlupdated to match. Thebasketball-jersey-demoprofile config (the one that surfaced the bug) is updated separately to use the multi-line variant so Telegram makes the link clickable.Bundled bug fix: session_id vs session_key
_pre_gateway_dispatchnow stashes the cached source under both the routingsession_keyAND the file-stylesession_id(e.g.20260427_133748_e36f7ec9). Production gateway dispatch passestask_id=session_id, notsession_key, which was causingtrigger_handoverto returnno_active_chatfor every real call. Bundled here because both touch the same handover dispatch path.Test plan
pytest -x— 34 passed (was 22 before this branch; adds 7 helper tests, 2 token-rendering tests, and 2 session_id regression tests; existing 22 still pass)hermes gateway restart -p basketball-jersey-demo— clean,gateway-policy loaded: handover=True, tool=True, no startup errors/tmp/handover_smoke.py) against the live profile with the report's actual LID122299244130458@lid— adapter receives:lid-mapping-122299244130458_reverse.json. No@lidleakage.Files modified
notify.py— addsformat_chat_linkhelper (pure, testable, never raises)tools/trigger_handover.py— passes new tokens throughformat(...)rules/handover.py— same for the/takebackexit pathconfig.py— defaultnotify_on_activateupdated; docstring example updatedconfig.example.yaml— sample template updated, placeholder docs extended__init__.py— bundled session_id/session_key dual-stash fixtests/test_rules.py—TestFormatChatLink,TestNotifyTokens,test_activates_via_session_id_lookup,test_pre_dispatch_hook_stashes_by_session_idOut of scope
gateway.whatsapp_identity.canonical_whatsapp_identifierexactly as the role-resolver plugin does.state.py,notify.py's send path,listen_only.py, role-resolver, kb-tools, and other profiles' configs — untouched.Summary by CodeRabbit
New Features
Tests