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,665 @@
|
|
|
1
|
+
# 10. Client Tools System
|
|
2
|
+
|
|
3
|
+
> Generalized, channel-agnostic tool execution for AI agent interactions.
|
|
4
|
+
> Last updated: 2026-04-02
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Problem: Current State
|
|
9
|
+
|
|
10
|
+
Tools are currently **duplicated and tightly coupled** to ElevenLabs:
|
|
11
|
+
|
|
12
|
+
| Location | Channel | Tools | Format |
|
|
13
|
+
|----------|---------|-------|--------|
|
|
14
|
+
| `whatsapp-agent.service.ts` (1000+ lines) | WhatsApp chat (ElevenLabs WS) | 10 tools | Inline in WS message handler |
|
|
15
|
+
| `elevenlabs-tool.service.ts` | Voice calls (ElevenLabs HTTP webhook) | 7 tools | HTTP request/response |
|
|
16
|
+
|
|
17
|
+
**Why this is a problem:**
|
|
18
|
+
|
|
19
|
+
- Same tools implemented twice (e.g., `check_availability` exists in both files).
|
|
20
|
+
- Business logic is mixed with protocol handling (WS framing, HTTP response format).
|
|
21
|
+
- Adding a new tool requires changes in 2+ places.
|
|
22
|
+
- Impossible to use tools from a different AI provider (e.g., OpenAI function calling).
|
|
23
|
+
- No way to configure which tools are available per tenant or agent.
|
|
24
|
+
- No tool execution logging or analytics.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Architecture: Three Layers
|
|
29
|
+
|
|
30
|
+
The target system separates concerns into three layers. Each layer has a single responsibility and zero knowledge of the layers above it.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
+--------------------------------------------------------------+
|
|
34
|
+
| CALLER (AI Provider) |
|
|
35
|
+
| |
|
|
36
|
+
| ElevenLabs WS ElevenLabs HTTP OpenAI Functions ... |
|
|
37
|
+
| (WhatsApp chat) (Voice call) (Future) |
|
|
38
|
+
+-------+----------------+------------------+------------------+
|
|
39
|
+
| | |
|
|
40
|
+
v v v
|
|
41
|
+
+--------------------------------------------------------------+
|
|
42
|
+
| ADAPTER LAYER |
|
|
43
|
+
| |
|
|
44
|
+
| ElevenLabsWsAdapter ElevenLabsHttpAdapter OpenAIAdapter |
|
|
45
|
+
| - Parse WS message - Parse HTTP body - Parse FC |
|
|
46
|
+
| - Extract tool call - Extract tool call - Extract FC |
|
|
47
|
+
| - Format result - Format response - Format resp |
|
|
48
|
+
+-------+------------------------------------------------------+
|
|
49
|
+
|
|
|
50
|
+
v Standardized ToolCall + ToolContext
|
|
51
|
+
+--------------------------------------------------------------+
|
|
52
|
+
| TOOL REGISTRY |
|
|
53
|
+
| |
|
|
54
|
+
| ToolRegistryService |
|
|
55
|
+
| - Discovers all @Tool() decorated handlers |
|
|
56
|
+
| - Validates parameters against schema |
|
|
57
|
+
| - Resolves tool by name |
|
|
58
|
+
| - Checks tenant permissions / feature flags |
|
|
59
|
+
| - Executes tool handler |
|
|
60
|
+
| - Logs execution (ToolExecutionLog) |
|
|
61
|
+
+-------+------------------------------------------------------+
|
|
62
|
+
|
|
|
63
|
+
v
|
|
64
|
+
+--------------------------------------------------------------+
|
|
65
|
+
| TOOL HANDLERS |
|
|
66
|
+
| |
|
|
67
|
+
| @Tool('check_availability') -> AppointmentService |
|
|
68
|
+
| @Tool('reserve_slot') -> AppointmentService |
|
|
69
|
+
| @Tool('list_reservations') -> AppointmentService |
|
|
70
|
+
| @Tool('cancel_reservation') -> AppointmentService |
|
|
71
|
+
| @Tool('reschedule_reservation')-> AppointmentService |
|
|
72
|
+
| @Tool('check_patient_history') -> PatientService |
|
|
73
|
+
| @Tool('forward_to_operator') -> OperatorService |
|
|
74
|
+
| @Tool('forward_conversation') -> OperatorService |
|
|
75
|
+
| @Tool('send_example_photo') -> MediaService + MinIO |
|
|
76
|
+
| @Tool('call_patient') -> ElevenLabsService |
|
|
77
|
+
| @Tool('confirm_appointment_validation') -> ValidationService |
|
|
78
|
+
| @Tool('request_payment') -> TekTipPayService (stub) |
|
|
79
|
+
| @Tool('send_sms') -> NetGsmService (stub) |
|
|
80
|
+
| |
|
|
81
|
+
| Each handler: receives ToolContext + params -> returns result |
|
|
82
|
+
| Pure business logic -- zero knowledge of AI provider format |
|
|
83
|
+
+--------------------------------------------------------------+
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Core Interfaces
|
|
89
|
+
|
|
90
|
+
### ToolContext (Channel-Agnostic)
|
|
91
|
+
|
|
92
|
+
Every tool handler receives a `ToolContext` that identifies who is calling, which tenant, which channel, and all channel-specific metadata. The handler never needs to know whether the call came from a WebSocket message or an HTTP webhook.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
interface ToolContext {
|
|
96
|
+
// Who
|
|
97
|
+
tenantId: string;
|
|
98
|
+
tenant: TenantWithSettings; // Full tenant with parsed settings
|
|
99
|
+
clinicId: string | null; // Which clinic this interaction belongs to
|
|
100
|
+
clinic: ClinicWithSettings | null;
|
|
101
|
+
|
|
102
|
+
// Patient / contact
|
|
103
|
+
patientPhone: string; // E.164 format
|
|
104
|
+
patientName: string;
|
|
105
|
+
|
|
106
|
+
// Channel info
|
|
107
|
+
channel: 'whatsapp' | 'voice_call' | 'instagram' | 'test_chat';
|
|
108
|
+
channelMetadata: {
|
|
109
|
+
chatId?: string; // WhatsApp chat ID
|
|
110
|
+
sessionId?: string; // WhatsApp session ID
|
|
111
|
+
conversationId?: string; // ElevenLabs conversation ID
|
|
112
|
+
agentId?: string; // ElevenLabs agent ID
|
|
113
|
+
phoneNumberId?: string; // Which PhoneNumber received this interaction
|
|
114
|
+
patientId?: string; // Resolved Patient ID (looked up on tool execution by phone match)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### ToolDefinition
|
|
120
|
+
|
|
121
|
+
Describes a tool for discovery, validation, and AI prompt generation.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
interface ToolDefinition {
|
|
125
|
+
name: string; // e.g., 'check_availability'
|
|
126
|
+
description: string; // For AI agent prompt
|
|
127
|
+
parameters: JsonSchema; // JSON Schema for parameter validation
|
|
128
|
+
requiredFeatures?: string[]; // Tenant feature flags needed (e.g., ['google_calendar'])
|
|
129
|
+
channels?: string[]; // Which channels support this tool (default: all)
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### ToolResult
|
|
134
|
+
|
|
135
|
+
Every tool handler returns a `ToolResult`. Adapters translate this into the provider-specific format.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
interface ToolResult {
|
|
139
|
+
data: any; // Tool-specific result payload
|
|
140
|
+
isError: boolean; // Whether this is an error result
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## @Tool() Decorator and Auto-Discovery
|
|
147
|
+
|
|
148
|
+
### The Decorator
|
|
149
|
+
|
|
150
|
+
The `@Tool()` decorator attaches a `ToolDefinition` to a method via NestJS `SetMetadata`. No registration boilerplate is needed -- the registry finds everything automatically.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { SetMetadata } from '@nestjs/common';
|
|
154
|
+
|
|
155
|
+
export const TOOL_METADATA_KEY = 'tool:definition';
|
|
156
|
+
|
|
157
|
+
export function Tool(definition: ToolDefinition): MethodDecorator {
|
|
158
|
+
return SetMetadata(TOOL_METADATA_KEY, definition);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Auto-Discovery via DiscoveryService
|
|
163
|
+
|
|
164
|
+
On module initialization, `ToolRegistryService` uses NestJS `DiscoveryService` to scan every provider in the application. For each provider instance, it iterates over all methods and checks for the `TOOL_METADATA_KEY` metadata. Any decorated method is registered in the internal `tools` map.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
@Injectable()
|
|
168
|
+
export class ToolRegistryService implements OnModuleInit {
|
|
169
|
+
private tools = new Map<string, {
|
|
170
|
+
instance: any;
|
|
171
|
+
method: string;
|
|
172
|
+
definition: ToolDefinition;
|
|
173
|
+
}>();
|
|
174
|
+
|
|
175
|
+
constructor(
|
|
176
|
+
private readonly discoveryService: DiscoveryService,
|
|
177
|
+
private readonly reflector: Reflector,
|
|
178
|
+
private readonly prisma: PrismaService,
|
|
179
|
+
) {}
|
|
180
|
+
|
|
181
|
+
onModuleInit() {
|
|
182
|
+
const providers = this.discoveryService.getProviders();
|
|
183
|
+
for (const wrapper of providers) {
|
|
184
|
+
const instance = wrapper.instance;
|
|
185
|
+
if (!instance) continue;
|
|
186
|
+
|
|
187
|
+
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(instance));
|
|
188
|
+
for (const method of methods) {
|
|
189
|
+
const definition = this.reflector.get<ToolDefinition>(
|
|
190
|
+
TOOL_METADATA_KEY,
|
|
191
|
+
instance[method],
|
|
192
|
+
);
|
|
193
|
+
if (definition) {
|
|
194
|
+
this.tools.set(definition.name, { instance, method, definition });
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This means adding a new tool is a single-step process: write a method with `@Tool()` in any `@Injectable()` class, and the registry picks it up on next startup.
|
|
203
|
+
|
|
204
|
+
### Usage in a Handler Class
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
@Injectable()
|
|
208
|
+
export class CalendarTools {
|
|
209
|
+
constructor(
|
|
210
|
+
private readonly appointmentService: AppointmentService,
|
|
211
|
+
private readonly prisma: PrismaService,
|
|
212
|
+
private readonly eventEmitter: EventEmitter2,
|
|
213
|
+
) {}
|
|
214
|
+
|
|
215
|
+
@Tool({
|
|
216
|
+
name: 'check_availability',
|
|
217
|
+
description: 'Check available appointment slots for a given date',
|
|
218
|
+
parameters: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
properties: {
|
|
221
|
+
date: { type: 'string', description: 'Date in YYYY-MM-DD format' },
|
|
222
|
+
},
|
|
223
|
+
required: ['date'],
|
|
224
|
+
},
|
|
225
|
+
requiredFeatures: ['appointments'],
|
|
226
|
+
})
|
|
227
|
+
async checkAvailability(ctx: ToolContext, params: { date: string }): Promise<ToolResult> {
|
|
228
|
+
const today = new Date().toISOString().split('T')[0];
|
|
229
|
+
if (params.date < today) {
|
|
230
|
+
return {
|
|
231
|
+
data: { error: `Past date. Today is: ${today}` },
|
|
232
|
+
isError: true,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const result = await this.appointmentService.checkAvailability(ctx.clinicId, params.date);
|
|
237
|
+
return { data: result, isError: false };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Tool Registry Service
|
|
245
|
+
|
|
246
|
+
The registry is the central coordinator. It handles discovery (described above), tool lookup by name, feature flag enforcement, execution, error handling, and logging.
|
|
247
|
+
|
|
248
|
+
### getAvailableTools()
|
|
249
|
+
|
|
250
|
+
Returns all tools that a given tenant can use on a given channel. Used by adapters to generate tool schemas for AI providers.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
getAvailableTools(tenant: TenantWithSettings, channel: string): ToolDefinition[] {
|
|
254
|
+
return Array.from(this.tools.values())
|
|
255
|
+
.filter(({ definition }) => {
|
|
256
|
+
if (definition.channels && !definition.channels.includes(channel)) return false;
|
|
257
|
+
if (definition.requiredFeatures) {
|
|
258
|
+
return definition.requiredFeatures.every(f => tenant.enabledFeatures.includes(f));
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
})
|
|
262
|
+
.map(({ definition }) => definition);
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### execute()
|
|
267
|
+
|
|
268
|
+
Resolves a tool by name, checks feature flags, runs the handler, catches errors, and logs the result.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
async execute(
|
|
272
|
+
toolName: string,
|
|
273
|
+
ctx: ToolContext,
|
|
274
|
+
params: Record<string, any>,
|
|
275
|
+
): Promise<ToolResult> {
|
|
276
|
+
const tool = this.tools.get(toolName);
|
|
277
|
+
if (!tool) {
|
|
278
|
+
return { data: { error: `Unknown tool: ${toolName}` }, isError: true };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Feature flag check
|
|
282
|
+
if (tool.definition.requiredFeatures) {
|
|
283
|
+
const missing = tool.definition.requiredFeatures.find(
|
|
284
|
+
f => !ctx.tenant.enabledFeatures.includes(f),
|
|
285
|
+
);
|
|
286
|
+
if (missing) {
|
|
287
|
+
return { data: { error: `Feature not enabled: ${missing}` }, isError: true };
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// TODO: Validate params against definition.parameters (JSON Schema)
|
|
292
|
+
|
|
293
|
+
const startTime = Date.now();
|
|
294
|
+
try {
|
|
295
|
+
const result = await tool.instance[tool.method](ctx, params);
|
|
296
|
+
this.logExecution(toolName, ctx, params, result, Date.now() - startTime);
|
|
297
|
+
return result;
|
|
298
|
+
} catch (error) {
|
|
299
|
+
const errorResult = { data: { error: error.message }, isError: true };
|
|
300
|
+
this.logExecution(toolName, ctx, params, errorResult, Date.now() - startTime);
|
|
301
|
+
return errorResult;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Adapters
|
|
309
|
+
|
|
310
|
+
Adapters translate between a provider-specific protocol and the generic `ToolContext` + `ToolResult` format. Each adapter is an `@Injectable()` class that depends on `ToolRegistryService`.
|
|
311
|
+
|
|
312
|
+
### ElevenLabsWsAdapter (WhatsApp Chat)
|
|
313
|
+
|
|
314
|
+
Handles WebSocket `client_tool_call` messages from ElevenLabs during WhatsApp AI conversations.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
@Injectable()
|
|
318
|
+
export class ElevenLabsWsToolAdapter {
|
|
319
|
+
constructor(private readonly toolRegistry: ToolRegistryService) {}
|
|
320
|
+
|
|
321
|
+
async handleToolCall(
|
|
322
|
+
wsMessage: ElevenLabsWsToolCallMessage,
|
|
323
|
+
ctx: ToolContext,
|
|
324
|
+
): Promise<ElevenLabsWsToolResultMessage> {
|
|
325
|
+
const { tool_call_id, tool_name, parameters } = wsMessage;
|
|
326
|
+
|
|
327
|
+
const result = await this.toolRegistry.execute(tool_name, ctx, parameters);
|
|
328
|
+
|
|
329
|
+
return {
|
|
330
|
+
type: 'client_tool_result', // MUST be lowercase
|
|
331
|
+
tool_call_id,
|
|
332
|
+
result: JSON.stringify(result.data),
|
|
333
|
+
is_error: result.isError, // REQUIRED field -- omitting causes WS 1008 disconnect
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Flow:** Patient message (via Meta Business API webhook) -> ElevenLabs WS -> `client_tool_call` -> `WhatsAppAgentService.handleToolCall()` -> `ElevenLabsWsAdapter.handleToolCall()` -> `ToolRegistryService.execute()` -> handler -> adapter formats `client_tool_result` -> WS sends to ElevenLabs -> AI continues. Tools that send messages (e.g., `forward_to_operator`, `send_example_photo`) use `MetaWhatsAppService` directly.
|
|
340
|
+
|
|
341
|
+
### ElevenLabsHttpAdapter (Voice Calls)
|
|
342
|
+
|
|
343
|
+
Handles HTTP webhook POST requests from ElevenLabs during SIP trunk voice calls.
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
@Injectable()
|
|
347
|
+
export class ElevenLabsHttpToolAdapter {
|
|
348
|
+
constructor(private readonly toolRegistry: ToolRegistryService) {}
|
|
349
|
+
|
|
350
|
+
async handleToolCall(
|
|
351
|
+
toolName: string,
|
|
352
|
+
body: ElevenLabsToolWebhookBody,
|
|
353
|
+
ctx: ToolContext,
|
|
354
|
+
): Promise<any> {
|
|
355
|
+
const result = await this.toolRegistry.execute(toolName, ctx, body.parameters || body);
|
|
356
|
+
return result.data; // HTTP response body (JSON)
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Flow:** Voice call -> AI needs data -> ElevenLabs calls `POST /webhooks/elevenlabs/tools/:toolName` -> `ElevenLabsToolController` resolves tenant from `agent_id` -> `ElevenLabsHttpAdapter.handleToolCall()` -> `ToolRegistryService.execute()` -> handler -> return JSON response.
|
|
362
|
+
|
|
363
|
+
### OpenAIFunctionAdapter (Future)
|
|
364
|
+
|
|
365
|
+
Converts tool definitions to OpenAI function calling schemas and handles function call results. This adapter enables switching AI providers without touching any tool handler.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
@Injectable()
|
|
369
|
+
export class OpenAIFunctionAdapter {
|
|
370
|
+
constructor(private readonly toolRegistry: ToolRegistryService) {}
|
|
371
|
+
|
|
372
|
+
getToolSchemas(tenant: TenantWithSettings, channel: string) {
|
|
373
|
+
return this.toolRegistry.getAvailableTools(tenant, channel).map(def => ({
|
|
374
|
+
type: 'function' as const,
|
|
375
|
+
function: {
|
|
376
|
+
name: def.name,
|
|
377
|
+
description: def.description,
|
|
378
|
+
parameters: def.parameters,
|
|
379
|
+
},
|
|
380
|
+
}));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async handleFunctionCall(
|
|
384
|
+
functionCall: { name: string; arguments: string },
|
|
385
|
+
ctx: ToolContext,
|
|
386
|
+
) {
|
|
387
|
+
const params = JSON.parse(functionCall.arguments);
|
|
388
|
+
const result = await this.toolRegistry.execute(functionCall.name, ctx, params);
|
|
389
|
+
return JSON.stringify(result.data);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## Complete Tool Inventory (13 Tools)
|
|
397
|
+
|
|
398
|
+
### 1. check_availability
|
|
399
|
+
|
|
400
|
+
- **Parameters:** `{ date: string }` (YYYY-MM-DD)
|
|
401
|
+
- **Required features:** `appointments`
|
|
402
|
+
- **Channels:** all
|
|
403
|
+
- **What it does:** Queries the local appointment database for the given date. Returns available time slots based on clinic working hours, blocked dates, and existing appointments. Our calendar is the source of truth; Google Calendar is optional sync.
|
|
404
|
+
- **Result:** `{ available_slots: [{ start, end }], date, timezone }`
|
|
405
|
+
|
|
406
|
+
### 2. reserve_slot
|
|
407
|
+
|
|
408
|
+
- **Parameters:** `{ patient_name?: string, iso_start: string, iso_end: string, notes?: string }`
|
|
409
|
+
- **Required features:** `appointments`
|
|
410
|
+
- **Channels:** all
|
|
411
|
+
- **What it does:** Re-checks availability for race protection, creates an appointment in the local database. If Google Calendar sync is enabled for the clinic, the event is also pushed to Google Calendar. Emits `appointment.created` event.
|
|
412
|
+
- **Result:** `{ appointment_id, start, end, patient_name }`
|
|
413
|
+
|
|
414
|
+
### 3. list_reservations
|
|
415
|
+
|
|
416
|
+
- **Parameters:** none
|
|
417
|
+
- **Required features:** `appointments`
|
|
418
|
+
- **Channels:** all
|
|
419
|
+
- **What it does:** Lists the current patient's upcoming appointments from the local database, filtered by `patient_id` (resolved from `patientPhone`).
|
|
420
|
+
- **Result:** `{ reservations: [{ appointment_id, start, end, summary }] }`
|
|
421
|
+
|
|
422
|
+
### 4. cancel_reservation
|
|
423
|
+
|
|
424
|
+
- **Parameters:** `{ appointment_id: string }`
|
|
425
|
+
- **Required features:** `appointments`
|
|
426
|
+
- **Channels:** all
|
|
427
|
+
- **What it does:** Verifies patient ownership before cancelling. Updates status to `cancelled` in local DB. Syncs to Google Calendar if connected. Emits `appointment.cancelled` event.
|
|
428
|
+
- **Result:** `{ cancelled: true, appointment_id }`
|
|
429
|
+
|
|
430
|
+
### 5. reschedule_reservation
|
|
431
|
+
|
|
432
|
+
- **Parameters:** `{ old_appointment_id: string, new_iso_start: string, new_iso_end: string, notes?: string }`
|
|
433
|
+
- **Required features:** `appointments`
|
|
434
|
+
- **Channels:** all
|
|
435
|
+
- **What it does:** Cancels the old appointment and creates a new one. Re-checks availability for the new slot. Syncs both changes to Google Calendar if connected. Emits `appointment.rescheduled` event.
|
|
436
|
+
- **Result:** `{ old_appointment_id, new_appointment_id, new_start, new_end }`
|
|
437
|
+
|
|
438
|
+
### 6. check_patient_history
|
|
439
|
+
|
|
440
|
+
- **Parameters:** none
|
|
441
|
+
- **Required features:** none
|
|
442
|
+
- **Channels:** all
|
|
443
|
+
- **What it does:** Queries the `Patient` model (replacing the old `WhatsAppContactProfile`) by phone match. Returns the patient's full profile, medical history, treatment plans, past appointments, examination records, and session summaries. The `patientId` is resolved on tool execution and stored in `channelMetadata.patientId`.
|
|
444
|
+
- **Result:** `{ patient, medical_history, treatment_plans, appointments, examination_records, sessions }`
|
|
445
|
+
|
|
446
|
+
### 7. forward_to_operator
|
|
447
|
+
|
|
448
|
+
- **Parameters:** `{ message?: string }`
|
|
449
|
+
- **Required features:** `operator_workflow`
|
|
450
|
+
- **Channels:** whatsapp, instagram
|
|
451
|
+
- **What it does:** Finds all media messages in the current session, forwards each to the operator (doctor) phone number via Meta Business API with 500ms delay between sends. Creates an `OperatorRequest` with a unique REF code. Sets `awaiting_operator` flag on the session.
|
|
452
|
+
- **Result:** `{ ref_code, forwarded_count, failed_count }`
|
|
453
|
+
|
|
454
|
+
### 8. forward_conversation_to_operator
|
|
455
|
+
|
|
456
|
+
- **Parameters:** `{ summary?: string, patient_messages?: string }`
|
|
457
|
+
- **Required features:** `conversation_forwarding`
|
|
458
|
+
- **Channels:** whatsapp, instagram
|
|
459
|
+
- **What it does:** Forwards conversation text (not media) to the operator. Useful when the doctor needs conversation context rather than photos.
|
|
460
|
+
- **Result:** `{ forwarded: true }`
|
|
461
|
+
|
|
462
|
+
### 9. send_example_photo
|
|
463
|
+
|
|
464
|
+
- **Parameters:** none
|
|
465
|
+
- **Required features:** `operator_workflow`
|
|
466
|
+
- **Channels:** whatsapp, instagram
|
|
467
|
+
- **What it does:** Sends a pre-configured guide image (from MinIO) to the patient via Meta Business API send media endpoint, showing camera angle and posing instructions. Uses the tenant's `operator_example_photo_caption`.
|
|
468
|
+
- **Result:** `{ sent: true }`
|
|
469
|
+
|
|
470
|
+
### 10. call_patient
|
|
471
|
+
|
|
472
|
+
- **Parameters:** `{ reason?: string }`
|
|
473
|
+
- **Required features:** none
|
|
474
|
+
- **Channels:** whatsapp
|
|
475
|
+
- **What it does:** Initiates an outbound voice call to the patient via ElevenLabs SIP trunk. Passes the reason as context to the voice agent.
|
|
476
|
+
- **Result:** `{ call_initiated: true, conversation_id }`
|
|
477
|
+
|
|
478
|
+
### 11. confirm_appointment_validation
|
|
479
|
+
|
|
480
|
+
- **Parameters:** `{ result: 'confirmed' | 'cancelled' | 'reschedule', reschedule_request?: string, patient_message?: string }`
|
|
481
|
+
- **Required features:** `appointment_validation`
|
|
482
|
+
- **Channels:** voice_call
|
|
483
|
+
- **What it does:** Records the outcome of a validation call. Updates the `AppointmentValidationEntry` status. If rescheduled, stores the patient's preferred time.
|
|
484
|
+
- **Result:** `{ recorded: true, result }`
|
|
485
|
+
|
|
486
|
+
### 12. request_payment (stub)
|
|
487
|
+
|
|
488
|
+
- **Parameters:** `{ amount: number, description?: string, appointment_id?: string }`
|
|
489
|
+
- **Required features:** `payments`
|
|
490
|
+
- **Channels:** whatsapp, voice_call
|
|
491
|
+
- **What it does:** Creates a payment link via TekTipPay and sends it to the patient (via WhatsApp message or SMS for voice calls). **Stub:** TekTipPay is an empty placeholder module -- handler is registered but returns a "not yet available" error until the integration is implemented.
|
|
492
|
+
- **Result:** `{ payment_link, payment_id, amount }`
|
|
493
|
+
|
|
494
|
+
### 13. send_sms (stub)
|
|
495
|
+
|
|
496
|
+
- **Parameters:** `{ phone?: string, message: string }`
|
|
497
|
+
- **Required features:** `sms_notifications`
|
|
498
|
+
- **Channels:** whatsapp, voice_call
|
|
499
|
+
- **What it does:** Sends an SMS to the patient (or a custom number if provided) via NetGSM. **Stub:** NetGSM is an empty placeholder module -- handler is registered but returns a "not yet available" error until the integration is implemented.
|
|
500
|
+
- **Result:** `{ sent: true, job_id }`
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Tool Execution Logging
|
|
505
|
+
|
|
506
|
+
Every tool invocation is logged to the `tool_execution_logs` table for analytics, debugging, and usage tracking.
|
|
507
|
+
|
|
508
|
+
### Prisma Model
|
|
509
|
+
|
|
510
|
+
```prisma
|
|
511
|
+
model ToolExecutionLog {
|
|
512
|
+
id String @id @default(uuid())
|
|
513
|
+
tenantId String
|
|
514
|
+
toolName String
|
|
515
|
+
channel String // 'whatsapp', 'voice_call', 'instagram', 'test_chat'
|
|
516
|
+
patientPhone String @default("")
|
|
517
|
+
conversationId String?
|
|
518
|
+
parameters Json @default("{}")
|
|
519
|
+
result Json @default("{}")
|
|
520
|
+
isError Boolean @default(false)
|
|
521
|
+
durationMs Int @default(0)
|
|
522
|
+
createdAt DateTime @default(now())
|
|
523
|
+
|
|
524
|
+
@@index([tenantId, createdAt(sort: Desc)])
|
|
525
|
+
@@index([toolName, createdAt(sort: Desc)])
|
|
526
|
+
@@index([conversationId])
|
|
527
|
+
@@map("tool_execution_logs")
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Write Behavior
|
|
532
|
+
|
|
533
|
+
Logs are written fire-and-forget after each tool execution. A failed log write never causes the tool result to fail.
|
|
534
|
+
|
|
535
|
+
```typescript
|
|
536
|
+
private async logExecution(
|
|
537
|
+
toolName: string, ctx: ToolContext, params: any, result: ToolResult, durationMs: number,
|
|
538
|
+
) {
|
|
539
|
+
await this.prisma.toolExecutionLog.create({
|
|
540
|
+
data: {
|
|
541
|
+
tenantId: ctx.tenantId,
|
|
542
|
+
toolName,
|
|
543
|
+
channel: ctx.channel,
|
|
544
|
+
patientPhone: ctx.patientPhone,
|
|
545
|
+
conversationId: ctx.channelMetadata.conversationId,
|
|
546
|
+
parameters: params,
|
|
547
|
+
result: result.data,
|
|
548
|
+
isError: result.isError,
|
|
549
|
+
durationMs,
|
|
550
|
+
},
|
|
551
|
+
}).catch(() => {}); // fire-and-forget
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Cleanup
|
|
556
|
+
|
|
557
|
+
BullMQ repeatable job deletes logs older than 30 days (or per-tenant `log_retention_days` setting).
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## Per-Tenant Tool Configuration (Future)
|
|
562
|
+
|
|
563
|
+
The system supports future per-tenant tool customization via tenant settings:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
// In TenantSettings:
|
|
567
|
+
tools: {
|
|
568
|
+
disabled_tools: string[]; // e.g., ['call_patient'] -- disable specific tools
|
|
569
|
+
tool_overrides: Record<string, { // Per-tool config overrides
|
|
570
|
+
custom_prompt?: string; // Override tool description sent to AI
|
|
571
|
+
parameters_override?: JsonSchema; // Override parameter schema
|
|
572
|
+
}>;
|
|
573
|
+
};
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
This allows tenants to:
|
|
577
|
+
|
|
578
|
+
- **Disable tools** they do not need, reducing AI confusion.
|
|
579
|
+
- **Customize tool descriptions** for their specific AI agent prompt.
|
|
580
|
+
- **Add parameter constraints** (e.g., limit booking to specific time ranges).
|
|
581
|
+
|
|
582
|
+
The registry checks `disabled_tools` during `getAvailableTools()` and merges `tool_overrides` into the definition before returning to adapters.
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## File Structure
|
|
587
|
+
|
|
588
|
+
```
|
|
589
|
+
src/tools/
|
|
590
|
+
tools.module.ts # ToolsModule -- imports all handler classes
|
|
591
|
+
tool.decorator.ts # @Tool() decorator
|
|
592
|
+
tool.interfaces.ts # ToolContext, ToolDefinition, ToolResult, ToolHandler
|
|
593
|
+
tool-registry.service.ts # Discovery, validation, execution, logging
|
|
594
|
+
adapters/
|
|
595
|
+
elevenlabs-ws.adapter.ts # WS client_tool_call <-> ToolRegistry
|
|
596
|
+
elevenlabs-http.adapter.ts # HTTP webhook <-> ToolRegistry
|
|
597
|
+
openai-function.adapter.ts # OpenAI function calling <-> ToolRegistry (future)
|
|
598
|
+
handlers/
|
|
599
|
+
calendar.tools.ts # check_availability, reserve_slot, list, cancel, reschedule
|
|
600
|
+
operator.tools.ts # forward_to_operator, forward_conversation, send_example_photo
|
|
601
|
+
patient.tools.ts # check_patient_history, call_patient
|
|
602
|
+
validation.tools.ts # confirm_appointment_validation
|
|
603
|
+
payment.tools.ts # request_payment (stub -- TekTipPay not yet implemented)
|
|
604
|
+
notification.tools.ts # send_sms (stub -- NetGSM not yet implemented)
|
|
605
|
+
schemas/ # JSON Schema definitions for each tool (optional, can be inline)
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Integration Flows
|
|
611
|
+
|
|
612
|
+
### WhatsApp Chat (ElevenLabs WebSocket)
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
Patient message
|
|
616
|
+
-> ElevenLabs WS
|
|
617
|
+
-> agent_response / client_tool_call
|
|
618
|
+
-> WhatsAppAgentService.handleToolCall()
|
|
619
|
+
-> ElevenLabsWsAdapter.handleToolCall()
|
|
620
|
+
-> ToolRegistryService.execute(toolName, ctx, params)
|
|
621
|
+
-> CalendarTools.reserveSlot(ctx, params)
|
|
622
|
+
-> ElevenLabsWsAdapter formats -> client_tool_result
|
|
623
|
+
-> WS sends result
|
|
624
|
+
-> AI continues conversation
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
### Voice Call (ElevenLabs HTTP Webhook)
|
|
628
|
+
|
|
629
|
+
```
|
|
630
|
+
Voice call
|
|
631
|
+
-> AI needs data
|
|
632
|
+
-> ElevenLabs calls POST /webhooks/elevenlabs/tools/:toolName
|
|
633
|
+
-> ElevenLabsToolController.handleTool()
|
|
634
|
+
-> Resolve ToolContext (tenant from agent_id header)
|
|
635
|
+
-> ElevenLabsHttpAdapter.handleToolCall()
|
|
636
|
+
-> ToolRegistryService.execute(toolName, ctx, params)
|
|
637
|
+
-> CalendarTools.reserveSlot(ctx, params)
|
|
638
|
+
-> Return JSON response to ElevenLabs
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### Test Chat (Admin Panel)
|
|
642
|
+
|
|
643
|
+
```
|
|
644
|
+
Admin sends test message
|
|
645
|
+
-> TestChatService
|
|
646
|
+
-> AI response / tool_call
|
|
647
|
+
-> Same ToolRegistry.execute() -- channel = 'test_chat'
|
|
648
|
+
-> Tool executes (or mocks based on flag)
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
## Benefits
|
|
654
|
+
|
|
655
|
+
| Benefit | How |
|
|
656
|
+
|---------|-----|
|
|
657
|
+
| **Zero duplication** | Each tool implemented once, used from any channel |
|
|
658
|
+
| **AI provider agnostic** | Adapters handle protocol differences; handlers never know about ElevenLabs/OpenAI |
|
|
659
|
+
| **Easy to add tools** | Write a handler method with `@Tool()` -- auto-discovered on startup |
|
|
660
|
+
| **Easy to add providers** | Write a new adapter -- all existing tools work immediately |
|
|
661
|
+
| **Feature-flag gated** | `requiredFeatures` on each tool, checked at registry level |
|
|
662
|
+
| **Channel-aware** | `channels` field limits which channels can use which tools |
|
|
663
|
+
| **Observable** | `ToolExecutionLog` tracks every invocation with timing and error state |
|
|
664
|
+
| **Testable** | Tool handlers are pure business logic -- inject mocks, test independently |
|
|
665
|
+
| **Per-tenant configurable** | Disable/customize tools per tenant (future) |
|