elevenlabs-webhook-nodejs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +27 -0
- package/.dockerignore +6 -0
- package/.env.example +43 -0
- package/BEFORE-PRODUCTION.md +32 -0
- package/Dockerfile +23 -0
- package/SYSTEM_OVERVIEW.md +942 -0
- package/SYSTEM_STATUS.md +332 -0
- package/backup_script/main.py +146 -0
- package/baileys/.dockerignore +7 -0
- package/baileys/Dockerfile +13 -0
- package/baileys/README.md +412 -0
- package/baileys/index.js +499 -0
- package/baileys/package-lock.json +2532 -0
- package/baileys/package.json +25 -0
- package/baileys/server.js +96 -0
- package/baileys/src/config.js +55 -0
- package/baileys/src/middleware/api-key.js +16 -0
- package/baileys/src/routes/accounts.js +51 -0
- package/baileys/src/routes/chats.js +103 -0
- package/baileys/src/routes/webhooks.js +34 -0
- package/baileys/src/services/account-store.js +259 -0
- package/baileys/src/services/webhook-dispatcher.js +161 -0
- package/baileys/src/services/worker-manager.js +597 -0
- package/baileys/src/utils/jid.js +79 -0
- package/baileys/src/utils/logger.js +16 -0
- package/baileys/src/utils/use-mongodb-auth-state.js +122 -0
- package/baileys/worker.js +721 -0
- package/dist/app.d.ts +1 -0
- package/dist/app.js +84 -0
- package/dist/app.js.map +1 -0
- package/dist/config/agentPrompts.json +19 -0
- package/dist/config/database.d.ts +1 -0
- package/dist/config/database.js +26 -0
- package/dist/config/database.js.map +1 -0
- package/dist/config/env.d.ts +41 -0
- package/dist/config/env.js +81 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +73 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controllers/webhook.controller.d.ts +10 -0
- package/dist/controllers/webhook.controller.js +128 -0
- package/dist/controllers/webhook.controller.js.map +1 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.js +13 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/hooks/webhookValidator.d.ts +2 -0
- package/dist/hooks/webhookValidator.js +47 -0
- package/dist/hooks/webhookValidator.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/001_session-architecture.d.ts +3 -0
- package/dist/migrations/001_session-architecture.js +119 -0
- package/dist/migrations/001_session-architecture.js.map +1 -0
- package/dist/migrations/002_agent-ref.d.ts +3 -0
- package/dist/migrations/002_agent-ref.js +55 -0
- package/dist/migrations/002_agent-ref.js.map +1 -0
- package/dist/migrations/003_shift-schedule.d.ts +3 -0
- package/dist/migrations/003_shift-schedule.js +48 -0
- package/dist/migrations/003_shift-schedule.js.map +1 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.d.ts +3 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js +27 -0
- package/dist/migrations/004_invert-shift-to-clinic-hours.js.map +1 -0
- package/dist/migrations/005_composite-baileys-chat-ids.d.ts +3 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js +47 -0
- package/dist/migrations/005_composite-baileys-chat-ids.js.map +1 -0
- package/dist/migrations/migration.model.d.ts +18 -0
- package/dist/migrations/migration.model.js +45 -0
- package/dist/migrations/migration.model.js.map +1 -0
- package/dist/migrations/migration.routes.d.ts +2 -0
- package/dist/migrations/migration.routes.js +37 -0
- package/dist/migrations/migration.routes.js.map +1 -0
- package/dist/migrations/migration.runner.d.ts +19 -0
- package/dist/migrations/migration.runner.js +74 -0
- package/dist/migrations/migration.runner.js.map +1 -0
- package/dist/models/ConversationClaim.d.ts +13 -0
- package/dist/models/ConversationClaim.js +44 -0
- package/dist/models/ConversationClaim.js.map +1 -0
- package/dist/models/ConversationEvaluation.d.ts +23 -0
- package/dist/models/ConversationEvaluation.js +92 -0
- package/dist/models/ConversationEvaluation.js.map +1 -0
- package/dist/models/Summary.d.ts +37 -0
- package/dist/models/Summary.js +78 -0
- package/dist/models/Summary.js.map +1 -0
- package/dist/models/Transcription.d.ts +34 -0
- package/dist/models/Transcription.js +71 -0
- package/dist/models/Transcription.js.map +1 -0
- package/dist/models/WhatsAppRecipient.d.ts +23 -0
- package/dist/models/WhatsAppRecipient.js +53 -0
- package/dist/models/WhatsAppRecipient.js.map +1 -0
- package/dist/modules/admin/admin.routes.d.ts +2 -0
- package/dist/modules/admin/admin.routes.js +1966 -0
- package/dist/modules/admin/admin.routes.js.map +1 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js +158 -0
- package/dist/modules/admin/elevenlabs-test-chat.routes.js.map +1 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.d.ts +2 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js +204 -0
- package/dist/modules/admin/whatsapp-test-chat.routes.js.map +1 -0
- package/dist/modules/agents/agent.model.d.ts +38 -0
- package/dist/modules/agents/agent.model.js +92 -0
- package/dist/modules/agents/agent.model.js.map +1 -0
- package/dist/modules/agents/agent.routes.d.ts +2 -0
- package/dist/modules/agents/agent.routes.js +61 -0
- package/dist/modules/agents/agent.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.model.d.ts +76 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js +118 -0
- package/dist/modules/appointment-validation/appointment-validation.model.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.d.ts +2 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js +202 -0
- package/dist/modules/appointment-validation/appointment-validation.routes.js.map +1 -0
- package/dist/modules/appointment-validation/appointment-validation.service.d.ts +53 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js +827 -0
- package/dist/modules/appointment-validation/appointment-validation.service.js.map +1 -0
- package/dist/modules/auth/auth.model.d.ts +17 -0
- package/dist/modules/auth/auth.model.js +64 -0
- package/dist/modules/auth/auth.model.js.map +1 -0
- package/dist/modules/auth/auth.routes.d.ts +2 -0
- package/dist/modules/auth/auth.routes.js +202 -0
- package/dist/modules/auth/auth.routes.js.map +1 -0
- package/dist/modules/auth/auth.service.d.ts +28 -0
- package/dist/modules/auth/auth.service.js +183 -0
- package/dist/modules/auth/auth.service.js.map +1 -0
- package/dist/modules/auth/refresh-token.model.d.ts +13 -0
- package/dist/modules/auth/refresh-token.model.js +52 -0
- package/dist/modules/auth/refresh-token.model.js.map +1 -0
- package/dist/modules/billing/billing-alert.model.d.ts +16 -0
- package/dist/modules/billing/billing-alert.model.js +47 -0
- package/dist/modules/billing/billing-alert.model.js.map +1 -0
- package/dist/modules/billing/billing-period-snapshot.model.d.ts +35 -0
- package/dist/modules/billing/billing-period-snapshot.model.js +68 -0
- package/dist/modules/billing/billing-period-snapshot.model.js.map +1 -0
- package/dist/modules/billing/billing.model.d.ts +18 -0
- package/dist/modules/billing/billing.model.js +62 -0
- package/dist/modules/billing/billing.model.js.map +1 -0
- package/dist/modules/billing/billing.routes.d.ts +2 -0
- package/dist/modules/billing/billing.routes.js +63 -0
- package/dist/modules/billing/billing.routes.js.map +1 -0
- package/dist/modules/billing/billing.service.d.ts +69 -0
- package/dist/modules/billing/billing.service.js +498 -0
- package/dist/modules/billing/billing.service.js.map +1 -0
- package/dist/modules/billing/payment.model.d.ts +24 -0
- package/dist/modules/billing/payment.model.js +57 -0
- package/dist/modules/billing/payment.model.js.map +1 -0
- package/dist/modules/calls/call.model.d.ts +41 -0
- package/dist/modules/calls/call.model.js +97 -0
- package/dist/modules/calls/call.model.js.map +1 -0
- package/dist/modules/calls/call.routes.d.ts +2 -0
- package/dist/modules/calls/call.routes.js +103 -0
- package/dist/modules/calls/call.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.model.d.ts +45 -0
- package/dist/modules/campaigns/campaign.model.js +98 -0
- package/dist/modules/campaigns/campaign.model.js.map +1 -0
- package/dist/modules/campaigns/campaign.routes.d.ts +2 -0
- package/dist/modules/campaigns/campaign.routes.js +323 -0
- package/dist/modules/campaigns/campaign.routes.js.map +1 -0
- package/dist/modules/campaigns/campaign.service.d.ts +11 -0
- package/dist/modules/campaigns/campaign.service.js +86 -0
- package/dist/modules/campaigns/campaign.service.js.map +1 -0
- package/dist/modules/google-calendar/google-calendar.routes.d.ts +2 -0
- package/dist/modules/google-calendar/google-calendar.routes.js +32 -0
- package/dist/modules/google-calendar/google-calendar.routes.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call-config.model.d.ts +20 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js +68 -0
- package/dist/modules/inbound-call/inbound-call-config.model.js.map +1 -0
- package/dist/modules/inbound-call/inbound-call.routes.d.ts +2 -0
- package/dist/modules/inbound-call/inbound-call.routes.js +243 -0
- package/dist/modules/inbound-call/inbound-call.routes.js.map +1 -0
- package/dist/modules/leads/lead.model.d.ts +24 -0
- package/dist/modules/leads/lead.model.js +54 -0
- package/dist/modules/leads/lead.model.js.map +1 -0
- package/dist/modules/leads/lead.routes.d.ts +2 -0
- package/dist/modules/leads/lead.routes.js +201 -0
- package/dist/modules/leads/lead.routes.js.map +1 -0
- package/dist/modules/plans/plan.model.d.ts +25 -0
- package/dist/modules/plans/plan.model.js +59 -0
- package/dist/modules/plans/plan.model.js.map +1 -0
- package/dist/modules/surveys/survey.model.d.ts +30 -0
- package/dist/modules/surveys/survey.model.js +75 -0
- package/dist/modules/surveys/survey.model.js.map +1 -0
- package/dist/modules/surveys/survey.routes.d.ts +2 -0
- package/dist/modules/surveys/survey.routes.js +153 -0
- package/dist/modules/surveys/survey.routes.js.map +1 -0
- package/dist/modules/tenants/tenant.model.d.ts +86 -0
- package/dist/modules/tenants/tenant.model.js +127 -0
- package/dist/modules/tenants/tenant.model.js.map +1 -0
- package/dist/modules/tenants/tenant.routes.d.ts +2 -0
- package/dist/modules/tenants/tenant.routes.js +65 -0
- package/dist/modules/tenants/tenant.routes.js.map +1 -0
- package/dist/modules/users/user.routes.d.ts +2 -0
- package/dist/modules/users/user.routes.js +106 -0
- package/dist/modules/users/user.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.d.ts +20 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js +85 -0
- package/dist/modules/webhooks/elevenlabs-tool.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.d.ts +11 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js +360 -0
- package/dist/modules/webhooks/elevenlabs-tool.service.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.routes.d.ts +2 -0
- package/dist/modules/webhooks/elevenlabs.routes.js +34 -0
- package/dist/modules/webhooks/elevenlabs.routes.js.map +1 -0
- package/dist/modules/webhooks/elevenlabs.service.d.ts +6 -0
- package/dist/modules/webhooks/elevenlabs.service.js +512 -0
- package/dist/modules/webhooks/elevenlabs.service.js.map +1 -0
- package/dist/modules/webhooks/unipile.routes.d.ts +2 -0
- package/dist/modules/webhooks/unipile.routes.js +780 -0
- package/dist/modules/webhooks/unipile.routes.js.map +1 -0
- package/dist/modules/whatsapp/appointment.model.d.ts +27 -0
- package/dist/modules/whatsapp/appointment.model.js +58 -0
- package/dist/modules/whatsapp/appointment.model.js.map +1 -0
- package/dist/modules/whatsapp/operator-request.model.d.ts +29 -0
- package/dist/modules/whatsapp/operator-request.model.js +65 -0
- package/dist/modules/whatsapp/operator-request.model.js.map +1 -0
- package/dist/modules/whatsapp/stt-usage.model.d.ts +16 -0
- package/dist/modules/whatsapp/stt-usage.model.js +53 -0
- package/dist/modules/whatsapp/stt-usage.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js +55 -0
- package/dist/modules/whatsapp/whatsapp-chat.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.d.ts +23 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js +54 -0
- package/dist/modules/whatsapp/whatsapp-contact-profile.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-message.model.d.ts +30 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js +52 -0
- package/dist/modules/whatsapp/whatsapp-message.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp-session.model.d.ts +33 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js +65 -0
- package/dist/modules/whatsapp/whatsapp-session.model.js.map +1 -0
- package/dist/modules/whatsapp/whatsapp.routes.d.ts +2 -0
- package/dist/modules/whatsapp/whatsapp.routes.js +1237 -0
- package/dist/modules/whatsapp/whatsapp.routes.js.map +1 -0
- package/dist/plugins/cors.d.ts +3 -0
- package/dist/plugins/cors.js +11 -0
- package/dist/plugins/cors.js.map +1 -0
- package/dist/plugins/jwt.d.ts +3 -0
- package/dist/plugins/jwt.js +22 -0
- package/dist/plugins/jwt.js.map +1 -0
- package/dist/plugins/rawBody.d.ts +3 -0
- package/dist/plugins/rawBody.js +16 -0
- package/dist/plugins/rawBody.js.map +1 -0
- package/dist/plugins/rbac.d.ts +5 -0
- package/dist/plugins/rbac.js +29 -0
- package/dist/plugins/rbac.js.map +1 -0
- package/dist/routes/admin.routes.d.ts +2 -0
- package/dist/routes/admin.routes.js +169 -0
- package/dist/routes/admin.routes.js.map +1 -0
- package/dist/routes/health.routes.d.ts +2 -0
- package/dist/routes/health.routes.js +16 -0
- package/dist/routes/health.routes.js.map +1 -0
- package/dist/routes/webhook.routes.d.ts +2 -0
- package/dist/routes/webhook.routes.js +17 -0
- package/dist/routes/webhook.routes.js.map +1 -0
- package/dist/services/ai/base.ai.d.ts +19 -0
- package/dist/services/ai/base.ai.js +120 -0
- package/dist/services/ai/base.ai.js.map +1 -0
- package/dist/services/ai/gemini.service.d.ts +11 -0
- package/dist/services/ai/gemini.service.js +43 -0
- package/dist/services/ai/gemini.service.js.map +1 -0
- package/dist/services/ai/index.d.ts +2 -0
- package/dist/services/ai/index.js +26 -0
- package/dist/services/ai/index.js.map +1 -0
- package/dist/services/ai/openai.service.d.ts +11 -0
- package/dist/services/ai/openai.service.js +50 -0
- package/dist/services/ai/openai.service.js.map +1 -0
- package/dist/services/elevenlabs.service.d.ts +52 -0
- package/dist/services/elevenlabs.service.js +447 -0
- package/dist/services/elevenlabs.service.js.map +1 -0
- package/dist/services/google-calendar.service.d.ts +60 -0
- package/dist/services/google-calendar.service.js +494 -0
- package/dist/services/google-calendar.service.js.map +1 -0
- package/dist/services/inbound-call-schedule.service.d.ts +11 -0
- package/dist/services/inbound-call-schedule.service.js +162 -0
- package/dist/services/inbound-call-schedule.service.js.map +1 -0
- package/dist/services/netgsm.service.d.ts +41 -0
- package/dist/services/netgsm.service.js +89 -0
- package/dist/services/netgsm.service.js.map +1 -0
- package/dist/services/unipile.service.d.ts +41 -0
- package/dist/services/unipile.service.js +149 -0
- package/dist/services/unipile.service.js.map +1 -0
- package/dist/services/whatsapp-agent.service.d.ts +139 -0
- package/dist/services/whatsapp-agent.service.js +2055 -0
- package/dist/services/whatsapp-agent.service.js.map +1 -0
- package/dist/services/whatsapp.service.d.ts +26 -0
- package/dist/services/whatsapp.service.js +206 -0
- package/dist/services/whatsapp.service.js.map +1 -0
- package/dist/templates/index.d.ts +39 -0
- package/dist/templates/index.js +35 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/receptionist.d.ts +2 -0
- package/dist/templates/receptionist.js +39 -0
- package/dist/templates/receptionist.js.map +1 -0
- package/dist/templates/survey.d.ts +2 -0
- package/dist/templates/survey.js +41 -0
- package/dist/templates/survey.js.map +1 -0
- package/dist/types/index.d.ts +173 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.js +105 -0
- package/dist/utils/logger.js.map +1 -0
- package/docker-compose.nestjs.yml +89 -0
- package/docker-compose.yml +78 -0
- package/docs/AI_AGENT_ENHANCEMENT_PLAN.md +164 -0
- package/docs/API.md +1193 -0
- package/docs/API_ENDPOINTS.md +344 -0
- package/docs/ARCHITECTURE.md +305 -0
- package/docs/AUTH_API.md +252 -0
- package/docs/BILLING_SMS_ALERTS.md +94 -0
- package/docs/CHAT_ASSIGNMENT_SYSTEM.md +118 -0
- package/docs/CLIENT_TOOLS_AND_FEATURES.md +337 -0
- package/docs/ELEVENLABS_WEBHOOK_TOOLS.md +644 -0
- package/docs/FRONTEND_CHECKLIST.md +227 -0
- package/docs/IMPLEMENTATION_STATUS.md +470 -0
- package/docs/MIGRATION_GUIDE.md +96 -0
- package/docs/MISSINGS_REPORT.md +507 -0
- package/docs/NESTJS_MIGRATION_REFERENCE.md +5136 -0
- package/docs/PROJECT_DESCRIPTION.md +1038 -0
- package/docs/SCALING.md +148 -0
- package/docs/SESSION_SUMMARY_2026_03_17.md +135 -0
- package/docs/WHATSAPP_AGENT.md +1086 -0
- package/docs/architecture/00-SYSTEM-OVERVIEW.md +318 -0
- package/docs/architecture/01-DATABASE-SCHEMA.md +2564 -0
- package/docs/architecture/02-AUTHENTICATION.md +1040 -0
- package/docs/architecture/03-MULTI-CLINIC.md +742 -0
- package/docs/architecture/04-WHATSAPP-AGENT.md +608 -0
- package/docs/architecture/05-OPERATOR-WORKFLOW.md +444 -0
- package/docs/architecture/06-BAILEYS-MICROSERVICE.md +616 -0
- package/docs/architecture/07-APPOINTMENTS.md +849 -0
- package/docs/architecture/08-VOICE-CALLS.md +470 -0
- package/docs/architecture/09-OUTBOUND-CAMPAIGNS.md +542 -0
- package/docs/architecture/10-CLIENT-TOOLS.md +665 -0
- package/docs/architecture/11-BILLING.md +458 -0
- package/docs/architecture/12-SECURITY.md +216 -0
- package/docs/architecture/13-LOGGING-AUDIT.md +549 -0
- package/docs/architecture/14-META-BUSINESS-API.md +454 -0
- package/docs/architecture/15-AI-MODULE.md +479 -0
- package/docs/architecture/16-BACKGROUND-JOBS.md +469 -0
- package/docs/architecture/17-REALTIME-LIVECHAT.md +447 -0
- package/docs/architecture/18-FILE-STORAGE.md +410 -0
- package/docs/architecture/19-PATIENTS.md +1034 -0
- package/docs/architecture/20-TREATMENTS-AND-PLANS.md +774 -0
- package/docs/architecture/21-BEFORE-AFTER-PHOTOS.md +519 -0
- package/docs/database.md +456 -0
- package/docs/ornek-randevu-onay.csv +3 -0
- package/ecosystem.config.js +16 -0
- package/elevenlabs-convai-api-reference.md +1171 -0
- package/frontend/.dockerignore +2 -0
- package/frontend/Dockerfile +24 -0
- package/frontend/README.md +75 -0
- package/frontend/components.json +25 -0
- package/frontend/eslint.config.js +23 -0
- package/frontend/index.html +13 -0
- package/frontend/nginx.conf +37 -0
- package/frontend/package-lock.json +8709 -0
- package/frontend/package.json +71 -0
- package/frontend/public/favicon.svg +1 -0
- package/frontend/public/icons.svg +24 -0
- package/frontend/src/App.tsx +125 -0
- package/frontend/src/components/error-boundary.tsx +50 -0
- package/frontend/src/components/shared/activity-timeline.tsx +66 -0
- package/frontend/src/components/shared/appointment-calendar.css +80 -0
- package/frontend/src/components/shared/appointment-calendar.tsx +245 -0
- package/frontend/src/components/shared/chat-bubble.tsx +72 -0
- package/frontend/src/components/shared/combobox.tsx +119 -0
- package/frontend/src/components/shared/confirm-dialog.tsx +57 -0
- package/frontend/src/components/shared/data-table-pagination.tsx +97 -0
- package/frontend/src/components/shared/data-table-toolbar.tsx +39 -0
- package/frontend/src/components/shared/empty-state.tsx +27 -0
- package/frontend/src/components/shared/file-upload.tsx +140 -0
- package/frontend/src/components/shared/index.ts +20 -0
- package/frontend/src/components/shared/language-switcher.tsx +29 -0
- package/frontend/src/components/shared/notification-dropdown.tsx +115 -0
- package/frontend/src/components/shared/page-header.tsx +23 -0
- package/frontend/src/components/shared/stat-card.tsx +37 -0
- package/frontend/src/components/shared/status-badge.tsx +70 -0
- package/frontend/src/components/shared/status-dot.tsx +43 -0
- package/frontend/src/components/ui/alert-dialog.tsx +187 -0
- package/frontend/src/components/ui/alert.tsx +76 -0
- package/frontend/src/components/ui/avatar.tsx +109 -0
- package/frontend/src/components/ui/badge.tsx +52 -0
- package/frontend/src/components/ui/breadcrumb.tsx +125 -0
- package/frontend/src/components/ui/button.tsx +60 -0
- package/frontend/src/components/ui/calendar.tsx +219 -0
- package/frontend/src/components/ui/card.tsx +103 -0
- package/frontend/src/components/ui/chart.tsx +371 -0
- package/frontend/src/components/ui/checkbox.tsx +29 -0
- package/frontend/src/components/ui/collapsible.tsx +19 -0
- package/frontend/src/components/ui/command.tsx +194 -0
- package/frontend/src/components/ui/dialog.tsx +158 -0
- package/frontend/src/components/ui/dropdown-menu.tsx +268 -0
- package/frontend/src/components/ui/input-group.tsx +156 -0
- package/frontend/src/components/ui/input.tsx +20 -0
- package/frontend/src/components/ui/label.tsx +20 -0
- package/frontend/src/components/ui/pagination.tsx +130 -0
- package/frontend/src/components/ui/popover.tsx +90 -0
- package/frontend/src/components/ui/progress.tsx +83 -0
- package/frontend/src/components/ui/radio-group.tsx +36 -0
- package/frontend/src/components/ui/scroll-area.tsx +54 -0
- package/frontend/src/components/ui/select.tsx +199 -0
- package/frontend/src/components/ui/separator.tsx +23 -0
- package/frontend/src/components/ui/sheet.tsx +138 -0
- package/frontend/src/components/ui/sidebar.tsx +723 -0
- package/frontend/src/components/ui/skeleton.tsx +13 -0
- package/frontend/src/components/ui/sonner.tsx +47 -0
- package/frontend/src/components/ui/switch.tsx +30 -0
- package/frontend/src/components/ui/table.tsx +114 -0
- package/frontend/src/components/ui/tabs.tsx +82 -0
- package/frontend/src/components/ui/textarea.tsx +18 -0
- package/frontend/src/components/ui/toggle-group.tsx +89 -0
- package/frontend/src/components/ui/toggle.tsx +43 -0
- package/frontend/src/components/ui/tooltip.tsx +64 -0
- package/frontend/src/hooks/use-mobile.ts +19 -0
- package/frontend/src/i18n/index.ts +20 -0
- package/frontend/src/i18n/locales/en.json +786 -0
- package/frontend/src/i18n/locales/tr.json +786 -0
- package/frontend/src/index.css +134 -0
- package/frontend/src/layouts/admin-layout.tsx +111 -0
- package/frontend/src/layouts/app-header.tsx +130 -0
- package/frontend/src/layouts/app-layout.tsx +19 -0
- package/frontend/src/layouts/app-sidebar.tsx +212 -0
- package/frontend/src/layouts/auth-guard.tsx +31 -0
- package/frontend/src/layouts/mobile-sidebar.tsx +120 -0
- package/frontend/src/lib/api.ts +68 -0
- package/frontend/src/lib/hooks/use-appointments.ts +224 -0
- package/frontend/src/lib/hooks/use-availability-blocks.ts +83 -0
- package/frontend/src/lib/hooks/use-chats.ts +236 -0
- package/frontend/src/lib/hooks/use-clinic-detail.ts +171 -0
- package/frontend/src/lib/hooks/use-clinics.ts +37 -0
- package/frontend/src/lib/hooks/use-doctor-calendar.ts +80 -0
- package/frontend/src/lib/hooks/use-examinations.ts +89 -0
- package/frontend/src/lib/hooks/use-medical-history.ts +52 -0
- package/frontend/src/lib/hooks/use-patients.ts +296 -0
- package/frontend/src/lib/hooks/use-photo-sets.ts +118 -0
- package/frontend/src/lib/hooks/use-treatment-plans.ts +152 -0
- package/frontend/src/lib/hooks/use-treatments.ts +125 -0
- package/frontend/src/lib/hooks/use-users.ts +172 -0
- package/frontend/src/lib/utils.ts +6 -0
- package/frontend/src/main.tsx +17 -0
- package/frontend/src/pages/admin/agents/detail.tsx +774 -0
- package/frontend/src/pages/admin/agents/import.tsx +280 -0
- package/frontend/src/pages/admin/agents/index.tsx +245 -0
- package/frontend/src/pages/admin/ai-playground.tsx +543 -0
- package/frontend/src/pages/appointments/create-appointment-dialog.tsx +390 -0
- package/frontend/src/pages/appointments/index.tsx +860 -0
- package/frontend/src/pages/audit/index.tsx +24 -0
- package/frontend/src/pages/auth/login.tsx +194 -0
- package/frontend/src/pages/billing/index.tsx +24 -0
- package/frontend/src/pages/calendar/index.tsx +704 -0
- package/frontend/src/pages/calendar-connections/index.tsx +295 -0
- package/frontend/src/pages/calls/index.tsx +24 -0
- package/frontend/src/pages/campaigns/index.tsx +24 -0
- package/frontend/src/pages/chats/index.tsx +981 -0
- package/frontend/src/pages/clinics/index.tsx +224 -0
- package/frontend/src/pages/clinics/settings.tsx +412 -0
- package/frontend/src/pages/components-showcase.tsx +773 -0
- package/frontend/src/pages/connections/index.tsx +328 -0
- package/frontend/src/pages/dashboard.tsx +50 -0
- package/frontend/src/pages/leads/index.tsx +24 -0
- package/frontend/src/pages/my-schedule/index.tsx +496 -0
- package/frontend/src/pages/patients/create-patient-dialog.tsx +358 -0
- package/frontend/src/pages/patients/detail.tsx +1195 -0
- package/frontend/src/pages/patients/edit-patient-dialog.tsx +387 -0
- package/frontend/src/pages/patients/examinations-tab.tsx +460 -0
- package/frontend/src/pages/patients/index.tsx +381 -0
- package/frontend/src/pages/patients/medical-history-dialog.tsx +207 -0
- package/frontend/src/pages/patients/photo-sets-tab.tsx +616 -0
- package/frontend/src/pages/patients/timeline-tab.tsx +164 -0
- package/frontend/src/pages/patients/treatment-plans-tab.tsx +598 -0
- package/frontend/src/pages/phone-numbers/detail.tsx +427 -0
- package/frontend/src/pages/phone-numbers/index.tsx +455 -0
- package/frontend/src/pages/platform/index.tsx +454 -0
- package/frontend/src/pages/settings/index.tsx +126 -0
- package/frontend/src/pages/treatments/index.tsx +487 -0
- package/frontend/src/pages/users/doctor-profile.tsx +672 -0
- package/frontend/src/pages/users/edit.tsx +329 -0
- package/frontend/src/pages/users/index.tsx +407 -0
- package/frontend/src/pages/validation/index.tsx +24 -0
- package/frontend/src/stores/auth.store.ts +108 -0
- package/frontend/src/stores/ui.store.ts +41 -0
- package/frontend/tsconfig.app.json +32 -0
- package/frontend/tsconfig.json +13 -0
- package/frontend/tsconfig.node.json +26 -0
- package/frontend/vite.config.ts +29 -0
- package/nestjs/.dockerignore +5 -0
- package/nestjs/.env.docker +64 -0
- package/nestjs/.prettierrc +4 -0
- package/nestjs/Dockerfile +36 -0
- package/nestjs/README.md +98 -0
- package/nestjs/eslint.config.mjs +35 -0
- package/nestjs/nest-cli.json +8 -0
- package/nestjs/package-lock.json +13390 -0
- package/nestjs/package.json +114 -0
- package/nestjs/prisma/migrations/20260409161536_add_message_metadata_fields/migration.sql +1746 -0
- package/nestjs/prisma/migrations/20260410140436_add_agent_ai_fields/migration.sql +36 -0
- package/nestjs/prisma/migrations/20260410175519_add_agent_clinic_assignments/migration.sql +21 -0
- package/nestjs/prisma/migrations/20260412094344_make_agent_tenant_optional/migration.sql +2 -0
- package/nestjs/prisma/migrations/20260412110008_add_admin_chat_sessions/migration.sql +47 -0
- package/nestjs/prisma/migrations/migration_lock.toml +3 -0
- package/nestjs/prisma/schema.prisma +1843 -0
- package/nestjs/prisma/seed.ts +375 -0
- package/nestjs/prisma.config.ts +14 -0
- package/nestjs/src/admin/admin.controller.ts +27 -0
- package/nestjs/src/admin/admin.module.ts +16 -0
- package/nestjs/src/admin/admin.service.ts +91 -0
- package/nestjs/src/admin/ai-chat-session.service.ts +454 -0
- package/nestjs/src/admin/ai-test.controller.ts +191 -0
- package/nestjs/src/admin/superadmin.controller.ts +106 -0
- package/nestjs/src/agents/agents.controller.ts +262 -0
- package/nestjs/src/agents/agents.module.ts +13 -0
- package/nestjs/src/agents/agents.service.ts +733 -0
- package/nestjs/src/agents/dto/create-agent.dto.ts +99 -0
- package/nestjs/src/agents/dto/index.ts +2 -0
- package/nestjs/src/agents/dto/update-agent.dto.ts +148 -0
- package/nestjs/src/app.module.ts +115 -0
- package/nestjs/src/appointment-validation/appointment-validation.controller.ts +194 -0
- package/nestjs/src/appointment-validation/appointment-validation.module.ts +16 -0
- package/nestjs/src/appointment-validation/appointment-validation.service.ts +450 -0
- package/nestjs/src/appointment-validation/dto/create-batch.dto.ts +105 -0
- package/nestjs/src/appointment-validation/dto/index.ts +1 -0
- package/nestjs/src/appointment-validation/processors/validation-dispatch.processor.ts +26 -0
- package/nestjs/src/appointment-validation/processors/validation-sync.processor.ts +23 -0
- package/nestjs/src/appointments/appointments.controller.ts +268 -0
- package/nestjs/src/appointments/appointments.module.ts +13 -0
- package/nestjs/src/appointments/appointments.service.ts +773 -0
- package/nestjs/src/appointments/dto/create-appointment.dto.ts +72 -0
- package/nestjs/src/appointments/dto/index.ts +4 -0
- package/nestjs/src/appointments/dto/query-appointments.dto.ts +60 -0
- package/nestjs/src/appointments/dto/update-appointment.dto.ts +43 -0
- package/nestjs/src/appointments/dto/update-status.dto.ts +18 -0
- package/nestjs/src/appointments/processors/reminder.processor.ts +243 -0
- package/nestjs/src/audit/audit.controller.ts +84 -0
- package/nestjs/src/audit/audit.decorator.ts +20 -0
- package/nestjs/src/audit/audit.interceptor.ts +67 -0
- package/nestjs/src/audit/audit.interfaces.ts +15 -0
- package/nestjs/src/audit/audit.module.ts +12 -0
- package/nestjs/src/audit/audit.service.ts +177 -0
- package/nestjs/src/auth/auth.controller.ts +116 -0
- package/nestjs/src/auth/auth.module.ts +25 -0
- package/nestjs/src/auth/auth.service.ts +612 -0
- package/nestjs/src/auth/dto/change-password.dto.ts +13 -0
- package/nestjs/src/auth/dto/forgot-password.dto.ts +8 -0
- package/nestjs/src/auth/dto/index.ts +6 -0
- package/nestjs/src/auth/dto/login.dto.ts +13 -0
- package/nestjs/src/auth/dto/refresh.dto.ts +8 -0
- package/nestjs/src/auth/dto/register.dto.ts +28 -0
- package/nestjs/src/auth/dto/reset-password.dto.ts +13 -0
- package/nestjs/src/auth/permissions.config.ts +85 -0
- package/nestjs/src/availability-blocks/availability-blocks.controller.ts +83 -0
- package/nestjs/src/availability-blocks/availability-blocks.module.ts +10 -0
- package/nestjs/src/availability-blocks/availability-blocks.service.ts +202 -0
- package/nestjs/src/billing/billing.controller.ts +104 -0
- package/nestjs/src/billing/billing.module.ts +12 -0
- package/nestjs/src/billing/billing.service.ts +398 -0
- package/nestjs/src/billing/dto/index.ts +2 -0
- package/nestjs/src/billing/dto/query-billing.dto.ts +29 -0
- package/nestjs/src/billing/dto/record-payment.dto.ts +60 -0
- package/nestjs/src/billing/processors/alerts.processor.ts +216 -0
- package/nestjs/src/billing/processors/snapshot.processor.ts +181 -0
- package/nestjs/src/calls/calls.controller.ts +92 -0
- package/nestjs/src/calls/calls.module.ts +10 -0
- package/nestjs/src/calls/calls.service.ts +359 -0
- package/nestjs/src/calls/dto/index.ts +1 -0
- package/nestjs/src/calls/dto/query-calls.dto.ts +46 -0
- package/nestjs/src/clinics/clinics.controller.ts +226 -0
- package/nestjs/src/clinics/clinics.module.ts +11 -0
- package/nestjs/src/clinics/clinics.service.ts +203 -0
- package/nestjs/src/clinics/dto/create-clinic.dto.ts +40 -0
- package/nestjs/src/clinics/dto/create-meta-connection.dto.ts +44 -0
- package/nestjs/src/clinics/dto/index.ts +4 -0
- package/nestjs/src/clinics/dto/update-clinic.dto.ts +133 -0
- package/nestjs/src/clinics/dto/update-meta-connection.dto.ts +22 -0
- package/nestjs/src/clinics/meta-connections.service.ts +210 -0
- package/nestjs/src/common/decorators/accessible-clinics.decorator.ts +9 -0
- package/nestjs/src/common/decorators/current-user.decorator.ts +10 -0
- package/nestjs/src/common/decorators/features.decorator.ts +7 -0
- package/nestjs/src/common/decorators/index.ts +4 -0
- package/nestjs/src/common/decorators/permissions.decorator.ts +13 -0
- package/nestjs/src/common/gateways/events.gateway.ts +157 -0
- package/nestjs/src/common/guards/clinic-access.guard.ts +40 -0
- package/nestjs/src/common/guards/features.guard.ts +38 -0
- package/nestjs/src/common/guards/index.ts +5 -0
- package/nestjs/src/common/guards/jwt-auth.guard.ts +54 -0
- package/nestjs/src/common/guards/permissions.guard.ts +50 -0
- package/nestjs/src/common/guards/superadmin.guard.ts +35 -0
- package/nestjs/src/common/interceptors/request-context.interceptor.ts +32 -0
- package/nestjs/src/common/interceptors/superadmin-tenant.interceptor.ts +42 -0
- package/nestjs/src/common/interfaces/jwt-payload.interface.ts +11 -0
- package/nestjs/src/config/config.module.ts +13 -0
- package/nestjs/src/database/database.module.ts +9 -0
- package/nestjs/src/database/prisma.service.ts +20 -0
- package/nestjs/src/database/tenant-context.ts +27 -0
- package/nestjs/src/google-calendar/google-calendar.controller.ts +259 -0
- package/nestjs/src/google-calendar/google-calendar.module.ts +10 -0
- package/nestjs/src/google-calendar/google-calendar.service.ts +811 -0
- package/nestjs/src/integrations/ai/ai.interface.ts +74 -0
- package/nestjs/src/integrations/ai/ai.module.ts +11 -0
- package/nestjs/src/integrations/ai/ai.service.ts +148 -0
- package/nestjs/src/integrations/ai/providers/anthropic.provider.ts +146 -0
- package/nestjs/src/integrations/ai/providers/openai.provider.ts +158 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.module.ts +8 -0
- package/nestjs/src/integrations/elevenlabs/elevenlabs.service.ts +226 -0
- package/nestjs/src/integrations/encryption/encryption.module.ts +9 -0
- package/nestjs/src/integrations/encryption/encryption.service.ts +31 -0
- package/nestjs/src/integrations/image/image.module.ts +9 -0
- package/nestjs/src/integrations/image/image.service.ts +61 -0
- package/nestjs/src/integrations/meta-business/meta-business.module.ts +10 -0
- package/nestjs/src/integrations/meta-business/meta-instagram.service.ts +94 -0
- package/nestjs/src/integrations/meta-business/meta-webhook.service.ts +52 -0
- package/nestjs/src/integrations/meta-business/meta-whatsapp.service.ts +254 -0
- package/nestjs/src/integrations/minio/minio.module.ts +9 -0
- package/nestjs/src/integrations/minio/minio.service.ts +88 -0
- package/nestjs/src/integrations/netgsm/netgsm.module.ts +8 -0
- package/nestjs/src/integrations/netgsm/netgsm.service.ts +17 -0
- package/nestjs/src/integrations/tektippay/tektippay.module.ts +8 -0
- package/nestjs/src/integrations/tektippay/tektippay.service.ts +23 -0
- package/nestjs/src/leads/dto/index.ts +2 -0
- package/nestjs/src/leads/dto/query-leads.dto.ts +50 -0
- package/nestjs/src/leads/dto/update-lead.dto.ts +26 -0
- package/nestjs/src/leads/leads.controller.ts +184 -0
- package/nestjs/src/leads/leads.module.ts +10 -0
- package/nestjs/src/leads/leads.service.ts +375 -0
- package/nestjs/src/logging/logging.controller.ts +82 -0
- package/nestjs/src/logging/logging.module.ts +11 -0
- package/nestjs/src/logging/logging.service.ts +180 -0
- package/nestjs/src/main.ts +86 -0
- package/nestjs/src/outbound-campaigns/dto/create-campaign.dto.ts +47 -0
- package/nestjs/src/outbound-campaigns/dto/index.ts +3 -0
- package/nestjs/src/outbound-campaigns/dto/update-campaign.dto.ts +31 -0
- package/nestjs/src/outbound-campaigns/dto/upload-entries.dto.ts +35 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.controller.ts +307 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.module.ts +13 -0
- package/nestjs/src/outbound-campaigns/outbound-campaigns.service.ts +471 -0
- package/nestjs/src/outbound-campaigns/processors/campaign-dispatch.processor.ts +366 -0
- package/nestjs/src/patients/documents.service.ts +231 -0
- package/nestjs/src/patients/dto/create-examination.dto.ts +34 -0
- package/nestjs/src/patients/dto/create-note.dto.ts +14 -0
- package/nestjs/src/patients/dto/create-patient.dto.ts +86 -0
- package/nestjs/src/patients/dto/create-photo-set.dto.ts +32 -0
- package/nestjs/src/patients/dto/index.ts +10 -0
- package/nestjs/src/patients/dto/update-examination.dto.ts +29 -0
- package/nestjs/src/patients/dto/update-medical-history.dto.ts +47 -0
- package/nestjs/src/patients/dto/update-patient.dto.ts +87 -0
- package/nestjs/src/patients/dto/update-photo-set.dto.ts +28 -0
- package/nestjs/src/patients/dto/upload-document.dto.ts +31 -0
- package/nestjs/src/patients/dto/upload-photo.dto.ts +27 -0
- package/nestjs/src/patients/examinations.service.ts +271 -0
- package/nestjs/src/patients/medical-history.service.ts +149 -0
- package/nestjs/src/patients/notes.service.ts +172 -0
- package/nestjs/src/patients/patients.controller.ts +485 -0
- package/nestjs/src/patients/patients.module.ts +22 -0
- package/nestjs/src/patients/patients.service.ts +412 -0
- package/nestjs/src/patients/photo-sets.service.ts +389 -0
- package/nestjs/src/phone-numbers/dto/create-phone-number.dto.ts +57 -0
- package/nestjs/src/phone-numbers/dto/index.ts +3 -0
- package/nestjs/src/phone-numbers/dto/update-phone-number.dto.ts +38 -0
- package/nestjs/src/phone-numbers/dto/update-schedule.dto.ts +39 -0
- package/nestjs/src/phone-numbers/phone-numbers.controller.ts +125 -0
- package/nestjs/src/phone-numbers/phone-numbers.module.ts +10 -0
- package/nestjs/src/phone-numbers/phone-numbers.service.ts +209 -0
- package/nestjs/src/plans/dto/create-plan.dto.ts +70 -0
- package/nestjs/src/plans/dto/index.ts +2 -0
- package/nestjs/src/plans/dto/update-plan.dto.ts +80 -0
- package/nestjs/src/plans/plans.controller.ts +50 -0
- package/nestjs/src/plans/plans.module.ts +10 -0
- package/nestjs/src/plans/plans.service.ts +115 -0
- package/nestjs/src/platform/dto/create-tenant.dto.ts +36 -0
- package/nestjs/src/platform/dto/index.ts +2 -0
- package/nestjs/src/platform/dto/update-tenant-platform.dto.ts +44 -0
- package/nestjs/src/platform/platform.controller.ts +79 -0
- package/nestjs/src/platform/platform.module.ts +10 -0
- package/nestjs/src/platform/platform.service.ts +301 -0
- package/nestjs/src/queue/queue.module.ts +56 -0
- package/nestjs/src/redis/redis.module.ts +20 -0
- package/nestjs/src/tenants/dto/index.ts +1 -0
- package/nestjs/src/tenants/dto/update-tenant.dto.ts +15 -0
- package/nestjs/src/tenants/tenants.controller.ts +45 -0
- package/nestjs/src/tenants/tenants.module.ts +10 -0
- package/nestjs/src/tenants/tenants.service.ts +41 -0
- package/nestjs/src/tools/adapters/elevenlabs-http.adapter.ts +51 -0
- package/nestjs/src/tools/adapters/elevenlabs-ws.adapter.ts +59 -0
- package/nestjs/src/tools/handlers/calendar.tools.ts +441 -0
- package/nestjs/src/tools/handlers/notification.tools.ts +34 -0
- package/nestjs/src/tools/handlers/operator.tools.ts +303 -0
- package/nestjs/src/tools/handlers/patient.tools.ts +242 -0
- package/nestjs/src/tools/handlers/payment.tools.ts +43 -0
- package/nestjs/src/tools/handlers/validation.tools.ts +152 -0
- package/nestjs/src/tools/tool-registry.service.ts +221 -0
- package/nestjs/src/tools/tool.decorator.ts +16 -0
- package/nestjs/src/tools/tool.interfaces.ts +26 -0
- package/nestjs/src/tools/tools.module.ts +50 -0
- package/nestjs/src/treatments/dto/create-plan-item.dto.ts +27 -0
- package/nestjs/src/treatments/dto/create-treatment-plan.dto.ts +69 -0
- package/nestjs/src/treatments/dto/create-treatment.dto.ts +59 -0
- package/nestjs/src/treatments/dto/index.ts +6 -0
- package/nestjs/src/treatments/dto/update-plan-item.dto.ts +23 -0
- package/nestjs/src/treatments/dto/update-treatment-plan.dto.ts +22 -0
- package/nestjs/src/treatments/dto/update-treatment.dto.ts +70 -0
- package/nestjs/src/treatments/treatment-plans.service.ts +362 -0
- package/nestjs/src/treatments/treatments.controller.ts +265 -0
- package/nestjs/src/treatments/treatments.module.ts +14 -0
- package/nestjs/src/treatments/treatments.service.ts +165 -0
- package/nestjs/src/users/doctor-profiles.service.ts +202 -0
- package/nestjs/src/users/dto/index.ts +4 -0
- package/nestjs/src/users/dto/invite-user.dto.ts +52 -0
- package/nestjs/src/users/dto/update-clinic-assignments.dto.ts +9 -0
- package/nestjs/src/users/dto/update-doctor-profile.dto.ts +49 -0
- package/nestjs/src/users/dto/update-user.dto.ts +41 -0
- package/nestjs/src/users/users.controller.ts +142 -0
- package/nestjs/src/users/users.module.ts +11 -0
- package/nestjs/src/users/users.service.ts +250 -0
- package/nestjs/src/webhooks/elevenlabs-tool.controller.ts +66 -0
- package/nestjs/src/webhooks/elevenlabs-webhook.controller.ts +60 -0
- package/nestjs/src/webhooks/meta-webhook.controller.ts +178 -0
- package/nestjs/src/webhooks/processors/elevenlabs-webhook.processor.ts +28 -0
- package/nestjs/src/webhooks/webhooks.module.ts +17 -0
- package/nestjs/src/whatsapp/chat-context.service.ts +281 -0
- package/nestjs/src/whatsapp/dto/add-blacklist.dto.ts +13 -0
- package/nestjs/src/whatsapp/dto/index.ts +2 -0
- package/nestjs/src/whatsapp/dto/send-message.dto.ts +14 -0
- package/nestjs/src/whatsapp/listeners/meta-message.listener.ts +579 -0
- package/nestjs/src/whatsapp/meta-auth.controller.ts +268 -0
- package/nestjs/src/whatsapp/meta-instagram-auth.controller.ts +244 -0
- package/nestjs/src/whatsapp/operator.service.ts +692 -0
- package/nestjs/src/whatsapp/processors/cost-sweep.processor.ts +130 -0
- package/nestjs/src/whatsapp/processors/grace.processor.ts +191 -0
- package/nestjs/src/whatsapp/processors/message-buffer.processor.ts +138 -0
- package/nestjs/src/whatsapp/processors/message-cleanup.processor.ts +148 -0
- package/nestjs/src/whatsapp/processors/meta-token-refresh.processor.ts +114 -0
- package/nestjs/src/whatsapp/processors/operator-expiry.processor.ts +105 -0
- package/nestjs/src/whatsapp/processors/profile-update.processor.ts +234 -0
- package/nestjs/src/whatsapp/processors/session-cleanup.processor.ts +178 -0
- package/nestjs/src/whatsapp/processors/session-labels.processor.ts +248 -0
- package/nestjs/src/whatsapp/whatsapp-agent.service.ts +2506 -0
- package/nestjs/src/whatsapp/whatsapp-recovery.service.ts +117 -0
- package/nestjs/src/whatsapp/whatsapp.controller.ts +398 -0
- package/nestjs/src/whatsapp/whatsapp.module.ts +51 -0
- package/nestjs/src/whatsapp/whatsapp.service.ts +592 -0
- package/nestjs/test/app.e2e-spec.ts +25 -0
- package/nestjs/test/jest-e2e.json +9 -0
- package/nestjs/tsconfig.build.json +4 -0
- package/nestjs/tsconfig.json +25 -0
- package/nginx.example.conf +18 -0
- package/package.json +47 -0
- package/scripts/addRecipient.ts +48 -0
- package/scripts/listRecipients.ts +31 -0
- package/scripts/migrate-agent-ref.ts +86 -0
- package/scripts/migrate-sessions.ts +183 -0
- package/scripts/promote.ts +27 -0
- package/scripts/retrigger.ts +84 -0
- package/scripts/seed.ts +435 -0
- package/scripts/testSend.ts +63 -0
- package/src/app.ts +85 -0
- package/src/config/agentPrompts.json +19 -0
- package/src/config/database.ts +21 -0
- package/src/config/env.ts +94 -0
- package/src/config/index.ts +86 -0
- package/src/controllers/webhook.controller.ts +150 -0
- package/src/errors/index.ts +9 -0
- package/src/hooks/webhookValidator.ts +55 -0
- package/src/index.ts +68 -0
- package/src/migrations/001_session-architecture.ts +138 -0
- package/src/migrations/002_agent-ref.ts +65 -0
- package/src/migrations/003_shift-schedule.ts +55 -0
- package/src/migrations/004_invert-shift-to-clinic-hours.ts +30 -0
- package/src/migrations/005_composite-baileys-chat-ids.ts +60 -0
- package/src/migrations/migration.model.ts +27 -0
- package/src/migrations/migration.routes.ts +40 -0
- package/src/migrations/migration.runner.ts +112 -0
- package/src/models/ConversationClaim.ts +17 -0
- package/src/models/ConversationEvaluation.ts +91 -0
- package/src/models/Summary.ts +77 -0
- package/src/models/Transcription.ts +68 -0
- package/src/models/WhatsAppRecipient.ts +37 -0
- package/src/modules/admin/admin.routes.ts +2385 -0
- package/src/modules/admin/elevenlabs-test-chat.routes.ts +193 -0
- package/src/modules/admin/whatsapp-test-chat.routes.ts +244 -0
- package/src/modules/agents/agent.model.ts +93 -0
- package/src/modules/agents/agent.routes.ts +65 -0
- package/src/modules/appointment-validation/appointment-validation.model.ts +163 -0
- package/src/modules/appointment-validation/appointment-validation.routes.ts +275 -0
- package/src/modules/appointment-validation/appointment-validation.service.ts +1028 -0
- package/src/modules/auth/auth.model.ts +42 -0
- package/src/modules/auth/auth.routes.ts +199 -0
- package/src/modules/auth/auth.service.ts +210 -0
- package/src/modules/auth/refresh-token.model.ts +26 -0
- package/src/modules/billing/billing-alert.model.ts +28 -0
- package/src/modules/billing/billing-period-snapshot.model.ts +68 -0
- package/src/modules/billing/billing.model.ts +42 -0
- package/src/modules/billing/billing.routes.ts +67 -0
- package/src/modules/billing/billing.service.ts +562 -0
- package/src/modules/billing/payment.model.ts +42 -0
- package/src/modules/calls/call.model.ts +102 -0
- package/src/modules/calls/call.routes.ts +118 -0
- package/src/modules/campaigns/campaign.model.ts +111 -0
- package/src/modules/campaigns/campaign.routes.ts +402 -0
- package/src/modules/campaigns/campaign.service.ts +99 -0
- package/src/modules/google-calendar/google-calendar.routes.ts +31 -0
- package/src/modules/inbound-call/inbound-call-config.model.ts +49 -0
- package/src/modules/inbound-call/inbound-call.routes.ts +289 -0
- package/src/modules/leads/lead.model.ts +40 -0
- package/src/modules/leads/lead.routes.ts +246 -0
- package/src/modules/logs/log.model.ts +27 -0
- package/src/modules/logs/log.routes.ts +102 -0
- package/src/modules/plans/plan.model.ts +45 -0
- package/src/modules/surveys/survey.model.ts +70 -0
- package/src/modules/surveys/survey.routes.ts +187 -0
- package/src/modules/tenants/tenant.model.ts +181 -0
- package/src/modules/tenants/tenant.routes.ts +78 -0
- package/src/modules/users/user.routes.ts +126 -0
- package/src/modules/webhooks/elevenlabs-tool.routes.ts +94 -0
- package/src/modules/webhooks/elevenlabs-tool.service.ts +491 -0
- package/src/modules/webhooks/elevenlabs.routes.ts +34 -0
- package/src/modules/webhooks/elevenlabs.service.ts +565 -0
- package/src/modules/webhooks/unipile.routes.ts +917 -0
- package/src/modules/whatsapp/appointment.model.ts +47 -0
- package/src/modules/whatsapp/operator-request.model.ts +58 -0
- package/src/modules/whatsapp/stt-usage.model.ts +30 -0
- package/src/modules/whatsapp/whatsapp-chat.model.ts +39 -0
- package/src/modules/whatsapp/whatsapp-contact-profile.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-message.model.ts +41 -0
- package/src/modules/whatsapp/whatsapp-session.model.ts +60 -0
- package/src/modules/whatsapp/whatsapp.routes.ts +1435 -0
- package/src/plugins/cors.ts +7 -0
- package/src/plugins/jwt.ts +18 -0
- package/src/plugins/rawBody.ts +12 -0
- package/src/plugins/rbac.ts +24 -0
- package/src/routes/admin.routes.ts +208 -0
- package/src/routes/health.routes.ts +12 -0
- package/src/routes/webhook.routes.ts +12 -0
- package/src/services/ai/base.ai.ts +132 -0
- package/src/services/ai/gemini.service.ts +41 -0
- package/src/services/ai/index.ts +24 -0
- package/src/services/ai/openai.service.ts +48 -0
- package/src/services/elevenlabs.service.ts +532 -0
- package/src/services/google-calendar.service.ts +656 -0
- package/src/services/inbound-call-schedule.service.ts +174 -0
- package/src/services/netgsm.service.ts +128 -0
- package/src/services/unipile.service.ts +200 -0
- package/src/services/whatsapp-agent.service.ts +2479 -0
- package/src/services/whatsapp.service.ts +245 -0
- package/src/templates/index.ts +71 -0
- package/src/templates/receptionist.ts +44 -0
- package/src/templates/survey.ts +44 -0
- package/src/types/index.ts +218 -0
- package/src/utils/logger.ts +83 -0
- package/tsconfig.json +19 -0
- package/web/.dockerignore +4 -0
- package/web/Dockerfile +18 -0
- package/web/README.md +73 -0
- package/web/components.json +23 -0
- package/web/eslint.config.js +23 -0
- package/web/index.html +14 -0
- package/web/nginx.conf +18 -0
- package/web/package-lock.json +10292 -0
- package/web/package.json +48 -0
- package/web/public/favicon.ico +0 -0
- package/web/public/vite.svg +1 -0
- package/web/src/App.tsx +191 -0
- package/web/src/assets/react.svg +1 -0
- package/web/src/components/Layout.tsx +261 -0
- package/web/src/components/LeadConversation.tsx +251 -0
- package/web/src/components/ProtectedRoute.tsx +20 -0
- package/web/src/components/conversation-review/CardAudioPlayer.tsx +200 -0
- package/web/src/components/conversation-review/CardEvaluation.tsx +351 -0
- package/web/src/components/conversation-review/CardMetadata.tsx +44 -0
- package/web/src/components/conversation-review/ConversationCard.tsx +95 -0
- package/web/src/components/conversation-review/ReviewContainer.tsx +120 -0
- package/web/src/components/conversation-review/ReviewFilters.tsx +88 -0
- package/web/src/components/empty-state.tsx +15 -0
- package/web/src/components/page-header.tsx +19 -0
- package/web/src/components/page-loader.tsx +32 -0
- package/web/src/components/pagination.tsx +38 -0
- package/web/src/components/stat-card.tsx +27 -0
- package/web/src/components/status-badge.tsx +125 -0
- package/web/src/components/ui/alert.tsx +66 -0
- package/web/src/components/ui/badge.tsx +48 -0
- package/web/src/components/ui/button.tsx +64 -0
- package/web/src/components/ui/card.tsx +92 -0
- package/web/src/components/ui/checkbox.tsx +32 -0
- package/web/src/components/ui/dialog.tsx +158 -0
- package/web/src/components/ui/dropdown-menu.tsx +255 -0
- package/web/src/components/ui/input.tsx +21 -0
- package/web/src/components/ui/label.tsx +22 -0
- package/web/src/components/ui/progress.tsx +29 -0
- package/web/src/components/ui/select.tsx +188 -0
- package/web/src/components/ui/separator.tsx +28 -0
- package/web/src/components/ui/sheet.tsx +123 -0
- package/web/src/components/ui/skeleton.tsx +13 -0
- package/web/src/components/ui/sonner.tsx +35 -0
- package/web/src/components/ui/table.tsx +116 -0
- package/web/src/components/ui/tabs.tsx +89 -0
- package/web/src/components/ui/textarea.tsx +18 -0
- package/web/src/components/ui/tooltip.tsx +57 -0
- package/web/src/components/whatsapp/ChatDetail.tsx +417 -0
- package/web/src/components/whatsapp/ChatHeader.tsx +78 -0
- package/web/src/components/whatsapp/ChatList.tsx +107 -0
- package/web/src/components/whatsapp/ChatListItem.tsx +60 -0
- package/web/src/components/whatsapp/MessageBubble.tsx +46 -0
- package/web/src/components/whatsapp/MessageInput.tsx +63 -0
- package/web/src/components/whatsapp/MessageStream.tsx +135 -0
- package/web/src/components/whatsapp/SessionDivider.tsx +65 -0
- package/web/src/components/whatsapp/SessionHistory.tsx +119 -0
- package/web/src/components/whatsapp/settings/AiSettingsTab.tsx +268 -0
- package/web/src/components/whatsapp/settings/CalendarTab.tsx +339 -0
- package/web/src/components/whatsapp/settings/ConnectionTab.tsx +236 -0
- package/web/src/components/whatsapp/settings/NotificationsTab.tsx +109 -0
- package/web/src/components/whatsapp/settings/OperatorTab.tsx +303 -0
- package/web/src/contexts/AuthContext.tsx +103 -0
- package/web/src/index.css +130 -0
- package/web/src/lib/api.ts +92 -0
- package/web/src/lib/utils.ts +6 -0
- package/web/src/main.tsx +10 -0
- package/web/src/pages/AppointmentDetail.tsx +206 -0
- package/web/src/pages/AppointmentValidation.tsx +157 -0
- package/web/src/pages/AppointmentValidationDetail.tsx +617 -0
- package/web/src/pages/AppointmentValidationNew.tsx +1005 -0
- package/web/src/pages/Appointments.tsx +283 -0
- package/web/src/pages/Billing.tsx +126 -0
- package/web/src/pages/CallDetail.tsx +293 -0
- package/web/src/pages/CallSettings.tsx +313 -0
- package/web/src/pages/Calls.tsx +188 -0
- package/web/src/pages/CampaignDetail.tsx +216 -0
- package/web/src/pages/CampaignNew.tsx +277 -0
- package/web/src/pages/CampaignResults.tsx +185 -0
- package/web/src/pages/Campaigns.tsx +171 -0
- package/web/src/pages/Dashboard.tsx +336 -0
- package/web/src/pages/InboundSchedule.tsx +246 -0
- package/web/src/pages/LeadDetail.tsx +183 -0
- package/web/src/pages/Leads.tsx +258 -0
- package/web/src/pages/Login.tsx +99 -0
- package/web/src/pages/Register.tsx +129 -0
- package/web/src/pages/Settings.tsx +133 -0
- package/web/src/pages/SurveyDetail.tsx +232 -0
- package/web/src/pages/SurveyPreview.tsx +179 -0
- package/web/src/pages/Surveys.tsx +207 -0
- package/web/src/pages/Users.tsx +199 -0
- package/web/src/pages/WhatsApp.tsx +147 -0
- package/web/src/pages/WhatsAppSettings.tsx +215 -0
- package/web/src/pages/admin/AdminBaileysMessageLog.tsx +331 -0
- package/web/src/pages/admin/AdminBaileysRawMessages.tsx +318 -0
- package/web/src/pages/admin/AdminConversationReview.tsx +116 -0
- package/web/src/pages/admin/AdminCredits.tsx +467 -0
- package/web/src/pages/admin/AdminElevenLabsAgentDetail.tsx +332 -0
- package/web/src/pages/admin/AdminElevenLabsAgents.tsx +164 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCallDetail.tsx +214 -0
- package/web/src/pages/admin/AdminElevenLabsBatchCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsConversationDetail.tsx +230 -0
- package/web/src/pages/admin/AdminElevenLabsConversations.tsx +228 -0
- package/web/src/pages/admin/AdminElevenLabsInboundCalls.tsx +293 -0
- package/web/src/pages/admin/AdminElevenLabsPhoneNumbers.tsx +506 -0
- package/web/src/pages/admin/AdminElevenLabsTestChat.tsx +258 -0
- package/web/src/pages/admin/AdminElevenLabsWebhooks.tsx +289 -0
- package/web/src/pages/admin/AdminEvaluationDashboard.tsx +520 -0
- package/web/src/pages/admin/AdminLeads.tsx +339 -0
- package/web/src/pages/admin/AdminLogs.tsx +283 -0
- package/web/src/pages/admin/AdminMigrations.tsx +247 -0
- package/web/src/pages/admin/AdminPlans.tsx +313 -0
- package/web/src/pages/admin/AdminSystem.tsx +391 -0
- package/web/src/pages/admin/AdminTenantBillableItems.tsx +464 -0
- package/web/src/pages/admin/AdminTenantDetail.tsx +1317 -0
- package/web/src/pages/admin/AdminTenants.tsx +274 -0
- package/web/src/pages/admin/AdminWhatsApp.tsx +618 -0
- package/web/src/pages/admin/AdminWhatsAppTestChat.tsx +328 -0
- package/web/src/types/index.ts +242 -0
- package/web/tsconfig.app.json +32 -0
- package/web/tsconfig.json +13 -0
- package/web/tsconfig.node.json +26 -0
- package/web/vite.config.ts +23 -0
|
@@ -0,0 +1,1038 @@
|
|
|
1
|
+
# VoiceAI SaaS Platform — Development Roadmap
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
A SaaS platform offering AI-powered voice agents over real phone lines (PSTN/GSM). Tenants enable features based on their needs — any tenant can use any combination of capabilities:
|
|
6
|
+
|
|
7
|
+
* **Inbound Agent:** AI receptionist — answers calls, handles FAQs, books appointments, sends WhatsApp summaries.
|
|
8
|
+
* **Outbound Campaigns:** AI caller — dials number lists, conducts surveys with branching logic, extracts structured responses, provides analytics.
|
|
9
|
+
|
|
10
|
+
The platform is **feature-driven, not customer-type-driven.** A clinic can enable outbound appointment reminders. A survey company can enable an inbound support line. New use cases (debt collection, appointment reminders, lead qualification) are added as agent templates without architectural changes.
|
|
11
|
+
|
|
12
|
+
## Tech Stack
|
|
13
|
+
|
|
14
|
+
| Layer | Technology |
|
|
15
|
+
| ------------- | ----------------------------------- |
|
|
16
|
+
| Frontend | React + Vite + TypeScript |
|
|
17
|
+
| Backend | Node.js + Fastify + TypeScript |
|
|
18
|
+
| Database | MongoDB (Atlas) + Mongoose |
|
|
19
|
+
| Auth | @fastify/jwt + bcrypt (custom RBAC) |
|
|
20
|
+
| Job Queue | BullMQ + Redis |
|
|
21
|
+
| Cache | Redis |
|
|
22
|
+
| Voice Engine | ElevenLabs Conversational AI |
|
|
23
|
+
| Telephony | Asterisk + NetGSM SIP Trunk |
|
|
24
|
+
| Notifications | Twilio (WhatsApp) |
|
|
25
|
+
| Post-Call LLM | OpenAI / Google Gemini |
|
|
26
|
+
| Payments | Param |
|
|
27
|
+
|
|
28
|
+
## Existing Infrastructure (Already Working)
|
|
29
|
+
|
|
30
|
+
* [X] NetGSM ↔ Asterisk ↔ ElevenLabs voice pipeline
|
|
31
|
+
* [X] ElevenLabs post-call webhook → LLM summarization → Twilio WhatsApp notification
|
|
32
|
+
* [X] Basic Express backend with Mongoose, OpenAI, Gemini, Twilio SDKs
|
|
33
|
+
* [X] Pricing model defined
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Architecture Principles
|
|
38
|
+
|
|
39
|
+
### Feature-Driven Tenancy
|
|
40
|
+
|
|
41
|
+
Tenants have **no type field** . Instead, each tenant has an `enabled_features` array that controls what they can access. Features are gated at the route level via middleware.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Available features:
|
|
45
|
+
- inbound_agent → receive and handle incoming calls
|
|
46
|
+
- outbound_campaigns → create campaigns and dial number lists
|
|
47
|
+
- survey_builder → create and manage surveys
|
|
48
|
+
- whatsapp_notifications → post-call WhatsApp summaries
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Agent Templates
|
|
52
|
+
|
|
53
|
+
Agent behavior is defined by **templates** , not tenant type. Each template has its own config schema and prompt builder. Adding a new use case = adding a new template.
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Current templates:
|
|
57
|
+
- receptionist → inbound call handling, FAQs, appointment booking
|
|
58
|
+
- survey → outbound survey conducting with structured Q&A
|
|
59
|
+
- custom → tenant provides their own prompt (future/advanced)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Post-Call Processing Strategies
|
|
63
|
+
|
|
64
|
+
Each agent defines its own post-call processing strategy, independent of tenant type:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Strategies:
|
|
68
|
+
- summarize → LLM summarizes the call (clinic use case)
|
|
69
|
+
- extract_survey → LLM extracts structured survey answers
|
|
70
|
+
- summarize_and_extract → both (future)
|
|
71
|
+
- none → no post-processing
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Project Structure
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
src/
|
|
80
|
+
├── app.ts # Fastify instance + plugin registration
|
|
81
|
+
├── server.ts # Entry point
|
|
82
|
+
├── config/
|
|
83
|
+
│ └── env.ts # Typed environment variables
|
|
84
|
+
├── plugins/
|
|
85
|
+
│ ├── auth.ts # JWT verification + RBAC middleware
|
|
86
|
+
│ ├── features.ts # Feature-gating middleware (requireFeature)
|
|
87
|
+
│ ├── mongo.ts # Mongoose connection
|
|
88
|
+
│ └── redis.ts # Redis + BullMQ setup
|
|
89
|
+
├── modules/
|
|
90
|
+
│ ├── auth/
|
|
91
|
+
│ │ ├── auth.model.ts # User model (email, password_hash, tenant_id, role)
|
|
92
|
+
│ │ ├── auth.routes.ts # POST /auth/login, /auth/register, /auth/refresh
|
|
93
|
+
│ │ └── auth.service.ts # JWT generation, password hashing, validation
|
|
94
|
+
│ ├── tenants/
|
|
95
|
+
│ │ ├── tenant.model.ts
|
|
96
|
+
│ │ ├── tenant.routes.ts
|
|
97
|
+
│ │ └── tenant.service.ts
|
|
98
|
+
│ ├── agents/
|
|
99
|
+
│ │ ├── agent.model.ts
|
|
100
|
+
│ │ ├── agent.routes.ts
|
|
101
|
+
│ │ └── agent.service.ts
|
|
102
|
+
│ ├── calls/
|
|
103
|
+
│ │ ├── call.model.ts
|
|
104
|
+
│ │ ├── call.routes.ts
|
|
105
|
+
│ │ └── call.service.ts
|
|
106
|
+
│ ├── surveys/
|
|
107
|
+
│ │ ├── survey.model.ts
|
|
108
|
+
│ │ ├── survey.routes.ts
|
|
109
|
+
│ │ └── survey.service.ts
|
|
110
|
+
│ ├── campaigns/
|
|
111
|
+
│ │ ├── campaign.model.ts
|
|
112
|
+
│ │ ├── campaign.routes.ts
|
|
113
|
+
│ │ ├── campaign.service.ts
|
|
114
|
+
│ │ └── campaign.worker.ts # BullMQ worker for dialer logic
|
|
115
|
+
│ ├── billing/
|
|
116
|
+
│ │ ├── billing.model.ts
|
|
117
|
+
│ │ ├── billing.routes.ts
|
|
118
|
+
│ │ └── billing.service.ts # Param integration
|
|
119
|
+
│ └── webhooks/
|
|
120
|
+
│ ├── elevenlabs.routes.ts
|
|
121
|
+
│ └── elevenlabs.service.ts # Post-call processing pipeline
|
|
122
|
+
├── templates/
|
|
123
|
+
│ ├── index.ts # Template registry — maps template name → builder
|
|
124
|
+
│ ├── receptionist.ts # Prompt builder + config schema for receptionist
|
|
125
|
+
│ └── survey.ts # Prompt builder + config schema for survey agent
|
|
126
|
+
├── utils/
|
|
127
|
+
│ ├── llm.ts # OpenAI/Gemini wrapper for post-call processing
|
|
128
|
+
│ ├── twilio.ts # WhatsApp notification helper
|
|
129
|
+
│ ├── prompt-builder.ts # Dispatches to correct template builder
|
|
130
|
+
│ └── logger.ts # Winston logger
|
|
131
|
+
└── types/
|
|
132
|
+
└── index.ts # Shared TypeScript interfaces
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Database Collections (MongoDB)
|
|
138
|
+
|
|
139
|
+
### tenants
|
|
140
|
+
|
|
141
|
+
No type field. Features control what the tenant can access.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
{
|
|
145
|
+
_id: ObjectId,
|
|
146
|
+
name: string,
|
|
147
|
+
plan: string,
|
|
148
|
+
enabled_features: string[], // ["inbound_agent", "whatsapp_notifications"]
|
|
149
|
+
settings: {
|
|
150
|
+
kvkk_consent: boolean,
|
|
151
|
+
notification_recipients: string[], // phone numbers for WhatsApp
|
|
152
|
+
default_language: string, // "tr", "en"
|
|
153
|
+
},
|
|
154
|
+
created_at: Date,
|
|
155
|
+
updated_at: Date
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### users
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
{
|
|
163
|
+
_id: ObjectId,
|
|
164
|
+
tenant_id: ObjectId, // ref → tenants
|
|
165
|
+
email: string,
|
|
166
|
+
password_hash: string,
|
|
167
|
+
role: "admin" | "manager" | "viewer",
|
|
168
|
+
name: string,
|
|
169
|
+
created_at: Date
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### agents
|
|
174
|
+
|
|
175
|
+
Agent carries all behavior. Template defines config schema and prompt generation.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
{
|
|
179
|
+
_id: ObjectId,
|
|
180
|
+
tenant_id: ObjectId, // ref → tenants
|
|
181
|
+
phone_number: string, // NetGSM number assigned
|
|
182
|
+
elevenlabs_agent_id: string,
|
|
183
|
+
direction: "inbound" | "outbound" | "both",
|
|
184
|
+
agent_template: string, // "receptionist" | "survey" | "custom"
|
|
185
|
+
|
|
186
|
+
config: {
|
|
187
|
+
// Common fields (all templates)
|
|
188
|
+
voice_id: string,
|
|
189
|
+
language: string,
|
|
190
|
+
greeting: string,
|
|
191
|
+
|
|
192
|
+
// Template-specific fields (flexible schema per template)
|
|
193
|
+
template_data: object
|
|
194
|
+
// For "receptionist":
|
|
195
|
+
// {
|
|
196
|
+
// business_name: string,
|
|
197
|
+
// business_hours: { day: string, open: string, close: string }[],
|
|
198
|
+
// transfer_number: string,
|
|
199
|
+
// faq_entries: { question: string, answer: string }[],
|
|
200
|
+
// services: string[]
|
|
201
|
+
// }
|
|
202
|
+
//
|
|
203
|
+
// For "survey":
|
|
204
|
+
// {
|
|
205
|
+
// intro_script: string,
|
|
206
|
+
// outro_script: string,
|
|
207
|
+
// default_survey_id: ObjectId | null
|
|
208
|
+
// }
|
|
209
|
+
//
|
|
210
|
+
// For "custom":
|
|
211
|
+
// {
|
|
212
|
+
// custom_prompt: string
|
|
213
|
+
// }
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
post_call_processing: {
|
|
217
|
+
strategy: "summarize" | "extract_survey" | "summarize_and_extract" | "none",
|
|
218
|
+
llm_provider: "openai" | "gemini",
|
|
219
|
+
whatsapp_notify: boolean,
|
|
220
|
+
notification_template: string // "call_summary" | "survey_progress" | "custom"
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
is_active: boolean,
|
|
224
|
+
created_at: Date,
|
|
225
|
+
updated_at: Date
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### surveys
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
{
|
|
233
|
+
_id: ObjectId,
|
|
234
|
+
tenant_id: ObjectId, // ref → tenants
|
|
235
|
+
name: string,
|
|
236
|
+
description: string,
|
|
237
|
+
questions: [
|
|
238
|
+
{
|
|
239
|
+
id: string, // e.g. "Q1", "Q2"
|
|
240
|
+
text: string, // "How would you rate our service from 1 to 5?"
|
|
241
|
+
type: "open" | "multiple_choice" | "rating" | "yes_no",
|
|
242
|
+
options: string[], // for multiple_choice
|
|
243
|
+
required: boolean,
|
|
244
|
+
branch_logic: {
|
|
245
|
+
condition: string, // e.g. "answer == 'yes'"
|
|
246
|
+
go_to: string // question id to jump to
|
|
247
|
+
} | null
|
|
248
|
+
}
|
|
249
|
+
],
|
|
250
|
+
status: "draft" | "active" | "archived",
|
|
251
|
+
created_at: Date,
|
|
252
|
+
updated_at: Date
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### campaigns
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
{
|
|
260
|
+
_id: ObjectId,
|
|
261
|
+
tenant_id: ObjectId, // ref → tenants
|
|
262
|
+
survey_id: ObjectId, // ref → surveys
|
|
263
|
+
agent_id: ObjectId, // ref → agents
|
|
264
|
+
name: string,
|
|
265
|
+
status: "draft" | "scheduled" | "running" | "paused" | "completed",
|
|
266
|
+
phone_list: [
|
|
267
|
+
{
|
|
268
|
+
number: string,
|
|
269
|
+
status: "pending" | "completed" | "failed" | "no_answer" | "voicemail",
|
|
270
|
+
attempts: number,
|
|
271
|
+
last_attempt_at: Date | null
|
|
272
|
+
}
|
|
273
|
+
],
|
|
274
|
+
schedule: {
|
|
275
|
+
start_date: Date,
|
|
276
|
+
end_date: Date,
|
|
277
|
+
daily_start_time: string, // "09:00"
|
|
278
|
+
daily_end_time: string, // "18:00"
|
|
279
|
+
days_of_week: number[], // [1,2,3,4,5] = weekdays
|
|
280
|
+
max_concurrent_calls: number,
|
|
281
|
+
max_retries: number,
|
|
282
|
+
retry_delay_minutes: number
|
|
283
|
+
},
|
|
284
|
+
stats: {
|
|
285
|
+
total: number,
|
|
286
|
+
completed: number,
|
|
287
|
+
failed: number,
|
|
288
|
+
no_answer: number,
|
|
289
|
+
voicemail: number,
|
|
290
|
+
pending: number
|
|
291
|
+
},
|
|
292
|
+
created_at: Date,
|
|
293
|
+
updated_at: Date
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### calls
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
{
|
|
301
|
+
_id: ObjectId,
|
|
302
|
+
tenant_id: ObjectId, // ref → tenants
|
|
303
|
+
agent_id: ObjectId, // ref → agents
|
|
304
|
+
campaign_id: ObjectId | null, // ref → campaigns (null for inbound)
|
|
305
|
+
direction: "inbound" | "outbound",
|
|
306
|
+
caller_number: string,
|
|
307
|
+
callee_number: string,
|
|
308
|
+
duration_seconds: number,
|
|
309
|
+
status: "completed" | "failed" | "no_answer" | "voicemail" | "transferred",
|
|
310
|
+
transcript: string,
|
|
311
|
+
llm_summary: string | null,
|
|
312
|
+
survey_responses: [
|
|
313
|
+
{
|
|
314
|
+
question_id: string,
|
|
315
|
+
question_text: string,
|
|
316
|
+
answer: string,
|
|
317
|
+
parsed_value: any // structured: number for rating, boolean for yes/no, etc.
|
|
318
|
+
}
|
|
319
|
+
] | null,
|
|
320
|
+
whatsapp_notification_sent: boolean,
|
|
321
|
+
recording_url: string | null,
|
|
322
|
+
created_at: Date
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### billing_events
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
{
|
|
330
|
+
_id: ObjectId,
|
|
331
|
+
tenant_id: ObjectId, // ref → tenants
|
|
332
|
+
type: "call_charge" | "subscription" | "top_up" | "refund",
|
|
333
|
+
amount: number,
|
|
334
|
+
currency: "TRY",
|
|
335
|
+
call_id: ObjectId | null, // ref → calls
|
|
336
|
+
param_transaction_id: string | null,
|
|
337
|
+
description: string,
|
|
338
|
+
created_at: Date
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Required Indexes
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
// calls — most queried collection
|
|
346
|
+
calls: { tenant_id: 1, created_at: -1 }
|
|
347
|
+
calls: { campaign_id: 1, status: 1 }
|
|
348
|
+
calls: { tenant_id: 1, direction: 1, created_at: -1 }
|
|
349
|
+
|
|
350
|
+
// campaigns
|
|
351
|
+
campaigns: { tenant_id: 1, status: 1 }
|
|
352
|
+
|
|
353
|
+
// billing
|
|
354
|
+
billing_events: { tenant_id: 1, created_at: -1 }
|
|
355
|
+
|
|
356
|
+
// users
|
|
357
|
+
users: { email: 1 } // unique
|
|
358
|
+
users: { tenant_id: 1 }
|
|
359
|
+
|
|
360
|
+
// agents
|
|
361
|
+
agents: { tenant_id: 1 }
|
|
362
|
+
agents: { elevenlabs_agent_id: 1 } // for webhook lookup
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Auth & Permissions (RBAC)
|
|
368
|
+
|
|
369
|
+
### JWT Flow
|
|
370
|
+
|
|
371
|
+
1. `POST /auth/login` → validate email + password → return access token (15min) + refresh token (7d)
|
|
372
|
+
2. React stores access token in memory (NOT localStorage)
|
|
373
|
+
3. Every API request includes `Authorization: Bearer <token>`
|
|
374
|
+
4. Fastify `onRequest` hook decodes JWT → attaches `request.user = { id, tenant_id, role, enabled_features }`
|
|
375
|
+
5. Route-level permission check via role middleware + feature middleware
|
|
376
|
+
|
|
377
|
+
### Role Permissions Matrix
|
|
378
|
+
|
|
379
|
+
| Permission | admin | manager | viewer |
|
|
380
|
+
| -------------------------- | ----- | ------- | ------ |
|
|
381
|
+
| Edit agent config | ✓ | | |
|
|
382
|
+
| View call history | ✓ | ✓ | ✓ |
|
|
383
|
+
| View/play transcripts | ✓ | ✓ | ✓ |
|
|
384
|
+
| Create/edit surveys | ✓ | ✓ | |
|
|
385
|
+
| Create/manage campaigns | ✓ | ✓ | |
|
|
386
|
+
| Start/pause/stop campaigns | ✓ | ✓ | |
|
|
387
|
+
| Export data | ✓ | ✓ | ✓ |
|
|
388
|
+
| Invite/manage users | ✓ | | |
|
|
389
|
+
| Manage billing | ✓ | | |
|
|
390
|
+
| Edit notification settings | ✓ | ✓ | |
|
|
391
|
+
|
|
392
|
+
### Middleware Stack
|
|
393
|
+
|
|
394
|
+
Routes are protected by two layers: **role** and **feature** .
|
|
395
|
+
|
|
396
|
+
```typescript
|
|
397
|
+
// Role middleware — checks user role
|
|
398
|
+
function requireRole(...roles: string[]) {
|
|
399
|
+
return (request, reply) => {
|
|
400
|
+
if (!roles.includes(request.user.role)) {
|
|
401
|
+
return reply.code(403).send({ error: "Insufficient role" })
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Feature middleware — checks tenant features
|
|
407
|
+
function requireFeature(...features: string[]) {
|
|
408
|
+
return (request, reply) => {
|
|
409
|
+
const tenantFeatures = request.user.enabled_features
|
|
410
|
+
if (!features.every(f => tenantFeatures.includes(f))) {
|
|
411
|
+
return reply.code(403).send({ error: "Feature not available on your plan" })
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Usage in routes — combined:
|
|
417
|
+
fastify.get('/surveys', {
|
|
418
|
+
preHandler: [requireFeature('survey_builder'), requireRole('admin', 'manager', 'viewer')]
|
|
419
|
+
}, handler)
|
|
420
|
+
|
|
421
|
+
fastify.post('/campaigns', {
|
|
422
|
+
preHandler: [requireFeature('outbound_campaigns'), requireRole('admin', 'manager')]
|
|
423
|
+
}, handler)
|
|
424
|
+
|
|
425
|
+
fastify.get('/calls', {
|
|
426
|
+
preHandler: [requireRole('admin', 'manager', 'viewer')]
|
|
427
|
+
}, handler)
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Super Admin
|
|
431
|
+
|
|
432
|
+
Separate role for internal team. `role: "superadmin"` bypasses tenant scoping and feature checks. Used for:
|
|
433
|
+
|
|
434
|
+
* Provisioning new tenants and setting their enabled_features
|
|
435
|
+
* Assigning phone numbers to agents
|
|
436
|
+
* System-wide monitoring
|
|
437
|
+
* Debugging call issues
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## API Routes
|
|
442
|
+
|
|
443
|
+
### Auth
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
POST /auth/register # Create first user + tenant (onboarding)
|
|
447
|
+
POST /auth/login # Returns JWT access + refresh tokens
|
|
448
|
+
POST /auth/refresh # Refresh access token
|
|
449
|
+
POST /auth/logout # Invalidate refresh token
|
|
450
|
+
GET /auth/me # Current user profile + tenant features
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Tenants
|
|
454
|
+
|
|
455
|
+
```
|
|
456
|
+
GET /tenants/me # Get current tenant details + enabled_features
|
|
457
|
+
PUT /tenants/me # Update tenant settings
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Users (tenant-scoped)
|
|
461
|
+
|
|
462
|
+
```
|
|
463
|
+
GET /users # List users in tenant
|
|
464
|
+
POST /users/invite # Invite user to tenant
|
|
465
|
+
PUT /users/:id # Update user role
|
|
466
|
+
DELETE /users/:id # Remove user from tenant
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Agents (tenant-scoped)
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
GET /agents # List agents for tenant
|
|
473
|
+
GET /agents/:id # Get agent details + config
|
|
474
|
+
PUT /agents/:id/config # Update agent configuration (template_data + post_call_processing)
|
|
475
|
+
POST /agents/:id/toggle # Enable/disable agent
|
|
476
|
+
GET /agents/templates # List available agent templates + their config schemas
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Calls (tenant-scoped)
|
|
480
|
+
|
|
481
|
+
```
|
|
482
|
+
GET /calls # List calls (paginated, filterable by date/direction/status/agent)
|
|
483
|
+
GET /calls/:id # Get call details + transcript + summary + survey_responses
|
|
484
|
+
GET /calls/:id/recording # Get call recording URL
|
|
485
|
+
GET /calls/stats # Aggregated call statistics
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Surveys (tenant-scoped, requires: survey_builder feature)
|
|
489
|
+
|
|
490
|
+
```
|
|
491
|
+
GET /surveys # List surveys
|
|
492
|
+
POST /surveys # Create new survey
|
|
493
|
+
GET /surveys/:id # Get survey with questions
|
|
494
|
+
PUT /surveys/:id # Update survey
|
|
495
|
+
DELETE /surveys/:id # Delete survey (only if no active campaigns)
|
|
496
|
+
POST /surveys/:id/duplicate # Clone a survey
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Campaigns (tenant-scoped, requires: outbound_campaigns feature)
|
|
500
|
+
|
|
501
|
+
```
|
|
502
|
+
GET /campaigns # List campaigns
|
|
503
|
+
POST /campaigns # Create campaign (survey_id, phone_list, schedule)
|
|
504
|
+
GET /campaigns/:id # Get campaign details + stats
|
|
505
|
+
PUT /campaigns/:id # Update campaign config
|
|
506
|
+
POST /campaigns/:id/start # Start campaign
|
|
507
|
+
POST /campaigns/:id/pause # Pause campaign
|
|
508
|
+
POST /campaigns/:id/resume # Resume campaign
|
|
509
|
+
POST /campaigns/:id/stop # Stop campaign permanently
|
|
510
|
+
GET /campaigns/:id/results # Get structured survey responses
|
|
511
|
+
GET /campaigns/:id/results/export # Export results as CSV/Excel
|
|
512
|
+
POST /campaigns/:id/phone-list # Upload/update phone number list
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### Billing (tenant-scoped)
|
|
516
|
+
|
|
517
|
+
```
|
|
518
|
+
GET /billing/usage # Current period usage summary
|
|
519
|
+
GET /billing/history # Billing event history
|
|
520
|
+
POST /billing/checkout # Initiate Param payment
|
|
521
|
+
POST /billing/webhook # Param payment confirmation webhook
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Webhooks (internal, no auth — secured by signature verification)
|
|
525
|
+
|
|
526
|
+
```
|
|
527
|
+
POST /webhooks/elevenlabs # ElevenLabs post-call webhook
|
|
528
|
+
POST /webhooks/param # Param payment webhook
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Super Admin (superadmin role only)
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
GET /admin/tenants # List all tenants
|
|
535
|
+
POST /admin/tenants # Create tenant manually
|
|
536
|
+
PUT /admin/tenants/:id # Update tenant (plan, enabled_features)
|
|
537
|
+
PUT /admin/tenants/:id/features # Toggle features for a tenant
|
|
538
|
+
POST /admin/agents # Provision new agent (assign phone number to tenant)
|
|
539
|
+
GET /admin/system/health # System health (active calls, queue depth, errors)
|
|
540
|
+
GET /admin/system/usage # Global usage statistics
|
|
541
|
+
GET /admin/templates # List all agent templates
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## React Dashboard Pages
|
|
547
|
+
|
|
548
|
+
### Navigation Rendering
|
|
549
|
+
|
|
550
|
+
The sidebar dynamically renders based on `tenant.enabled_features`:
|
|
551
|
+
|
|
552
|
+
```tsx
|
|
553
|
+
// Always visible
|
|
554
|
+
<NavItem to="/dashboard" />
|
|
555
|
+
<NavItem to="/calls" />
|
|
556
|
+
<NavItem to="/settings" />
|
|
557
|
+
|
|
558
|
+
// Feature-gated
|
|
559
|
+
{features.includes('survey_builder') && <NavItem to="/surveys" />}
|
|
560
|
+
{features.includes('outbound_campaigns') && <NavItem to="/campaigns" />}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Core Pages (All Tenants)
|
|
564
|
+
|
|
565
|
+
```
|
|
566
|
+
/login # Login page
|
|
567
|
+
/dashboard # Overview — call stats, recent calls, usage summary
|
|
568
|
+
/calls # Call history table (filterable, sortable, paginated)
|
|
569
|
+
/calls/:id # Call detail — transcript, summary, recording playback
|
|
570
|
+
# If survey responses exist, show structured answers too
|
|
571
|
+
/settings # Tenant settings
|
|
572
|
+
/settings/agent # Agent configuration form
|
|
573
|
+
# Renders different config fields based on agent_template:
|
|
574
|
+
# - receptionist: business hours, FAQ builder, services, transfer number
|
|
575
|
+
# - survey: intro/outro scripts, default survey link
|
|
576
|
+
# - custom: raw prompt editor
|
|
577
|
+
/settings/notifications # WhatsApp notification preferences (requires: whatsapp_notifications)
|
|
578
|
+
/settings/users # User management (invite, roles)
|
|
579
|
+
/settings/billing # Usage, payment history, add funds via Param
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Feature-Gated Pages
|
|
583
|
+
|
|
584
|
+
```
|
|
585
|
+
/surveys # Survey list (requires: survey_builder)
|
|
586
|
+
/surveys/new # Survey builder — questions, types, branching
|
|
587
|
+
/surveys/:id/edit # Edit survey
|
|
588
|
+
|
|
589
|
+
/campaigns # Campaign list with status badges (requires: outbound_campaigns)
|
|
590
|
+
/campaigns/new # Create campaign — select survey → upload numbers → set schedule
|
|
591
|
+
/campaigns/:id # Campaign detail — live stats, progress bar, controls
|
|
592
|
+
/campaigns/:id/results # Structured results table + charts + export button
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### Super Admin Pages
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
/admin/tenants # Tenant management — list, create, toggle features
|
|
599
|
+
/admin/tenants/:id # Tenant detail + agent provisioning + feature toggles
|
|
600
|
+
/admin/system # System dashboard (health, queues, active calls)
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Agent Template System
|
|
606
|
+
|
|
607
|
+
### How Templates Work
|
|
608
|
+
|
|
609
|
+
Each agent template is a module that defines:
|
|
610
|
+
|
|
611
|
+
1. **Config schema** — what fields the tenant configures in the dashboard
|
|
612
|
+
2. **Prompt builder** — generates the ElevenLabs system prompt from config
|
|
613
|
+
3. **Config UI hint** — tells the React dashboard which form fields to render
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
// templates/index.ts — Template registry
|
|
617
|
+
import { receptionistTemplate } from './receptionist'
|
|
618
|
+
import { surveyTemplate } from './survey'
|
|
619
|
+
|
|
620
|
+
export const templates = {
|
|
621
|
+
receptionist: receptionistTemplate,
|
|
622
|
+
survey: surveyTemplate,
|
|
623
|
+
// Add new templates here — no other code changes needed
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
export function buildPrompt(agent: Agent): string {
|
|
627
|
+
const template = templates[agent.agent_template]
|
|
628
|
+
if (!template) throw new Error(`Unknown template: ${agent.agent_template}`)
|
|
629
|
+
return template.buildPrompt(agent.config)
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
```typescript
|
|
634
|
+
// templates/receptionist.ts
|
|
635
|
+
export const receptionistTemplate = {
|
|
636
|
+
name: 'receptionist',
|
|
637
|
+
direction: 'inbound',
|
|
638
|
+
|
|
639
|
+
configSchema: {
|
|
640
|
+
business_name: { type: 'string', required: true },
|
|
641
|
+
business_hours: { type: 'array', items: { day: 'string', open: 'string', close: 'string' } },
|
|
642
|
+
transfer_number: { type: 'string', required: false },
|
|
643
|
+
faq_entries: { type: 'array', items: { question: 'string', answer: 'string' } },
|
|
644
|
+
services: { type: 'array', items: 'string' },
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
defaultPostCallProcessing: {
|
|
648
|
+
strategy: 'summarize',
|
|
649
|
+
whatsapp_notify: true,
|
|
650
|
+
notification_template: 'call_summary',
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
buildPrompt(config): string {
|
|
654
|
+
return `You are a receptionist for ${config.template_data.business_name}.
|
|
655
|
+
Business hours: ${JSON.stringify(config.template_data.business_hours)}
|
|
656
|
+
Services offered: ${config.template_data.services.join(', ')}
|
|
657
|
+
|
|
658
|
+
FAQ:
|
|
659
|
+
${config.template_data.faq_entries.map(f => `Q: ${f.question}\nA: ${f.answer}`).join('\n\n')}
|
|
660
|
+
|
|
661
|
+
If the caller needs something you cannot handle, transfer to: ${config.template_data.transfer_number}
|
|
662
|
+
${config.greeting}`
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
// templates/survey.ts
|
|
669
|
+
export const surveyTemplate = {
|
|
670
|
+
name: 'survey',
|
|
671
|
+
direction: 'outbound',
|
|
672
|
+
|
|
673
|
+
configSchema: {
|
|
674
|
+
intro_script: { type: 'string', required: true },
|
|
675
|
+
outro_script: { type: 'string', required: true },
|
|
676
|
+
default_survey_id: { type: 'ObjectId', required: false },
|
|
677
|
+
},
|
|
678
|
+
|
|
679
|
+
defaultPostCallProcessing: {
|
|
680
|
+
strategy: 'extract_survey',
|
|
681
|
+
whatsapp_notify: true,
|
|
682
|
+
notification_template: 'survey_progress',
|
|
683
|
+
},
|
|
684
|
+
|
|
685
|
+
// Prompt is built dynamically per campaign using the survey definition
|
|
686
|
+
buildPrompt(config, survey?): string {
|
|
687
|
+
const questions = survey?.questions.map(q =>
|
|
688
|
+
`${q.id}: ${q.text} (type: ${q.type}${q.options?.length ? ', options: ' + q.options.join('/') : ''})`
|
|
689
|
+
).join('\n')
|
|
690
|
+
|
|
691
|
+
return `${config.template_data.intro_script}
|
|
692
|
+
|
|
693
|
+
You are conducting a survey. Ask the following questions in order, respecting branch logic:
|
|
694
|
+
${questions}
|
|
695
|
+
|
|
696
|
+
When complete: ${config.template_data.outro_script}`
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Adding a New Template
|
|
702
|
+
|
|
703
|
+
To add a new use case (e.g., appointment reminder, debt collection, lead qualification):
|
|
704
|
+
|
|
705
|
+
1. Create `templates/new-template.ts` with config schema + prompt builder
|
|
706
|
+
2. Register it in `templates/index.ts`
|
|
707
|
+
3. The dashboard auto-renders the correct config form via the schema
|
|
708
|
+
4. No database migration. No route changes. No middleware changes.
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## Post-Call Processing Pipeline
|
|
713
|
+
|
|
714
|
+
This is the webhook flow triggered after every call. The pipeline reads from the agent's `post_call_processing` config — no hardcoded tenant type checks.
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
1. ElevenLabs call ends → POST /webhooks/elevenlabs
|
|
718
|
+
Payload: { agent_id, transcript, duration, metadata }
|
|
719
|
+
|
|
720
|
+
2. Backend looks up agent by elevenlabs_agent_id
|
|
721
|
+
→ Gets tenant, agent config, and post_call_processing settings
|
|
722
|
+
|
|
723
|
+
3. Enqueue job to `post-call-processing` queue with:
|
|
724
|
+
{
|
|
725
|
+
call_id, transcript, agent_id, tenant_id,
|
|
726
|
+
strategy: agent.post_call_processing.strategy,
|
|
727
|
+
llm_provider: agent.post_call_processing.llm_provider,
|
|
728
|
+
survey_definition: (if strategy includes survey extraction, fetch from campaign)
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
4. Worker picks up job and dispatches by strategy:
|
|
732
|
+
|
|
733
|
+
strategy: "summarize"
|
|
734
|
+
→ LLM prompt: "Summarize this call. Extract: caller intent, key details,
|
|
735
|
+
action items, urgency level. Return as JSON."
|
|
736
|
+
→ Save llm_summary to call record
|
|
737
|
+
|
|
738
|
+
strategy: "extract_survey"
|
|
739
|
+
→ LLM prompt: "Given this survey definition: {questions}
|
|
740
|
+
And this call transcript: {transcript}
|
|
741
|
+
Extract the answer to each question. Return as JSON:
|
|
742
|
+
[{ question_id, answer, parsed_value }]"
|
|
743
|
+
→ Save survey_responses to call record
|
|
744
|
+
→ Update campaign stats
|
|
745
|
+
|
|
746
|
+
strategy: "summarize_and_extract"
|
|
747
|
+
→ Run both prompts
|
|
748
|
+
→ Save both llm_summary and survey_responses
|
|
749
|
+
|
|
750
|
+
strategy: "none"
|
|
751
|
+
→ Save call record with transcript only, skip LLM
|
|
752
|
+
|
|
753
|
+
5. If agent.post_call_processing.whatsapp_notify == true:
|
|
754
|
+
→ Enqueue WhatsApp notification job
|
|
755
|
+
→ Template selected by agent.post_call_processing.notification_template:
|
|
756
|
+
"call_summary": "New call from {number}. Summary: {llm_summary}"
|
|
757
|
+
"survey_progress": "Campaign {name}: {completed}/{total} completed"
|
|
758
|
+
|
|
759
|
+
6. Log billing event (call_charge)
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
---
|
|
763
|
+
|
|
764
|
+
## BullMQ Job Queues
|
|
765
|
+
|
|
766
|
+
### Queue: `campaign-dialer`
|
|
767
|
+
|
|
768
|
+
Handles outbound call scheduling and execution.
|
|
769
|
+
|
|
770
|
+
```typescript
|
|
771
|
+
// Job data
|
|
772
|
+
{
|
|
773
|
+
campaign_id: string,
|
|
774
|
+
phone_number: string,
|
|
775
|
+
attempt: number
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Worker logic:
|
|
779
|
+
// 1. Check if campaign is still "running"
|
|
780
|
+
// 2. Check if within schedule window (time of day, day of week)
|
|
781
|
+
// 3. Tell Asterisk to originate call to this number via NetGSM
|
|
782
|
+
// 4. Connect call to ElevenLabs agent configured for this campaign's survey
|
|
783
|
+
// 5. On failure/no_answer: re-queue with delay if retries remaining
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### Queue: `post-call-processing`
|
|
787
|
+
|
|
788
|
+
Handles async LLM processing after calls. Strategy-driven, not type-driven.
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
// Job data
|
|
792
|
+
{
|
|
793
|
+
call_id: string,
|
|
794
|
+
transcript: string,
|
|
795
|
+
strategy: "summarize" | "extract_survey" | "summarize_and_extract" | "none",
|
|
796
|
+
llm_provider: "openai" | "gemini",
|
|
797
|
+
survey_definition?: object // only when strategy includes survey extraction
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Worker logic:
|
|
801
|
+
// 1. Dispatch to correct processing function based on strategy
|
|
802
|
+
// 2. Call OpenAI/Gemini with appropriate prompt
|
|
803
|
+
// 3. Parse structured response
|
|
804
|
+
// 4. Update call record in MongoDB
|
|
805
|
+
// 5. Enqueue WhatsApp notification if configured
|
|
806
|
+
// 6. Update campaign stats if outbound call
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
### Queue: `whatsapp-notifications`
|
|
810
|
+
|
|
811
|
+
Handles WhatsApp sending with rate limiting.
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
// Job data
|
|
815
|
+
{
|
|
816
|
+
tenant_id: string,
|
|
817
|
+
recipients: string[],
|
|
818
|
+
notification_template: string,
|
|
819
|
+
template_data: object // variables to fill into the template
|
|
820
|
+
}
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
---
|
|
824
|
+
|
|
825
|
+
## Feature Gating — How It Works End-to-End
|
|
826
|
+
|
|
827
|
+
### Backend
|
|
828
|
+
|
|
829
|
+
```typescript
|
|
830
|
+
// Tenant onboarding — superadmin sets features
|
|
831
|
+
await Tenant.create({
|
|
832
|
+
name: "Dr. Yılmaz Clinic",
|
|
833
|
+
plan: "pro",
|
|
834
|
+
enabled_features: ["inbound_agent", "whatsapp_notifications"]
|
|
835
|
+
})
|
|
836
|
+
|
|
837
|
+
// Later, clinic wants outbound reminders — superadmin adds feature:
|
|
838
|
+
await Tenant.updateOne(
|
|
839
|
+
{ _id: tenantId },
|
|
840
|
+
{ $addToSet: { enabled_features: "outbound_campaigns" } }
|
|
841
|
+
)
|
|
842
|
+
// No migration. No type change. Just a feature toggle.
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
### Route Protection
|
|
846
|
+
|
|
847
|
+
```typescript
|
|
848
|
+
// Survey routes — only accessible if tenant has survey_builder feature
|
|
849
|
+
fastify.register(surveyRoutes, { prefix: '/surveys' })
|
|
850
|
+
// Inside surveyRoutes:
|
|
851
|
+
fastify.addHook('onRequest', requireFeature('survey_builder'))
|
|
852
|
+
|
|
853
|
+
// Campaign routes — only accessible if tenant has outbound_campaigns feature
|
|
854
|
+
fastify.register(campaignRoutes, { prefix: '/campaigns' })
|
|
855
|
+
// Inside campaignRoutes:
|
|
856
|
+
fastify.addHook('onRequest', requireFeature('outbound_campaigns'))
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
### Frontend
|
|
860
|
+
|
|
861
|
+
```typescript
|
|
862
|
+
// Auth response includes tenant features
|
|
863
|
+
GET /auth/me → { user: {...}, tenant: { enabled_features: [...] } }
|
|
864
|
+
|
|
865
|
+
// Feature context provider
|
|
866
|
+
const { features } = useTenant()
|
|
867
|
+
|
|
868
|
+
// Conditional rendering
|
|
869
|
+
{features.includes('survey_builder') && <SurveySection />}
|
|
870
|
+
{features.includes('outbound_campaigns') && <CampaignSection />}
|
|
871
|
+
|
|
872
|
+
// Route protection
|
|
873
|
+
<Route path="/surveys/*" element={
|
|
874
|
+
features.includes('survey_builder') ? <SurveyRoutes /> : <Navigate to="/dashboard" />
|
|
875
|
+
} />
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
## Development Phases
|
|
881
|
+
|
|
882
|
+
### Phase 0: Foundation (Week 1)
|
|
883
|
+
|
|
884
|
+
* [ ] Initialize Fastify + TypeScript project with the structure above
|
|
885
|
+
* [ ] Set up MongoDB connection via Mongoose with all models and indexes
|
|
886
|
+
* [ ] Set up Redis connection
|
|
887
|
+
* [ ] Implement JWT auth (register, login, refresh, logout)
|
|
888
|
+
* [ ] Implement RBAC middleware (requireRole)
|
|
889
|
+
* [ ] Implement feature-gating middleware (requireFeature)
|
|
890
|
+
* [ ] Set up Winston logger
|
|
891
|
+
* [ ] Set up BullMQ with Redis (queue definitions, basic worker skeleton)
|
|
892
|
+
* [ ] Environment config (.env typing and validation with zod or similar)
|
|
893
|
+
* [ ] Basic error handling middleware
|
|
894
|
+
* [ ] Agent template registry with receptionist and survey templates
|
|
895
|
+
|
|
896
|
+
### Phase 1: Core Backend (Week 2)
|
|
897
|
+
|
|
898
|
+
* [ ] Tenant CRUD routes
|
|
899
|
+
* [ ] User management routes (invite, update role, delete)
|
|
900
|
+
* [ ] Agent CRUD + config update routes
|
|
901
|
+
* [ ] Agent template config validation (validate template_data against template schema)
|
|
902
|
+
* [ ] Prompt builder — dispatches to correct template, generates ElevenLabs system prompt
|
|
903
|
+
* [ ] Call listing and detail routes (with pagination and filters)
|
|
904
|
+
* [ ] ElevenLabs webhook endpoint — receive post-call data
|
|
905
|
+
* [ ] Post-call processing worker — strategy-driven (summarize / extract_survey / both / none)
|
|
906
|
+
* [ ] LLM wrapper service (OpenAI + Gemini, switchable per agent config)
|
|
907
|
+
* [ ] Twilio WhatsApp notification service + queue worker
|
|
908
|
+
* [ ] Wire up: webhook → post-call-processing queue → WhatsApp notification queue
|
|
909
|
+
|
|
910
|
+
### Phase 2: Survey & Campaign Engine (Week 3)
|
|
911
|
+
|
|
912
|
+
* [ ] Survey CRUD routes with question/branching validation
|
|
913
|
+
* [ ] Campaign CRUD routes
|
|
914
|
+
* [ ] Campaign state machine (draft → scheduled → running → paused → completed)
|
|
915
|
+
* [ ] Campaign dialer worker (BullMQ) — orchestrates outbound calls via Asterisk
|
|
916
|
+
* [ ] Phone list upload and management (CSV upload endpoint)
|
|
917
|
+
* [ ] Survey response extraction (LLM post-processing with extract_survey strategy)
|
|
918
|
+
* [ ] Campaign stats aggregation and update logic
|
|
919
|
+
* [ ] Results export endpoint (CSV/Excel generation)
|
|
920
|
+
* [ ] Voicemail/answering machine detection handling
|
|
921
|
+
|
|
922
|
+
### Phase 3: Billing Integration (Week 3-4)
|
|
923
|
+
|
|
924
|
+
* [ ] Usage metering — track calls per tenant, calculate charges
|
|
925
|
+
* [ ] Param payment integration (checkout initiation)
|
|
926
|
+
* [ ] Param webhook handler (payment confirmation)
|
|
927
|
+
* [ ] Billing event logging
|
|
928
|
+
* [ ] Usage summary and history endpoints
|
|
929
|
+
|
|
930
|
+
### Phase 4: React Dashboard — Core (Week 4-5)
|
|
931
|
+
|
|
932
|
+
* [ ] React + Vite + TypeScript project setup
|
|
933
|
+
* [ ] Auth pages (login, register)
|
|
934
|
+
* [ ] Tenant context provider (loads enabled_features, gates UI)
|
|
935
|
+
* [ ] Layout with feature-aware sidebar navigation
|
|
936
|
+
* [ ] Dashboard overview page (call stats cards, recent calls, usage chart)
|
|
937
|
+
* [ ] Call history page (table with filters, pagination, search)
|
|
938
|
+
* [ ] Call detail page (transcript viewer, summary, survey responses if present, recording playback)
|
|
939
|
+
* [ ] Settings pages:
|
|
940
|
+
* [ ] Agent config form — dynamically renders fields based on agent_template
|
|
941
|
+
* [ ] Notification preferences (gated by whatsapp_notifications feature)
|
|
942
|
+
* [ ] User management (invite, role assignment, remove)
|
|
943
|
+
* [ ] Billing (current usage, payment history, add funds via Param)
|
|
944
|
+
|
|
945
|
+
### Phase 5: React Dashboard — Feature-Gated Pages (Week 5-6)
|
|
946
|
+
|
|
947
|
+
* [ ] Survey list page (gated by survey_builder)
|
|
948
|
+
* [ ] Survey builder page (add questions, set types, configure branching logic)
|
|
949
|
+
* [ ] Survey preview/test
|
|
950
|
+
* [ ] Campaign list page with status badges (gated by outbound_campaigns)
|
|
951
|
+
* [ ] Campaign creation wizard (select survey → upload numbers → set schedule → review → launch)
|
|
952
|
+
* [ ] Campaign detail page (live progress, stats, controls: start/pause/stop)
|
|
953
|
+
* [ ] Campaign results page (structured response table, basic charts, export button)
|
|
954
|
+
|
|
955
|
+
### Phase 6: Super Admin Panel (Week 6-7)
|
|
956
|
+
|
|
957
|
+
* [ ] Super admin routes (tenant list, create, update)
|
|
958
|
+
* [ ] Tenant feature toggle UI (enable/disable features per tenant)
|
|
959
|
+
* [ ] Agent provisioning (assign phone number + template to tenant)
|
|
960
|
+
* [ ] System health dashboard (active calls, queue depths, error rates)
|
|
961
|
+
* [ ] Global usage statistics
|
|
962
|
+
* [ ] Agent template management (view registered templates)
|
|
963
|
+
|
|
964
|
+
### Phase 7: Hardening (Week 7-8)
|
|
965
|
+
|
|
966
|
+
* [ ] Input validation on all routes (fastify schemas or zod)
|
|
967
|
+
* [ ] Rate limiting on auth routes and webhooks
|
|
968
|
+
* [ ] Webhook signature verification (ElevenLabs, Param)
|
|
969
|
+
* [ ] KVKK compliance review (data retention policies, consent tracking)
|
|
970
|
+
* [ ] Call recording consent handling
|
|
971
|
+
* [ ] Error monitoring setup (Sentry or similar)
|
|
972
|
+
* [ ] API documentation (Swagger/OpenAPI via fastify-swagger)
|
|
973
|
+
* [ ] Load testing on campaign dialer (concurrent call limits)
|
|
974
|
+
* [ ] ElevenLabs rate limit handling and graceful degradation
|
|
975
|
+
* [ ] Backup strategy for MongoDB Atlas
|
|
976
|
+
* [ ] End-to-end testing of full call flows (inbound + outbound)
|
|
977
|
+
|
|
978
|
+
---
|
|
979
|
+
|
|
980
|
+
## Environment Variables
|
|
981
|
+
|
|
982
|
+
```env
|
|
983
|
+
# Server
|
|
984
|
+
PORT=3000
|
|
985
|
+
NODE_ENV=production
|
|
986
|
+
|
|
987
|
+
# MongoDB
|
|
988
|
+
MONGODB_URI=mongodb+srv://...
|
|
989
|
+
|
|
990
|
+
# Redis
|
|
991
|
+
REDIS_URL=redis://...
|
|
992
|
+
|
|
993
|
+
# JWT
|
|
994
|
+
JWT_SECRET=your-secret-key
|
|
995
|
+
JWT_REFRESH_SECRET=your-refresh-secret
|
|
996
|
+
JWT_ACCESS_EXPIRY=15m
|
|
997
|
+
JWT_REFRESH_EXPIRY=7d
|
|
998
|
+
|
|
999
|
+
# ElevenLabs
|
|
1000
|
+
ELEVENLABS_API_KEY=...
|
|
1001
|
+
ELEVENLABS_WEBHOOK_SECRET=...
|
|
1002
|
+
|
|
1003
|
+
# OpenAI
|
|
1004
|
+
OPENAI_API_KEY=...
|
|
1005
|
+
|
|
1006
|
+
# Google Gemini
|
|
1007
|
+
GOOGLE_AI_API_KEY=...
|
|
1008
|
+
|
|
1009
|
+
# Twilio (WhatsApp)
|
|
1010
|
+
TWILIO_ACCOUNT_SID=...
|
|
1011
|
+
TWILIO_AUTH_TOKEN=...
|
|
1012
|
+
TWILIO_WHATSAPP_FROM=whatsapp:+...
|
|
1013
|
+
|
|
1014
|
+
# Param (Payment)
|
|
1015
|
+
PARAM_CLIENT_CODE=...
|
|
1016
|
+
PARAM_CLIENT_USERNAME=...
|
|
1017
|
+
PARAM_CLIENT_PASSWORD=...
|
|
1018
|
+
PARAM_GUID=...
|
|
1019
|
+
|
|
1020
|
+
# NetGSM / Asterisk
|
|
1021
|
+
ASTERISK_ARI_URL=http://...
|
|
1022
|
+
ASTERISK_ARI_USERNAME=...
|
|
1023
|
+
ASTERISK_ARI_PASSWORD=...
|
|
1024
|
+
```
|
|
1025
|
+
|
|
1026
|
+
---
|
|
1027
|
+
|
|
1028
|
+
## Key Technical Notes
|
|
1029
|
+
|
|
1030
|
+
1. **All routes are tenant-scoped.** Every query must filter by `tenant_id` from the JWT. Never allow cross-tenant data access.
|
|
1031
|
+
2. **Feature gating is the core access control pattern.** Routes check features via middleware. The dashboard checks features to render UI. Super admins toggle features per tenant. No hardcoded tenant types anywhere.
|
|
1032
|
+
3. **Agent templates are the extensibility mechanism.** New use cases = new templates. No database changes, no route changes, no middleware changes. Just a new file in `templates/` and a registration in the registry.
|
|
1033
|
+
4. **Post-call processing is strategy-driven.** The webhook handler reads the agent's `post_call_processing.strategy` and dispatches accordingly. Adding a new strategy = adding a new case in the worker.
|
|
1034
|
+
5. **The prompt builder is critical.** It takes structured agent config and dispatches to the correct template's `buildPrompt()`. This is where AI agent quality lives — invest in prompt engineering per template.
|
|
1035
|
+
6. **Campaign dialer must respect concurrency limits.** Both Asterisk trunk capacity and ElevenLabs concurrent session limits. Make `max_concurrent_calls` configurable per campaign and enforce globally via Redis counters.
|
|
1036
|
+
7. **Survey response extraction quality determines product value.** Invest in prompt engineering for the extract_survey strategy. Test edge cases: caller goes off-topic, gives ambiguous answers, skips questions, hangs up mid-survey.
|
|
1037
|
+
8. **WhatsApp notifications should be non-blocking.** Use the BullMQ queue, don't hold up the webhook response.
|
|
1038
|
+
9. **MongoDB transactions** are needed for campaign stat updates where you update both the call record and campaign stats atomically.
|