mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage-server
synced 2026-04-11 18:08:16 +00:00
fix: appointmentStatus→status, missed call visibility, webhook callbackstatus, KB logging
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,7 @@ export class AiChatController {
|
||||
private async buildKnowledgeBase(auth: string): Promise<string> {
|
||||
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({
|
||||
|
||||
@@ -52,7 +52,7 @@ export class CallAssistService {
|
||||
|
||||
const apptResult = await this.platform.queryWithAuth<any>(
|
||||
`{ 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) {
|
||||
|
||||
@@ -50,7 +50,7 @@ export class SearchController {
|
||||
|
||||
this.platform.queryWithAuth<any>(
|
||||
`{ 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: [] } })),
|
||||
|
||||
@@ -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' };
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ export class WorklistService {
|
||||
|
||||
private async getMissedCalls(agentName: string, authHeader: string): Promise<any[]> {
|
||||
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<any>(
|
||||
`{ 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 }
|
||||
|
||||
Reference in New Issue
Block a user