fix+feat: morning QA fixes, worklist pagination, misc sidecar improvements

- caller-resolution: drop cache, use indexed phone filter (lead.contactPhone.primaryPhoneNumber.like)
- worklist: externalize page size (WORKLIST_PAGE_SIZE × WORKLIST_MAX_PAGES), paginate getMissedCalls/getAssignedLeads/getPendingFollowUps
- maint: unlock-agent, force-ready, backfill-caller-resolution, clear-analysis-cache, fix-timestamps
- ozonetel agent.service: force logout+re-login on "already logged in"
- ai chat: context expansion
- livekit-agent: updates
- widget: session handling
- masterdata: clinic list cache

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 06:49:02 +05:30
parent b6b597fdda
commit fbe782b5ac
17 changed files with 685 additions and 269 deletions

View File

@@ -394,6 +394,48 @@ export class OzonetelAgentService {
}
}
// Fetch a single CDR record by UCID. Preferred over fetchCDR + .find()
// for recording lookups — Ozonetel resolves leg-pair UCIDs internally,
// so the agent-side UCID we hold reliably returns the call row.
// Same rate limit as fetchCDR (2 req/min, 15-day window).
async fetchCdrByUCID(params: { date: string; ucid: string }): Promise<Record<string, any> | null> {
const url = `https://${this.apiDomain}/ca_reports/fetchCdrByUCID`;
this.logger.log(`Fetch CDR by UCID: ucid=${params.ucid} date=${params.date}`);
try {
const token = await this.getToken();
const body = {
userName: this.accountId,
fromDate: `${params.date} 00:00:00`,
toDate: `${params.date} 23:59:59`,
ucid: params.ucid,
};
const response = await axios({
method: 'GET',
url,
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
data: JSON.stringify(body),
});
const data = response.data;
if (data.status === 'success' && Array.isArray(data.details) && data.details.length > 0) {
return data.details[0];
}
if (data.status === 'success' && data.details && !Array.isArray(data.details)) {
return data.details;
}
return null;
} catch (error: any) {
const responseData = error?.response?.data ? JSON.stringify(error.response.data) : '';
this.logger.error(`Fetch CDR by UCID failed: ${error.message} ${responseData}`);
return null;
}
}
async getAgentSummary(agentId: string, date: string): Promise<{
totalLoginDuration: string;
totalBusyTime: string;