@agent-native/scheduling 0.2.1 → 0.2.2-nightly-20260927023146

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/dist/actions/_helpers.d.ts +0 -13
  2. package/dist/actions/_helpers.d.ts.map +1 -1
  3. package/dist/actions/_helpers.js +0 -16
  4. package/dist/actions/_helpers.js.map +1 -1
  5. package/dist/actions/create-team.js +0 -1
  6. package/dist/actions/create-team.js.map +1 -1
  7. package/dist/actions/list-bookings.js +0 -4
  8. package/dist/actions/list-bookings.js.map +1 -1
  9. package/dist/actions/refresh-busy-times.js +0 -1
  10. package/dist/actions/refresh-busy-times.js.map +1 -1
  11. package/dist/actions/revoke-private-link.js +0 -2
  12. package/dist/actions/revoke-private-link.js.map +1 -1
  13. package/dist/actions/update-profile.js +0 -5
  14. package/dist/actions/update-profile.js.map +1 -1
  15. package/dist/core/buffers.d.ts +0 -18
  16. package/dist/core/buffers.d.ts.map +1 -1
  17. package/dist/core/buffers.js +0 -6
  18. package/dist/core/buffers.js.map +1 -1
  19. package/dist/core/conflicts.d.ts +0 -4
  20. package/dist/core/conflicts.d.ts.map +1 -1
  21. package/dist/core/conflicts.js +0 -1
  22. package/dist/core/conflicts.js.map +1 -1
  23. package/dist/core/limits.d.ts +0 -8
  24. package/dist/core/limits.d.ts.map +1 -1
  25. package/dist/core/limits.js.map +1 -1
  26. package/dist/core/round-robin.d.ts +0 -17
  27. package/dist/core/round-robin.d.ts.map +1 -1
  28. package/dist/core/round-robin.js.map +1 -1
  29. package/dist/core/rrule.d.ts.map +1 -1
  30. package/dist/core/rrule.js +0 -7
  31. package/dist/core/rrule.js.map +1 -1
  32. package/dist/core/rules.d.ts +0 -17
  33. package/dist/core/rules.d.ts.map +1 -1
  34. package/dist/core/rules.js +0 -8
  35. package/dist/core/rules.js.map +1 -1
  36. package/dist/core/slots.d.ts +0 -31
  37. package/dist/core/slots.d.ts.map +1 -1
  38. package/dist/core/slots.js +0 -9
  39. package/dist/core/slots.js.map +1 -1
  40. package/dist/core/time.d.ts +0 -24
  41. package/dist/core/time.d.ts.map +1 -1
  42. package/dist/core/time.js +0 -37
  43. package/dist/core/time.js.map +1 -1
  44. package/dist/index.d.ts +0 -10
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/index.js +0 -10
  47. package/dist/index.js.map +1 -1
  48. package/dist/manifest.d.ts +0 -9
  49. package/dist/manifest.d.ts.map +1 -1
  50. package/dist/manifest.js +0 -18
  51. package/dist/manifest.js.map +1 -1
  52. package/dist/react/components/SlotPicker.d.ts +0 -8
  53. package/dist/react/components/SlotPicker.d.ts.map +1 -1
  54. package/dist/react/components/SlotPicker.js.map +1 -1
  55. package/dist/react/components/TimezoneSelect.d.ts.map +1 -1
  56. package/dist/react/components/TimezoneSelect.js +0 -2
  57. package/dist/react/components/TimezoneSelect.js.map +1 -1
  58. package/dist/react/components/booking-links/AvailabilityEditor.d.ts +0 -4
  59. package/dist/react/components/booking-links/AvailabilityEditor.d.ts.map +1 -1
  60. package/dist/react/components/booking-links/AvailabilityEditor.js +0 -15
  61. package/dist/react/components/booking-links/AvailabilityEditor.js.map +1 -1
  62. package/dist/react/components/booking-links/BookingLinkCreateDialog.d.ts +0 -6
  63. package/dist/react/components/booking-links/BookingLinkCreateDialog.d.ts.map +1 -1
  64. package/dist/react/components/booking-links/BookingLinkCreateDialog.js +0 -16
  65. package/dist/react/components/booking-links/BookingLinkCreateDialog.js.map +1 -1
  66. package/dist/react/components/booking-links/ConferencingSelector.d.ts +0 -2
  67. package/dist/react/components/booking-links/ConferencingSelector.d.ts.map +1 -1
  68. package/dist/react/components/booking-links/ConferencingSelector.js +0 -24
  69. package/dist/react/components/booking-links/ConferencingSelector.js.map +1 -1
  70. package/dist/react/components/booking-links/CustomFieldsEditor.d.ts +0 -1
  71. package/dist/react/components/booking-links/CustomFieldsEditor.d.ts.map +1 -1
  72. package/dist/react/components/booking-links/CustomFieldsEditor.js +0 -14
  73. package/dist/react/components/booking-links/CustomFieldsEditor.js.map +1 -1
  74. package/dist/react/components/booking-links/DurationPicker.d.ts +0 -1
  75. package/dist/react/components/booking-links/DurationPicker.d.ts.map +1 -1
  76. package/dist/react/components/booking-links/DurationPicker.js +1 -11
  77. package/dist/react/components/booking-links/DurationPicker.js.map +1 -1
  78. package/dist/react/components/booking-links/SlugEditor.d.ts +0 -3
  79. package/dist/react/components/booking-links/SlugEditor.d.ts.map +1 -1
  80. package/dist/react/components/booking-links/SlugEditor.js +0 -11
  81. package/dist/react/components/booking-links/SlugEditor.js.map +1 -1
  82. package/dist/react/components/booking-links/index.d.ts +0 -9
  83. package/dist/react/components/booking-links/index.d.ts.map +1 -1
  84. package/dist/react/components/booking-links/index.js +0 -9
  85. package/dist/react/components/booking-links/index.js.map +1 -1
  86. package/dist/react/components/index.d.ts +0 -10
  87. package/dist/react/components/index.d.ts.map +1 -1
  88. package/dist/react/components/index.js +0 -10
  89. package/dist/react/components/index.js.map +1 -1
  90. package/dist/react/hooks/useBookingFlow.d.ts.map +1 -1
  91. package/dist/react/hooks/useBookingFlow.js +0 -10
  92. package/dist/react/hooks/useBookingFlow.js.map +1 -1
  93. package/dist/react/hooks/useEventType.d.ts.map +1 -1
  94. package/dist/react/hooks/useEventType.js +0 -4
  95. package/dist/react/hooks/useEventType.js.map +1 -1
  96. package/dist/react/hooks/useReschedule.d.ts.map +1 -1
  97. package/dist/react/hooks/useReschedule.js +0 -4
  98. package/dist/react/hooks/useReschedule.js.map +1 -1
  99. package/dist/react/hooks/useSlots.d.ts +0 -2
  100. package/dist/react/hooks/useSlots.d.ts.map +1 -1
  101. package/dist/react/hooks/useSlots.js +0 -8
  102. package/dist/react/hooks/useSlots.js.map +1 -1
  103. package/dist/react/hooks/useTimezone.d.ts.map +1 -1
  104. package/dist/react/hooks/useTimezone.js +0 -4
  105. package/dist/react/hooks/useTimezone.js.map +1 -1
  106. package/dist/react/index.d.ts +0 -5
  107. package/dist/react/index.d.ts.map +1 -1
  108. package/dist/react/index.js +0 -5
  109. package/dist/react/index.js.map +1 -1
  110. package/dist/schema/bookings.d.ts +0 -7
  111. package/dist/schema/bookings.d.ts.map +1 -1
  112. package/dist/schema/bookings.js +0 -29
  113. package/dist/schema/bookings.js.map +1 -1
  114. package/dist/schema/calendar-cache.d.ts.map +1 -1
  115. package/dist/schema/calendar-cache.js +0 -11
  116. package/dist/schema/calendar-cache.js.map +1 -1
  117. package/dist/schema/credentials.d.ts +0 -8
  118. package/dist/schema/credentials.d.ts.map +1 -1
  119. package/dist/schema/credentials.js +0 -28
  120. package/dist/schema/credentials.js.map +1 -1
  121. package/dist/schema/event-types.d.ts +0 -10
  122. package/dist/schema/event-types.d.ts.map +1 -1
  123. package/dist/schema/event-types.js +0 -42
  124. package/dist/schema/event-types.js.map +1 -1
  125. package/dist/schema/index.d.ts +0 -11
  126. package/dist/schema/index.d.ts.map +1 -1
  127. package/dist/schema/index.js +0 -11
  128. package/dist/schema/index.js.map +1 -1
  129. package/dist/schema/routing-forms.d.ts.map +1 -1
  130. package/dist/schema/routing-forms.js +0 -17
  131. package/dist/schema/routing-forms.js.map +1 -1
  132. package/dist/schema/schedules.d.ts +0 -12
  133. package/dist/schema/schedules.d.ts.map +1 -1
  134. package/dist/schema/schedules.js +0 -25
  135. package/dist/schema/schedules.js.map +1 -1
  136. package/dist/schema/teams.d.ts.map +1 -1
  137. package/dist/schema/teams.js +0 -7
  138. package/dist/schema/teams.js.map +1 -1
  139. package/dist/schema/workflows.d.ts +0 -7
  140. package/dist/schema/workflows.d.ts.map +1 -1
  141. package/dist/schema/workflows.js +0 -19
  142. package/dist/schema/workflows.js.map +1 -1
  143. package/dist/server/availability-engine.d.ts +0 -12
  144. package/dist/server/availability-engine.d.ts.map +1 -1
  145. package/dist/server/availability-engine.js +0 -20
  146. package/dist/server/availability-engine.js.map +1 -1
  147. package/dist/server/booking-service.d.ts +0 -14
  148. package/dist/server/booking-service.d.ts.map +1 -1
  149. package/dist/server/booking-service.js +0 -8
  150. package/dist/server/booking-service.js.map +1 -1
  151. package/dist/server/bookings-repo.d.ts +0 -7
  152. package/dist/server/bookings-repo.d.ts.map +1 -1
  153. package/dist/server/bookings-repo.js +0 -3
  154. package/dist/server/bookings-repo.js.map +1 -1
  155. package/dist/server/context.d.ts +0 -16
  156. package/dist/server/context.d.ts.map +1 -1
  157. package/dist/server/context.js.map +1 -1
  158. package/dist/server/db-types.d.ts +0 -11
  159. package/dist/server/db-types.d.ts.map +1 -1
  160. package/dist/server/event-types-repo.d.ts +0 -10
  161. package/dist/server/event-types-repo.d.ts.map +1 -1
  162. package/dist/server/event-types-repo.js +0 -21
  163. package/dist/server/event-types-repo.js.map +1 -1
  164. package/dist/server/hooks.d.ts.map +1 -1
  165. package/dist/server/hooks.js +0 -11
  166. package/dist/server/hooks.js.map +1 -1
  167. package/dist/server/ics.d.ts +0 -7
  168. package/dist/server/ics.d.ts.map +1 -1
  169. package/dist/server/ics.js.map +1 -1
  170. package/dist/server/providers/builtin-video.d.ts +0 -5
  171. package/dist/server/providers/builtin-video.d.ts.map +1 -1
  172. package/dist/server/providers/builtin-video.js.map +1 -1
  173. package/dist/server/providers/google-calendar.d.ts +0 -3
  174. package/dist/server/providers/google-calendar.d.ts.map +1 -1
  175. package/dist/server/providers/google-calendar.js +0 -2
  176. package/dist/server/providers/google-calendar.js.map +1 -1
  177. package/dist/server/providers/google-meet.d.ts +0 -7
  178. package/dist/server/providers/google-meet.d.ts.map +1 -1
  179. package/dist/server/providers/google-meet.js.map +1 -1
  180. package/dist/server/providers/office365.d.ts +0 -6
  181. package/dist/server/providers/office365.d.ts.map +1 -1
  182. package/dist/server/providers/office365.js.map +1 -1
  183. package/dist/server/providers/registry.d.ts +0 -4
  184. package/dist/server/providers/registry.d.ts.map +1 -1
  185. package/dist/server/providers/registry.js.map +1 -1
  186. package/dist/server/providers/teams.d.ts +0 -6
  187. package/dist/server/providers/teams.d.ts.map +1 -1
  188. package/dist/server/providers/teams.js +0 -2
  189. package/dist/server/providers/teams.js.map +1 -1
  190. package/dist/server/providers/types.d.ts +0 -27
  191. package/dist/server/providers/types.d.ts.map +1 -1
  192. package/dist/server/providers/zoom.d.ts +0 -19
  193. package/dist/server/providers/zoom.d.ts.map +1 -1
  194. package/dist/server/providers/zoom.js +0 -2
  195. package/dist/server/providers/zoom.js.map +1 -1
  196. package/dist/server/schedules-repo.d.ts.map +1 -1
  197. package/dist/server/schedules-repo.js +0 -4
  198. package/dist/server/schedules-repo.js.map +1 -1
  199. package/dist/server/video-oauth-state.d.ts +0 -5
  200. package/dist/server/video-oauth-state.d.ts.map +1 -1
  201. package/dist/server/video-oauth-state.js +1 -9
  202. package/dist/server/video-oauth-state.js.map +1 -1
  203. package/dist/server/video-oauth.d.ts +0 -4
  204. package/dist/server/video-oauth.d.ts.map +1 -1
  205. package/dist/server/video-oauth.js +0 -23
  206. package/dist/server/video-oauth.js.map +1 -1
  207. package/dist/shared/index.d.ts +0 -37
  208. package/dist/shared/index.d.ts.map +1 -1
  209. package/dist/shared/index.js +0 -4
  210. package/dist/shared/index.js.map +1 -1
  211. package/package.json +4 -4
  212. package/src/actions/_helpers.ts +0 -16
  213. package/src/actions/booking-authz.spec.ts +0 -6
  214. package/src/actions/create-team.ts +0 -1
  215. package/src/actions/event-type-authz.spec.ts +0 -11
  216. package/src/actions/list-bookings.ts +0 -4
  217. package/src/actions/refresh-busy-times.ts +0 -1
  218. package/src/actions/revoke-private-link.ts +0 -2
  219. package/src/actions/update-profile.ts +0 -5
  220. package/src/core/buffers.ts +0 -18
  221. package/src/core/conflicts.ts +0 -4
  222. package/src/core/limits.ts +0 -8
  223. package/src/core/round-robin.test.ts +0 -1
  224. package/src/core/round-robin.ts +0 -17
  225. package/src/core/rrule.ts +0 -7
  226. package/src/core/rules.ts +0 -17
  227. package/src/core/slots.test.ts +1 -11
  228. package/src/core/slots.ts +0 -40
  229. package/src/core/time.ts +0 -37
  230. package/src/index.ts +0 -11
  231. package/src/manifest.ts +0 -19
  232. package/src/react/components/SlotPicker.tsx +0 -8
  233. package/src/react/components/TimezoneSelect.tsx +0 -2
  234. package/src/react/components/_shadcn-shims.d.ts +0 -35
  235. package/src/react/components/booking-links/AvailabilityEditor.tsx +0 -15
  236. package/src/react/components/booking-links/BookingLinkCreateDialog.tsx +0 -22
  237. package/src/react/components/booking-links/ConferencingSelector.tsx +0 -26
  238. package/src/react/components/booking-links/CustomFieldsEditor.tsx +0 -15
  239. package/src/react/components/booking-links/DurationPicker.tsx +1 -12
  240. package/src/react/components/booking-links/SlugEditor.tsx +0 -14
  241. package/src/react/components/booking-links/index.ts +0 -9
  242. package/src/react/components/index.ts +0 -10
  243. package/src/react/hooks/useBookingFlow.ts +0 -10
  244. package/src/react/hooks/useEventType.ts +0 -4
  245. package/src/react/hooks/useReschedule.ts +0 -4
  246. package/src/react/hooks/useSlots.ts +0 -10
  247. package/src/react/hooks/useTimezone.ts +0 -4
  248. package/src/react/index.ts +0 -5
  249. package/src/schema/bookings.ts +0 -29
  250. package/src/schema/calendar-cache.ts +0 -11
  251. package/src/schema/credentials.ts +0 -28
  252. package/src/schema/event-types.ts +0 -42
  253. package/src/schema/index.ts +0 -11
  254. package/src/schema/routing-forms.ts +0 -17
  255. package/src/schema/schedules.ts +0 -25
  256. package/src/schema/teams.ts +0 -7
  257. package/src/schema/workflows.ts +0 -19
  258. package/src/server/availability-engine.test.ts +0 -1
  259. package/src/server/availability-engine.ts +0 -22
  260. package/src/server/booking-service.spec.ts +0 -15
  261. package/src/server/booking-service.ts +0 -22
  262. package/src/server/bookings-repo.ts +0 -10
  263. package/src/server/context.ts +0 -16
  264. package/src/server/db-types.ts +0 -11
  265. package/src/server/event-types-repo.ts +0 -31
  266. package/src/server/hooks.ts +0 -11
  267. package/src/server/ics.ts +0 -7
  268. package/src/server/providers/builtin-video.ts +0 -5
  269. package/src/server/providers/google-calendar.ts +0 -5
  270. package/src/server/providers/google-meet.ts +0 -7
  271. package/src/server/providers/office365.ts +0 -6
  272. package/src/server/providers/registry.ts +0 -4
  273. package/src/server/providers/teams.ts +0 -8
  274. package/src/server/providers/types.ts +0 -27
  275. package/src/server/providers/zoom.ts +0 -21
  276. package/src/server/schedules-repo.ts +0 -4
  277. package/src/server/video-oauth-state.ts +1 -10
  278. package/src/server/video-oauth.ts +0 -23
  279. package/src/shared/index.ts +0 -38
