-
Notifications
You must be signed in to change notification settings - Fork 10.4k
feat: cal.ai self serve #21827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: cal.ai self serve #21827
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 2 Skipped Deployments
|
✅ No security or compliance issues detected. Reviewed everything up to b1b9aac. Security Overview
Detected Code ChangesThe diff is too large to display a summary of code changes. Reply to this PR with |
makeSelfServePhoneCall: authedProcedure | ||
.input(z.object({ eventTypeId: z.number(), numberToCall: z.string() })) | ||
.mutation(async ({ ctx, input }) => { | ||
const { eventTypeId, numberToCall } = input; | ||
console.log("makeSelfServePhoneCall", ctx, input); | ||
|
||
const { handleCreateSelfServePhoneCall } = await import( | ||
"@calcom/features/ee/cal-ai-phone/handleCreateSelfServePhoneCall" | ||
); | ||
const call = await handleCreateSelfServePhoneCall({ | ||
userId: ctx.user.id, | ||
eventTypeId, | ||
numberToCall, | ||
}); | ||
return call; | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Endpoint for making phone call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (1)
40-63
: Add validation for subscription status.The status mapping logic is well-implemented, but consider adding validation for
subscription.status
to handle cases where it might be undefined or null.const statusMap: Record<string, PhoneNumberSubscriptionStatus> = { active: PhoneNumberSubscriptionStatus.ACTIVE, past_due: PhoneNumberSubscriptionStatus.PAST_DUE, cancelled: PhoneNumberSubscriptionStatus.CANCELLED, incomplete: PhoneNumberSubscriptionStatus.INCOMPLETE, incomplete_expired: PhoneNumberSubscriptionStatus.INCOMPLETE_EXPIRED, trialing: PhoneNumberSubscriptionStatus.TRIALING, unpaid: PhoneNumberSubscriptionStatus.UNPAID, }; - const subscriptionStatus = statusMap[subscription.status] || PhoneNumberSubscriptionStatus.UNPAID; + const subscriptionStatus = subscription.status + ? statusMap[subscription.status] || PhoneNumberSubscriptionStatus.UNPAID + : PhoneNumberSubscriptionStatus.UNPAID;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/web/app/api/phone-numbers/subscription/success/route.ts
(1 hunks)packages/features/ee/billing/api/webhook/_checkout.session.completed.ts
(2 hunks)packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/web/app/api/phone-numbers/subscription/success/route.ts
- packages/features/ee/billing/api/webhook/_checkout.session.completed.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
**/*.ts
: For Prisma queries, only select data you need; never useinclude
, always useselect
Ensure thecredential.key
field is never returned from tRPC endpoints or APIs
Files:
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()
in hot paths like loops
Files:
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#21827
File: packages/lib/server/repository/phoneNumber.ts:153-160
Timestamp: 2025-08-05T13:17:23.491Z
Learning: In the Cal.com Cal AI phone feature, the deletePhoneNumber repository method validation is properly handled in the service layer (RetellAIService.deletePhoneNumber) which validates user ownership and authorization before calling the repository method. The repository layer correctly focuses on data access only.
📚 Learning: the office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is spec...
Learnt from: vijayraghav-io
PR: calcom/cal.com#21072
File: packages/app-store/office365calendar/api/webhook.ts:120-123
Timestamp: 2025-07-18T17:57:16.395Z
Learning: The office365calendar webhook handler in packages/app-store/office365calendar/api/webhook.ts is specifically designed for Office365 calendar integration, not as a generic webhook handler. Therefore, it's safe to assume that fetchAvailabilityAndSetCache method will be implemented in the Office365CalendarService, making explicit validation checks unnecessary.
Applied to files:
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
📚 Learning: applies to **/*.ts : for prisma queries, only select data you need; never use `include`, always use ...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : For Prisma queries, only select data you need; never use `include`, always use `select`
Applied to files:
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
📚 Learning: applies to **/*.ts : ensure the `credential.key` field is never returned from trpc endpoints or apis...
Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-28T11:50:23.946Z
Learning: Applies to **/*.ts : Ensure the `credential.key` field is never returned from tRPC endpoints or APIs
Applied to files:
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts
🧬 Code Graph Analysis (1)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (1)
packages/features/ee/billing/api/webhook/__handler.ts (2)
SWHMap
(10-14)HttpCode
(25-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (3)
packages/features/ee/billing/api/webhook/_customer.subscription.updated.ts (3)
1-8
: LGTM! Proper imports and type definitions.The imports are well-organized and the type definition using
SWHMap
provides good type safety for Stripe webhook data.
9-32
: LGTM! Proper error handling and optimized database queries.The handler correctly validates the subscription ID and uses the
select
clause to fetch only required fields, addressing previous optimization concerns. The HTTP 202 status for "Phone number not found" is appropriate for webhook handlers.
34-39
: LGTM! Proper TypeScript types replace previousany
usage.The function signature now uses proper TypeScript types instead of
any
, significantly improving type safety and maintainability. This addresses the previous concern about type definitions.
|
name="phoneNumber" | ||
control={phoneNumberForm.control} | ||
render={({ field: { value } }) => ( | ||
<TextField |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I'll update the placeholder. Edit: It's already updated. I think you are on previous commit |
|
Can't we add this always to the template by default, hidden from the user? I feel like we alway want to end the call at the end of the template, no? |
yes end_call should be there for every prompt but it should be customizable when user wants the agent to end the call. For:- |
But can we make sure in case the user doesn't add end_call, it will still end the call by default when the end of prompt is reached? Or is this already done? |
/> | ||
)} | ||
</div> | ||
<TextArea |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
@CarinaWolli do you mean this? |
PRs are merged now |
What does this PR do?
This PR introduces a comprehensive AI phone system that enables users to create AI agents, manage phone numbers, and integrate AI-powered calls into Cal.com workflows
I have used Repository Pattern for database queries (one place instead of scattered), Strategy Pattern so all AI providers work identically (easy to swap), Factory Pattern to create the right provider automatically, Service Pattern to bundle complex operations.
Core AI Phone Capabilities
Workflow Integration
Billing & Credits
More in https://github.com/calcom/cal.com/pull/21827/files#r2251947957
Mandatory Tasks (DO NOT REMOVE)
How should this be tested?
Environment Variables Required
RETELL_AI_KEY=your_retell_ai_api_key
STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID=price_xxxxxxxxxxxx
Create a workflow and select cal ai voice agent as action and click on setup
https://github.com/user-attachments/assets/bc66ea5f-4b90-493b-93f3-3d8939d16bf5
Click on edit and go to Phone Number tab to buy/import phone number
Screen.Recording.2025-08-05.at.12.59.01.AM.mov
Then you can fill any US based phone number then you see that a task is created in tasker which can be executed if you run tasker
Summary by cubic
Added a self-serve feature for creating and managing AI-powered phone agents for event types, including phone number purchase, agent setup, and test calls.