Commit Graph

30 Commits

Author SHA1 Message Date
4b5edc4e55 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>
2026-03-23 14:42:38 +05:30
0b98d490f0 fix: use HH:MM:SS format for Ozonetel abandonCalls time params
Ozonetel API expects time-of-day format (HH:MM:SS), not full datetime.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:50:57 +05:30
30a4cda178 feat: add token refresh endpoint for auto-renewal
POST /auth/refresh exchanges refresh token for new access token
via platform's renewToken mutation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 11:53:02 +05:30
feedec0588 docs: add team onboarding README with architecture and troubleshooting guide
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:47:15 +05:30
cec2526d37 feat: Phase 2 — missed call queue ingestion, auto-assignment, endpoints
- MissedQueueService: polls Ozonetel abandonCalls every 30s, dedup by phone
- Auto-assigns oldest PENDING_CALLBACK call on agent Ready (dispose + state change)
- GET /api/worklist/missed-queue, PATCH /api/worklist/missed-queue/:id/status
- Worklist query updated with callback fields and FIFO ordering
- PlatformGraphqlService.query() made public for server-to-server ops
- forwardRef circular dependency resolution between WorklistModule and OzonetelAgentModule

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 09:17:33 +05:30
4963a698d9 feat: agent state endpoint + search module
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:21:40 +05:30
8ba326589c feat: agent summary, AHT, and performance aggregation endpoint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:41:05 +05:30
bbf77ed0e9 feat: call control, recording, CDR, missed calls, live call assist
- Call Control API (CONFERENCE/HOLD/MUTE/KICK_CALL)
- Recording pause/unpause
- Fetch CDR Detailed (call history with recordings)
- Abandon Calls (missed calls from Ozonetel)
- Call Assist WebSocket gateway (Deepgram STT + OpenAI suggestions)
- Call Assist service (lead context loading)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 10:36:35 +05:30
58225b7943 feat: webhook field fixes, Force Ready endpoint, improved error logging
- Fix Call record field names (recording, callerNumber, durationSec)
- Add POST /api/ozonetel/agent-ready using logout+login for Force Ready
- Add callerNumber to kookoo callback
- Better error logging with response body

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:22:47 +05:30
8c6cd2c156 feat: add Ozonetel Set Disposition API for proper ACW release
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:35:59 +05:30
72e6373acf docs: critical finding — outbound needs CloudAgent WebSocket session
The toolbar uses TWO WebSocket connections:
1. CloudAgent WS (mdlConnection.php) for control events (newCall, busyAgent)
2. SIP WS (blr-pub-rtc4) for audio

tbManualDial requires browserSessionId + usId from the CloudAgent WS session.
Without these, CloudAgent doesn't route the SIP INVITE to our browser.

Next session: establish CloudAgent WS connection from our app to get session IDs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 07:20:23 +05:30
68c03b0af4 test: try 0-prefix SIP extension in Kookoo dial — still fails
Kookoo <dial> only routes to PSTN numbers, not SIP extensions.
Tested: 523590, 0523590 — both result in not_answered.
The bridge from Kookoo to browser SIP requires either:
- Ozonetel enabling /ca_apis/ auth (CloudAgent API)
- Or a way to route Kookoo calls to internal SIP extensions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 07:01:39 +05:30
d0cb68d8d7 feat: Kookoo IVR endpoint — outbound calls now bridge to agent SIP
When customer answers outbound call, Kookoo hits /kookoo/ivr which
returns <dial record="true">523590</dial> to bridge the call to
the agent's SIP extension. Agent's browser rings, both connect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:19:50 +05:30
6812006b53 feat: switch outbound dial to Kookoo API — outbound calls now work
- Replace CloudAgent V3 tbManualDial with Kookoo outbound.php
- Simple HTTP GET with api_key — no auth issues
- Kookoo callback endpoint: POST /webhooks/kookoo/callback
  - Creates Call record in platform
  - Matches caller to Lead by phone
