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,942 @@
|
|
|
1
|
+
# Tektip VoiceAI SaaS Platform - Complete System Overview
|
|
2
|
+
|
|
3
|
+
> Multi-tenant AI-powered voice call platform with ElevenLabs integration, survey campaigns, WhatsApp notifications, and billing.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Tech Stack](#1-tech-stack)
|
|
10
|
+
2. [Architecture Overview](#2-architecture-overview)
|
|
11
|
+
3. [Database Schemas](#3-database-schemas)
|
|
12
|
+
4. [API Endpoints](#4-api-endpoints)
|
|
13
|
+
5. [Authentication Flow](#5-authentication-flow)
|
|
14
|
+
6. [Core Business Flows](#6-core-business-flows)
|
|
15
|
+
7. [Third-Party Integrations](#7-third-party-integrations)
|
|
16
|
+
8. [Middleware & Plugins](#8-middleware--plugins)
|
|
17
|
+
9. [Frontend Pages & Routing](#9-frontend-pages--routing)
|
|
18
|
+
10. [Frontend State Management](#10-frontend-state-management)
|
|
19
|
+
11. [Environment Variables](#11-environment-variables)
|
|
20
|
+
12. [Project Structure](#12-project-structure)
|
|
21
|
+
13. [Deployment](#13-deployment)
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 1. Tech Stack
|
|
26
|
+
|
|
27
|
+
| Layer | Technology |
|
|
28
|
+
|-------|-----------|
|
|
29
|
+
| **Backend** | Fastify 5 + TypeScript 5.9 |
|
|
30
|
+
| **Frontend** | React 19 + Vite 7 + TypeScript 5.9 |
|
|
31
|
+
| **Styling** | Tailwind CSS v4 + shadcn/ui (New York style) |
|
|
32
|
+
| **Database** | MongoDB via Mongoose 8 |
|
|
33
|
+
| **Auth** | JWT dual-token (access + refresh) via @fastify/jwt + jsonwebtoken |
|
|
34
|
+
| **AI** | OpenAI (gpt-5.4-mini) or Google Gemini (configurable) |
|
|
35
|
+
| **Voice** | ElevenLabs (webhook-based post-call processing) |
|
|
36
|
+
| **Messaging** | Twilio WhatsApp API |
|
|
37
|
+
| **Validation** | Zod 4 |
|
|
38
|
+
| **Logging** | Winston |
|
|
39
|
+
| **Process Manager** | PM2 |
|
|
40
|
+
| **Icons** | Lucide React |
|
|
41
|
+
| **Toasts** | Sonner |
|
|
42
|
+
| **HTTP Client** | Axios (frontend) |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Architecture Overview
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
+-------------------+
|
|
50
|
+
| ElevenLabs AI |
|
|
51
|
+
| (Voice Agents) |
|
|
52
|
+
+--------+----------+
|
|
53
|
+
|
|
|
54
|
+
POST /webhooks/elevenlabs WebSocket (text-only)
|
|
55
|
+
(HMAC-SHA256 signed) (signed URL, 15min)
|
|
56
|
+
| |
|
|
57
|
+
v v
|
|
58
|
+
+------------+ +--------+----------+ +----------+
|
|
59
|
+
| React SPA | <-------> | Fastify API | <-------> | MongoDB |
|
|
60
|
+
| (Vite dev | /api/* | (port 3005) | | |
|
|
61
|
+
| port 5173)| proxy | | +----------+
|
|
62
|
+
+------------+ +---+-----+----+----+
|
|
63
|
+
| | |
|
|
64
|
+
v v v
|
|
65
|
+
+------+-+ +--+------+ +----------+
|
|
66
|
+
| OpenAI | | Twilio | | Unipile |
|
|
67
|
+
| Gemini | | WhatsApp| | WhatsApp |
|
|
68
|
+
+--------+ +---------+ +----------+
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Multi-tenant design**: Every data entity is scoped by `tenant_id`. All queries filter by tenant. Feature flags control which capabilities each tenant can use.
|
|
72
|
+
|
|
73
|
+
**Role hierarchy**: `superadmin` > `admin` > `manager` > `viewer`
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 3. Database Schemas
|
|
78
|
+
|
|
79
|
+
### 3.1 Tenant
|
|
80
|
+
|
|
81
|
+
| Field | Type | Details |
|
|
82
|
+
|-------|------|---------|
|
|
83
|
+
| `name` | String | Required |
|
|
84
|
+
| `plan` | String | `free` / `starter` / `pro` / `premium`, default: `free` |
|
|
85
|
+
| `enabled_features` | [String] | Enum: `inbound_agent`, `outbound_campaigns`, `survey_builder`, `whatsapp_notifications`, `whatsapp_agent` |
|
|
86
|
+
| `settings.whatsapp_agent.unipile_account_id` | String | Unipile WhatsApp account ID |
|
|
87
|
+
| `settings.whatsapp_agent.unipile_account_status` | String | Connection status |
|
|
88
|
+
| `settings.whatsapp_agent.agent_id` | ObjectId → Agent | Reference to the Agent model that handles WhatsApp AI (resolved to ElevenLabs agent ID at runtime, checks is_active) |
|
|
89
|
+
| `settings.whatsapp_agent.connected_at` | Date | When WhatsApp was connected |
|
|
90
|
+
| `settings.whatsapp_agent.connected_phone` | String | Connected phone number |
|
|
91
|
+
| `settings.whatsapp_agent.grace_period_seconds` | Number | Default: 180 (seconds before AI takes over) |
|
|
92
|
+
| `settings.whatsapp_agent.blacklisted_numbers` | [String] | Numbers excluded from AI |
|
|
93
|
+
| `settings.kvkk_consent` | Boolean | Default: false |
|
|
94
|
+
| `settings.notification_recipients` | [String] | Phone numbers |
|
|
95
|
+
| `settings.default_language` | String | Default: `tr` |
|
|
96
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
97
|
+
|
|
98
|
+
### 3.2 User
|
|
99
|
+
|
|
100
|
+
| Field | Type | Details |
|
|
101
|
+
|-------|------|---------|
|
|
102
|
+
| `tenant_id` | ObjectId → Tenant | Required, indexed |
|
|
103
|
+
| `email` | String | Required, unique, lowercase, trimmed, indexed |
|
|
104
|
+
| `password_hash` | String | Bcrypt, 12 salt rounds |
|
|
105
|
+
| `role` | String | `superadmin` / `admin` / `manager` / `viewer`, default: `viewer` |
|
|
106
|
+
| `name` | String | Required |
|
|
107
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
108
|
+
|
|
109
|
+
### 3.3 RefreshToken
|
|
110
|
+
|
|
111
|
+
| Field | Type | Details |
|
|
112
|
+
|-------|------|---------|
|
|
113
|
+
| `user_id` | ObjectId → User | Required, indexed |
|
|
114
|
+
| `token` | String | Required, unique |
|
|
115
|
+
| `expires_at` | Date | Required, TTL index (auto-deletes expired tokens) |
|
|
116
|
+
| `createdAt` | Date | Auto |
|
|
117
|
+
|
|
118
|
+
### 3.4 Agent
|
|
119
|
+
|
|
120
|
+
| Field | Type | Details |
|
|
121
|
+
|-------|------|---------|
|
|
122
|
+
| `tenant_id` | ObjectId → Tenant | Required, indexed |
|
|
123
|
+
| `phone_number` | String | Required |
|
|
124
|
+
| `elevenlabs_agent_id` | String | Required, indexed |
|
|
125
|
+
| `direction` | String | `inbound` / `outbound` / `both` |
|
|
126
|
+
| `agent_template` | String | `receptionist` / `survey` / `custom` |
|
|
127
|
+
| `config.voice_id` | String | Required |
|
|
128
|
+
| `config.language` | String | Default: `tr` |
|
|
129
|
+
| `config.greeting` | String | Default: `''` |
|
|
130
|
+
| `config.template_data` | Mixed | Template-specific data |
|
|
131
|
+
| `post_call_processing.strategy` | String | `summarize` / `extract_survey` / `summarize_and_extract` / `none` |
|
|
132
|
+
| `post_call_processing.llm_provider` | String | `openai` / `gemini` |
|
|
133
|
+
| `post_call_processing.whatsapp_notify` | Boolean | Default: true |
|
|
134
|
+
| `post_call_processing.notification_template` | String | `call_summary` / `survey_progress` / `custom` |
|
|
135
|
+
| `is_active` | Boolean | Default: true |
|
|
136
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
137
|
+
|
|
138
|
+
### 3.5 Call
|
|
139
|
+
|
|
140
|
+
| Field | Type | Details |
|
|
141
|
+
|-------|------|---------|
|
|
142
|
+
| `tenant_id` | ObjectId → Tenant | Required |
|
|
143
|
+
| `agent_id` | ObjectId → Agent | Required |
|
|
144
|
+
| `campaign_id` | ObjectId → Campaign | Nullable |
|
|
145
|
+
| `direction` | String | `inbound` / `outbound` |
|
|
146
|
+
| `caller_number` | String | Required |
|
|
147
|
+
| `callee_number` | String | Required |
|
|
148
|
+
| `duration_seconds` | Number | Default: 0 |
|
|
149
|
+
| `status` | String | `completed` / `failed` / `no_answer` / `voicemail` / `transferred` |
|
|
150
|
+
| `transcript` | String | Default: `''` |
|
|
151
|
+
| `llm_summary` | String | Nullable |
|
|
152
|
+
| `survey_responses` | Array | `[{ question_id, question_text, answer, parsed_value }]` |
|
|
153
|
+
| `whatsapp_notification_sent` | Boolean | Default: false |
|
|
154
|
+
| `recording_url` | String | Nullable |
|
|
155
|
+
| `createdAt` | Date | Auto |
|
|
156
|
+
|
|
157
|
+
**Indexes**: `(tenant_id, createdAt)`, `(campaign_id, status)`, `(tenant_id, direction, createdAt)`
|
|
158
|
+
|
|
159
|
+
### 3.6 Survey
|
|
160
|
+
|
|
161
|
+
| Field | Type | Details |
|
|
162
|
+
|-------|------|---------|
|
|
163
|
+
| `tenant_id` | ObjectId → Tenant | Required, indexed |
|
|
164
|
+
| `name` | String | Required |
|
|
165
|
+
| `description` | String | Default: `''` |
|
|
166
|
+
| `questions` | Array | See below |
|
|
167
|
+
| `status` | String | `draft` / `active` / `archived`, default: `draft` |
|
|
168
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
169
|
+
|
|
170
|
+
**Question schema**: `{ id, text, type (open/multiple_choice/rating/yes_no), options: [String], required: Boolean, branch_logic: { condition, go_to } | null }`
|
|
171
|
+
|
|
172
|
+
### 3.7 Campaign
|
|
173
|
+
|
|
174
|
+
| Field | Type | Details |
|
|
175
|
+
|-------|------|---------|
|
|
176
|
+
| `tenant_id` | ObjectId → Tenant | Required |
|
|
177
|
+
| `survey_id` | ObjectId → Survey | Required |
|
|
178
|
+
| `agent_id` | ObjectId → Agent | Required |
|
|
179
|
+
| `name` | String | Required |
|
|
180
|
+
| `status` | String | `draft` / `scheduled` / `running` / `paused` / `completed` |
|
|
181
|
+
| `phone_list` | Array | `[{ number, status, attempts, last_attempt_at }]` |
|
|
182
|
+
| `schedule.start_date` | Date | Required |
|
|
183
|
+
| `schedule.end_date` | Date | Required |
|
|
184
|
+
| `schedule.daily_start_time` | String | Default: `09:00` |
|
|
185
|
+
| `schedule.daily_end_time` | String | Default: `18:00` |
|
|
186
|
+
| `schedule.days_of_week` | [Number] | Default: `[1,2,3,4,5]` (Mon-Fri) |
|
|
187
|
+
| `schedule.max_concurrent_calls` | Number | Default: 1 |
|
|
188
|
+
| `schedule.max_retries` | Number | Default: 3 |
|
|
189
|
+
| `schedule.retry_delay_minutes` | Number | Default: 60 |
|
|
190
|
+
| `stats` | Object | `{ total, completed, failed, no_answer, voicemail, pending }` |
|
|
191
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
192
|
+
|
|
193
|
+
**Index**: `(tenant_id, status)`
|
|
194
|
+
**State machine**: `draft → scheduled → running → paused/completed`, `paused → running/completed`
|
|
195
|
+
|
|
196
|
+
### 3.8 BillingEvent
|
|
197
|
+
|
|
198
|
+
| Field | Type | Details |
|
|
199
|
+
|-------|------|---------|
|
|
200
|
+
| `tenant_id` | ObjectId → Tenant | Required |
|
|
201
|
+
| `type` | String | `call_charge` / `subscription` / `top_up` / `refund` |
|
|
202
|
+
| `amount` | Number | Required |
|
|
203
|
+
| `currency` | String | Default: `TRY` |
|
|
204
|
+
| `call_id` | ObjectId → Call | Nullable |
|
|
205
|
+
| `param_transaction_id` | String | Nullable |
|
|
206
|
+
| `description` | String | Default: `''` |
|
|
207
|
+
| `createdAt` | Date | Auto |
|
|
208
|
+
|
|
209
|
+
**Index**: `(tenant_id, createdAt)`
|
|
210
|
+
**Pricing**: 1.5 TRY per minute (rounded up)
|
|
211
|
+
|
|
212
|
+
### 3.9 WhatsAppChat
|
|
213
|
+
|
|
214
|
+
| Field | Type | Details |
|
|
215
|
+
|-------|------|---------|
|
|
216
|
+
| `tenant_id` | ObjectId → Tenant | Required, indexed |
|
|
217
|
+
| `unipile_chat_id` | String | Required, unique |
|
|
218
|
+
| `unipile_account_id` | String | Unipile account this chat belongs to |
|
|
219
|
+
| `contact_name` | String | Contact's display name |
|
|
220
|
+
| `contact_phone` | String | Contact's phone number |
|
|
221
|
+
| `is_closed` | Boolean | Whether chat has been manually closed (default: false) |
|
|
222
|
+
| `active_session_id` | ObjectId → WhatsAppSession | Current active session (null if no session) |
|
|
223
|
+
| `last_message_at` | Date | Timestamp of most recent message |
|
|
224
|
+
| `last_message_preview` | String | First 100 chars of last message |
|
|
225
|
+
| `message_count` | Number | Total messages in chat |
|
|
226
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
227
|
+
|
|
228
|
+
**Indexes**: `(tenant_id, last_message_at)`, `(unipile_chat_id)` unique
|
|
229
|
+
|
|
230
|
+
### 3.10 WhatsAppSession
|
|
231
|
+
|
|
232
|
+
Tracks the lifecycle of a human/AI conversation session within a chat. Each new contact interaction starts a session with a grace period where humans get first chance to respond.
|
|
233
|
+
|
|
234
|
+
| Field | Type | Details |
|
|
235
|
+
|-------|------|---------|
|
|
236
|
+
| `chat_id` | ObjectId → WhatsAppChat | Required |
|
|
237
|
+
| `tenant_id` | ObjectId → Tenant | Required |
|
|
238
|
+
| `status` | String | `waiting` / `active` / `resolved` |
|
|
239
|
+
| `resolved_by` | String | `human` / `ai_timeout` / `manual` / `timeout` / null |
|
|
240
|
+
| `started_at` | Date | When session was created |
|
|
241
|
+
| `resolved_at` | Date | When session ended (null if still open) |
|
|
242
|
+
| `grace_deadline` | Date | When AI takes over if human doesn't respond |
|
|
243
|
+
| `taken_over_by` | ObjectId → User | User who took over (null = AI mode) |
|
|
244
|
+
| `taken_over_at` | Date | When takeover happened |
|
|
245
|
+
| `elevenlabs_conversation_id` | String | Active ElevenLabs conversation (null until AI connects) |
|
|
246
|
+
| `elevenlabs_conversation_created_at` | Date | When EL conversation was created |
|
|
247
|
+
| `elevenlabs_last_interaction_at` | Date | Last message sent to EL |
|
|
248
|
+
| `message_count` | Number | Messages in this session |
|
|
249
|
+
| `createdAt` / `updatedAt` | Date | Auto |
|
|
250
|
+
|
|
251
|
+
**Indexes**: `(chat_id, status)`, `(status, grace_deadline)`, `(tenant_id, status)`
|
|
252
|
+
|
|
253
|
+
**Session lifecycle**:
|
|
254
|
+
```
|
|
255
|
+
Contact sends message
|
|
256
|
+
│
|
|
257
|
+
▼
|
|
258
|
+
[waiting] ─── grace period timer (e.g. 180s) ───→ [active] (AI takes over)
|
|
259
|
+
│ │
|
|
260
|
+
│ Human responds │ Human takeover button
|
|
261
|
+
▼ ▼
|
|
262
|
+
[resolved] [active] (human mode)
|
|
263
|
+
resolved_by='human' taken_over_by=<userId>
|
|
264
|
+
│
|
|
265
|
+
│ Release / Close
|
|
266
|
+
▼
|
|
267
|
+
[resolved]
|
|
268
|
+
resolved_by='manual'
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### 3.11 WhatsAppMessage
|
|
272
|
+
|
|
273
|
+
| Field | Type | Details |
|
|
274
|
+
|-------|------|---------|
|
|
275
|
+
| `chat_id` | ObjectId → WhatsAppChat | Required |
|
|
276
|
+
| `session_id` | ObjectId → WhatsAppSession | Nullable (null for blacklisted/legacy) |
|
|
277
|
+
| `tenant_id` | ObjectId → Tenant | Required |
|
|
278
|
+
| `unipile_message_id` | String | Unipile's message ID (null for AI responses) |
|
|
279
|
+
| `sender` | String | `contact` / `ai` / `human` |
|
|
280
|
+
| `sender_name` | String | Display name of sender |
|
|
281
|
+
| `text` | String | Message content |
|
|
282
|
+
| `sent_via_unipile` | Boolean | Whether sent through Unipile API |
|
|
283
|
+
| `createdAt` | Date | Auto |
|
|
284
|
+
|
|
285
|
+
**Indexes**: `(chat_id, createdAt)`, `(session_id, createdAt)`
|
|
286
|
+
|
|
287
|
+
### 3.12 Legacy Models (still in codebase)
|
|
288
|
+
|
|
289
|
+
- **Transcription** - Raw ElevenLabs transcription storage with processing pipeline status
|
|
290
|
+
- **Summary** - AI-generated call summaries with sentiment analysis
|
|
291
|
+
- **WhatsAppRecipient** - Notification recipients with agent/duration filters
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 4. API Endpoints
|
|
296
|
+
|
|
297
|
+
### 4.1 Auth (`/auth`)
|
|
298
|
+
|
|
299
|
+
| Method | Path | Auth | Role | Description |
|
|
300
|
+
|--------|------|------|------|-------------|
|
|
301
|
+
| POST | `/auth/register` | - | - | Create tenant + first admin user. Returns tokens. |
|
|
302
|
+
| POST | `/auth/login` | - | - | Email/password login. Returns tokens + user + tenant. |
|
|
303
|
+
| POST | `/auth/refresh` | - | - | Rotate refresh token, get new access token. |
|
|
304
|
+
| POST | `/auth/logout` | Yes | Any | Revoke refresh token. |
|
|
305
|
+
| GET | `/auth/me` | Yes | Any | Current user profile + tenant info. |
|
|
306
|
+
|
|
307
|
+
### 4.2 Users (`/users`)
|
|
308
|
+
|
|
309
|
+
| Method | Path | Auth | Role | Description |
|
|
310
|
+
|--------|------|------|------|-------------|
|
|
311
|
+
| GET | `/users` | Yes | Any | List users in tenant. |
|
|
312
|
+
| POST | `/users/invite` | Yes | admin | Invite new user (email, password, name, role). |
|
|
313
|
+
| PUT | `/users/:id` | Yes | admin | Update user role/name. |
|
|
314
|
+
| DELETE | `/users/:id` | Yes | admin | Delete user (cannot self-delete). |
|
|
315
|
+
|
|
316
|
+
### 4.3 Tenants (`/tenants`)
|
|
317
|
+
|
|
318
|
+
| Method | Path | Auth | Role | Description |
|
|
319
|
+
|--------|------|------|------|-------------|
|
|
320
|
+
| GET | `/tenants/me` | Yes | Any | Get current tenant. |
|
|
321
|
+
| PUT | `/tenants/me` | Yes | admin | Update tenant name/settings. |
|
|
322
|
+
|
|
323
|
+
### 4.4 Agents (`/agents`)
|
|
324
|
+
|
|
325
|
+
| Method | Path | Auth | Role | Description |
|
|
326
|
+
|--------|------|------|------|-------------|
|
|
327
|
+
| GET | `/agents` | Yes | Any | List agents for tenant. |
|
|
328
|
+
| GET | `/agents/:id` | Yes | Any | Get agent detail. |
|
|
329
|
+
| PUT | `/agents/:id/config` | Yes | admin | Update agent config / post-call processing. |
|
|
330
|
+
| POST | `/agents/:id/toggle` | Yes | admin | Enable/disable agent. |
|
|
331
|
+
|
|
332
|
+
### 4.5 Calls (`/calls`)
|
|
333
|
+
|
|
334
|
+
| Method | Path | Auth | Role | Description |
|
|
335
|
+
|--------|------|------|------|-------------|
|
|
336
|
+
| GET | `/calls` | Yes | Any | Paginated list. Filters: `direction`, `status`, `agent_id`, `from`, `to`. |
|
|
337
|
+
| GET | `/calls/stats` | Yes | Any | Aggregated stats: total, completed, failed, avg duration, etc. |
|
|
338
|
+
| GET | `/calls/:id` | Yes | Any | Call detail with transcript, summary, survey responses. |
|
|
339
|
+
|
|
340
|
+
### 4.6 Surveys (`/surveys`)
|
|
341
|
+
|
|
342
|
+
| Method | Path | Auth | Role | Feature | Description |
|
|
343
|
+
|--------|------|------|------|---------|-------------|
|
|
344
|
+
| GET | `/surveys` | Yes | Any | `survey_builder` | List surveys. |
|
|
345
|
+
| POST | `/surveys` | Yes | admin/mgr | `survey_builder` | Create survey. |
|
|
346
|
+
| GET | `/surveys/:id` | Yes | Any | `survey_builder` | Survey detail with questions. |
|
|
347
|
+
| PUT | `/surveys/:id` | Yes | admin/mgr | `survey_builder` | Update survey. |
|
|
348
|
+
| DELETE | `/surveys/:id` | Yes | admin/mgr | `survey_builder` | Delete (fails if active campaigns exist). |
|
|
349
|
+
| POST | `/surveys/:id/duplicate` | Yes | admin/mgr | `survey_builder` | Duplicate survey. |
|
|
350
|
+
|
|
351
|
+
### 4.7 Campaigns (`/campaigns`)
|
|
352
|
+
|
|
353
|
+
| Method | Path | Auth | Role | Feature | Description |
|
|
354
|
+
|--------|------|------|------|---------|-------------|
|
|
355
|
+
| GET | `/campaigns` | Yes | Any | `outbound_campaigns` | Paginated list. Filter: `status`. |
|
|
356
|
+
| POST | `/campaigns` | Yes | admin/mgr | `outbound_campaigns` | Create campaign (name, survey, agent, schedule). |
|
|
357
|
+
| GET | `/campaigns/:id` | Yes | Any | `outbound_campaigns` | Detail with populated survey/agent. |
|
|
358
|
+
| PUT | `/campaigns/:id` | Yes | admin/mgr | `outbound_campaigns` | Update (draft/scheduled only). |
|
|
359
|
+
| POST | `/campaigns/:id/start` | Yes | admin/mgr | `outbound_campaigns` | Start campaign. |
|
|
360
|
+
| POST | `/campaigns/:id/pause` | Yes | admin/mgr | `outbound_campaigns` | Pause campaign. |
|
|
361
|
+
| POST | `/campaigns/:id/resume` | Yes | admin/mgr | `outbound_campaigns` | Resume campaign. |
|
|
362
|
+
| POST | `/campaigns/:id/stop` | Yes | admin/mgr | `outbound_campaigns` | Stop permanently. |
|
|
363
|
+
| POST | `/campaigns/:id/phone-list` | Yes | admin/mgr | `outbound_campaigns` | Upload phone numbers (array or CSV). |
|
|
364
|
+
| GET | `/campaigns/:id/results` | Yes | Any | `outbound_campaigns` | Campaign results with survey responses. |
|
|
365
|
+
| GET | `/campaigns/:id/results/export` | Yes | Any | `outbound_campaigns` | Export results as CSV download. |
|
|
366
|
+
|
|
367
|
+
### 4.8 Billing (`/billing`)
|
|
368
|
+
|
|
369
|
+
| Method | Path | Auth | Role | Description |
|
|
370
|
+
|--------|------|------|------|-------------|
|
|
371
|
+
| GET | `/billing/usage` | Yes | admin | Current month: total calls, duration, charges. |
|
|
372
|
+
| GET | `/billing/history` | Yes | admin | Paginated billing events. Filter: `type`. |
|
|
373
|
+
|
|
374
|
+
### 4.9 Admin - SuperAdmin Only (`/admin`)
|
|
375
|
+
|
|
376
|
+
| Method | Path | Auth | Role | Description |
|
|
377
|
+
|--------|------|------|------|-------------|
|
|
378
|
+
| GET | `/admin/tenants` | Yes | superadmin | List all tenants with user_count. Filters: `search`, `page`. |
|
|
379
|
+
| POST | `/admin/tenants` | Yes | superadmin | Create tenant. |
|
|
380
|
+
| GET | `/admin/tenants/:id` | Yes | superadmin | Tenant detail: users, agents, call/campaign counts. |
|
|
381
|
+
| PUT | `/admin/tenants/:id` | Yes | superadmin | Update tenant (name, plan, features, settings). |
|
|
382
|
+
| PUT | `/admin/tenants/:id/features` | Yes | superadmin | Toggle tenant features. |
|
|
383
|
+
| POST | `/admin/agents` | Yes | superadmin | Provision agent for a tenant. |
|
|
384
|
+
| GET | `/admin/system/health` | Yes | superadmin | System: uptime, tenant/user/agent/call counts, revenue. |
|
|
385
|
+
| GET | `/admin/system/usage` | Yes | superadmin | Per-tenant usage this month. |
|
|
386
|
+
| GET | `/admin/templates` | Yes | superadmin | List available agent templates. |
|
|
387
|
+
|
|
388
|
+
### 4.10 WhatsApp Agent (`/whatsapp`) — Feature: `whatsapp_agent`
|
|
389
|
+
|
|
390
|
+
**Connection Management**:
|
|
391
|
+
|
|
392
|
+
| Method | Path | Auth | Role | Description |
|
|
393
|
+
|--------|------|------|------|-------------|
|
|
394
|
+
| POST | `/whatsapp/connect` | Yes | admin | Initiate WhatsApp QR code connection via Unipile |
|
|
395
|
+
| GET | `/whatsapp/connection-status` | Yes | Any | Check Unipile account connection status |
|
|
396
|
+
| POST | `/whatsapp/disconnect` | Yes | admin | Disconnect WhatsApp account |
|
|
397
|
+
| PUT | `/whatsapp/config` | Yes | admin | Set `agent_id` (ObjectId → Agent) and/or `grace_period_seconds` |
|
|
398
|
+
| GET | `/whatsapp/agents` | Yes | admin | List tenant's agents for selection dropdown |
|
|
399
|
+
| POST | `/whatsapp/register-webhook` | Yes | admin | Register Unipile webhook URL |
|
|
400
|
+
|
|
401
|
+
**Blacklist Management**:
|
|
402
|
+
|
|
403
|
+
| Method | Path | Auth | Role | Description |
|
|
404
|
+
|--------|------|------|------|-------------|
|
|
405
|
+
| GET | `/whatsapp/blacklist` | Yes | admin/mgr | Get blacklisted numbers |
|
|
406
|
+
| POST | `/whatsapp/blacklist` | Yes | admin/mgr | Add phone to blacklist |
|
|
407
|
+
| DELETE | `/whatsapp/blacklist/:phone` | Yes | admin/mgr | Remove phone from blacklist |
|
|
408
|
+
|
|
409
|
+
**Chat Management**:
|
|
410
|
+
|
|
411
|
+
| Method | Path | Auth | Role | Description |
|
|
412
|
+
|--------|------|------|------|-------------|
|
|
413
|
+
| GET | `/whatsapp/stats` | Yes | Any | Chat/session statistics (total, AI, human, waiting, closed) |
|
|
414
|
+
| GET | `/whatsapp/chats` | Yes | Any | Paginated list. Filter: `mode` (ai/human/closed). Enriched with session info. |
|
|
415
|
+
| GET | `/whatsapp/chats/:id` | Yes | Any | Chat detail (enriched with mode/session_status from active session) |
|
|
416
|
+
| GET | `/whatsapp/chats/:id/messages` | Yes | Any | Paginated messages |
|
|
417
|
+
| GET | `/whatsapp/chats/:id/sessions` | Yes | Any | Paginated session history for a chat |
|
|
418
|
+
| POST | `/whatsapp/chats/:id/takeover` | Yes | admin/mgr | Human takes over from AI |
|
|
419
|
+
| POST | `/whatsapp/chats/:id/release` | Yes | admin/mgr | Release back to AI. Body: `{ immediate?: boolean }` |
|
|
420
|
+
| POST | `/whatsapp/chats/:id/close` | Yes | admin/mgr | Close chat (resolves active session) |
|
|
421
|
+
| POST | `/whatsapp/chats/:id/reopen` | Yes | admin/mgr | Reopen closed chat |
|
|
422
|
+
| POST | `/whatsapp/chats/:id/send` | Yes | admin/mgr | Send manual message (human mode only). If session is `waiting`, resolves it as human. |
|
|
423
|
+
|
|
424
|
+
**Note**: The `enrichChat()` function derives backward-compatible virtual fields from the active session:
|
|
425
|
+
- `mode` → `'ai'` (no session or active+no takeover), `'human'` (waiting or taken over), `'closed'` (is_closed)
|
|
426
|
+
- `session_status` → `'waiting'` (grace period) or `'idle'` (all other states)
|
|
427
|
+
- `taken_over_by`, `taken_over_at`, `session_started_at`, `session_grace_deadline`
|
|
428
|
+
- Removes internal fields (`active_session_id`, `is_closed`) and aggregation pipeline temporaries (`_session`, `_activeSession`, `_mode`)
|
|
429
|
+
|
|
430
|
+
### 4.11 Webhooks
|
|
431
|
+
|
|
432
|
+
| Method | Path | Auth | Description |
|
|
433
|
+
|--------|------|------|-------------|
|
|
434
|
+
| POST | `/webhooks/elevenlabs` | Signature (HMAC-SHA256) | ElevenLabs post-call webhook. Returns 200 immediately, processes async. |
|
|
435
|
+
| POST | `/webhooks/unipile` | Shared secret header | Unipile WhatsApp message webhook. Returns 200 immediately, processes async. |
|
|
436
|
+
|
|
437
|
+
### 4.11 Health & Legacy
|
|
438
|
+
|
|
439
|
+
| Method | Path | Auth | Description |
|
|
440
|
+
|--------|------|------|-------------|
|
|
441
|
+
| GET | `/health` | - | Health check: `{ status: 'ok', timestamp }` |
|
|
442
|
+
| GET | `/whatsapp/status` | - | WhatsApp service status. |
|
|
443
|
+
| POST | `/legacy-admin/login` | - | Legacy admin auth (password only). |
|
|
444
|
+
| GET/POST/PUT/PATCH/DELETE | `/legacy-admin/*` | JWT | Legacy recipient & transcription CRUD. |
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 5. Authentication Flow
|
|
449
|
+
|
|
450
|
+
### Dual-Token JWT System
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
Register/Login
|
|
454
|
+
|
|
|
455
|
+
v
|
|
456
|
+
+-----+-------+ +----------+
|
|
457
|
+
| Access Token | | Refresh |
|
|
458
|
+
| (JWT, 15min) | | Token |
|
|
459
|
+
| in-memory / | | (JWT,7d) |
|
|
460
|
+
| localStorage | | DB-stored|
|
|
461
|
+
+--------------+ +----------+
|
|
462
|
+
| |
|
|
463
|
+
| On 401 |
|
|
464
|
+
| +--------+ |
|
|
465
|
+
+->| Retry |<-------+ POST /auth/refresh
|
|
466
|
+
| with | (old token revoked,
|
|
467
|
+
| new AT | new pair issued)
|
|
468
|
+
+--------+
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Access token payload**: `{ id, tenant_id, role, enabled_features }`
|
|
472
|
+
**Refresh token payload**: `{ id, type: 'refresh' }`
|
|
473
|
+
|
|
474
|
+
**Security measures**:
|
|
475
|
+
- Bcrypt (12 rounds) password hashing
|
|
476
|
+
- Token rotation on every refresh (old token revoked)
|
|
477
|
+
- MongoDB TTL index auto-deletes expired refresh tokens
|
|
478
|
+
- `requireFeature` middleware re-fetches tenant from DB (prevents stale JWT features)
|
|
479
|
+
- Users cannot delete themselves or change their own role
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## 6. Core Business Flows
|
|
484
|
+
|
|
485
|
+
### 6.1 Inbound Call Flow (Webhook Processing)
|
|
486
|
+
|
|
487
|
+
```
|
|
488
|
+
1. Phone call comes in → ElevenLabs AI agent handles it
|
|
489
|
+
2. Call ends → ElevenLabs sends POST /webhooks/elevenlabs
|
|
490
|
+
3. Signature validated (HMAC-SHA256, 30-min timestamp tolerance)
|
|
491
|
+
4. Agent looked up by elevenlabs_agent_id
|
|
492
|
+
5. Call record created in DB
|
|
493
|
+
6. Post-call processing (based on agent.post_call_processing.strategy):
|
|
494
|
+
├── "summarize" → AI generates summary
|
|
495
|
+
├── "extract_survey" → AI extracts survey responses
|
|
496
|
+
├── "summarize_and_extract" → Both
|
|
497
|
+
└── "none" → Skip
|
|
498
|
+
7. WhatsApp notification sent (if whatsapp_notify=true)
|
|
499
|
+
8. Billing event logged (1.5 TRY/min, rounded up)
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 6.2 Outbound Campaign Flow
|
|
503
|
+
|
|
504
|
+
```
|
|
505
|
+
1. Create Survey → define questions (open/multiple_choice/rating/yes_no)
|
|
506
|
+
2. Set survey status to "active"
|
|
507
|
+
3. Create Campaign → link survey + agent + schedule
|
|
508
|
+
4. Upload phone list (paste numbers or CSV)
|
|
509
|
+
5. Start campaign (draft → scheduled → running)
|
|
510
|
+
6. For each phone number:
|
|
511
|
+
├── ElevenLabs agent calls the number
|
|
512
|
+
├── Call ends → webhook fires → Call record created
|
|
513
|
+
├── Survey responses extracted from transcript
|
|
514
|
+
└── Phone list entry status updated
|
|
515
|
+
7. View results → table with responses per phone number
|
|
516
|
+
8. Export results as CSV
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### 6.3 Campaign State Machine
|
|
520
|
+
|
|
521
|
+
```
|
|
522
|
+
draft ──→ scheduled ──→ running ──→ completed
|
|
523
|
+
│
|
|
524
|
+
↓
|
|
525
|
+
paused ──→ running
|
|
526
|
+
│
|
|
527
|
+
└──→ completed
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### 6.4 Registration Flow
|
|
531
|
+
|
|
532
|
+
```
|
|
533
|
+
1. User submits: email, password, name, tenant_name
|
|
534
|
+
2. Tenant created: plan=free, features=[inbound_agent, whatsapp_notifications]
|
|
535
|
+
3. User created: role=admin, linked to tenant
|
|
536
|
+
4. Access + refresh tokens issued
|
|
537
|
+
5. User lands on dashboard
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### 6.5 WhatsApp Agent Flow (Session-Based Architecture)
|
|
541
|
+
|
|
542
|
+
The WhatsApp Agent system uses a **grace period** pattern: when a contact sends a message, a session is created in `waiting` state. Humans get first chance to respond. If no human responds before the deadline, AI takes over.
|
|
543
|
+
|
|
544
|
+
```
|
|
545
|
+
Contact sends WhatsApp message
|
|
546
|
+
│
|
|
547
|
+
┌────▼────────────────────────────────────────────────┐
|
|
548
|
+
│ Unipile webhook → POST /webhooks/unipile │
|
|
549
|
+
│ 1. Find/create WhatsAppChat │
|
|
550
|
+
│ 2. Check blacklist (if blacklisted → store only) │
|
|
551
|
+
│ 3. Look up active session │
|
|
552
|
+
└────┬────────────────────────────────────────────────┘
|
|
553
|
+
│
|
|
554
|
+
┌────┴───────────────┐
|
|
555
|
+
│ │
|
|
556
|
+
No Active Session Session Exists
|
|
557
|
+
│ │
|
|
558
|
+
▼ │
|
|
559
|
+
Create WhatsAppSession │
|
|
560
|
+
status='waiting' │
|
|
561
|
+
grace_deadline=now+180s │
|
|
562
|
+
│ │
|
|
563
|
+
├────────────────────┤
|
|
564
|
+
│ │
|
|
565
|
+
│ ┌─────────────────┴──────────────────┐
|
|
566
|
+
│ │ │
|
|
567
|
+
│ status='waiting' status='active'
|
|
568
|
+
│ Store msg, timer running Forward to AI agent
|
|
569
|
+
│ │ (or skip if human-taken)
|
|
570
|
+
│ │
|
|
571
|
+
│ │ ┌──── Human responds in WhatsApp ────┐
|
|
572
|
+
│ │ │ → resolveSessionAsHuman() │
|
|
573
|
+
│ │ │ → cancel timer, status='resolved' │
|
|
574
|
+
│ │ └─────────────────────────────────────┘
|
|
575
|
+
│ │
|
|
576
|
+
│ │ ┌──── Human clicks "Takeover" in UI ──┐
|
|
577
|
+
│ │ │ → set taken_over_by, close EL WS │
|
|
578
|
+
│ │ │ → session stays 'active' (human) │
|
|
579
|
+
│ │ └──────────────────────────────────────┘
|
|
580
|
+
│ │
|
|
581
|
+
│ └──── Grace period expires (no human response) ───┐
|
|
582
|
+
│ → session status='active' (AI) │
|
|
583
|
+
│ → replayPendingMessages() │
|
|
584
|
+
│ → create ElevenLabs WebSocket (text-only) │
|
|
585
|
+
│ → send context + combined messages │
|
|
586
|
+
│ → AI responds → send via Unipile │
|
|
587
|
+
└─────────────────────────────────────────────────────┘
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**Key components**:
|
|
591
|
+
- **WhatsAppAgentService** (`src/services/whatsapp-agent.service.ts`): Manages grace period timers (in-memory `Map<sessionId, Timeout>`), ElevenLabs WebSocket connections, message replay, and session recovery on startup
|
|
592
|
+
- **createSession()** in webhook handler: Creates `WhatsAppSession`, links to chat via `active_session_id`
|
|
593
|
+
- **enrichChat()** in routes: Derives `mode`/`session_status` from active session for backward-compatible API responses
|
|
594
|
+
- **Stuck session sweeper**: Every 5min, finds sessions stuck in `waiting` past deadline without timers
|
|
595
|
+
- **Idle connection cleanup**: Every 1min, closes ElevenLabs WebSocket connections idle > 10min
|
|
596
|
+
- **Conversation timeout**: If ElevenLabs conversation is > 30min old, starts fresh one
|
|
597
|
+
|
|
598
|
+
**Message buffer**: 20-second debounce — contact messages are buffered, timer resets on each new message, combined text sent to AI after 20s of silence.
|
|
599
|
+
|
|
600
|
+
**WebSocket reconnection**: Auto-reconnect with exponential backoff (1.5s, 3s, 6s, max 3 retries) on unexpected WS close.
|
|
601
|
+
|
|
602
|
+
**Inactivity auto-resolve**: Active sessions with no activity for 30 minutes auto-resolve as `timeout`.
|
|
603
|
+
|
|
604
|
+
**Agent reference**: ElevenLabs agent ID is now resolved through the Agent model (checks `is_active`).
|
|
605
|
+
|
|
606
|
+
**Release dialog** (frontend): When releasing a chat back to AI, user can choose:
|
|
607
|
+
- "Hemen Yanit Ver" (Respond Immediately) — replays pending messages to AI
|
|
608
|
+
- "Mesaj Bekle" (Wait for Message) — releases without triggering AI
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## 7. Third-Party Integrations
|
|
613
|
+
|
|
614
|
+
### ElevenLabs (Voice AI)
|
|
615
|
+
- **Purpose**: AI voice agents for inbound/outbound calls
|
|
616
|
+
- **Integration**: Webhook-based (POST /webhooks/elevenlabs)
|
|
617
|
+
- **Auth**: HMAC-SHA256 signature validation
|
|
618
|
+
- **Events processed**: `post_call_transcription`
|
|
619
|
+
- **Data received**: conversation_id, agent_id, transcript, metadata, call status
|
|
620
|
+
|
|
621
|
+
### OpenAI
|
|
622
|
+
- **Purpose**: Call summarization & survey response extraction
|
|
623
|
+
- **Model**: gpt-5.4-mini (configurable via env)
|
|
624
|
+
- **Temperature**: 0.3
|
|
625
|
+
- **Features**: Token usage tracking, custom prompts per agent (via agentPrompts.json)
|
|
626
|
+
|
|
627
|
+
### Google Gemini
|
|
628
|
+
- **Purpose**: Alternative AI provider for summarization
|
|
629
|
+
- **Model**: gemini-pro (configurable)
|
|
630
|
+
- **Usage**: Swappable with OpenAI via `AI_PROVIDER` env var
|
|
631
|
+
|
|
632
|
+
### Twilio WhatsApp
|
|
633
|
+
- **Purpose**: Post-call notifications to recipients
|
|
634
|
+
- **Method**: Template-based messages (template SID: HX47645724f174e91c4d90b25ee10fe612)
|
|
635
|
+
- **Variables**: caller_number, call_summary
|
|
636
|
+
- **Features**: Recipient filters (agent_ids, min_call_duration), notification tracking
|
|
637
|
+
|
|
638
|
+
### Unipile (WhatsApp Messaging)
|
|
639
|
+
- **Purpose**: WhatsApp message relay for the AI agent chat system
|
|
640
|
+
- **Integration**: REST API + webhooks
|
|
641
|
+
- **Auth**: API key (`UNIPILE_API_KEY`)
|
|
642
|
+
- **Connection flow**: `POST /api/v1/accounts` → returns QR code → user scans → account connected
|
|
643
|
+
- **Capabilities**:
|
|
644
|
+
- `connectWhatsApp()` — Create new WhatsApp account (returns QR code checkpoint)
|
|
645
|
+
- `reconnectAccount(id)` — Reconnect existing account
|
|
646
|
+
- `getAccountStatus(id)` — Check connection status
|
|
647
|
+
- `sendMessage(chatId, text)` — Send WhatsApp message
|
|
648
|
+
- `createWebhook(url)` — Register webhook for incoming messages
|
|
649
|
+
- **Webhook payload**: `{ account_id, event, chat_id, message_id, message, is_sender, sender, attendees }`
|
|
650
|
+
- **Webhook secret**: Optional `x-unipile-secret` header validation
|
|
651
|
+
|
|
652
|
+
### ElevenLabs WebSocket (WhatsApp Chat AI)
|
|
653
|
+
- **Purpose**: Real-time text-only AI conversations for WhatsApp agent
|
|
654
|
+
- **Integration**: Signed WebSocket URL (15min expiry)
|
|
655
|
+
- **Flow**: `getSignedUrl({ agentId })` → WebSocket connect with `?textOnly=true`
|
|
656
|
+
- **Messages**:
|
|
657
|
+
- `conversation_initiation_metadata` — Connection ready, contains conversation_id
|
|
658
|
+
- `user_message` — Send contact's message to AI
|
|
659
|
+
- `agent_response` — AI's reply (forwarded to contact via Unipile)
|
|
660
|
+
- `contextual_update` — Send conversation history for context
|
|
661
|
+
- **First message suppression**: Agent greeting is suppressed (only real responses sent)
|
|
662
|
+
- **Conversation timeout**: 30min idle → new conversation created
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## 8. Middleware & Plugins
|
|
667
|
+
|
|
668
|
+
| Plugin/Middleware | File | Purpose |
|
|
669
|
+
|-------------------|------|---------|
|
|
670
|
+
| **JWT Plugin** | `src/plugins/jwt.ts` | Registers @fastify/jwt, provides `fastify.authenticate` decorator |
|
|
671
|
+
| **RBAC - requireRole** | `src/plugins/rbac.ts` | Role-based access control. Superadmin bypasses all. Returns 403. |
|
|
672
|
+
| **RBAC - requireFeature** | `src/plugins/rbac.ts` | Feature flag check. Fetches tenant from DB (not JWT). Returns 403. |
|
|
673
|
+
| **CORS** | `src/plugins/cors.ts` | @fastify/cors with defaults |
|
|
674
|
+
| **Raw Body** | `src/plugins/rawBody.ts` | Stores raw body for webhook signature validation |
|
|
675
|
+
| **Webhook Validator** | `src/hooks/webhookValidator.ts` | HMAC-SHA256 signature + timestamp check (30-min window) |
|
|
676
|
+
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
## 9. Frontend Pages & Routing
|
|
680
|
+
|
|
681
|
+
### Route Structure (React Router v6)
|
|
682
|
+
|
|
683
|
+
```
|
|
684
|
+
/ → redirect to /dashboard
|
|
685
|
+
├── /login Public - email/password login
|
|
686
|
+
├── /register Public - signup with company name
|
|
687
|
+
└── <ProtectedRoute> + <Layout>
|
|
688
|
+
├── /dashboard Stats cards, recent calls, usage summary
|
|
689
|
+
├── /calls Call list with direction/status filters, pagination
|
|
690
|
+
├── /calls/:id Call detail: transcript, AI summary, survey responses
|
|
691
|
+
├── /surveys Survey list with duplicate/delete actions
|
|
692
|
+
├── /surveys/:id Survey builder: add/edit/delete questions
|
|
693
|
+
├── /surveys/:id/preview Interactive survey preview
|
|
694
|
+
├── /campaigns Campaign list with status filter, progress bars
|
|
695
|
+
├── /campaigns/new 3-step wizard: Info → Schedule → Phone list
|
|
696
|
+
├── /campaigns/:id Campaign detail with start/pause/resume/stop
|
|
697
|
+
├── /campaigns/:id/results Results table + CSV export
|
|
698
|
+
├── /whatsapp WhatsApp two-panel layout: chat list + detail
|
|
699
|
+
├── /whatsapp/:chatId Same WhatsApp component (two-panel), detail panel shows selected chat
|
|
700
|
+
├── /settings Tabs: Company settings + User management
|
|
701
|
+
├── /billing Usage summary + transaction history
|
|
702
|
+
├── /admin/tenants [superadmin] Tenant list with search
|
|
703
|
+
├── /admin/tenants/:id [superadmin] Tenant detail: users, agents, stats
|
|
704
|
+
└── /admin/system [superadmin] System health, uptime, usage
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
**Note**: Both `/whatsapp` and `/whatsapp/:chatId` render the same `WhatsApp` component (two-panel layout). The WhatsApp UI is composed of 10 dedicated components in `web/src/components/whatsapp/`.
|
|
708
|
+
|
|
709
|
+
### Layout Shell
|
|
710
|
+
- Collapsible sidebar with navigation icons
|
|
711
|
+
- User dropdown menu (profile, logout)
|
|
712
|
+
- Conditional nav items based on `enabled_features` and `role`
|
|
713
|
+
- Sonner toast notifications (top-right)
|
|
714
|
+
|
|
715
|
+
### Shared Components
|
|
716
|
+
|
|
717
|
+
| Component | Props | Purpose |
|
|
718
|
+
|-----------|-------|---------|
|
|
719
|
+
| `PageHeader` | title, description?, children? | Page title + optional action buttons |
|
|
720
|
+
| `StatCard` | label, value, icon?, className? | Metric display card |
|
|
721
|
+
| `PageLoader` | - | Skeleton loading state |
|
|
722
|
+
| `TableLoader` | rows?, cols? | Table skeleton |
|
|
723
|
+
| `EmptyState` | message, icon? | Empty data state |
|
|
724
|
+
| `Pagination` | page, totalPages, onPageChange | Prev/next navigation |
|
|
725
|
+
| `CallStatusBadge` | status | Colored badge for call status |
|
|
726
|
+
| `CampaignStatusBadge` | status | Colored badge for campaign status |
|
|
727
|
+
| `SurveyStatusBadge` | status | Colored badge for survey status |
|
|
728
|
+
| `DirectionBadge` | direction | inbound (sky) / outbound (violet) |
|
|
729
|
+
| `BillingTypeBadge` | type | Badge for billing event type |
|
|
730
|
+
| `ChatModeBadge` | mode | AI (green) / Human (amber) / Closed (gray) |
|
|
731
|
+
| `SessionStatusBadge` | status | Shows "Bekleniyor" badge only when status='waiting' |
|
|
732
|
+
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
## 10. Frontend State Management
|
|
736
|
+
|
|
737
|
+
**Approach**: React hooks only (no Redux/Zustand)
|
|
738
|
+
|
|
739
|
+
### AuthContext (Global)
|
|
740
|
+
```typescript
|
|
741
|
+
{
|
|
742
|
+
user: User | null
|
|
743
|
+
tenant: Tenant | null
|
|
744
|
+
isLoading: boolean
|
|
745
|
+
login(email, password): Promise<void>
|
|
746
|
+
register(email, password, name, tenantName): Promise<void>
|
|
747
|
+
logout(): Promise<void>
|
|
748
|
+
}
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
**`useFeature(feature)`** hook: checks `tenant.enabled_features` for conditional rendering.
|
|
752
|
+
|
|
753
|
+
### API Client (`/lib/api.ts`)
|
|
754
|
+
- Axios instance with baseURL `/api`
|
|
755
|
+
- Request interceptor: attaches `Authorization: Bearer {token}`
|
|
756
|
+
- Response interceptor: on 401 → refresh token → retry request → on failure → redirect to `/login`
|
|
757
|
+
|
|
758
|
+
### Data Fetching Pattern
|
|
759
|
+
- `useState` + `useEffect` for API calls on mount/param change
|
|
760
|
+
- `useSearchParams` for pagination and filter state in URL
|
|
761
|
+
- No caching layer (direct API calls)
|
|
762
|
+
|
|
763
|
+
---
|
|
764
|
+
|
|
765
|
+
## 11. Environment Variables
|
|
766
|
+
|
|
767
|
+
```bash
|
|
768
|
+
# Server
|
|
769
|
+
PORT=3005 # Backend port
|
|
770
|
+
NODE_ENV=development # development | production
|
|
771
|
+
|
|
772
|
+
# Database
|
|
773
|
+
MONGODB_URI=mongodb://localhost:27017/elevenlabs-webhook
|
|
774
|
+
|
|
775
|
+
# ElevenLabs
|
|
776
|
+
ELEVENLABS_WEBHOOK_SECRET=wsec_... # HMAC-SHA256 webhook signing secret
|
|
777
|
+
|
|
778
|
+
# AI Provider
|
|
779
|
+
AI_PROVIDER=openai # openai | gemini
|
|
780
|
+
SUMMARY_LANGUAGE=tr # tr | en
|
|
781
|
+
SUMMARY_MAX_TOKENS=500
|
|
782
|
+
|
|
783
|
+
# OpenAI
|
|
784
|
+
OPENAI_API_KEY=sk-...
|
|
785
|
+
OPENAI_MODEL=gpt-5.4-mini
|
|
786
|
+
|
|
787
|
+
# Gemini
|
|
788
|
+
GEMINI_API_KEY=...
|
|
789
|
+
GEMINI_MODEL=gemini-pro
|
|
790
|
+
|
|
791
|
+
# Twilio WhatsApp
|
|
792
|
+
TWILIO_ACCOUNT_SID=...
|
|
793
|
+
TWILIO_AUTH_TOKEN=...
|
|
794
|
+
TWILIO_WHATSAPP_NUMBER=+1234567890
|
|
795
|
+
|
|
796
|
+
# Unipile (WhatsApp Agent)
|
|
797
|
+
UNIPILE_API_KEY=... # Unipile API key
|
|
798
|
+
UNIPILE_DSN=https://api.unipile.com # Unipile API base URL
|
|
799
|
+
UNIPILE_WEBHOOK_SECRET=... # Shared secret for webhook validation
|
|
800
|
+
|
|
801
|
+
# JWT
|
|
802
|
+
JWT_SECRET=... # Access token secret
|
|
803
|
+
JWT_REFRESH_SECRET=... # Refresh token secret (separate)
|
|
804
|
+
JWT_ACCESS_EXPIRY=15m
|
|
805
|
+
JWT_REFRESH_EXPIRY=7d
|
|
806
|
+
|
|
807
|
+
# Legacy Admin
|
|
808
|
+
ADMIN_PASSWORD=... # Single password for legacy admin panel
|
|
809
|
+
|
|
810
|
+
# Logging
|
|
811
|
+
LOG_LEVEL=info
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
## 12. Project Structure
|
|
817
|
+
|
|
818
|
+
```
|
|
819
|
+
elevenlabs-webhook-nodejs/
|
|
820
|
+
├── src/
|
|
821
|
+
│ ├── index.ts # Server entry point
|
|
822
|
+
│ ├── app.ts # Fastify app setup & plugin registration
|
|
823
|
+
│ ├── config/
|
|
824
|
+
│ │ ├── index.ts # Config object
|
|
825
|
+
│ │ ├── env.ts # Zod env validation
|
|
826
|
+
│ │ └── database.ts # MongoDB connection
|
|
827
|
+
│ ├── plugins/
|
|
828
|
+
│ │ ├── jwt.ts # JWT auth plugin
|
|
829
|
+
│ │ ├── rbac.ts # Role & feature middleware
|
|
830
|
+
│ │ ├── cors.ts # CORS
|
|
831
|
+
│ │ └── rawBody.ts # Raw body for webhooks
|
|
832
|
+
│ ├── hooks/
|
|
833
|
+
│ │ └── webhookValidator.ts # ElevenLabs signature validation
|
|
834
|
+
│ ├── modules/
|
|
835
|
+
│ │ ├── auth/ # Routes, service, model (User, RefreshToken)
|
|
836
|
+
│ │ ├── users/ # Routes (CRUD)
|
|
837
|
+
│ │ ├── tenants/ # Routes, model
|
|
838
|
+
│ │ ├── agents/ # Routes, model
|
|
839
|
+
│ │ ├── calls/ # Routes, model
|
|
840
|
+
│ │ ├── surveys/ # Routes, model
|
|
841
|
+
│ │ ├── campaigns/ # Routes, service, model
|
|
842
|
+
│ │ ├── billing/ # Routes, service, model
|
|
843
|
+
│ │ ├── whatsapp/ # WhatsApp Agent (chat, session, message models + routes)
|
|
844
|
+
│ │ ├── webhooks/ # ElevenLabs & Unipile webhook routes + services
|
|
845
|
+
│ │ └── admin/ # SuperAdmin routes
|
|
846
|
+
│ ├── models/ # Legacy models (Transcription, Summary, WhatsAppRecipient)
|
|
847
|
+
│ ├── routes/
|
|
848
|
+
│ │ ├── health.routes.ts # Health & WhatsApp status
|
|
849
|
+
│ │ ├── admin.routes.ts # Legacy admin CRUD
|
|
850
|
+
│ │ └── webhook.routes.ts # Generic webhook handler
|
|
851
|
+
│ ├── services/
|
|
852
|
+
│ │ ├── whatsapp.service.ts # Twilio WhatsApp integration
|
|
853
|
+
│ │ ├── unipile.service.ts # Unipile WhatsApp API client
|
|
854
|
+
│ │ ├── elevenlabs.service.ts # ElevenLabs API + signed URL
|
|
855
|
+
│ │ ├── whatsapp-agent.service.ts # Session timers, EL WebSocket, AI responses
|
|
856
|
+
│ │ └── ai/
|
|
857
|
+
│ │ ├── base.ai.ts # Abstract AI service
|
|
858
|
+
│ │ ├── openai.service.ts # OpenAI implementation
|
|
859
|
+
│ │ ├── gemini.service.ts # Gemini implementation
|
|
860
|
+
│ │ └── index.ts # Factory: createAIService()
|
|
861
|
+
│ ├── templates/
|
|
862
|
+
│ │ ├── index.ts # Template exports
|
|
863
|
+
│ │ ├── receptionist.ts # Receptionist agent template
|
|
864
|
+
│ │ └── survey.ts # Survey agent template
|
|
865
|
+
│ ├── types/
|
|
866
|
+
│ │ └── index.ts # TypeScript interfaces
|
|
867
|
+
│ └── utils/
|
|
868
|
+
│ └── logger.ts # Winston logger
|
|
869
|
+
│
|
|
870
|
+
├── web/
|
|
871
|
+
│ ├── src/
|
|
872
|
+
│ │ ├── main.tsx # React entry point
|
|
873
|
+
│ │ ├── App.tsx # Router setup
|
|
874
|
+
│ │ ├── index.css # Tailwind v4 imports + theme vars
|
|
875
|
+
│ │ ├── contexts/
|
|
876
|
+
│ │ │ └── AuthContext.tsx # Auth state, login/register/logout, useFeature
|
|
877
|
+
│ │ ├── lib/
|
|
878
|
+
│ │ │ ├── api.ts # Axios instance with interceptors
|
|
879
|
+
│ │ │ └── utils.ts # cn() utility (clsx + tailwind-merge)
|
|
880
|
+
│ │ ├── pages/ # 17 page components (WhatsApp is single page, two-panel)
|
|
881
|
+
│ │ └── components/
|
|
882
|
+
│ │ ├── ui/ # shadcn/ui components
|
|
883
|
+
│ │ ├── whatsapp/ # 10 WhatsApp-specific components
|
|
884
|
+
│ │ ├── stat-card.tsx
|
|
885
|
+
│ │ ├── status-badge.tsx
|
|
886
|
+
│ │ ├── page-header.tsx
|
|
887
|
+
│ │ ├── page-loader.tsx
|
|
888
|
+
│ │ ├── empty-state.tsx
|
|
889
|
+
│ │ └── pagination.tsx
|
|
890
|
+
│ ├── components.json # shadcn/ui config
|
|
891
|
+
│ ├── vite.config.ts # Vite + React + Tailwind + /api proxy
|
|
892
|
+
│ ├── tsconfig.json # TS config with @/* path alias
|
|
893
|
+
│ └── package.json
|
|
894
|
+
│
|
|
895
|
+
├── scripts/ # CLI utilities (add recipient, retrigger, migrate-agent-ref, etc.)
|
|
896
|
+
├── ecosystem.config.js # PM2 production config
|
|
897
|
+
├── .env.example # Environment template
|
|
898
|
+
├── .env # Actual env (gitignored)
|
|
899
|
+
├── tsconfig.json # Backend TS config (CommonJS, ES2022)
|
|
900
|
+
└── package.json # Backend dependencies & scripts
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
---
|
|
904
|
+
|
|
905
|
+
## 13. Deployment
|
|
906
|
+
|
|
907
|
+
### PM2 Config
|
|
908
|
+
- **App name**: `asistan724-webhook`
|
|
909
|
+
- **Path**: `/var/www/asistan724-webhook-handler/dist/index.js`
|
|
910
|
+
- **Instances**: 1 (single process)
|
|
911
|
+
- **Auto-restart**: enabled
|
|
912
|
+
- **Memory limit**: 500MB
|
|
913
|
+
|
|
914
|
+
### Build Commands
|
|
915
|
+
```bash
|
|
916
|
+
# Backend
|
|
917
|
+
npm run build # tsc → dist/ + copy agentPrompts.json
|
|
918
|
+
|
|
919
|
+
# Frontend
|
|
920
|
+
cd web && npm run build # tsc --noEmit && vite build
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
### Dev Commands
|
|
924
|
+
```bash
|
|
925
|
+
npm run dev # tsx watch mode (backend, port 3005)
|
|
926
|
+
cd web && npm run dev # vite dev server (port 5173, proxies /api → :3005)
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
### No CI/CD or Docker configured.
|
|
930
|
+
|
|
931
|
+
---
|
|
932
|
+
|
|
933
|
+
## Key Notes
|
|
934
|
+
|
|
935
|
+
- **No cron jobs needed**: The WhatsApp agent system is fully event-driven (webhooks + in-memory timers). A stuck session sweeper runs every 5 minutes as a safety net. Campaign execution (placing outbound calls) is not yet automated.
|
|
936
|
+
- **Session-based architecture**: WhatsApp chats use a session model (`WhatsAppSession`) to cleanly track conversation boundaries. Messages are scoped to sessions via `session_id`, eliminating fragile backwards-scanning for message boundaries.
|
|
937
|
+
- **Backward-compatible API**: The `enrichChat()` helper derives `mode`, `session_status`, `taken_over_by` from the active session — frontend types/components remain unchanged.
|
|
938
|
+
- **Migration**: Run `npx tsx scripts/migrate-sessions.ts` to migrate existing chat data to the session model. Supports `--dry-run` flag.
|
|
939
|
+
- **Legacy code**: `src/models/` and `src/routes/admin.routes.ts` contain the original pre-SaaS system (single-tenant, password-only auth). Still functional but separate from the multi-tenant module system.
|
|
940
|
+
- **Billing**: Currently tracks call charges only (1.5 TRY/min). No payment gateway integration - billing events are logged but not collected.
|
|
941
|
+
- **Feature flags**: `inbound_agent`, `outbound_campaigns`, `survey_builder`, `whatsapp_notifications`, `whatsapp_agent` - controlled per-tenant by superadmin.
|
|
942
|
+
- **WebSocket reconnection & message buffering**: Production-ready improvements — auto-reconnect with exponential backoff (1.5s, 3s, 6s, max 3 retries) on unexpected WS close, and 20-second message debounce that buffers contact messages before sending combined text to AI.
|