feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more#41
Conversation
…port, guided prompt
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Deployment failed with the following error: View Documentation: https://vercel.com/docs/accounts/team-members-and-roles |
…endly messages, schema fixes Part A: Fix misleading error messages - A1: Add isCalcomApiError classifier + friendlyCalcomError helper with status-specific messages - A2: Add isSlackAuthError guard to /cal slash command and retry_response handlers - A3: Soften Slack auth error message (less alarming, directs to admin) - A4: Sanitize confirm_booking error (don't expose raw API errors) - A5: Fix App Home catch-all to only suggest reconnecting on 401/403 Part B: Fix API schema mismatches - B1: Fix getAvailableSlots to use cal-api-version 2024-09-04 - B2: Rename responses → bookingFieldsResponses (matches OpenAPI spec) - B3: Add rescheduledBy param to rescheduleBooking for auto-confirm - B4: Add bookingUidToReschedule to GetSlotsParams for reschedule flow - B5: Remove phantom notes field from CreateBookingInput types Part C: Structural improvements - C1: Add CalcomApiError awareness to all getCustomErrorMessage callbacks - C2: Centralized friendlyCalcomError helper in bot.ts
…past meeting lookup - Expand GetBookingsParams with attendeeEmail, attendeeName, afterStart, beforeEnd, sortStart - Pass new params through in getBookings() query string - Add all new params to list_bookings tool Zod schema - Update list_bookings description to mention attendee and date range filtering - Add FINDING PAST MEETINGS WITH SOMEONE section to system prompt
…es steering, critical rule - Add 'Checking Your Availability / Am I Free?' system prompt section with 3-step flow (determine time range, fetch bookings, answer question) and edge cases - Update check_busy_times description to note credential limitations and steer toward list_bookings - Add rule 10 to CRITICAL RULES: use list_bookings for availability checks
…ync, tool descriptions - Add 'Profile Management' system prompt section with viewing/updating guidance, timezone abbreviation resolution, email verification warning, and fast-path - Sync email/timezone changes back to Redis via linkUser() after update_profile to prevent stale cache in system prompt and timezone conversions - Add linkUser import from user-linking - Update get_my_profile description to steer toward cached data for basic info - Update update_profile description to require confirmation and IANA timezones
…ng URLs - Add 'Managing Event Types' system prompt section with create/update/delete/list guidance, slug generation, common requests, and advanced settings redirect - Relax critical rule #9 to guard booking flows only, not explicit user requests - Add minimumBookingNotice, beforeEventBuffer, afterEventBuffer, slotInterval, scheduleId to create_event_type and update_event_type tool schemas + types - Update create/update/delete tool descriptions for clarity - Include bookingUrl in list_event_types response using linked user's username
…ma, prompt guidance
…heduledBy, recurring detection
… Cal.com API calls
…rich descriptions, add prompt section
…alendar booking with custom fields
…lidate CalcomApiError handling via deps
There was a problem hiding this comment.
2 issues found across 6 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/chat/lib/handlers/slack.ts">
<violation number="1" location="apps/chat/lib/handlers/slack.ts:944">
P2: This booking-specific Cal.com error mapping never runs because `withBotErrorHandling` handles `CalcomApiError` before `getCustomErrorMessage`. As written, 409 booking conflicts still fall back to the generic Cal.com conflict message instead of the new slot-unavailable text.</violation>
</file>
<file name="apps/chat/lib/calcom/client.ts">
<violation number="1" location="apps/chat/lib/calcom/client.ts:84">
P1: Default retries now reissue mutating Cal.com requests, so timeouts/5xxs can duplicate creates or replay cancel/reschedule actions.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…#42) * feat: add get_event_type tool for fetching single event type details * fix: align get_event_type tool description with actual response fields * feat: gate agentic features behind Cal.com Organizations plan * fix: address review comments — org sync on refresh, split link check, withSlackToken wrapper
There was a problem hiding this comment.
3 issues found across 6 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/chat/lib/bot.ts">
<violation number="1" location="apps/chat/lib/bot.ts:840">
P2: Re-read the linked user after token refresh before enforcing the org-plan gate.</violation>
</file>
<file name="apps/chat/lib/user-linking.ts">
<violation number="1" location="apps/chat/lib/user-linking.ts:218">
P1: Persist the refreshed tokens before calling `getMe()`. Doing another retried API call inside the refresh lock can make concurrent requests return `null` or trigger a second refresh.</violation>
</file>
<file name="apps/chat/lib/handlers/slack.ts">
<violation number="1" location="apps/chat/lib/handlers/slack.ts:525">
P1: This org-plan gate will falsely block already-linked organizations users whose cached Redis record predates the new org fields.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…re-read linked user after refresh
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/chat/lib/calcom/client.ts">
<violation number="1" location="apps/chat/lib/calcom/client.ts:325">
P2: Passing `0` here disables the new retry/backoff logic, so transient Cal.com 5xx or timeout failures still break this mutation after one attempt.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
d69fae5
into
devin/1773320873-smart-mention-booking-flow
…edis persistence (#32) * feat: smart @mention booking flow with multi-attendee support - Rewrite booking flow in system prompt to clarification-first logic with fast-path for fully-specified requests - Add guestEmails field to book_meeting tool for email-only additional attendees (Strategy A: guests array in initial POST) - Add add_booking_attendee tool for full attendee records with name + timezone after booking (Strategy B: POST /bookings/{uid}/attendees) - Add AddAttendeeInput type and addBookingAttendee() client function - Add guests field to CreateBookingInput type - Relax CRITICAL RULES to support multi-step booking flows and re-calling check_availability for alternative slots - Update check_availability description to allow re-calls - Bump MAX_STEPS from 10 to 15 for multi-attendee flows - Update Available Capabilities to list add_booking_attendee * fix * refactor: simplify agent booking flow with pre-resolution, tool filtering, and Redis persistence - Remove check_account_linked tool (bot.ts already checks before agent) - Pre-resolve Slack @mentions to name+email before calling agent - Inject linked user context (email/timezone/username) into system prompt - Rewrite system prompt with checklist-based single-decision booking - Persist tool results in Redis (keyed by threadId, 30min TTL) - Context-aware tool filtering: CORE (7 booking tools) vs EXTENDED (admin) - Add loop guard: force text if same tool called 3x with identical args - Reduce MAX_STEPS from 15 to 8 (agent needs 3-4 steps with optimizations) * update * update 2 * fix: booking flow — timezone-aware dates, tighter loop guard, ASAP handling, tool context reuse - Replace bare ISO timestamp with timezone-aware date in system prompt - Add explicit past-date comparison rule against user's timezone - Lower loop guard threshold from 3 to 2 identical calls - Reduce MAX_STEPS from 8 to 6 - Rewrite tool context injection: user role, deduplicate by tool name, inject at start of history - Add ASAP/urgency shortcut section to booking flow - Add duration mismatch detection rule - Strengthen tool usage rules (no same tool twice per step, must use returned data) - Add single event type auto-select logic * update the code * feat: add attendee calendar booking flow — list_event_types_by_username tool - Add getEventTypesByUsername() to calcom/client.ts (public API, no auth needed) - Add list_event_types_by_username tool to agent createCalTools - Add list_event_types_by_username to CORE_TOOL_NAMES - Add WHOSE CALENDAR TO USE section to system prompt booking flow * update code * update * fix: prevent false-positive Slack auth error + add custom booking field support Fix 1: Updated getCustomErrorMessage in all 3 handlers to return generic error when lastStreamErrorRef is set and caught error is Slack auth error. Fix 2a: Added responses?: Record<string, unknown> to CreateBookingInput and CreatePublicBookingInput types. Fix 2b: Added responses parameter to book_meeting and book_meeting_public tool schemas, passed through to API calls. Fix 2c: Included bookingFields in list_event_types_by_username response. Fix 2d: Added CUSTOM BOOKING FIELDS section to system prompt instructing agent to collect required custom field values and pass as responses. Fix 3: Hardened postAgentStream to re-throw generic error when Slack auth error is secondary to an agent stream failure. Also fixed duplicate rule #6 numbering in CRITICAL RULES. * fix: replace non-null assertions with nullish coalescing in check_availability_public * revert the prod url in manifest * fix: encrypt tool-context in Redis + pass metadata for webhook notification routing 1. Encrypt tool-context entries in Redis using existing encryptData/decryptData (PII protection for attendee names, emails, booking details). Legacy plaintext entries are handled gracefully by decryptData. 2. Added metadata?: Record<string, string> to CreatePublicBookingInput. 3. Added platform parameter to createCalTools, threaded from runAgentStream. 4. Both book_meeting and book_meeting_public now pass metadata with slack_team_id/slack_user_id or telegram_chat_id so Cal.com webhooks can route notifications back to the correct Slack/Telegram user. * feat: agentic flows, error handling, API robustness, search, profile, event types, reschedule & more (#41) * feat: agentic cancel booking flow — enriched responses, recurring support, guided prompt * feat: agentic confirm/decline flow — enriched responses, guided prompt, batch support * update code * fix: error handling & API robustness — CalcomApiError classifier, friendly messages, schema fixes Part A: Fix misleading error messages - A1: Add isCalcomApiError classifier + friendlyCalcomError helper with status-specific messages - A2: Add isSlackAuthError guard to /cal slash command and retry_response handlers - A3: Soften Slack auth error message (less alarming, directs to admin) - A4: Sanitize confirm_booking error (don't expose raw API errors) - A5: Fix App Home catch-all to only suggest reconnecting on 401/403 Part B: Fix API schema mismatches - B1: Fix getAvailableSlots to use cal-api-version 2024-09-04 - B2: Rename responses → bookingFieldsResponses (matches OpenAPI spec) - B3: Add rescheduledBy param to rescheduleBooking for auto-confirm - B4: Add bookingUidToReschedule to GetSlotsParams for reschedule flow - B5: Remove phantom notes field from CreateBookingInput types Part C: Structural improvements - C1: Add CalcomApiError awareness to all getCustomErrorMessage callbacks - C2: Centralized friendlyCalcomError helper in bot.ts * update * feat: booking search enhancement — attendee/date filtering, sorting, past meeting lookup - Expand GetBookingsParams with attendeeEmail, attendeeName, afterStart, beforeEnd, sortStart - Pass new params through in getBookings() query string - Add all new params to list_bookings tool Zod schema - Update list_bookings description to mention attendee and date range filtering - Add FINDING PAST MEETINGS WITH SOMEONE section to system prompt * update - pass hosts * feat: 'Am I Free?' flow — availability prompt section, check_busy_times steering, critical rule - Add 'Checking Your Availability / Am I Free?' system prompt section with 3-step flow (determine time range, fetch bookings, answer question) and edge cases - Update check_busy_times description to note credential limitations and steer toward list_bookings - Add rule 10 to CRITICAL RULES: use list_bookings for availability checks * feat: profile management flow — system prompt guidance, Redis cache sync, tool descriptions - Add 'Profile Management' system prompt section with viewing/updating guidance, timezone abbreviation resolution, email verification warning, and fast-path - Sync email/timezone changes back to Redis via linkUser() after update_profile to prevent stale cache in system prompt and timezone conversions - Add linkUser import from user-linking - Update get_my_profile description to steer toward cached data for basic info - Update update_profile description to require confirmation and IANA timezones * feat: event type CRUD flow — prompt guidance, expanded schemas, booking URLs - Add 'Managing Event Types' system prompt section with create/update/delete/list guidance, slug generation, common requests, and advanced settings redirect - Relax critical rule #9 to guard booking flows only, not explicit user requests - Add minimumBookingNotice, beforeEventBuffer, afterEventBuffer, slotInterval, scheduleId to create_event_type and update_event_type tool schemas + types - Update create/update/delete tool descriptions for clarity - Include bookingUrl in list_event_types response using linked user's username * feat: no-show and unlink flows — mark_no_show body fix, expanded schema, prompt guidance * feat: agentic reschedule flow — prompt guidance, slot exclusion, rescheduledBy, recurring detection * feat: promote event type CRUD tools to CORE_TOOL_NAMES, remove stale ADMIN_KEYWORDS * refactor: eliminate keyword-based tool gating — always expose all tools * feat: add fetchWithRetry with exponential backoff and timeouts to all Cal.com API calls * feat: schedule availability tools — expose availability/overrides, enrich descriptions, add prompt section * feat: include bookingFields in list_event_types response to fix own-calendar booking with custom fields * feat: add skip param and hasMore pagination flag to list_bookings tool * feat: enrich tool descriptions for get_booking, confirm/decline, and schedule tools * feat: actionable error messages — overhaul friendlyCalcomError, consolidate CalcomApiError handling via deps * refactor: extract duplicates and magic numbers across agent, bot, and user-linking * feat: add get_event_type tool + gate agentic features behind org plan (#42) * feat: add get_event_type tool for fetching single event type details * fix: align get_event_type tool description with actual response fields * feat: gate agentic features behind Cal.com Organizations plan * fix: address review comments — org sync on refresh, split link check, withSlackToken wrapper * fix: disable retries for mutating API calls, reorder error handlers, re-read linked user after refresh
Summary
Adds guided cancellation, reschedule, and confirm/decline flows to the chat agent, a comprehensive error handling & API robustness overhaul, booking search enhancement with attendee/date filtering, an "Am I Free?" availability flow, a profile management flow with Redis cache sync, an event type CRUD flow with expanded schemas, no-show/unlink account flows, a full agentic reschedule flow with slot exclusion and auto-confirmation, eliminates the keyword-based tool gating system entirely, adds exponential backoff retry logic with AbortSignal timeouts to all Cal.com API calls, gates agentic (AI-powered) features behind the Cal.com Organizations plan, and adds a
get_event_typetool for fetching single event types — across 7 files (agent.ts,bot.ts,client.ts,types.ts,slack.ts,user-linking.ts,callback/route.ts).Cancel booking flow
client.ts—cancelBookingnow accepts an optionalcancelSubsequentBookingsparam, forwarded to the Cal.com API for recurring booking cancellation.agent.ts— system prompt — New## Cancelling a Bookingsection with a 2-step flow (identify → confirm+reason), fast-path for clear intent, recurring booking handling, and batch cancellation capped at 3 per turn.agent.ts—cancel_bookingtool — Fetches booking details viagetBookingbefore cancelling, returns enriched response (title, start, end, attendees), addscancelSubsequentBookingsschema param.agent.ts—list_bookingstool — AddseventType(id/title/slug) anddescriptionto response.agent.ts—get_bookingtool — Same enrichment as list_bookings.Reschedule booking flow
agent.ts— system prompt — New## Rescheduling a Bookingsection (~70 lines) with 4-step flow: identify booking → determine new time → check availability (mandatory, withbookingUidToReschedule) → confirm and reschedule. Includes fast-path, recurring booking handling (single occurrence only), andrescheduledByauto-confirmation guidance.agent.ts—check_availabilitytool — Added optionalbookingUidToRescheduleparam to Zod schema; passed through togetAvailableSlots()in both primary and extended (no-slots fallback) calls.agent.ts—check_availability_publictool — SamebookingUidToRescheduleparam added; passed through togetAvailableSlotsPublic()in both primary and extended calls.client.ts—GetPublicSlotsParams— AddedbookingUidToReschedule?: string; wired into query string ingetAvailableSlotsPublic().agent.ts—reschedule_bookingtool — Enhanced: fetches original booking viagetBookingbefore rescheduling (returnspreviousStart/previousEnd+newStart/newEnd+ attendees), addsrescheduledByparam for auto-confirmation on confirmation-required event types. Description updated.types.ts—CalcomBooking— AddedrecurringBookingUid: string | nullto detect recurring bookings.agent.ts—list_bookings+get_bookingresponses — Now surfacerecurringBookingUidin each booking object.agent.ts— CRITICAL RULES — Added rule 11: "NEVER call reschedule_booking without first checking availability. Always pass bookingUidToReschedule."Confirm/decline booking flow
agent.ts— system prompt — New## Confirming or Declining a Bookingsection with the same patterns: 2-step flow (identify pending → confirm/decline), fast-path, batch cap at 3, and post-action guidance.agent.ts—confirm_bookingtool — Fetches booking details viagetBookingbefore confirming, returns enriched response with start/end/attendees.agent.ts—decline_bookingtool — Same enrichment, plus returnsreasonin response.agent.ts— Behavior section — Replaced the old confirm/decline one-liner with a reference to the new dedicated section.Error handling & API robustness
Part A — Fix misleading error messages:
18.
bot.ts— AddedfriendlyCalcomErrorhelper that mapsCalcomApiErrorstatus codes (400/401/403/404/409/422/429/5xx) to user-friendly messages.19.
bot.ts—CalcomApiErrorbranch inwithBotErrorHandlingnow runs aftergetCustomErrorMessage, so callers (e.g. the booking modal) can provide context-specific messages first. PreviouslyCalcomApiErrorwas caught beforegetCustomErrorMessage, making context-aware handlers likefriendlyCalcomError(err, "booking")dead code.20.
bot.ts— Softened Slack auth error message: now says "I'm having trouble connecting to Slack" instead of the alarming "token has expired or been revoked".21.
slack.ts— AddedisSlackAuthErrorguard to/calslash command andretry_responseaction handlers (previously missing, causing false "token expired" messages).22.
slack.ts— Sanitizedconfirm_bookingerror: no longer exposes raw API error messages; shows status-specific messages (409 → "slot no longer available", 422 → "details incomplete").23.
slack.ts— App Home catch-all now only suggests "reconnect" on 401/403; otherwise shows "Could not load bookings. Please try again later."Part B — Fix API schema mismatches:
24.
client.ts— FixedgetAvailableSlotsto usecal-api-version: 2024-09-04(was using default2024-08-13;/v2/slotsendpoint requires2024-09-04).25.
types.ts+agent.ts— Renamedresponses→bookingFieldsResponsesto match the OpenAPI spec. Removed phantomnotesfield fromCreateBookingInputandCreatePublicBookingInput(notes should go viabookingFieldsResponses.notes).26.
client.ts— AddedrescheduledByparam torescheduleBookingfor auto-confirm when rescheduler is the host.27.
client.ts— AddedbookingUidToRescheduletoGetSlotsParamsto exclude the current booking from busy-time calculations during reschedule.Part C — Structural improvements:
28.
bot.ts+slack.ts— All 6getCustomErrorMessagecallbacks now checklastStreamErrorRef.current instanceof CalcomApiErrorand returnfriendlyCalcomError(...)messages, so stream errors from Cal.com API calls surface specific messages rather than generic fallbacks.Booking search enhancement
client.ts— ExpandedGetBookingsParamswithattendeeEmail,attendeeName,afterStart,beforeEnd,sortStartand wired them through as query params ingetBookings().agent.ts—list_bookingstool — Added all 5 new optional params to the Zod schema (attendeeEmail,attendeeName,afterStart,beforeEnd,sortStart) and passes them togetBookings().agent.ts— tool description — Updated to mention attendee/date filtering and notes that attendee filters only match attendees, not hosts.agent.ts— system prompt — NewFINDING PAST MEETINGS WITH SOMEONEsection with attendee/host fallback strategy: if attendee filters return no results, does an unfiltered call and scans thehostsfield.agent.ts—list_bookings+get_bookingresponses — Now includehostsarray (name + email) alongsideattendees, enabling the agent to find meetings where the person was the host."Am I Free?" availability flow
agent.ts— system prompt — New## Checking Your Availability / "Am I Free?"section with a 3-step flow: determine time range → fetch bookings vialist_bookingswithafterStart/beforeEnd→ answer the question. Covers specific-time checks, daily schedules, weekly overviews, and edge cases (past dates, duration-based gaps, "block off" requests).agent.ts—check_busy_timestool description — Updated to note credential limitations and steer the agent towardlist_bookingsfor availability checks.agent.ts— CRITICAL RULES — Added rule 10: "For 'am I free?' questions, use list_bookings with afterStart/beforeEnd date filters — do NOT use check_busy_times."Profile management flow
agent.ts— system prompt — New## Profile Managementsection with guidance for viewing profile (use cached "Your Account" data, only callget_my_profilefor full details), updating profile (confirm before changes, resolve timezone abbreviations to IANA, warn about email verification), field reference list, and fast-path for clear-intent updates.agent.ts—update_profiletool — After a successfulupdateMe()call, syncs changedemailandtimeZoneback to theLinkedUserin Redis vialinkUser(). This fixes a stale cache bug where the system prompt's "Your Account" section and all subsequent timezone conversions would use outdated values after a profile update.agent.ts— imports — AddedlinkUserto imports fromuser-linking.agent.ts—get_my_profiledescription — Updated to steer the agent toward using cached system prompt data for basic info (email, username, timezone) and only calling the API for full profile fields (bio, time format, week start, locale).agent.ts—update_profiledescription — Updated to require user confirmation before calling and to use IANA timezone strings. Notes that email changes require verification.Event type CRUD flow
agent.ts— system prompt — New## Managing Event Typessection with guidance for creating (auto-generate slug from title, show booking URL after creation), updating (identify → confirm → update), deleting (always confirm first, warn irreversible), listing (show booking URLs), and common requests (hide/unhide, buffers, notice, slot intervals). Redirects advanced settings to the web UI.agent.ts— CRITICAL RULES — Relaxed rule ci: add 6 new workflows, Blacksmith runners, and CI speed optimizations #9 from "NEVER call unless explicitly asked" to "NEVER call during a booking flow or unless explicitly asked to manage an event type. For delete, ALWAYS confirm first." Keeps the safety guard for booking flows without making the tools sound forbidden.agent.ts—create_event_typetool — AddedminimumBookingNotice,beforeEventBuffer,afterEventBuffer,slotInterval,scheduleIdto Zod schema. Updated description to mention buffers/notice/intervals.agent.ts—update_event_typetool — Same 5 new fields added to Zod schema. Execute function refactored to use{ eventTypeId, ...rest }destructuring. Updated description to list all configurable fields.agent.ts—delete_event_typetool — Description updated to "This is irreversible -- always confirm with the user first."types.ts— AddedminimumBookingNotice,beforeEventBuffer,afterEventBuffer,slotInterval,scheduleIdto bothCreateEventTypeInputandUpdateEventTypeInputinterfaces.agent.ts—list_event_typestool — Now fetchesLinkedUserin parallel with the access token and includesbookingUrl({CALCOM_APP_URL}/{username}/{slug}) in each event type's response.No-show & unlink account flows
client.ts—markNoShow— Now accepts optionalhost(boolean) andattendees(array of{ email, absent }) parameters and passes them in the request body. Previously sent an empty POST body which the API likely ignored.agent.ts—mark_no_showtool — Expanded schema withhost(boolean, mark host as absent) andattendeeEmails(string array, emails of absent attendees). Execute function maps emails to{ email, absent: true }objects before calling client. Description updated to explain host vs attendee no-show marking.agent.ts— system prompt — NewMARKING NO-SHOWSsection: identify past booking → ask who was absent (host or attendee, skip if clear from context) → call mark_no_show → confirm. Notes that no-shows only work for past bookings.agent.ts—unlink_accounttool description — Updated from bare "Unlink the user's Cal.com account." to include consequences (removes OAuth connection, re-auth required) and "always confirm before calling".agent.ts— system prompt — NewUNLINKING ACCOUNTsection: always confirm with explicit warning about consequences → on "yes" call unlink_account → confirm disconnection and explain how to reconnect.Eliminate keyword-based tool gating
agent.ts— DeletedCORE_TOOL_NAMES,ADMIN_KEYWORDS,detectToolSet(), andfilterTools()entirely. All 28+ tools are now always exposed to the model. The system prompt's critical rules are the guardrail against misuse, not keyword filtering.agent.ts— RemovedtoolSetfromAgentStreamOptionsinterface.runAgentStreamnow directly usescreateCalTools()output without filtering.bot.ts— Removed alldetectToolSet()calls andtoolSetarguments from the 3runAgentStreamcall sites (telegram freeform, mention handler, thread follow-up). RemoveddetectToolSetimport.API retry and timeouts
client.ts— Added constants:FETCH_TIMEOUT_MS(10s),MAX_RETRIES(2 = 3 total attempts),RETRY_BASE_MS(500ms),RETRY_MULTIPLIER(3),RETRYABLE_STATUS_CODES(500, 502, 503, 504).client.ts— AddedfetchWithRetry()helper that wrapsfetchwithAbortSignal.timeout(FETCH_TIMEOUT_MS), retries on server errors (5xx) and network/timeout errors with exponential backoff (500ms → 1500ms), and throwsCalcomApiErrorwith code"FETCH_RETRY_EXHAUSTED"after all attempts fail. Addedsleep()helper.client.ts— UpdatedcalcomFetchto accept an optionalretriesparameter (defaultMAX_RETRIES) and usefetchWithRetryinstead of rawfetch.client.ts— All mutating calls (POST/PATCH/DELETE) now passretries: 0— timeout protection only, no retry. This includes:createBooking,createBookingPublic,addBookingAttendee,cancelBooking,rescheduleBooking,updateMe,createSchedule,updateSchedule,deleteSchedule,confirmBooking,declineBooking,createEventType,updateEventType,deleteEventType,markNoShow. Only GET calls use full retry.client.ts— Replaced rawfetch()withfetchWithRetry()in 3 public (unauthenticated) functions:getAvailableSlotsPublic(full retry),createBookingPublic(retries: 0),getEventTypesByUsername(full retry).get_event_typetoolclient.ts— FixedgetEventTypeto normalize thelengthfield (raw.length ?? raw.lengthInMinutes ?? 0), matching the existinggetEventTypesbehavior.agent.ts— Addedget_event_typetool definition (import, Zod schema, execute function) for fetching a single event type by ID. Returns bookingFields, duration, description, bookingUrl, etc. Added system prompt guidance in CUSTOM BOOKING FIELDS and UPDATING AN EVENT TYPE sections.Org plan agentic gating
user-linking.ts— AddedcalcomOrganizationIdandcalcomOrgIsPlatformtoLinkedUserinterface. AddedisOrgPlanUser()helper that returnstruewhencalcomOrganizationId != null && calcomOrgIsPlatform === false. Org metadata is re-synced via/v2/meon every token refresh (non-fatal on failure).callback/route.ts— Expanded localCalcomMeto captureorganizationIdandorganization.isPlatformat OAuth link time.client.ts— Updated sharedCalcomMeinterface withorganizationIdandorganizationfields.bot.ts— Added org plan check inrunAgentHandler()after token validation — covers all agentic paths (Slack mentions, Telegram DMs/mentions, thread follow-ups). AftergetValidAccessToken, re-readsLinkedUserfrom Redis so freshly synced org data is used. Slack upgrade message is wrapped inwithSlackTokento avoidnot_authederrors.handlers/slack.ts— Gated the two directrunAgentStreamcalls that bypassrunAgentHandler:/cal book @userfallback (no modal) and/cal <natural language>default case. The default case correctly shows the OAuth link prompt for unlinked users instead of conflating with the upgrade message.Gating logic (from
/v2/meresponse):organizationIdisPlatformnulltruefalseCode quality improvements
agent.ts+user-linking.ts— Extracted named constants replacing magic numbers:MAX_HISTORY_MESSAGES,MAX_AGENT_STEPS,MAX_SLOTS_RETURNED,MAX_NEXT_AVAILABLE_SLOTS,EXTENDED_SEARCH_DAYS,MS_PER_DAY,LINKED_USER_TTL_SECONDS,BOOKING_FLOW_TTL_SECONDS,TOOL_CONTEXT_TTL_SECONDS,REFRESH_LOCK_WAIT_MS,REFRESH_LOCK_TTL_SECONDS.Other changes (from prior pushes)
isAIToolCallErrornow catches"tool choice is none"errorsonErrorbroadened to store all stream errors inonErrorRef(not just rate-limit and tool-call); preserves originalErrorinstances forinstanceofchecksbookingFieldsResponsesmust never be empty{}for required fields; default "Notes" slug is"notes"bookingFieldsResponsestype tightened fromRecord<string, unknown>toRecord<string, string>Updates since last revision
Addressed review comments in the latest commit:
Disabled retries for ALL mutating API calls (
client.ts): Previously onlycreateBooking,createBookingPublic, andaddBookingAttendeehadretries: 0. Now all POST/PATCH/DELETE calls (cancel, reschedule, confirm, decline, updateMe, create/update/deleteSchedule, create/update/deleteEventType, markNoShow) also passretries: 0. A timed-out cancel or reschedule will no longer silently retry and potentially create duplicates.Reordered error handlers in
withBotErrorHandling(bot.ts): Moved theCalcomApiErrorcatch block aftergetCustomErrorMessage. Previously, a 409 booking conflict in the Slack modal was caught by the genericCalcomApiErrorhandler before the modal's context-awarefriendlyCalcomError(err, "booking")could run — that handler was effectively dead code. Now callers get first crack at providing context-specific messages.Re-read linked user after token refresh (
bot.ts): Changedconst linkedtolet linkedinrunAgentHandler. AftergetValidAccessToken(which may have refreshed the token and synced org data via/v2/me), the linked user is re-read from Redis so the org-plan gate uses fresh data instead of the stale snapshot from before the refresh.Review & Testing Checklist for Human
/v2/mereturnsorganizationIdandorganization.isPlatformwith thecal-api-version: 2024-08-13header. Test with a free user (should see upgrade message on @mention //cal how are you), an Org plan user (should get AI response), and a Platform API-tier user (should see upgrade message). Verify all three can still use/cal bookings,/cal help,/cal availability.undefinedfor org fields in Redis and will be treated as non-org (blocked from agentic) until their next token refresh (roughly hourly for active users) or re-link. Decide if this grace period is acceptable or if a migration is needed./v2/mecall on every token refresh (user-linking.ts): Adds one API call per token refresh (~1/hour per active user). Non-fatal on failure. Confirm this overhead is acceptable.responses→bookingFieldsResponsesrename is the highest-risk change. The OpenAPI spec saysbookingFieldsResponses, but if the live API silently acceptsresponsesas an alias and does NOT acceptbookingFieldsResponses, all bookings with custom fields will break. Test a real booking with custom fields (including thenotesfield) end-to-end to confirm the API acceptsbookingFieldsResponses.retries: 0. Verify that slow-but-successful API responses (>10s) don't get prematurely aborted by theAbortSignal.timeout(10_000). If Cal.com cancel/reschedule endpoints sometimes take >10s, users will see timeout errors. Previously cancel/reschedule/confirm/decline retried on timeout — now they don't.withBotErrorHandling: Verify thatgetCustomErrorMessagecallbacks in the Slack modal flow (friendlyCalcomError(err, "booking")) now correctly handle 409 conflicts with the context-aware "booking" message, and that genericCalcomApiErrorstill works as a fallback for paths without a custom handler.recurringBookingUidonCalcomBooking— Verify the API returns this field on booking objects. If not, recurring booking detection in reschedule prompts won't fire.bookingUidToReschedulequery param — Verify the/v2/slotsAPI accepts this parameter. If silently ignored, the original time slot appears as "busy" during reschedule.rescheduledByinrescheduleBooking— Verify the API accepts this in thePOST /v2/bookings/{uid}/reschedulebody for auto-confirmation.markNoShowrequest body —POST /v2/bookings/{uid}/mark-absentnow receives{ host, attendees }. Verify the API accepts this shape.Notes
devin/1773320873-smart-mention-booking-flow)