- Remove agent login requirement before dial
- Tested: call queued successfully, phone rang

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 18:03:44 +05:30
ea482d0fed fix: restore callerNumber in missed calls worklist query
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:13:19 +05:30
8c0853dd19 feat: Ozonetel webhook handler — create call records from call events
- Parse Ozonetel POST payload (CallerID, Status, Duration, Recording URL)
- Create Call record in platform via API key auth
- Match caller to Lead by phone number
- Create LeadActivity timeline entry
- Update lead contactAttempts and lastContacted
- Map Ozonetel dispositions to platform enum values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:09:54 +05:30
5f185f37f5 feat: switch to global_healthx Ozonetel account, add Dockerfile
- Update default campaign to Inbound_918041763265
- Add Dockerfile and .dockerignore for container deployment
- Sidecar image: 043728036361.dkr.ecr.ap-south-1.amazonaws.com/fortytwo-eap/helix-engage-sidecar:alpha

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:27:40 +05:30
a0df752cfd feat: Ozonetel V3 dial endpoint, worklist query fixes
- Switch outbound dial to /CAServicesV3/mdlConnection.php (tbManualDial)
- Use both Apikey + Basic Auth headers matching Ozonetel toolbar pattern
- Auto-login agent before dial attempt
- Dial controller returns 502 (not 401) for Ozonetel errors to prevent session logout
- Fix worklist: remove non-existent callId from followUp query
- Fix worklist: use unquoted MISSED enum, remove callerNumber subfield issue
- Worklist controller resolves agent name from platform currentUser API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 18:34:32 +05:30
9688d5144e feat: migrate AI to Vercel AI SDK, add OpenAI provider, fix worklist
- Replace raw @anthropic-ai/sdk with Vercel AI SDK (generateText, tool, generateObject)
- Add provider abstraction (ai-provider.ts) — swap OpenAI/Anthropic via env var
- AI chat controller: dynamic KB from platform (clinics, packages, insurance), zero hardcoding
- AI enrichment service: use generateObject with Zod schema instead of manual JSON parsing
- Worklist: resolve agent name from platform currentUser API instead of JWT decode
- Worklist: fix GraphQL field names to match platform remapping (source, status, direction, etc.)
- Config: add AI_PROVIDER, AI_MODEL, OPENAI_API_KEY env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 16:45:05 +05:30
6f7d408724 feat: add worklist engine with prioritized missed calls, follow-ups, and leads 2026-03-18 11:26:04 +05:30
f0d3d2c9f1 feat: fetch user profile with custom roles (HelixEngage Manager/User) after login, determine app role, pass to frontend 2026-03-18 10:43:05 +05:30
22ac383107 feat: add call lookup endpoint with lead matching + AI enrichment, token passthrough on platform service 2026-03-18 09:11:15 +05:30
ccb4bc4ea6 fix: treat 'already logged in' as success in Ozonetel agent login 2026-03-18 07:35:11 +05:30
a42d479f06 feat: wire sidecar to platform — auth proxy with workspace subdomain, GraphQL proxy, health check 2026-03-18 07:15:47 +05:30
d488d551ed feat: add call events orchestrator with WebSocket gateway, wire Exotel → lookup → enrich → push flow
- CallEventsService orchestrates: Exotel webhook → lead lookup → AI enrichment → WebSocket push
- CallEventsGateway (Socket.IO /call-events namespace) with agent room registration and disposition handling
- EnrichedCallEvent/DispositionPayload types for frontend contract
- Disposition flow: creates Call record, updates lead status, logs lead activity
- Wired ExotelController to forward answered/ended events to CallEventsService
- forwardRef used to resolve circular dependency between gateway and service

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 09:08:57 +05:30
3e0d9a4351 feat: add auth proxy controller for login and token exchange
Adds POST /auth/login and POST /auth/tokens endpoints that proxy
GraphQL mutations to the fortytwo-eap-core platform, letting the
frontend use only the sidecar URL for authentication.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:08:07 +05:30
702afabfa7 feat: add AI enrichment service with Claude Haiku and rule-based fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:04:45 +05:30
30df1d0158 feat: add Exotel webhook controller and service for call event parsing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:04:15 +05:30
5b35c65e6e feat: add Platform GraphQL client service for lead lookup and CRUD
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:04:00 +05:30
a3172140b0 chore: scaffold NestJS sidecar with config, CORS, and dependency setup 2026-03-17 09:02:15 +05:30