* chore: Upgrade prisma to 6.7.0 * Build fixes * type fixes Signed-off-by: Omar López <zomars@me.com> * Update schema.prisma * Patching * Revert "Update schema.prisma" This reverts commit 47d8618bf89ef4d007b30084df766f17281e21a1. * Revert "Patching" This reverts commit a1d2e3040e71690a44d4324db95d73b4d68c6adb. * Revert schema changes Signed-off-by: Omar López <zomars@me.com> * WIP Signed-off-by: Omar López <zomars@me.com> * Update getPublicEvent.ts * Update imports Signed-off-by: Omar López <zomars@me.com> * Update gitignore Signed-off-by: Omar López <zomars@me.com> * update remaining imports Signed-off-by: Omar López <zomars@me.com> * Delete .cursor/config.json * Discard changes to packages/features/eventtypes/lib/getPublicEvent.ts * Update _get.ts * Update user.ts * Update .gitignore * update * Update WorkflowStepContainer.tsx * Update next-auth-custom-adapter.ts * Update getPublicEvent.ts * Update workflow.ts * Update next-auth-custom-adapter.ts * Update next-auth-options.ts * Update bookingScenario.ts * fix missing imports * upgrades prismock Signed-off-by: Omar López <zomars@me.com> * patches prismock Signed-off-by: Omar López <zomars@me.com> * Update reschedule.test.ts * Update prisma.ts * patch prismock Signed-off-by: Omar López <zomars@me.com> * fix enums imports Signed-off-by: Omar López <zomars@me.com> * Revert "Update prisma.ts" This reverts commit 64edcf8db54171ff4456c209d563b5d431d99619. * Revert "patch prismock" This reverts commit e95819113dc9d88e7130947aa120cd42710977c8. * fix patch * Fix test that overrun the boundary, it shouldn't test too much * Move prisma import to changeSMSLockState * Bring back broken test without illegal imports * Merge with main and fix filter hosts by same round robin host * Fixed buildDryRunBooking fn tests * Fix and move ooo create or update handler test * Fix packages/features/eventtypes/lib/isCurrentlyAvailable.test.ts * Fix packages/trpc/server/routers/viewer/organizations/listMembers.handler.test.ts * Mock @calcom/prisma * Fix: verify-email.test.ts * fix: Moved WebhookService test and fixed default import mock * Fix: Added missing prisma mock, handleNewBooking uses that of course * We're not testing createContext here * fix: Prisma mock fix for listMembers.test.ts * More fixes to broken testcases * Forgot to remove borked test * Prevent the need to mock a lot of dependencies by moving out buildBaseWhereCondition to its own file * Temporarily skip getCalendarEvents, needs a rewrite * Fix: turns out you can access protected in testcases * fix further mocks * Added packages/features/insights/server/buildBaseWhereCondition.ts, types * Always great to have a mock and then not use it * And one less again. * fix: confirm.handler.test, didn't mock prisma * fix: Address minor nit by @eunjae & fix ImpersonationProvider test * Updated isPrismaAvailableCheck that doesn't crash on import * fix: Get Prisma directly from the client, it usually involves the Validator and does not need 'local' inclusion * Add zod-prisma-types without the generator enabled (commented out) * Uncomment and see what happens * Change method of import as imports did not work in Input Schemas * Remove custom 'zod' booking model, it does not belong with Prisma * Fix all other global Model imports * Rewrite most schema includes AND remove barrel file * Add bookingCreateBodySchema to features/bookings * Flurry of type fixes for compatibility with new zod gen * Refactor out the custom prisma type createEventTypeInput * Work around nullable eventTypeLocations * HandlePayment type fix * More fixes, final fix remaining is CompleteEventType * Should fix a bunch more booking related type errors * Missed one * Some props missing from BookingCreateBodySchema * Fix location type in handleChildrenEventTypes * Little bit hacky imo but it works * Final type error \o/ * Forgot to include Prisma * Do not include zod-utils in booker/types * Oops, was already including Booker/types * Fix membership type, also disallow updating createdAt/updatedAt, make part of patch/post * Fix api v1 type errors * Fix EventTypeDescription typings * Remove getParserWithGeneric, use userBodySchema with UserSchema * use centralized timeZoneSchema * Implement feedback by @zomars * Couple of WIP pushes * Fix tests * Type fixes in `handleChildrenEventTypes` test * Try and parse metadata before use * Change zod-prisma-types configuration for optimal performance * Fix prisma validator error in `prisma/selects/credential` * Disable seperate relations model, hits a bug * Import absolute - this makes rollup work in @platform/libraries * Attempt at removing resolutions override * Refactor using `Prisma.validator` to `satisfies` * Build atoms using @calcom/prisma/client * Build atoms using @calcom/prisma/client * fixes * Update eventTypeSelect.ts * Adjust `eventTypeMetaDataSchemaWithUntypedApps` from `unknown` to `record(any)` * `EventTypeDescription` rely on `descriptionAsSafeHTML` instead of `description` * Add `seatsPerTimeSlot` to event type public select * Fix typing in `users-public-view` getServerSide props * Add missing `schedulingType` to prop * chore: bump platform libraries * Function return type is illegal, not sure how this passed eslint (#21567) * Merged with main * Update updateTokenObject.ts * Update handleResponse.ts * Update index.ts * Update handleChildrenEventTypes.ts * Update booking-idempotency-key.ts * Update WebhookService.test.ts * Update events.test.ts * Update queued-response.test.ts * Update events.test.ts * Update getRoutedUrl.test.ts * fix: type checks Signed-off-by: Omar López <zomars@me.com> * fixes Signed-off-by: Omar López <zomars@me.com> * chore: bump platform libraries * Update yarn.lock * more fixes Signed-off-by: Omar López <zomars@me.com> * fixes Signed-off-by: Omar López <zomars@me.com> * biuld fixes * chore: bump platform libraries * Update conferencing.repository.ts * Update conferencing.repository.ts * Update getCalendarsEvents.test.ts * Update vite.config.js * chore: bump platform libraries * Update users.ts * Discard changes to docs/api-reference/v2/openapi.json * Update vite.config.ts * updated platform libraries * Update get.handler.test.ts * Update get.handler.test.ts * Update schema.prisma * Discard changes to docs/api-reference/v2/openapi.json * Update next-auth-custom-adapter.ts * Update team.ts * Flurry of type fixes * Fix majority of insight related type errors * Type fixes for unlink of account * Make user nullable again * Fixed a bunch of unit tests and one type error * Attempted mock fix * Attempted fix for Attribute type * Ensure default import becomes prisma, but not direct usage * Import default as prisma in prisma.module * Add attributeOption to attribute type * Fix calcom/prisma mock * Refactor Prisma client imports to @calcom/prisma/client Updated all imports from '@prisma/client' to '@calcom/prisma/client' across tests and repository files for consistency and to use the correct Prisma client package. This change improves maintainability and ensures the correct client is referenced throughout the codebase. * Undo removal of max-warnings=0 to get main to merge * Remove unit tests for e2e fixtures, provide new prisma mock * Mock @calcom/prisma in event manager * Mock @calcom/prisma in event manager * Add correct format even with --no-verify * Mock prisma in CalendarManager * Add mock for permission-check.service * Better injection in PrismaApiKeyRepository imports * More mock fixes :) * Fix listMembers.handler.test * Fix User import * Appropriately adjust all types to be imported as types, there were a lot of types imported as normal deps * Why was this a thing? * Strictly speaking; Not using prismock anymore * Ditched patch file for prismock * Fix output.service.ts platform type imports, need concrete for plainToClass * Better typing and tests for unlinkConnectedAccount.handler * Small type fix * Disable calendar cache tests as they are dependent on prismock * chore: bump platform lib * getRoutedUrl test remove of unused import * Extract select to external const on getEventTypesFromDB * Direct select of userSelect from selects/user * fix type error from merging 23653 * Fixed integration tests by removing hardcoded values that were possible due to mocking, but as its now directly hitting the db no longer * fix: vite config atoms prisma client type location * revert: example app prisma client * revert: example app prisma client * bump platform libs * fix: use class instead of type for DI of PlatformBookingsService * update platform libs * remove unused variable * chore: generate prisma client for api v2 * fix: api v2 e2e * fix: atoms e2e * fix: atoms e2e * fix: atoms e2e * fix: api v2 e2e * fix: tsconfig apiv2 enums * publish libraries * Simplify check for existence teamId --------- Signed-off-by: Omar López <zomars@me.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com> Co-authored-by: supalarry <laurisskraucis@gmail.com> Co-authored-by: cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Benny Joo <sldisek783@gmail.com>
Cal.com AI Phone Service Architecture
This package provides a comprehensive, provider-agnostic architecture for AI phone services in Cal.com, offering easy integration with different AI service providers, template management, and self-service UI components.
Architecture Overview
The architecture implements multiple design patterns to create a maintainable, scalable, and flexible system:
Layered Architecture
┌─────────────────────────────────────────────┐
│ Frontend (React/Next.js) │
│ - UI Components (Agent/Phone Management) │
├─────────────────────────────────────────────┤
│ TRPC API Layer │
│ - Type-safe RPC endpoints │
│ - Request/Response validation │
├─────────────────────────────────────────────┤
│ Service Layer │
│ - Business logic orchestration │
│ - Provider abstraction │
├─────────────────────────────────────────────┤
│ Repository Layer │
│ - Data access abstraction │
│ - Query optimization │
├─────────────────────────────────────────────┤
│ Prisma ORM / Database │
│ - PostgreSQL with optimized queries │
└─────────────────────────────────────────────┘
Design Patterns Implemented
- Repository Pattern: Encapsulates data access logic
- Factory Pattern: Creates provider instances dynamically
- Strategy Pattern: Allows switching between AI providers
- Service Pattern: Orchestrates business logic
- Registry Pattern: Manages provider registration
- Template Pattern: Provides reusable conversation templates
- Mapper Pattern: Transforms data between layers
Key Components
1. Generic Interfaces (interfaces/AIPhoneService.interface.ts)
AIPhoneServiceProvider- Main interface that all providers must implementAIPhoneServiceConfiguration- Configuration for setting up AI servicesAIPhoneServiceProviderFactory- Factory interface for creating providers- Common data types (
AIPhoneServiceModel,AIPhoneServiceCall,AIPhoneServiceAgent, etc.) - Phone number management interfaces
- Agent and LLM management interfaces
2. Provider Registry (AIPhoneServiceRegistry.ts)
AIPhoneServiceRegistry- Central registry for managing providerscreateAIPhoneServiceProvider()- Helper function to create providerscreateDefaultAIPhoneServiceProvider()- Convenience function for default provider- Provider registration and management system
3. Template System
- Template Types:
CHECK_IN_APPOINTMENTandCUSTOM_TEMPLATE - Prompt Templates (
promptTemplates.ts): Pre-defined conversation templates with placeholders - Field Mapping (
template-fields-map.ts): Dynamic field definitions for different template types - Schema Validation (
zod-utils.ts): Comprehensive validation schemas for all data types - Template Field Schema (
getTemplateFieldsSchema.ts): Dynamic schema generation based on template type
4. Provider Implementations (providers/)
retellAI/- Complete Retell AI implementation with:- Provider class with full interface implementation
- Factory for provider creation
- SDK client for API communication
- Service layer for business logic
- Error handling and type definitions
example-future-provider/- Example showing how to add new providers
5. UI Components (components/)
CreateAgentStep.tsx- Step-by-step agent creation wizardCreateWorkflowAgent.tsx- Workflow-based agent setupAgentsListPage.tsx- Agent management and listingSkeletonLoaderList.tsx- Loading states for better UX
6. Pages (pages/)
agent.tsx- Agent management pageindex.tsx- Main AI phone service dashboard
7. Data Layer Components
- Repository Classes (
/packages/lib/server/repository/)PrismaAgentRepository- Manages agent data accessPrismaPhoneNumberRepository- Handles phone number operations
- Service Classes (
providers/retellAI/RetellAIService.ts)- Business logic orchestration
- External API integration
- Mapper Functions
- Transform between database models and DTOs
- Handle data serialization/deserialization
Architecture Patterns in Detail
Repository Pattern
The repository pattern provides an abstraction layer over data access, making the system database-agnostic and testable.
Benefits:
- Separation of Concerns: Business logic separated from data access
- Testability: Easy to mock for unit tests
- Flexibility: Can switch between Prisma ORM and raw SQL
- Reusability: Common queries centralized in one place
Factory Pattern
The factory pattern enables dynamic creation of provider instances without exposing instantiation logic.
Benefits:
- Loose Coupling: Client code doesn't depend on concrete classes
- Extensibility: Easy to add new providers
- Configuration Management: Centralized provider setup
Service Pattern
Service layer orchestrates business operations and coordinates between multiple repositories and external services.
Benefits:
- Business Logic Encapsulation: Complex operations in one place
- Transaction Management: Coordinates multiple operations
- Reusability: Common workflows available to all consumers
Registry Pattern
The registry pattern manages provider registration and lookup, acting as a service locator.
Benefits:
- Dynamic Provider Management: Add/remove providers at runtime
- Centralized Configuration: Single point for provider management
- Dependency Injection: Supports IoC principles
Mapper Pattern
Mappers transform data between different representations (database models, DTOs, API responses).
Benefits:
- Data Transformation: Clean separation between layers
- Flexibility: Different representations for different contexts
- Maintainability: Changes in one layer don't affect others
Strategy Pattern
The strategy pattern allows switching between different AI providers seamlessly.
Benefits:
- Provider Independence: Switch providers without changing client code
- Extensibility: Add new providers easily
- Testing: Mock providers for testing
Integration with Cal.com Workflows
The AI Phone system is designed specifically for Cal.com's workflow automation, enabling AI-powered phone calls as part of scheduling workflows.
Workflow Integration Architecture
┌─────────────────────────────────────────────┐
│ Cal.com Workflow Engine │
├─────────────────────────────────────────────┤
│ Workflow Step: AI Phone Call │
├─────────────────────────────────────────────┤
│ AI Phone Service (via Registry) │
├─────────────────────────────────────────────┤
│ Agent + Phone Number Setup │
└─────────────────────────────────────────────┘
Workflow Step Configuration
AI Phone calls are configured as workflow steps with specific triggers.
Supported Workflow Triggers
AI Phone calls can be triggered by various workflow events:
- BEFORE_EVENT: Call attendees before appointments
- AFTER_EVENT: Follow up after meetings
- NEW_EVENT: Welcome calls for new bookings
- RESCHEDULE_EVENT: Notify about schedule changes
- CANCELLED_EVENT: Handle cancellation calls
Workflow Execution Flow
1. Workflow Trigger (e.g., 24 hours before event)
↓
2. Workflow Engine schedules AI Phone Call task
↓
3. Task Runner (executeAIPhoneCall) executes
↓
4. AI Phone Service creates call with dynamic data
↓
5. Call connects and AI handles conversation
↓
6. Call results logged back to workflow
Rate Limiting for Workflows
To prevent abuse, workflow AI calls are rate-limited.
Data Flow Architecture
Workflow-Specific Data Flow
1. Workflow Trigger Event
↓
2. Workflow Step Configuration Retrieved
↓
3. Booking & Attendee Data Fetched
↓
4. Dynamic Variables Prepared
↓
5. AI Agent & Phone Number Selected
↓
6. Phone Call Initiated
↓
7. Results Logged to Workflow
Usage Examples
For complete usage examples, please refer to:
- Basic Usage: See commented examples in
index.ts - Provider Setup: Check provider factories in
providers/ - Workflow Integration: Review
packages/features/handleCreatePhoneCall.ts
Field Types
Supported field types include:
text,textarea,number,email,phoneaddress,multiemail,select,multiselectcheckbox,radio,radioInput,boolean
Template Variables
Templates support dynamic variables:
{{scheduler_name}}- Name of the scheduler{{name}}- Guest name{{email}}- Guest email{{company}}- Guest company{{current_time}}- Current timestamp- And many more
Adding New Providers
For detailed instructions on adding new providers, see the example provider implementation.
Environment Variables
RETELL_AI_KEY- API key for Retell AI (required when using Retell AI provider)STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID- Stripe price ID for monthly phone number subscriptions (required for billing)NODE_ENV- Controls logging behavior (logging disabled in production)
Stripe Integration
The AI Phone system integrates with Stripe for phone number billing. When users purchase phone numbers through the workflow system, they're redirected to Stripe checkout.
The STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID should be set to your Stripe price ID that represents the monthly subscription cost for AI phone numbers. This price ID is created in your Stripe dashboard and determines how much customers are charged monthly for each phone number.
Credit System and Billing
Webhook-Based Credit Deduction
The AI Phone system automatically deducts credits from user or team accounts when calls are completed. This is handled by the webhook at apps/web/app/api/webhooks/retellAI/route.ts.
Credit Deduction Flow
1. AI Phone Call Completes
↓
2. Provider sends "call_analyzed" webhook
↓
3. Webhook verifies signature for security
↓
4. System looks up phone number owner (user/team)
↓
5. Calculates credits based on usage factors
↓
6. Verifies sufficient credits available
↓
7. Deducts credits from account
↓
8. Logs transaction for audit
Credit Calculation
Credits are deducted based on multiple factors including:
- Call Duration: Longer calls consume more credits
- Prompt Complexity: Advanced prompts and conversation templates affect cost
- Voice Configuration: Different voice models and settings impact pricing
- Features Used: Additional AI capabilities and tools increase credit usage
The system calculates the total cost and converts it to credits for deduction from the user or team account.
Webhook Setup
The webhook requires proper configuration:
- Webhook URL: Add the webhook endpoint to your AI provider dashboard
- Environment Variables: Set appropriate API keys for webhook verification
- Security: Webhook signatures are verified to ensure authenticity
Credit Service Integration
The webhook integrates with Cal.com's credit system to check and deduct credits appropriately.
Error Handling
The webhook includes comprehensive error handling:
- Invalid Signatures: Returns 401 Unauthorized
- Missing Phone Number: Logs error, cannot deduct credits
- Insufficient Credits: Logs warning but doesn't block (call already completed)
- Missing Cost Data: Logs error and skips credit deduction
Supported Events
The webhook processes call completion events that contain the final usage data and cost information. Other events are acknowledged but not processed for billing purposes.
Provider-Specific Documentation
- Retell AI Provider - Complete Retell AI integration
- Example Provider - Template for new providers
Future Enhancements
- Multi-language template support
- Advanced workflow builder UI
- Provider health checks and automatic failover
- Real-time call monitoring and analytics
- Integration with Cal.com's webhook system
- Custom field type plugins
- Template marketplace and sharing
- Advanced agent training and optimization tools
- Integration with more AI service providers
- Voice cloning and customization options