From e442347b6e92663e0af4a0957f604eba0cc2ae1a Mon Sep 17 00:00:00 2001 From: Yashas Date: Thu, 27 Aug 2026 12:31:11 +0530 Subject: [PATCH] feat: play the recording on the Live monitor too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The operator watches the Live monitor and never sees My calls, so the recording was reachable only by the colleague who took the call. Now both audiences get it, by the route each already uses: operator -> call_recording_url on the lead, via the record view colleague -> GET /api/agent-sessions/:id/call, authorised by owning the session Two paths because they are looking at two different things — a lead record and a conversation — not because the data differs. Placed ABOVE the summary in the drawer: the summary is a claim about the call and this is the call, so on a demo about whether the AI captured things fairly the evidence should not sit below the fold. preload="none" on both. The drawer opens on every row click, and a WAV of a whole phone call is not something to fetch speculatively. tsc -b and vite build clean. --- src/config.ts | 2 ++ src/pages/CallMonitor.tsx | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/config.ts b/src/config.ts index d0c4dda..4cdc91e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -39,6 +39,8 @@ export const FIELDS = { CALL_DURATION: 'call_duration_seconds', CALL_SUMMARY: 'call_summary', CONTACT_NOTES: 'contact_notes', + /** Dual-channel WAV of the call, written when it ends. */ + CALL_RECORDING: 'call_recording_url', } as const /** diff --git a/src/pages/CallMonitor.tsx b/src/pages/CallMonitor.tsx index 28942d3..636fa94 100644 --- a/src/pages/CallMonitor.tsx +++ b/src/pages/CallMonitor.tsx @@ -169,6 +169,7 @@ function DetailDrawer({ row, onClose }: { row: LeadRow; onClose: () => void }) { const summary = str(row[FIELDS.CALL_SUMMARY]) const notes = str(row[FIELDS.CONTACT_NOTES]) const transferred = str(row[FIELDS.CALL_END_REASON]) === END_REASON_HANDOVER + const recording = str(row[FIELDS.CALL_RECORDING]) return (
@@ -205,6 +206,25 @@ function DetailDrawer({ row, onClose }: { row: LeadRow; onClose: () => void }) {
)} + {/* The recording sits ABOVE the summary on purpose: the summary is a + claim about the conversation, and this is the conversation. On a demo + about whether the AI captured things fairly, the evidence should not + be below the fold. */} +
+

Recording

+ {recording ? ( + // preload="none": a WAV of a whole call, and the drawer opens on + // every row click. Fetch it when someone actually presses play. +
+