Skip to content

Conversation

Udit-takkar
Copy link
Contributor

@Udit-takkar Udit-takkar commented Oct 8, 2025

What does this PR do?

This PR uses orgId for charging credits.

Different email template for cal ai

Screenshot 2025-10-08 at 8 12 16 PM

Discussion https://calendso.slack.com/archives/C08BBA7J2LU/p1759913325556449

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • N/A I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. If N/A, write N/A here and check the checkbox.
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

@graphite-app graphite-app bot requested a review from a team October 8, 2025 15:45
@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Oct 8, 2025
Comment on lines -116 to -118
throw new Error(
`Insufficient credits to make AI phone call. Please purchase more credits. user: ${data?.userId}, team: ${data?.teamId}`
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of throwing error on our tasker we should also send email about low credits again

Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

Walkthrough

Tightens typing for the Retell AI webhook (adds RetellCallData), expands Retell webhook tests for Cal.ai credit charging, idempotency, email notifications, and error paths, and updates team resolution for web/phone calls. Propagates creditFor?: CreditUsageType through credit charging, low-balance handling, email-manager, and email templates (adds Cal.ai-specific locale keys). CreditService now prefers organization (parent) credits when selecting memberships. Repositories and task/workflow code updated to surface parentId or admin members and to send limit-reached emails on insufficient credits.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title references the Cal AI webhook and indicates a fix, which is relevant to part of the changes, but it is overly broad and does not capture the main intent of using orgId for credit charging or the introduction of Cal AI–specific email templates.
Description Check ✅ Passed The description clearly states that the PR uses orgId for charging credits and adds a different email template for Cal AI, matching the extensive changes to billing logic and email handling observed in the code.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/cal-ai-credits

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c95a63c and fd9dfc7.

📒 Files selected for processing (10)
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (4 hunks)
  • apps/web/app/api/webhooks/retell-ai/route.ts (4 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts (1 hunks)
  • packages/features/ee/billing/credit-service.test.ts (9 hunks)
  • packages/features/ee/billing/credit-service.ts (13 hunks)
  • packages/lib/getOrgIdFromMemberOrTeamId.ts (2 hunks)
  • packages/lib/server/repository/PrismaAgentRepository.ts (1 hunks)
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts (1 hunks)
  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/ee/billing/credit-service.test.ts
  • packages/features/ee/billing/credit-service.ts
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/getOrgIdFromMemberOrTeamId.ts
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.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/credit-service.test.ts
  • packages/features/ee/billing/credit-service.ts
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/getOrgIdFromMemberOrTeamId.ts
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/ee/billing/credit-service.test.ts
  • packages/features/ee/billing/credit-service.ts
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/getOrgIdFromMemberOrTeamId.ts
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
**/*Repository.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Repository files must include Repository suffix, prefix with technology if applicable (e.g., PrismaAppRepository.ts), and use PascalCase matching the exported class

Files:

  • packages/lib/server/repository/PrismaAgentRepository.ts
**/*Service.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Service files must include Service suffix, use PascalCase matching exported class, and avoid generic names (e.g., MembershipService.ts)

Files:

  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
🧠 Learnings (5)
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
📚 Learning: 2025-08-19T08:45:41.834Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts:167-193
Timestamp: 2025-08-19T08:45:41.834Z
Learning: In calcom/cal.com AI phone call scheduling (aiPhoneCallManager.ts), workflow reminder records are intentionally kept in the database even when task scheduling fails, as they provide valuable debugging information for troubleshooting scheduling issues, per maintainer Udit-takkar in PR #22995.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
🧬 Code graph analysis (2)
packages/features/ee/billing/credit-service.test.ts (2)
packages/lib/getOrgIdFromMemberOrTeamId.ts (1)
  • getOrgIdFromMemberOrTeamId (47-62)
packages/lib/server/repository/credits.ts (1)
  • CreditsRepository (6-242)
packages/features/ee/billing/credit-service.ts (3)
packages/lib/getOrgIdFromMemberOrTeamId.ts (1)
  • getOrgIdFromMemberOrTeamId (47-62)
packages/lib/server/repository/credits.ts (1)
  • CreditsRepository (6-242)
packages/emails/email-manager.ts (2)
  • sendCreditBalanceLimitReachedEmails (836-875)
  • sendCreditBalanceLowWarningEmails (796-834)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (3)
packages/features/calAIPhone/providers/retellAI/services/AgentService.ts (1)

40-40: LGTM! Branding update applied correctly.

The string change from "Cal AI Phone" to "Cal.ai Phone" correctly aligns with the broader branding updates in this PR.

packages/features/ee/billing/credit-service.ts (2)

170-203: LGTM: Organization-first credit checking implemented correctly.

The logic properly prioritizes organization credits when a team belongs to an org. The use of getOrgIdFromMemberOrTeamId with the transaction parameter and consistent application of teamIdToCheck throughout ensures correct credit balance checks and updates.


588-596: LGTM: SMS cancellation correctly handles legacy and explicit credit types.

The conditional !result.creditFor || result.creditFor === CreditUsageType.SMS properly addresses the regression concern from previous reviews by treating undefined creditFor as SMS while also supporting explicit SMS credit type. This ensures legacy callers that omit creditFor continue to have scheduled SMS canceled when credits run out.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot bot added ai area: AI, cal.ai webhooks area: webhooks, callback, webhook payload 🐛 bug Something isn't working labels Oct 8, 2025
@Udit-takkar Udit-takkar added this to the v5.8 milestone Oct 8, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/lib/server/repository/team.ts (1)

441-466: Add explicit return type to findTeamWithAdminMembers
The method omits a return type, reducing clarity and type safety—declare it explicitly (e.g.

async findTeamWithAdminMembers(...): Promise<{
  id: number;
  name: string;
  members: { user: { id: number; name: string | null; email: string; locale: string | null } }[];
} | null>

Existing callers (e.g. in executeAIPhoneCall.ts) don’t use parentId.

packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx (1)

30-31: Optional: Cal‑AI‑specific subject?

Consider Cal‑AI‑specific subjects mirroring body branching for clearer inbox context. Safe to defer.

Also applies to: 61-62

apps/web/app/api/webhooks/retell-ai/route.ts (1)

80-89: callCost param unused for billing; clarify or remove

Credits are computed from duration and rate; callCost is only logged. Either drop the param or document why it’s intentionally ignored to avoid confusion.

packages/features/tasker/tasks/executeAIPhoneCall.ts (1)

141-171: Optional: factor recipient resolution to a helper

The team/user resolution + translation loading could live in a small util to reuse in other credit flows.

Also applies to: 173-179

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4dfab87 and b0215ce.

📒 Files selected for processing (13)
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (4 hunks)
  • apps/web/app/api/webhooks/retell-ai/route.ts (6 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/emails/email-manager.ts (3 hunks)
  • packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx (4 hunks)
  • packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx (4 hunks)
  • packages/emails/templates/credit-balance-limit-reached-email.ts (3 hunks)
  • packages/emails/templates/credit-balance-low-warning-email.ts (3 hunks)
  • packages/features/ee/billing/credit-service.ts (7 hunks)
  • packages/features/tasker/tasks/executeAIPhoneCall.ts (2 hunks)
  • packages/lib/server/repository/PrismaAgentRepository.ts (1 hunks)
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts (1 hunks)
  • packages/lib/server/repository/team.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/emails/templates/credit-balance-limit-reached-email.ts
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • packages/emails/email-manager.ts
  • packages/emails/templates/credit-balance-low-warning-email.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/features/ee/billing/credit-service.ts
  • packages/lib/server/repository/team.ts
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.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/emails/templates/credit-balance-limit-reached-email.ts
  • packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • packages/emails/email-manager.ts
  • packages/emails/templates/credit-balance-low-warning-email.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/features/ee/billing/credit-service.ts
  • packages/lib/server/repository/team.ts
  • packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/emails/templates/credit-balance-limit-reached-email.ts
  • packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx
  • apps/web/app/api/webhooks/retell-ai/route.ts
  • packages/emails/email-manager.ts
  • packages/emails/templates/credit-balance-low-warning-email.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/features/ee/billing/credit-service.ts
  • packages/lib/server/repository/team.ts
  • packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx
  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx
  • packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx
**/*Repository.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Repository files must include Repository suffix, prefix with technology if applicable (e.g., PrismaAppRepository.ts), and use PascalCase matching the exported class

Files:

  • packages/lib/server/repository/PrismaAgentRepository.ts
  • packages/lib/server/repository/PrismaPhoneNumberRepository.ts
🧠 Learnings (3)
📚 Learning: 2025-08-26T20:22:47.013Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:83-88
Timestamp: 2025-08-26T20:22:47.013Z
Learning: In calcom/cal.com, the executeAIPhoneCall task in packages/features/tasker/tasks/executeAIPhoneCall.ts is executed internally by the workflow system and not accessible externally, so RBAC checks on eventTypeId within this internal execution path are not required for security (per maintainer Udit-takkar in PR #22995).

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
📚 Learning: 2025-08-08T10:26:13.362Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
📚 Learning: 2025-08-19T08:45:41.834Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts:167-193
Timestamp: 2025-08-19T08:45:41.834Z
Learning: In calcom/cal.com AI phone call scheduling (aiPhoneCallManager.ts), workflow reminder records are intentionally kept in the database even when task scheduling fails, as they provide valuable debugging information for troubleshooting scheduling issues, per maintainer Udit-takkar in PR #22995.

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
🧬 Code graph analysis (6)
packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx (1)
packages/emails/src/templates/BaseScheduledEmail.tsx (1)
  • BaseScheduledEmail (20-145)
packages/emails/email-manager.ts (4)
packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx (1)
  • CreditBalanceLowWarningEmail (9-81)
packages/emails/templates/credit-balance-low-warning-email.ts (1)
  • CreditBalanceLowWarningEmail (9-61)
packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx (1)
  • CreditBalanceLimitReachedEmail (9-72)
packages/emails/templates/credit-balance-limit-reached-email.ts (1)
  • CreditBalanceLimitReachedEmail (9-56)
apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (2)
packages/lib/server/repository/PrismaAgentRepository.ts (1)
  • PrismaAgentRepository (31-579)
packages/lib/server/repository/PrismaPhoneNumberRepository.ts (1)
  • PrismaPhoneNumberRepository (26-535)
packages/features/ee/billing/credit-service.ts (2)
packages/emails/email-manager.ts (2)
  • sendCreditBalanceLimitReachedEmails (836-875)
  • sendCreditBalanceLowWarningEmails (796-834)
packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
  • cancelScheduledMessagesAndScheduleEmails (377-380)
packages/emails/src/templates/CreditBalanceLimitReachedEmail.tsx (1)
packages/emails/src/templates/BaseScheduledEmail.tsx (1)
  • BaseScheduledEmail (20-145)
packages/features/tasker/tasks/executeAIPhoneCall.ts (1)
packages/emails/email-manager.ts (1)
  • sendCreditBalanceLimitReachedEmails (836-875)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Install dependencies / Yarn install & cache
  • GitHub Check: Detect changes
🔇 Additional comments (17)
packages/lib/server/repository/PrismaAgentRepository.ts (1)

180-186: LGTM!

The addition of the team relation with parentId correctly uses select instead of include, adhering to the coding guidelines. This change aligns with the PR's objective to support org-based credit charging by making the team's parent organization ID available to the webhook handler.

packages/lib/server/repository/PrismaPhoneNumberRepository.ts (1)

531-531: Ensure consumers handle expanded team shape

I couldn’t automatically locate any usages of PrismaPhoneNumberRepository.findByPhoneNumber. Manually verify that every caller can handle the added parentId field on team.

packages/emails/templates/credit-balance-limit-reached-email.ts (1)

20-35: Propagating creditFor for Cal‑AI messaging — LGTM

Adding creditFor?: CreditUsageType and passing it through to the renderer looks correct and enables template branching.

Also applies to: 47-48

packages/emails/src/templates/CreditBalanceLowWarningEmail.tsx (2)

25-27: Cal‑AI branching and i18n usage — LGTM

Clean creditFor plumb‑through, isCalAi branching, and consistent t() usage.

Also applies to: 35-39, 66-70


35-39: Add missing Cal-AI i18n keys in all locales
The keys cal_ai_low_credits_warning_message and cal_ai_low_credits_warning_message_user are defined only in en/common.json and missing from every other apps/web/public/static/locales/**/common.json. Add these entries for each supported locale to prevent fallback text.

⛔ Skipped due to learnings
Learnt from: Udit-takkar
PR: calcom/cal.com#23761
File: packages/features/shell/navigation/Navigation.tsx:125-130
Timestamp: 2025-09-12T14:46:29.720Z
Learning: In calcom/cal.com, translations for other locales are added later in the development process, so don't flag missing translation keys in non-English locale files when only the English locale has been updated.
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/features/insights/components/booking/LeastCompletedBookings.tsx:31-31
Timestamp: 2025-08-21T05:55:35.187Z
Learning: Cal.com uses an automated i18n system with lingo.dev that automatically propagates new translation keys from en/common.json to all other locale files and creates PRs with proper translations. The system includes a check-missing-translations.ts script that adds English placeholders for missing keys, and a GitHub workflow that triggers lingo.dev automation to translate and create PRs.
apps/web/app/api/webhooks/retell-ai/route.ts (2)

167-170: Charging by org via parentId — LGTM

teamId = team?.parentId ?? teamId aligns with “charge by org” intent for both agent and phone flows.

Also applies to: 182-184


95-100: Idempotency is already ensured by CreditService and DB constraint
CreditService calls findCreditExpenseLogByExternalRef and Prisma’s unique index on externalRef prevents duplicate charges on retries.

packages/features/tasker/tasks/executeAIPhoneCall.ts (1)

116-189: Insufficient‑credit email + early return — LGTM

Good: warn with context, resolve team admins/users with locale, send limit‑reached emails with creditFor: CAL_AI_PHONE_CALL, then exit cleanly. Repository selects align with Prisma guidance.

packages/emails/templates/credit-balance-low-warning-email.ts (1)

21-39: creditFor plumb‑through — LGTM

Type‑safe prop added and forwarded to renderer; matches TSX template branching.

Also applies to: 49-53

packages/features/ee/billing/credit-service.ts (5)

18-18: LGTM!

Import consolidation is correct and follows best practices.


39-39: LGTM!

The optional creditFor field is correctly typed and properly extends the result types through the base interface.


56-160: LGTM!

The creditFor parameter is correctly added to the method signature and properly threaded through the transaction flow to _createExpenseLog and _handleLowCreditBalance.


326-404: LGTM!

The creditFor parameter is correctly propagated to the repository layer. The method follows the coding guidelines by selecting only the required data.


544-565: LGTM! Proper conditional handling for Cal AI credits.

The refactored promise handling correctly prevents SMS cancellation for non-SMS credit types (e.g., Cal AI phone calls). The conditional logic ensures that cancelScheduledMessagesAndScheduleEmails is only invoked when creditFor is CreditUsageType.SMS, which is the appropriate behavior.

packages/emails/email-manager.ts (3)

13-13: LGTM!

Type import is correctly added for the new creditFor parameter.


796-834: LGTM!

The creditFor parameter is correctly added to the function signature and properly propagated to both team admin and user email templates.


836-875: LGTM!

The creditFor parameter is correctly added and consistently propagated to both team admin and user limit-reached email templates, following the same pattern as the warning emails.

Copy link

vercel bot commented Oct 9, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Oct 9, 2025 7:05pm
cal-eu Ignored Ignored Oct 9, 2025 7:05pm

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 95659ca and c2d3889.

📒 Files selected for processing (2)
  • packages/features/ee/billing/credit-service.test.ts (6 hunks)
  • packages/features/ee/billing/credit-service.ts (12 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/ee/billing/credit-service.test.ts
  • packages/features/ee/billing/credit-service.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/credit-service.test.ts
  • packages/features/ee/billing/credit-service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/ee/billing/credit-service.test.ts
  • packages/features/ee/billing/credit-service.ts
🧬 Code graph analysis (1)
packages/features/ee/billing/credit-service.ts (3)
packages/lib/server/repository/credits.ts (1)
  • CreditsRepository (6-242)
packages/emails/email-manager.ts (2)
  • sendCreditBalanceLimitReachedEmails (836-875)
  • sendCreditBalanceLowWarningEmails (796-834)
packages/features/ee/workflows/lib/reminders/reminderScheduler.ts (1)
  • cancelScheduledMessagesAndScheduleEmails (377-380)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Tests / Unit
  • GitHub Check: Linters / lint
  • GitHub Check: Type check / check-types
  • GitHub Check: Codacy Static Code Analysis

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c2d3889 and c95a63c.

📒 Files selected for processing (9)
  • apps/web/app/(use-page-wrapper)/workflow/new/page.tsx (1 hunks)
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (4 hunks)
  • apps/web/public/static/locales/en/common.json (1 hunks)
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts (1 hunks)
  • packages/features/calAIPhone/workflowTemplates.ts (2 hunks)
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts (2 hunks)
  • packages/features/tasker/tasks/executeAIPhoneCall.ts (3 hunks)
  • packages/lib/server/repository/PrismaApiKeyRepository.ts (1 hunks)
  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/features/calAIPhone/workflowTemplates.ts
  • packages/features/calAIPhone/providers/retellAI/services/AgentService.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/public/static/locales/en/common.json
🧰 Additional context used
📓 Path-based instructions (5)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/server/repository/PrismaApiKeyRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.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/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • apps/web/app/(use-page-wrapper)/workflow/new/page.tsx
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/server/repository/PrismaApiKeyRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • apps/web/app/(use-page-wrapper)/workflow/new/page.tsx
  • apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts
  • packages/lib/server/repository/PrismaApiKeyRepository.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • apps/web/app/(use-page-wrapper)/workflow/new/page.tsx
**/*Repository.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Repository files must include Repository suffix, prefix with technology if applicable (e.g., PrismaAppRepository.ts), and use PascalCase matching the exported class

Files:

  • packages/lib/server/repository/PrismaApiKeyRepository.ts
🧠 Learnings (7)
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
📚 Learning: 2025-08-19T08:45:41.834Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts:167-193
Timestamp: 2025-08-19T08:45:41.834Z
Learning: In calcom/cal.com AI phone call scheduling (aiPhoneCallManager.ts), workflow reminder records are intentionally kept in the database even when task scheduling fails, as they provide valuable debugging information for troubleshooting scheduling issues, per maintainer Udit-takkar in PR #22995.

Applied to files:

  • packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts
  • packages/features/tasker/tasks/executeAIPhoneCall.ts
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts
📚 Learning: 2025-08-26T20:22:47.013Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:83-88
Timestamp: 2025-08-26T20:22:47.013Z
Learning: In calcom/cal.com, the executeAIPhoneCall task in packages/features/tasker/tasks/executeAIPhoneCall.ts is executed internally by the workflow system and not accessible externally, so RBAC checks on eventTypeId within this internal execution path are not required for security (per maintainer Udit-takkar in PR #22995).

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
📚 Learning: 2025-08-08T10:26:13.362Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts:212-220
Timestamp: 2025-08-08T10:26:13.362Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/providers/retellAI/services/PhoneNumberService.ts should include the phone number in client-facing HttpError messages (e.g., in updatePhoneNumber/getPhoneNumber catch blocks). Do not suggest redacting the phone number from these errors unless requirements change (per maintainer: Udit-takkar).

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
  • packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • packages/features/tasker/tasks/executeAIPhoneCall.ts
🧬 Code graph analysis (2)
apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (2)
packages/lib/server/repository/PrismaAgentRepository.ts (1)
  • PrismaAgentRepository (31-579)
packages/lib/server/repository/PrismaPhoneNumberRepository.ts (1)
  • PrismaPhoneNumberRepository (26-535)
packages/features/tasker/tasks/executeAIPhoneCall.ts (2)
packages/lib/server/repository/team.ts (1)
  • TeamRepository (170-467)
packages/emails/email-manager.ts (1)
  • sendCreditBalanceLimitReachedEmails (836-875)
🔇 Additional comments (7)
packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts (1)

26-26: LGTM! Branding consistency update.

The log message update from "Cal AI" to "Cal.ai" aligns with the broader naming consistency changes across the codebase for Cal.ai branding.

apps/web/app/(use-page-wrapper)/workflow/new/page.tsx (1)

133-133: LGTM! Branding consistency update.

The error message now uses "Cal.ai" (with dot notation) consistent with the workflow names on lines 22 and 28.

packages/lib/server/repository/PrismaApiKeyRepository.ts (1)

31-31: Verify migration for existing API key notes

The filter was updated from "Cal AI Phone API Key""Cal.ai Phone API Key", so any API keys created before this change still use the old note format and won’t be filtered out. Confirm a data migration has been applied to rename existing apiKey.note values accordingly; otherwise, add a migration or temporarily support both patterns.

packages/features/ee/workflows/lib/reminders/aiPhoneCallManager.ts (1)

143-143: LGTM! Branding consistency improved.

The log messages now consistently use "Cal.ai" instead of "Cal AI", aligning with the branding standardization across the codebase.

Also applies to: 262-262

apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts (3)

1-877: Excellent test coverage and structure!

The test suite is comprehensive and well-organized, covering:

  • Authentication/authorization scenarios (signature validation, API key checks)
  • Event handling for different event types
  • Credit charging for both user and team phone numbers
  • Credit calculation accuracy across various call durations
  • Idempotency and error handling
  • Web call scenarios with agent resolution

The test isolation with beforeEach hooks and proper mocking of external dependencies demonstrates good testing practices.


879-1038: Cal.ai credit type tests align with PR objectives.

The tests correctly validate that CreditUsageType.CAL_AI_PHONE_CALL is passed to chargeCredits for:

  • Web calls (lines 885-931)
  • Phone calls (lines 933-984)
  • Team-based calls (lines 986-1037)

This ensures the webhook behavior correctly uses the Cal.ai credit type as intended by the PR changes.


1040-1240: Verify email triggering logic is tested in the actual implementation.

The email integration tests (lines 1048-1116 and 1118-1183) follow a pattern where mockChargeCredits is implemented to manually call the email functions (lines 1069-1082, 1135-1149). The tests then verify those email functions were called. This creates a circular testing pattern:

  1. Test mocks chargeCredits to call email functions
  2. Mock implementation invokes email functions
  3. Test verifies email functions were called

While this validates the contract between the webhook handler and the mocked services, it doesn't verify that the actual chargeCredits implementation or route handler triggers emails correctly. If the email triggering logic lives in the actual chargeCredits service or route handler, that behavior should be tested separately in integration tests or the service's own unit tests.

Please confirm whether:

  1. The actual chargeCredits implementation in credit-service has its own tests that verify email triggering behavior
  2. Or if there are integration tests that validate end-to-end email flow without mocks

If not, consider adding tests that verify the actual implementation (not the mock) correctly triggers emails when credits are low or exhausted.


/*
If user has memberships, it always returns a team, even if all have limit reached. In that case, limitReached: true is returned
Prioritizes organization credits over team credits
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, if user is member of an org we should always return the org never subteams

@Udit-takkar Udit-takkar marked this pull request as ready for review October 9, 2025 15:32
@Udit-takkar Udit-takkar marked this pull request as draft October 9, 2025 15:34
@Udit-takkar Udit-takkar marked this pull request as ready for review October 9, 2025 19:05
@graphite-app graphite-app bot requested a review from a team October 9, 2025 19:05
@dosubot dosubot bot added the billing area: billing, stripe, payments, paypal, get paid label Oct 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai area: AI, cal.ai billing area: billing, stripe, payments, paypal, get paid 🐛 bug Something isn't working core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO size/XL webhooks area: webhooks, callback, webhook payload

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants