Slot engine
import { computeAvailableSlots } from "@agent-native/scheduling/core"
Inputs
- Event type config (duration, buffers, minimum notice, period, limits, slot interval)
- Schedule (timezone + weekly availability + date overrides)
- Busy intervals (UTC, aggregated from external calendars + existing bookings)
- Booking counts by bucket (day/week/month/year) for limit enforcement
- Time range to compute over
- Optional seats-per-slot + seats-taken map
- Viewer timezone (for limit bucketing, if it differs from the schedule)
Output
- Array of
Slot { start: ISO, end: ISO, available: boolean, seatsRemaining?, hostEmail? }
Invariants
The function guarantees, in order:
- No slot falls in the past (
now + minimumBookingNoticeis the floor). - No slot overlaps a busy interval (with buffers applied).
- No slot falls outside the schedule's available intervals for that day.
- No slot exceeds a booking limit.
- No slot falls outside the event's period (rolling/range).
- DST-safe: we convert to UTC using the schedule's timezone before doing any interval arithmetic.
Debugging
If a slot is unexpectedly missing:
- Check the schedule's weekly availability for that day-of-week in the schedule's timezone (not UTC — weekends can shift across the date line).
- Check date overrides for that local date (empty intervals = fully blocked).
- Check merged busy intervals for overlap, including the before/after buffer expansion.
- Check booking limits: a single existing booking can close a day.
- Check period caps: rolling periods restrict how far in the future slots appear.
If a slot is unexpectedly present:
- Check that
nowis being passed correctly (defaults tonew Date()). - Check that busy intervals from providers are in UTC.
- Confirm slot interval matches what you expect (default = duration).