@@ -1,10 +1,4 @@
1
1
  import { accessFilter } from "@agent-native/core/sharing";
2
- /**
3
- * Data access for event types.
4
- *
5
- * All write paths funnel through here so ownership, slug uniqueness, and
6
- * redirect history are handled consistently.
7
- */
8
2
  import { eq, and } from "drizzle-orm";
9
3
  import { nanoid } from "nanoid";
10
4
 
@@ -75,29 +69,15 @@ function parseJson<T = any>(str: string | null | undefined): T | undefined {
75
69
  }
76
70
 
77
71
  export async function listEventTypes(params: {
78
- /**
79
- * If provided and `useAccessFilter` is not true, narrow rows to this owner.
80
- * For org-aware list calls, prefer `useAccessFilter: true` instead.
81
- */
82
72
  ownerEmail?: string;
83
73
  teamId?: string;
84
74
  includeHidden?: boolean;
85
- /**
86
- * When true, apply the framework `accessFilter` (owner OR shared OR
87
- * org-visibility OR public) instead of plain ownerEmail equality. This is
88
- * the right mode for any UI/agent listing, since it admits org-shared and
89
- * explicitly-shared event types in addition to the user's own.
90
- */
91
75
  useAccessFilter?: boolean;
92
76
  }): Promise<EventType[]> {
93
77
  const { getDb, schema } = getSchedulingContext();
94
78
  const db = getDb();
95
79
  let rows: any[];
96
80
  if (params.teamId) {
97
- // Team-scoped listings. Callers are responsible for asserting team
98
- // membership before invoking — the repo does not (it runs without a
99
- // request context in some paths, e.g. public booking pages that
100
- // explicitly pass a teamId).
101
81
  rows = await db
102
82
  .select()
103
83
  .from(schema.eventTypes)
@@ -113,8 +93,6 @@ export async function listEventTypes(params: {
113
93
  .from(schema.eventTypes)
114
94
  .where(eq(schema.eventTypes.ownerEmail, params.ownerEmail));
115
95
  } else {
116
- // Refuse to return unscoped results. Callers must supply at least
117
- // one of: teamId, useAccessFilter, or ownerEmail.
118
96
  return [];
119
97
  }
120
98
  return rows
@@ -185,9 +163,6 @@ export async function createEventType(input: {
185
163
  const db = getDb();
186
164
  const now = new Date().toISOString();
187
165
  const id = nanoid();
188
- // Default location: the user's `isDefault` conferencing credential if they
189
- // have one installed (Zoom, Meet, Teams), otherwise no location — the
190
- // editor will prompt them to pick.
191
166
  const defaultLocations: Location[] =
192
167
  input.locations ??
193
168
  (input.ownerEmail ? await resolveDefaultLocation(input.ownerEmail) : []);
@@ -242,7 +217,6 @@ export async function updateEventType(
242
217
  const dbPatch: Record<string, any> = {};
243
218
  if (patch.title != null) dbPatch.title = patch.title;
244
219
  if (patch.slug != null && patch.slug !== current.slug) {
245
- // Record slug redirect
246
220
  const oldKey = keyFor(
247
221
  current.ownerEmail ?? null,
248
222
  current.teamId ?? null,
@@ -337,11 +311,6 @@ export async function deleteEventType(id: string): Promise<void> {
337
311
  await getDb().delete(schema.eventTypes).where(eq(schema.eventTypes.id, id));
338
312
  }
339
313
 
340
- /**
341
- * Return a sensible default location for a freshly-created event type.
342
- * Priority: the user's `isDefault` video conferencing credential → the
343
- * first installed video credential → an empty list (editor prompts user).
344
- */
345
314
  async function resolveDefaultLocation(ownerEmail: string): Promise<Location[]> {
346
315
  const { getDb, schema } = getSchedulingContext();
347
316
  const rows = await getDb()
@@ -1,12 +1,3 @@
1
- /**
2
- * Booking lifecycle hooks → workflow / webhook dispatcher.
3
- *
4
- * When a booking is created / rescheduled / cancelled / no-shown, we:
5
- * - Materialize scheduled reminders for each active workflow step
6
- * - Enqueue outgoing webhook deliveries
7
- *
8
- * The actual reminder + webhook firing happens on a recurring job (not here).
9
- */
10
1
  import { eq, and, inArray } from "drizzle-orm";
11
2
  import { nanoid } from "nanoid";
12
3
 
@@ -31,7 +22,6 @@ export async function onBookingRescheduled(
31
22
  export async function onBookingCancelled(booking: Booking): Promise<void> {
32
23
  await materializeReminders(booking, "cancellation");
33
24
  await enqueueWebhooks(booking, "BOOKING_CANCELLED");
34
- // Cancel any pending before-event reminders
35
25
  const { getDb, schema } = getSchedulingContext();
36
26
  await getDb()
37
27
  .update(schema.scheduledReminders)
@@ -74,7 +64,6 @@ async function materializeRemindersBefore(booking: Booking): Promise<void> {
74
64
  const start = new Date(booking.startTime);
75
65
  for (const wf of workflows) {
76
66
  for (const step of wf.steps) {
77
- // offsetMinutes is how many minutes BEFORE the event
78
67
  const scheduledFor = addMinutes(start, -Math.abs(step.offsetMinutes));
79
68
  if (scheduledFor <= new Date()) continue;
80
69
  await writeReminder(booking, step, scheduledFor);
package/src/server/ics.ts CHANGED
@@ -1,10 +1,3 @@
1
- /**
2
- * Minimal iCalendar (RFC 5545) generator for booking confirmation emails and
3
- * the `/booking/:uid.ics` download endpoint.
4
- *
5
- * Not exhaustive — just enough for Apple Mail / Outlook / Gmail to render
6
- * the event card correctly and for Add-to-Calendar buttons to work.
7
- */
8
1
  import type { Booking } from "../shared/index.js";
9
2
 
10
3
  export function buildIcs(booking: Booking, organizerName: string): string {
@@ -1,12 +1,7 @@
1
- /**
2
- * Built-in video provider (Daily.co) — zero-OAuth video provider driven by a
3
- * server-to-server API key. Creates a Daily.co room per booking.
4
- */
5
1
  import type { VideoProvider } from "./types.js";
6
2
 
7
3
  export interface DailyVideoProviderConfig {
8
4
  apiKey: string;
9
- /** Prefix for Daily room names; defaults to "room-" */
10
5
  roomPrefix?: string;
11
6
  }
12
7
 
@@ -15,14 +15,11 @@ import type { CalendarProvider } from "./types.js";
15
15
  export interface GoogleCalendarProviderConfig {
16
16
  clientId: string;
17
17
  clientSecret: string;
18
- /** Resolve a fresh access token for a given credentialId (refresh if needed). */
19
18
  getAccessToken: (credentialId: string) => Promise<string>;
20
- /** Persist updated refresh/access tokens after a refresh. */
21
19
  updateTokens?: (
22
20
  credentialId: string,
23
21
  tokens: { accessToken: string; refreshToken?: string; expiresAt?: Date },
24
22
  ) => Promise<void>;
25
- /** Called when the API returns 401/403; the consumer should mark the credential invalid. */
26
23
  markInvalid?: (credentialId: string) => Promise<void>;
27
24
  }
28
25
 
@@ -104,7 +101,6 @@ export function createGoogleCalendarProvider(
104
101
  expiresAt: new Date(Date.now() + (tokens.expires_in ?? 3600) * 1000),
105
102
  });
106
103
 
107
- // Discover external email + calendar list
108
104
  const calendars = await apiCall<{
109
105
  items: { id: string; summary: string; primary?: boolean }[];
110
106
  }>(
@@ -208,7 +204,6 @@ export function createGoogleCalendarProvider(
208
204
  },
209
205
 
210
206
  async updateEvent({ credentialId, externalId, booking }) {
211
- // Bump sequence for RFC 5545 compliance
212
207
  const newSeq = booking.iCalSequence + 1;
213
208
  const body = {
214
209
  summary: booking.title,
@@ -1,10 +1,3 @@
1
- /**
2
- * Google Meet — piggy-backs on Google Calendar credentials. The meeting link
3
- * is created as part of the calendar event (conferenceData). This provider
4
- * exists so we can list Google Meet as an installable conferencing option in
5
- * the UI; the actual meeting creation happens in `google-calendar.createEvent`
6
- * when `includeConference` is true.
7
- */
8
1
  import type { VideoProvider } from "./types.js";
9
2
 
10
3
  export const googleMeetProvider: VideoProvider = {
@@ -1,10 +1,4 @@
1
1
  import type { BusyInterval } from "../../shared/index.js";
2
- /**
3
- * Office 365 / Outlook calendar provider via Microsoft Graph.
4
- *
5
- * Token flow is identical to Google but against login.microsoftonline.com.
6
- * Uses Microsoft Graph API for calendars and events.
7
- */
8
2
  import type { CalendarProvider } from "./types.js";
9
3
 
10
4
  export interface Office365ProviderConfig {
@@ -1,7 +1,3 @@
1
- /**
2
- * Provider registry — consumers register calendar/video/SMS providers at
3
- * startup. Actions look up providers by kind.
4
- */
5
1
  import type { CalendarProvider, VideoProvider, SmsProvider } from "./types.js";
6
2
 
7
3
  const calendarProviders = new Map<string, CalendarProvider>();
@@ -1,13 +1,8 @@
1
- /**
2
- * Microsoft Teams provider — delegated Microsoft OAuth with Graph-backed
3
- * standalone online meetings.
4
- */
5
1
  import type { VideoProvider } from "./types.js";
6
2
 
7
3
  export interface TeamsProviderConfig {
8
4
  clientId: string;
9
5
  clientSecret: string;
10
- /** Microsoft tenant id/domain; defaults to work-or-school accounts. */
11
6
  tenant?: string;
12
7
  getAccessToken: (credentialId: string) => Promise<string>;
13
8
  updateTokens?: (
@@ -19,7 +14,6 @@ export interface TeamsProviderConfig {
19
14
  rawResponse?: Record<string, unknown>;
20
15
  },
21
16
  ) => Promise<void>;
22
- /** Called when Graph returns 401/403; mark the credential invalid in UI. */
23
17
  markInvalid?: (credentialId: string) => Promise<void>;
24
18
  }
25
19
 
@@ -106,8 +100,6 @@ export function createTeamsProvider(
106
100
  rawResponse: tokens,
107
101
  });
108
102
 
109
- // Use the token from this exchange directly. The consumer's token store
110
- // may not be observable through getAccessToken until after this callback.
111
103
  const identityResponse = await fetch(
112
104
  `${GRAPH_BASE_URL}/me?$select=id,mail,userPrincipalName,displayName`,
113
105
  { headers: { authorization: `Bearer ${tokens.access_token}` } },
@@ -1,29 +1,15 @@
1
- /**
2
- * Pluggable provider interfaces for calendar reads and video-meeting writes.
3
- *
4
- * Consumers register providers via the registry. Each provider owns its own
5
- * OAuth/credential lifecycle; this package is agnostic to how the tokens
6
- * are stored (typically in core `oauth_tokens`).
7
- */
8
1
  import type { BusyInterval, Booking } from "../../shared/index.js";
9
2
 
10
3
  export interface CalendarProvider {
11
- /** Unique provider slug, e.g. "google_calendar" */
12
4
  kind: string;
13
5
 
14
- /** Human-friendly display name, e.g. "Google Calendar" */
15
6
  label: string;
16
7
 
17
- /**
18
- * Start the OAuth flow — return an authorization URL for the user to visit.
19
- * `redirectUri` is the server's OAuth callback path for this provider.
20
- */
21
8
  startOAuth(opts: {
22
9
  redirectUri: string;
23
10
  state: string;
24
11
  }): Promise<{ authUrl: string }>;
25
12
 
26
- /** Complete the OAuth flow with the received code; persist the credential. */
27
13
  completeOAuth(opts: {
28
14
  credentialId: string;
29
15
  userEmail: string;
@@ -34,12 +20,10 @@ export interface CalendarProvider {
34
20
  calendars: { externalId: string; name: string; primary: boolean }[];
35
21
  }>;
36
22
 
37
- /** List the calendars the user has access to (for Selected Calendars UI). */
38
23
  listCalendars(opts: {
39
24
  credentialId: string;
40
25
  }): Promise<{ externalId: string; name: string; primary: boolean }[]>;
41
26
 
42
- /** Read busy intervals across the user's selected calendars. */
43
27
  getBusy(opts: {
44
28
  credentialId: string;
45
29
  calendarExternalIds: string[];
@@ -47,7 +31,6 @@ export interface CalendarProvider {
47
31
  end: Date;
48
32
  }): Promise<BusyInterval[]>;
49
33
 
50
- /** Create a calendar event; return the external id. */
51
34
  createEvent(opts: {
52
35
  credentialId: string;
53
36
  calendarExternalId: string;
@@ -59,14 +42,12 @@ export interface CalendarProvider {
59
42
  icalUid?: string;
60
43
  }>;
61
44
 
62
- /** Update (e.g. after reschedule). Returns the new iCalSequence. */
63
45
  updateEvent(opts: {
64
46
  credentialId: string;
65
47
  externalId: string;
66
48
  booking: Booking;
67
49
  }): Promise<{ iCalSequence: number }>;
68
50
 
69
- /** Delete/cancel an event. */
70
51
  deleteEvent(opts: {
71
52
  credentialId: string;
72
53
  externalId: string;
@@ -88,12 +69,6 @@ export interface VideoProvider {
88
69
  state: string;
89
70
  }): Promise<{ authUrl: string }>;
90
71
 
91
- /**
92
- * Complete the OAuth flow — optional. Paired with `startOAuth`. Consumers
93
- * call this from their OAuth callback handler to exchange the `code` for
94
- * tokens and return identifying info so a `scheduling_credentials` row
95
- * can be written.
96
- */
97
72
  completeOAuth?(opts: {
98
73
  credentialId: string;
99
74
  userEmail: string;
@@ -105,14 +80,12 @@ export interface VideoProvider {
105
80
  displayName?: string;
106
81
  }>;
107
82
 
108
- /** Create a meeting room for a booking. */
109
83
  createMeeting(opts: { credentialId?: string; booking: Booking }): Promise<{
110
84
  meetingUrl: string;
111
85
  meetingId: string;
112
86
  meetingPassword?: string;
113
87
  }>;
114
88
 
115
- /** Delete the meeting when the booking is cancelled. */
116
89
  deleteMeeting?(opts: {
117
90
  credentialId?: string;
118
91
  meetingId: string;
@@ -1,16 +1,3 @@
1
- /**
2
- * Zoom provider — OAuth-based; creates a Zoom meeting per booking.
3
- *
4
- * Tokens are stored via the consumer's callback (typically core's
5
- * oauth_tokens), keyed by credentialId. Consumers wire up
6
- * `getAccessToken` + `updateTokens` against their token store.
7
- *
8
- * OAuth:
9
- * - Auth URL: https://zoom.us/oauth/authorize?response_type=code&...
10
- * - Token URL: https://zoom.us/oauth/token (basic-auth client_id:secret)
11
- * - Scopes: meeting:write meeting:read (so we can create + delete)
12
- * - User info: GET https://api.zoom.us/v2/users/me (returns account_id + email)
13
- */
14
1
  import type { VideoProvider } from "./types.js";
15
2
 
16
3
  export class ZoomProviderError extends Error {
@@ -27,11 +14,6 @@ export interface ZoomProviderConfig {
27
14
  clientId: string;
28
15
  clientSecret: string;
29
16
  getAccessToken: (credentialId: string) => Promise<string>;
30
- /**
31
- * Persist tokens after `completeOAuth` (and any later refresh). Optional —
32
- * if omitted, the consumer is responsible for doing the write inside their
33
- * own callback handler.
34
- */
35
17
  updateTokens?: (
36
18
  credentialId: string,
37
19
  tokens: {
@@ -41,11 +23,9 @@ export interface ZoomProviderConfig {
41
23
  rawResponse?: Record<string, unknown>;
42
24
  },
43
25
  ) => Promise<void>;
44
- /** Called when the API returns 401/403; mark credential invalid in UI. */
45
26
  markInvalid?: (credentialId: string) => Promise<void>;
46
27
  }
47
28
 
48
- // Minimum scope needed to create + read meetings on the user's behalf.
49
29
  const SCOPES = ["meeting:write", "meeting:read", "user:read"];
50
30
 
51
31
  export function createZoomProvider(config: ZoomProviderConfig): VideoProvider {
@@ -103,7 +83,6 @@ export function createZoomProvider(config: ZoomProviderConfig): VideoProvider {
103
83
  rawResponse: tokens as unknown as Record<string, unknown>,
104
84
  });
105
85
 
106
- // Pull user info to label the credential.
107
86
  const userRes = await fetch("https://api.zoom.us/v2/users/me", {
108
87
  headers: { authorization: `Bearer ${tokens.access_token}` },
109
88
  });
@@ -1,8 +1,4 @@
1
1
  import { accessFilter } from "@agent-native/core/sharing";
2
- /**
3
- * Data access for schedules — the weekly-hours + date-override definitions
4
- * that event types reference.
5
- */
6
2
  import { eq, and, inArray, type SQL } from "drizzle-orm";
7
3
  import { nanoid } from "nanoid";
8
4
 
@@ -18,7 +18,7 @@
18
18
  import crypto from "node:crypto";
19
19
 
20
20
  const SEPARATOR = ".";
21
- const STATE_TTL_MS = 10 * 60 * 1000; // 10 minutes
21
+ const STATE_TTL_MS = 10 * 60 * 1000;
22
22
 
23
23
  function getStateSecret(): string {
24
24
  const secret =
@@ -46,16 +46,9 @@ function hmac(message: string, secret: string): string {
46
46
  }
47
47
 
48
48
  function safeFragment(value: string): string {
49
- // The encoded payload uses dots as separators, so any literal dot in the
50
- // user email would corrupt parsing. Replace dots and any non-printable
51
- // characters before signing.
52
49
  return value.replace(/[^A-Za-z0-9_@-]/g, "_");
53
50
  }
54
51
 
55
- /**
56
- * Mint a fresh signed state value bound to the current authenticated user
57
- * and the requested OAuth `kind`.
58
- */
59
52
  export function signVideoOAuthState(opts: {
60
53
  kind: string;
61
54
  userEmail: string;
@@ -85,7 +78,6 @@ export function verifyVideoOAuthState(opts: {
85
78
  state: string | undefined | null;
86
79
  kind: string;
87
80
  userEmail: string;
88
- /** Override default 10-minute TTL (for tests). */
89
81
  ttlMs?: number;
90
82
  }): boolean {
91
83
  if (!opts.state || typeof opts.state !== "string") return false;
@@ -106,7 +98,6 @@ export function verifyVideoOAuthState(opts: {
106
98
  if (a.length !== b.length) return false;
107
99
  if (!crypto.timingSafeEqual(a, b)) return false;
108
100
 
109
- // Freshness check.
110
101
  const ttl = opts.ttlMs ?? STATE_TTL_MS;
111
102
  const issuedAt = Number.parseInt(timestamp, 36);
112
103
  if (!Number.isFinite(issuedAt)) return false;
@@ -1,19 +1,4 @@
1
1
  import { eq } from "drizzle-orm";
2
- /**
3
- * Server-side helper for completing video conferencing OAuth callbacks.
4
- *
5
- * Templates mount this under `/_agent-native/oauth/<kind>/callback.get.ts`
6
- * and forward the h3 event. The helper:
7
- * 1. Looks up the video provider by kind
8
- * 2. Allocates a `scheduling_credentials` row (so `credentialId` is stable)
9
- * 3. Calls the provider's `completeOAuth` (tokens get persisted via the
10
- * provider's `updateTokens` callback, typically against core's
11
- * `oauth_tokens` table, keyed by `credentialId`)
12
- * 4. Updates the credential row with display metadata
13
- *
14
- * It is intentionally agnostic to the consumer's auth/session plumbing —
15
- * pass in `userEmail` explicitly.
16
- */
17
2
  import { nanoid } from "nanoid";
18
3
 
19
4
  import { getSchedulingContext } from "./context.js";
@@ -27,10 +12,6 @@ export interface CompleteVideoOAuthResult {
27
12
  displayName?: string;
28
13
  }
29
14
 
30
- /**
31
- * Complete a video-provider OAuth callback. Throws on any failure so the
32
- * caller can decide how to render the error (HTML page, JSON, redirect).
33
- */
34
15
  export async function completeVideoOAuth(opts: {
35
16
  kind: string;
36
17
  userEmail: string;
@@ -50,8 +31,6 @@ export async function completeVideoOAuth(opts: {
50
31
  const now = new Date().toISOString();
51
32
  const credentialId = nanoid();
52
33
 
53
- // Insert row up-front so `updateTokens(credentialId, ...)` inside
54
- // completeOAuth has a stable key to write against.
55
34
  await getDb().insert(schema.schedulingCredentials).values({
56
35
  id: credentialId,
57
36
  type: kind,
@@ -73,14 +52,12 @@ export async function completeVideoOAuth(opts: {
73
52
  redirectUri,
74
53
  });
75
54
  } catch (err) {
76
- // Roll back the credentials row on failure.
77
55
  await getDb()
78
56
  .delete(schema.schedulingCredentials)
79
57
  .where(eq(schema.schedulingCredentials.id, credentialId));
80
58
  throw err;
81
59
  }
82
60
 
83
- // Update the credential row with external identity metadata.
84
61
  await getDb()
85
62
  .update(schema.schedulingCredentials)
86
63
  .set({
@@ -1,8 +1,3 @@
1
- /**
2
- * Wire-level types shared between server, actions, and React client.
3
- * These are the primary stable contract of the package.
4
- */
5
-
6
1
  export type SchedulingType =
7
2
  | "personal"
8
3
  | "collective"
@@ -30,28 +25,19 @@ export type LocationKind =
30
25
 
31
26
  export interface Location {
32
27
  kind: LocationKind;
33
- /** Provider credential id, if applicable */
34
28
  credentialId?: string;
35
- /** Meeting link override */
36
29
  link?: string;
37
- /** Street address for in-person */
38
30
  address?: string;
39
- /** Phone number for phone/organizer-phone */
40
31
  phone?: string;
41
- /** Display name shown in booking UI */
42
32
  label?: string;
43
33
  }
44
34
 
45
35
  export type PeriodType = "unlimited" | "rolling" | "range";
46
36
 
47
37
  export interface BookingLimits {
48
- /** Max bookings in one day */
49
38
  perDay?: number;
50
- /** Max bookings in one week (starting on user's configured start of week) */
51
39
  perWeek?: number;
52
- /** Max bookings in one month */
53
40
  perMonth?: number;
54
- /** Max bookings in one year */
55
41
  perYear?: number;
56
42
  }
57
43
 
@@ -71,18 +57,13 @@ export interface CustomField {
71
57
  placeholder?: string;
72
58
  required: boolean;
73
59
  options?: string[];
74
- /** Default/preset value for this field */
75
60
  defaultValue?: string | number | boolean;
76
- /** Internal identifier stored on booking responses */
77
61
  name: string;
78
62
  }
79
63
 
80
64
  export interface RecurringEventRule {
81
- /** iCal RRULE format, e.g. "FREQ=WEEKLY;COUNT=4" */
82
65
  rrule: string;
83
- /** Max number of occurrences */
84
66
  count?: number;
85
- /** How occurrences are labeled on the booker ("Weekly for 4 weeks") */
86
67
  description?: string;
87
68
  }
88
69
 
@@ -92,15 +73,12 @@ export interface EventType {
92
73
  slug: string;
93
74
  description?: string;
94
75
  length: number;
95
- /** Optional additional duration choices */
96
76
  durations?: number[];
97
77
  hidden: boolean;
98
78
  position: number;
99
79
  schedulingType: SchedulingType;
100
- /** If personal, the owner; if team, null (team event types) */
101
80
  ownerEmail?: string;
102
81
  teamId?: string;
103
- /** Default schedule ID if not set at event level */
104
82
  scheduleId?: string;
105
83
  locations: Location[];
106
84
  customFields: CustomField[];
@@ -128,35 +106,25 @@ export interface EventType {
128
106
  }
129
107
 
130
108
  export interface Slot {
131
- /** ISO 8601 start time in UTC */
132
109
  start: string;
133
- /** ISO 8601 end time in UTC */
134
110
  end: string;
135
- /** True if this slot can still be booked (not full for seated events) */
136
111
  available: boolean;
137
- /** Seats remaining, for seated events */
138
112
  seatsRemaining?: number;
139
- /** Assigned host for round-robin events (email) */
140
113
  hostEmail?: string;
141
114
  }
142
115
 
143
116
  export interface AvailabilityInterval {
144
- /** "HH:MM" in schedule's timezone */
145
117
  startTime: string;
146
- /** "HH:MM" in schedule's timezone */
147
118
  endTime: string;
148
119
  }
149
120
 
150
121
  export interface WeeklyAvailability {
151
- /** 0=Sunday … 6=Saturday, ISO-like */
152
122
  day: number;
153
123
  intervals: AvailabilityInterval[];
154
124
  }
155
125
 
156
126
  export interface DateOverride {
157
- /** YYYY-MM-DD in schedule's timezone */
158
127
  date: string;
159
- /** Empty array = fully blocked */
160
128
  intervals: AvailabilityInterval[];
161
129
  }
162
130
 
@@ -227,9 +195,7 @@ export interface Host {
227
195
  }
228
196
 
229
197
  export interface BusyInterval {
230
- /** ISO 8601 UTC */
231
198
  start: string;
232
- /** ISO 8601 UTC */
233
199
  end: string;
234
200
  source?: string;
235
201
  }
@@ -279,7 +245,6 @@ export interface WorkflowStep {
279
245
  id: string;
280
246
  order: number;
281
247
  action: WorkflowStepAction;
282
- /** Minutes from trigger; negative = before (for before-event), positive = after */
283
248
  offsetMinutes: number;
284
249
  sendTo?: string;
285
250
  emailSubject?: string;
@@ -321,7 +286,6 @@ export interface RoutingFormField {
321
286
 
322
287
  export interface RoutingFormRule {
323
288
  id: string;
324
- /** Array of `{fieldId, op, value}` expressions ANDed together */
325
289
  conditions: {
326
290
  fieldId: string;
327
291
  op: "equals" | "not-equals" | "contains" | "starts-with" | "in";
@@ -341,7 +305,6 @@ export interface RoutingForm {
341
305
  teamId?: string;
342
306
  fields: RoutingFormField[];
343
307
  rules: RoutingFormRule[];
344
- /** Action taken when no rules match */
345
308
  fallback:
346
309
  | { kind: "event-type"; eventTypeId: string }
347
310
  | { kind: "external-url"; url: string }
@@ -359,7 +322,6 @@ export interface HashedLink {
359
322
  usedAt?: string;
360
323
  }
361
324
 
362
- /** Round-robin assignment strategy */
363
325
  export type RoundRobinStrategy =
364
326
  | "lowest-recent-bookings"
365
327
  | "weighted"