From 4b5edc4e550ef2c28ff58fc470f014c1cfa53213 Mon Sep 17 00:00:00 2001 From: saridsa2 Date: Mon, 23 Mar 2026 14:42:38 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20appointmentStatus=E2=86=92status,=20miss?= =?UTF-8?q?ed=20call=20visibility,=20webhook=20callbackstatus,=20KB=20logg?= =?UTF-8?q?ing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renamed appointmentStatus to status in search + call-assist queries - Missed calls worklist: removed agentName filter (shared FIFO queue) - Webhook sets callbackstatus: PENDING_CALLBACK on missed calls - AI chat: added KB content logging for debugging Co-Authored-By: Claude Opus 4.6 (1M context) --- src/ai/ai-chat.controller.ts | 6 ++++++ src/call-assist/call-assist.service.ts | 4 ++-- src/search/search.controller.ts | 2 +- src/worklist/missed-call-webhook.controller.ts | 5 +++++ src/worklist/worklist.service.ts | 4 ++-- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/ai/ai-chat.controller.ts b/src/ai/ai-chat.controller.ts index 0429708..e3c9bd9 100644 --- a/src/ai/ai-chat.controller.ts +++ b/src/ai/ai-chat.controller.ts @@ -64,6 +64,7 @@ export class AiChatController { private async buildKnowledgeBase(auth: string): Promise { const now = Date.now(); if (this.knowledgeBase && now - this.kbLoadedAt < this.kbTtlMs) { + this.logger.log(`KB cache hit (${this.knowledgeBase.length} chars, age ${Math.round((now - this.kbLoadedAt) / 1000)}s)`); return this.knowledgeBase; } @@ -120,6 +121,7 @@ export class AiChatController { } } catch (err) { this.logger.warn(`Failed to fetch clinics: ${err}`); + sections.push('## Clinics\nFailed to load clinic data.'); } try { @@ -155,6 +157,7 @@ export class AiChatController { } } catch (err) { this.logger.warn(`Failed to fetch health packages: ${err}`); + sections.push('\n## Health Packages\nFailed to load package data.'); } try { @@ -175,6 +178,7 @@ export class AiChatController { } } catch (err) { this.logger.warn(`Failed to fetch insurance partners: ${err}`); + sections.push('\n## Insurance Partners\nFailed to load insurance data.'); } this.knowledgeBase = sections.join('\n') || 'No hospital information available yet.'; @@ -202,7 +206,9 @@ ${kb}`; private async chatWithTools(userMessage: string, auth: string) { const kb = await this.buildKnowledgeBase(auth); + this.logger.log(`KB content preview: ${kb.substring(0, 300)}...`); const systemPrompt = this.buildSystemPrompt(kb); + this.logger.log(`System prompt length: ${systemPrompt.length} chars, user message: "${userMessage.substring(0, 100)}"`); const platformService = this.platform; const { text, steps } = await generateText({ diff --git a/src/call-assist/call-assist.service.ts b/src/call-assist/call-assist.service.ts index e20f577..e26f148 100644 --- a/src/call-assist/call-assist.service.ts +++ b/src/call-assist/call-assist.service.ts @@ -52,7 +52,7 @@ export class CallAssistService { const apptResult = await this.platform.queryWithAuth( `{ appointments(first: 10, orderBy: [{ scheduledAt: DescNullsLast }]) { edges { node { - id scheduledAt appointmentStatus doctorName department reasonForVisit patientId + id scheduledAt status doctorName department reasonForVisit patientId } } } }`, undefined, authHeader, ); @@ -63,7 +63,7 @@ export class CallAssistService { parts.push('\nPAST APPOINTMENTS:'); for (const a of appts) { const date = a.scheduledAt ? new Date(a.scheduledAt).toLocaleDateString('en-IN') : '?'; - parts.push(`- ${date}: ${a.doctorName ?? '?'} (${a.department ?? '?'}) — ${a.appointmentStatus}`); + parts.push(`- ${date}: ${a.doctorName ?? '?'} (${a.department ?? '?'}) — ${a.status}`); } } } else if (callerPhone) { diff --git a/src/search/search.controller.ts b/src/search/search.controller.ts index 9944c51..5a7110a 100644 --- a/src/search/search.controller.ts +++ b/src/search/search.controller.ts @@ -50,7 +50,7 @@ export class SearchController { this.platform.queryWithAuth( `{ appointments(first: 50, orderBy: [{ scheduledAt: DescNullsLast }]) { edges { node { - id scheduledAt doctorName department appointmentStatus patientId + id scheduledAt doctorName department status patientId } } } }`, undefined, authHeader, ).catch(() => ({ appointments: { edges: [] } })), diff --git a/src/worklist/missed-call-webhook.controller.ts b/src/worklist/missed-call-webhook.controller.ts index 6fa3bb5..03ad05a 100644 --- a/src/worklist/missed-call-webhook.controller.ts +++ b/src/worklist/missed-call-webhook.controller.ts @@ -135,6 +135,11 @@ export class MissedCallWebhookController { durationSec: data.duration, disposition: this.mapDisposition(data.disposition), }; + // Set callback tracking fields for missed calls so they appear in the worklist + if (data.callStatus === 'MISSED') { + callData.callbackstatus = 'PENDING_CALLBACK'; + callData.missedcallcount = 1; + } if (data.recordingUrl) { callData.recording = { primaryLinkUrl: data.recordingUrl, primaryLinkLabel: 'Recording' }; } diff --git a/src/worklist/worklist.service.ts b/src/worklist/worklist.service.ts index 81bc8bb..a93a323 100644 --- a/src/worklist/worklist.service.ts +++ b/src/worklist/worklist.service.ts @@ -76,9 +76,9 @@ export class WorklistService { private async getMissedCalls(agentName: string, authHeader: string): Promise { try { - // FIFO ordering (AscNullsLast) — oldest first. Filter to active callback statuses only. + // FIFO ordering (AscNullsLast) — oldest first. No agentName filter — missed calls are a shared queue. const data = await this.platform.queryWithAuth( - `{ calls(first: 20, filter: { agentName: { eq: "${agentName}" }, callStatus: { eq: MISSED }, callbackstatus: { in: [PENDING_CALLBACK, CALLBACK_ATTEMPTED] } }, orderBy: [{ startedAt: AscNullsLast }]) { edges { node { + `{ calls(first: 20, filter: { callStatus: { eq: MISSED }, callbackstatus: { in: [PENDING_CALLBACK, CALLBACK_ATTEMPTED] } }, orderBy: [{ startedAt: AscNullsLast }]) { edges { node { id name createdAt direction callStatus agentName callerNumber { primaryPhoneNumber }