@plotday/tool-google-calendar 0.2.1 → 0.2.2

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.
@@ -0,0 +1,70 @@
1
+ import type { Activity } from "@plotday/agent";
2
+ export type GoogleEvent = {
3
+ id: string;
4
+ recurringEventId?: string;
5
+ originalStartTime?: {
6
+ dateTime?: string;
7
+ date?: string;
8
+ timeZone?: string;
9
+ };
10
+ summary?: string;
11
+ description?: string;
12
+ status: "confirmed" | "cancelled" | "tentative";
13
+ start?: {
14
+ dateTime?: string;
15
+ date?: string;
16
+ timeZone?: string;
17
+ };
18
+ end?: {
19
+ dateTime?: string;
20
+ date?: string;
21
+ timeZone?: string;
22
+ };
23
+ recurrence?: string[];
24
+ organizer?: {
25
+ email?: string;
26
+ displayName?: string;
27
+ self?: boolean;
28
+ };
29
+ attendees?: Array<{
30
+ email?: string;
31
+ displayName?: string;
32
+ responseStatus?: "accepted" | "declined" | "tentative" | "needsAction";
33
+ optional?: boolean;
34
+ organizer?: boolean;
35
+ self?: boolean;
36
+ resource?: boolean;
37
+ }>;
38
+ location?: string;
39
+ hangoutLink?: string;
40
+ htmlLink?: string;
41
+ created?: string;
42
+ updated?: string;
43
+ };
44
+ export type SyncState = {
45
+ calendarId: string;
46
+ state?: string;
47
+ more?: boolean;
48
+ min?: Date;
49
+ max?: Date;
50
+ sequence?: number;
51
+ };
52
+ export declare class GoogleApi {
53
+ accessToken: string;
54
+ constructor(accessToken: string);
55
+ call(method: string, url: string, params?: {
56
+ [key: string]: any;
57
+ }, body?: {
58
+ [key: string]: any;
59
+ }): Promise<any>;
60
+ }
61
+ export declare function parseRRule(recurrence?: string[]): string | undefined;
62
+ export declare function parseExDates(recurrence?: string[]): Date[];
63
+ export declare function parseRDates(recurrence?: string[]): Date[];
64
+ export declare function parseGoogleRecurrenceEnd(recurrence?: string[]): Date | string | null;
65
+ export declare function parseGoogleRecurrenceCount(recurrence?: string[]): number | null;
66
+ export declare function transformGoogleEvent(event: GoogleEvent, calendarId: string): Partial<Activity>;
67
+ export declare function syncGoogleCalendar(api: GoogleApi, calendarId: string, state: SyncState): Promise<{
68
+ events: GoogleEvent[];
69
+ state: SyncState;
70
+ }>;
@@ -0,0 +1,195 @@
1
+ import { ActivityType } from "@plotday/agent";
2
+ export class GoogleApi {
3
+ accessToken;
4
+ constructor(accessToken) {
5
+ this.accessToken = accessToken;
6
+ }
7
+ async call(method, url, params, body) {
8
+ const query = params ? `?${new URLSearchParams(params)}` : "";
9
+ const headers = {
10
+ Authorization: `Bearer ${this.accessToken}`,
11
+ Accept: "application/json",
12
+ ...(body ? { "Content-Type": "application/json" } : {}),
13
+ };
14
+ const response = await fetch(url + query, {
15
+ method,
16
+ headers,
17
+ ...(body ? { body: JSON.stringify(body) } : {}),
18
+ });
19
+ switch (response.status) {
20
+ case 400:
21
+ const responseBody = await response.json();
22
+ if (responseBody.status === "FAILED_PRECONDITION") {
23
+ return null;
24
+ }
25
+ throw new Error("Invalid request", { cause: responseBody });
26
+ case 401:
27
+ throw new Error("Authentication failed - token may be expired");
28
+ case 410:
29
+ return null;
30
+ case 200:
31
+ return await response.json();
32
+ default:
33
+ throw new Error(await response.text());
34
+ }
35
+ }
36
+ }
37
+ export function parseRRule(recurrence) {
38
+ if (!recurrence?.length)
39
+ return undefined;
40
+ const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
41
+ return rrule ? rrule.substring(6) : undefined; // Remove 'RRULE:' prefix
42
+ }
43
+ export function parseExDates(recurrence) {
44
+ if (!recurrence?.length)
45
+ return [];
46
+ return recurrence
47
+ .filter((rule) => rule.startsWith("EXDATE"))
48
+ .flatMap((rule) => {
49
+ const dates = rule.split(":")[1];
50
+ return dates ? dates.split(",").map((d) => new Date(d)) : [];
51
+ });
52
+ }
53
+ export function parseRDates(recurrence) {
54
+ if (!recurrence?.length)
55
+ return [];
56
+ return recurrence
57
+ .filter((rule) => rule.startsWith("RDATE"))
58
+ .flatMap((rule) => {
59
+ const dates = rule.split(":")[1];
60
+ return dates ? dates.split(",").map((d) => new Date(d)) : [];
61
+ });
62
+ }
63
+ export function parseGoogleRecurrenceEnd(recurrence) {
64
+ if (!recurrence?.length)
65
+ return null;
66
+ const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
67
+ if (!rrule)
68
+ return null;
69
+ const untilMatch = rrule.match(/UNTIL=([^;]+)/);
70
+ if (untilMatch) {
71
+ const untilValue = untilMatch[1];
72
+ if (untilValue.includes("T")) {
73
+ const year = untilValue.slice(0, 4);
74
+ const month = untilValue.slice(4, 6);
75
+ const day = untilValue.slice(6, 8);
76
+ const hour = untilValue.slice(9, 11);
77
+ const minute = untilValue.slice(11, 13);
78
+ const second = untilValue.slice(13, 15);
79
+ return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}Z`);
80
+ }
81
+ else {
82
+ const year = untilValue.slice(0, 4);
83
+ const month = untilValue.slice(4, 6);
84
+ const day = untilValue.slice(6, 8);
85
+ return `${year}-${month}-${day}`;
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+ export function parseGoogleRecurrenceCount(recurrence) {
91
+ if (!recurrence?.length)
92
+ return null;
93
+ const rrule = recurrence.find((rule) => rule.startsWith("RRULE:"));
94
+ if (!rrule)
95
+ return null;
96
+ const countMatch = rrule.match(/COUNT=([^;]+)/);
97
+ if (countMatch) {
98
+ const count = parseInt(countMatch[1]);
99
+ return isNaN(count) ? null : count;
100
+ }
101
+ return null;
102
+ }
103
+ export function transformGoogleEvent(event, calendarId) {
104
+ // Determine if this is an all-day event
105
+ const isAllDay = event.start?.date && !event.start?.dateTime;
106
+ const start = isAllDay
107
+ ? event.start?.date || null // All-day events use date strings
108
+ : event.start?.dateTime
109
+ ? new Date(event.start?.dateTime)
110
+ : null; // Timed events use Date objects
111
+ const end = isAllDay
112
+ ? event.end?.date || null // All-day events use date strings
113
+ : event.end?.dateTime
114
+ ? new Date(event.end?.dateTime)
115
+ : null; // Timed events use Date objects
116
+ const activity = {
117
+ type: ActivityType.Event,
118
+ title: event.summary || null,
119
+ note: event.description || null,
120
+ start,
121
+ end,
122
+ meta: {
123
+ source: `google-calendar:${event.id}`,
124
+ id: event.id,
125
+ calendarId: calendarId,
126
+ htmlLink: event.htmlLink,
127
+ hangoutLink: event.hangoutLink,
128
+ },
129
+ };
130
+ // Handle recurrence for master events (not instances)
131
+ if (event.recurrence && !event.recurringEventId) {
132
+ activity.recurrenceRule = parseRRule(event.recurrence);
133
+ // Parse recurrence count (takes precedence over UNTIL)
134
+ const recurrenceCount = parseGoogleRecurrenceCount(event.recurrence);
135
+ if (recurrenceCount) {
136
+ activity.recurrenceCount = recurrenceCount;
137
+ }
138
+ else {
139
+ // Parse recurrence end date for recurring activities if no count
140
+ const recurrenceUntil = parseGoogleRecurrenceEnd(event.recurrence);
141
+ if (recurrenceUntil) {
142
+ activity.recurrenceUntil = recurrenceUntil;
143
+ }
144
+ }
145
+ const exdates = parseExDates(event.recurrence);
146
+ if (exdates.length > 0) {
147
+ activity.recurrenceExdates = exdates;
148
+ }
149
+ const rdates = parseRDates(event.recurrence);
150
+ if (rdates.length > 0) {
151
+ activity.recurrenceDates = rdates;
152
+ }
153
+ }
154
+ return activity;
155
+ }
156
+ export async function syncGoogleCalendar(api, calendarId, state) {
157
+ const params = {
158
+ // Remove singleEvents to get recurring events as masters
159
+ singleEvents: false,
160
+ showDeleted: true,
161
+ };
162
+ if (state.state && state.more) {
163
+ params.pageToken = state.state;
164
+ }
165
+ else if (state.state && !state.more) {
166
+ params.syncToken = state.state;
167
+ }
168
+ else {
169
+ params.timeMin = state.min?.toISOString();
170
+ }
171
+ const data = (await api.call("GET", `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`, params));
172
+ if (!data) {
173
+ // Requires full sync
174
+ const newState = {
175
+ calendarId,
176
+ min: state.min,
177
+ max: state.max,
178
+ sequence: (state.sequence || 1) + 1,
179
+ };
180
+ return syncGoogleCalendar(api, calendarId, newState);
181
+ }
182
+ const nextState = {
183
+ calendarId,
184
+ state: data.nextPageToken || data.nextSyncToken,
185
+ more: !!data.nextPageToken,
186
+ min: state.min,
187
+ max: state.max,
188
+ sequence: state.sequence,
189
+ };
190
+ return {
191
+ events: data.items || [],
192
+ state: nextState,
193
+ };
194
+ }
195
+ //# sourceMappingURL=google-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-api.js","sourceRoot":"","sources":["../src/google-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { type Activity, type ActivityLink, Tool, type ToolBuilder } from "@plotday/agent";
2
+ import { type Calendar, type CalendarAuth, type CalendarTool } from "@plotday/agent/common/calendar";
3
+ import { type Callback } from "@plotday/agent/tools/callbacks";
4
+ import { type Authorization, Integrations } from "@plotday/agent/tools/integrations";
5
+ import { Network, type WebhookRequest } from "@plotday/agent/tools/network";
6
+ /**
7
+ * Google Calendar integration tool.
8
+ *
9
+ * Provides seamless integration with Google Calendar, supporting event
10
+ * synchronization, real-time updates via webhooks, and comprehensive
11
+ * recurrence pattern handling.
12
+ *
13
+ * **Features:**
14
+ * - OAuth 2.0 authentication with Google
15
+ * - Real-time event synchronization
16
+ * - Webhook-based change notifications
17
+ * - Support for recurring events and exceptions
18
+ * - Batch processing for large calendars
19
+ * - Automatic retry on failures
20
+ *
21
+ * **Required OAuth Scopes:**
22
+ * - `https://www.googleapis.com/auth/calendar.calendarlist.readonly` - Read calendar list
23
+ * - `https://www.googleapis.com/auth/calendar.events` - Read/write calendar events
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * class EventsAgent extends Agent {
28
+ * private googleCalendar: GoogleCalendar;
29
+ *
30
+ * constructor(id: string, tools: Tools) {
31
+ * super();
32
+ * this.googleCalendar = tools.get(GoogleCalendar);
33
+ * }
34
+ *
35
+ * async activate() {
36
+ * const authLink = await this.googleCalendar.requestAuth("onGoogleAuth", {
37
+ * provider: "google"
38
+ * });
39
+ *
40
+ * await this.plot.createActivity({
41
+ * type: ActivityType.Task,
42
+ * title: "Connect Google Calendar",
43
+ * links: [authLink]
44
+ * });
45
+ * }
46
+ *
47
+ * async onGoogleAuth(auth: CalendarAuth, context: any) {
48
+ * const calendars = await this.googleCalendar.getCalendars(auth.authToken);
49
+ *
50
+ * // Start syncing primary calendar
51
+ * const primary = calendars.find(c => c.primary);
52
+ * if (primary) {
53
+ * await this.googleCalendar.startSync(
54
+ * auth.authToken,
55
+ * primary.id,
56
+ * "onCalendarEvent",
57
+ * {
58
+ * options: {
59
+ * timeMin: new Date(), // Only sync future events
60
+ * }
61
+ * }
62
+ * );
63
+ * }
64
+ * }
65
+ *
66
+ * async onCalendarEvent(activity: Activity, context: any) {
67
+ * // Process Google Calendar events
68
+ * await this.plot.createActivity(activity);
69
+ * }
70
+ * }
71
+ * ```
72
+ */
73
+ export declare class GoogleCalendar extends Tool<GoogleCalendar> implements CalendarTool {
74
+ build(build: ToolBuilder): {
75
+ integrations: Promise<Integrations>;
76
+ network: Promise<Network>;
77
+ };
78
+ requestAuth<TCallback extends (auth: CalendarAuth, ...args: any[]) => any>(callback: TCallback, ...extraArgs: any[]): Promise<ActivityLink>;
79
+ private getApi;
80
+ getCalendars(authToken: string): Promise<Calendar[]>;
81
+ startSync<TCallback extends (activity: Activity, ...args: any[]) => any>(authToken: string, calendarId: string, callback: TCallback, ...extraArgs: any[]): Promise<void>;
82
+ stopSync(_authToken: string, calendarId: string): Promise<void>;
83
+ private setupCalendarWatch;
84
+ syncBatch(_args: any, batchNumber: number, mode: "full" | "incremental", authToken: string, calendarId: string): Promise<void>;
85
+ private processCalendarEvents;
86
+ private processEventException;
87
+ onCalendarWebhook(request: WebhookRequest, calendarId: string, authToken: string): Promise<void>;
88
+ private startIncrementalSync;
89
+ onAuthSuccess(authResult: Authorization, authToken: string, callback: Callback): Promise<void>;
90
+ }
91
+ export default GoogleCalendar;
@@ -0,0 +1,345 @@
1
+ import { Tool, } from "@plotday/agent";
2
+ import { AuthLevel, AuthProvider, Integrations, } from "@plotday/agent/tools/integrations";
3
+ import { Network } from "@plotday/agent/tools/network";
4
+ import { GoogleApi, syncGoogleCalendar, transformGoogleEvent, } from "./google-api";
5
+ /**
6
+ * Google Calendar integration tool.
7
+ *
8
+ * Provides seamless integration with Google Calendar, supporting event
9
+ * synchronization, real-time updates via webhooks, and comprehensive
10
+ * recurrence pattern handling.
11
+ *
12
+ * **Features:**
13
+ * - OAuth 2.0 authentication with Google
14
+ * - Real-time event synchronization
15
+ * - Webhook-based change notifications
16
+ * - Support for recurring events and exceptions
17
+ * - Batch processing for large calendars
18
+ * - Automatic retry on failures
19
+ *
20
+ * **Required OAuth Scopes:**
21
+ * - `https://www.googleapis.com/auth/calendar.calendarlist.readonly` - Read calendar list
22
+ * - `https://www.googleapis.com/auth/calendar.events` - Read/write calendar events
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * class EventsAgent extends Agent {
27
+ * private googleCalendar: GoogleCalendar;
28
+ *
29
+ * constructor(id: string, tools: Tools) {
30
+ * super();
31
+ * this.googleCalendar = tools.get(GoogleCalendar);
32
+ * }
33
+ *
34
+ * async activate() {
35
+ * const authLink = await this.googleCalendar.requestAuth("onGoogleAuth", {
36
+ * provider: "google"
37
+ * });
38
+ *
39
+ * await this.plot.createActivity({
40
+ * type: ActivityType.Task,
41
+ * title: "Connect Google Calendar",
42
+ * links: [authLink]
43
+ * });
44
+ * }
45
+ *
46
+ * async onGoogleAuth(auth: CalendarAuth, context: any) {
47
+ * const calendars = await this.googleCalendar.getCalendars(auth.authToken);
48
+ *
49
+ * // Start syncing primary calendar
50
+ * const primary = calendars.find(c => c.primary);
51
+ * if (primary) {
52
+ * await this.googleCalendar.startSync(
53
+ * auth.authToken,
54
+ * primary.id,
55
+ * "onCalendarEvent",
56
+ * {
57
+ * options: {
58
+ * timeMin: new Date(), // Only sync future events
59
+ * }
60
+ * }
61
+ * );
62
+ * }
63
+ * }
64
+ *
65
+ * async onCalendarEvent(activity: Activity, context: any) {
66
+ * // Process Google Calendar events
67
+ * await this.plot.createActivity(activity);
68
+ * }
69
+ * }
70
+ * ```
71
+ */
72
+ export class GoogleCalendar extends Tool {
73
+ build(build) {
74
+ return {
75
+ integrations: build(Integrations),
76
+ network: build(Network, {
77
+ urls: ["https://www.googleapis.com/calendar/*"],
78
+ }),
79
+ };
80
+ }
81
+ async requestAuth(callback, ...extraArgs) {
82
+ console.log("Requesting Google Calendar auth");
83
+ const calendarScopes = [
84
+ "https://www.googleapis.com/auth/calendar.calendarlist.readonly",
85
+ "https://www.googleapis.com/auth/calendar.events",
86
+ ];
87
+ // Generate opaque token for authorization
88
+ const authToken = crypto.randomUUID();
89
+ const callbackToken = await this.tools.callbacks.createFromParent(callback, ...extraArgs);
90
+ // Request auth and return the activity link
91
+ return await this.tools.integrations.request({
92
+ provider: AuthProvider.Google,
93
+ level: AuthLevel.User,
94
+ scopes: calendarScopes,
95
+ }, this.onAuthSuccess, authToken, callbackToken);
96
+ }
97
+ async getApi(authToken) {
98
+ const authorization = await this.get(`authorization:${authToken}`);
99
+ if (!authorization) {
100
+ throw new Error("Authorization no longer available");
101
+ }
102
+ const token = await this.tools.integrations.get(authorization);
103
+ if (!token) {
104
+ throw new Error("Authorization no longer available");
105
+ }
106
+ return new GoogleApi(token.token);
107
+ }
108
+ async getCalendars(authToken) {
109
+ console.log("Fetching Google Calendar list");
110
+ const api = await this.getApi(authToken);
111
+ const data = (await api.call("GET", "https://www.googleapis.com/calendar/v3/users/me/calendarList"));
112
+ console.log("Got Google Calendar list", data.items);
113
+ return data.items.map((item) => ({
114
+ id: item.id,
115
+ name: item.summary,
116
+ description: item.description || null,
117
+ primary: item.primary || false,
118
+ }));
119
+ }
120
+ async startSync(authToken, calendarId, callback, ...extraArgs) {
121
+ console.log("Saving callback");
122
+ // Create callback token for parent
123
+ const callbackToken = await this.tools.callbacks.createFromParent(callback, ...extraArgs);
124
+ await this.set("event_callback_token", callbackToken);
125
+ console.log("Setting up watch");
126
+ // Setup webhook for this calendar
127
+ await this.setupCalendarWatch(authToken, calendarId, authToken);
128
+ // Start initial sync
129
+ const now = new Date();
130
+ const min = new Date(now.getFullYear() - 2, 0, 1);
131
+ const max = new Date(now.getFullYear() + 1, 11, 31);
132
+ const initialState = {
133
+ calendarId,
134
+ min,
135
+ max,
136
+ sequence: 1,
137
+ };
138
+ await this.set(`sync_state_${calendarId}`, initialState);
139
+ console.log("Starting sync");
140
+ // Start sync batch using run tool for long-running operation
141
+ const syncCallback = await this.callback(this.syncBatch, 1, "full", authToken, calendarId);
142
+ await this.run(syncCallback);
143
+ }
144
+ async stopSync(_authToken, calendarId) {
145
+ // Stop webhook
146
+ const watchData = await this.get(`calendar_watch_${calendarId}`);
147
+ if (watchData) {
148
+ // Cancel the watch (would need Google API call)
149
+ await this.clear(`calendar_watch_${calendarId}`);
150
+ }
151
+ // Clear sync state
152
+ await this.clear(`sync_state_${calendarId}`);
153
+ }
154
+ async setupCalendarWatch(authToken, calendarId, opaqueAuthToken) {
155
+ const webhookUrl = await this.tools.network.createWebhook(this.onCalendarWebhook, calendarId, opaqueAuthToken);
156
+ // Check if webhook URL is localhost
157
+ if (URL.parse(webhookUrl)?.hostname === "localhost") {
158
+ console.log("Skipping webhook setup for localhost URL");
159
+ return;
160
+ }
161
+ const api = await this.getApi(authToken);
162
+ // Setup watch for calendar
163
+ const watchId = crypto.randomUUID();
164
+ const secret = crypto.randomUUID();
165
+ const watchData = (await api.call("POST", `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/watch`, undefined, {
166
+ id: watchId,
167
+ type: "web_hook",
168
+ address: webhookUrl,
169
+ token: new URLSearchParams({ secret }).toString(),
170
+ }));
171
+ await this.set(`calendar_watch_${calendarId}`, {
172
+ watchId,
173
+ secret,
174
+ calendarId,
175
+ expiry: new Date(parseInt(watchData.expiration)),
176
+ });
177
+ console.log("Calendar watch setup complete", { watchId, calendarId });
178
+ }
179
+ async syncBatch(_args, batchNumber, mode, authToken, calendarId) {
180
+ console.log(`Starting Google Calendar sync batch ${batchNumber} (${mode}) for calendar ${calendarId}`);
181
+ try {
182
+ const state = await this.get(`sync_state_${calendarId}`);
183
+ if (!state) {
184
+ throw new Error("No sync state found");
185
+ }
186
+ // Convert date strings back to Date objects after deserialization
187
+ if (state.min && typeof state.min === "string") {
188
+ state.min = new Date(state.min);
189
+ }
190
+ if (state.max && typeof state.max === "string") {
191
+ state.max = new Date(state.max);
192
+ }
193
+ const api = await this.getApi(authToken);
194
+ const result = await syncGoogleCalendar(api, calendarId, state);
195
+ if (result.events.length > 0) {
196
+ await this.processCalendarEvents(result.events, calendarId);
197
+ console.log(`Synced ${result.events.length} events in batch ${batchNumber} for calendar ${calendarId}`);
198
+ }
199
+ await this.set(`sync_state_${calendarId}`, result.state);
200
+ if (result.state.more) {
201
+ const syncCallback = await this.callback(this.syncBatch, batchNumber + 1, mode, authToken, calendarId);
202
+ await this.run(syncCallback);
203
+ }
204
+ else {
205
+ console.log(`Google Calendar ${mode} sync completed after ${batchNumber} batches for calendar ${calendarId}`);
206
+ if (mode === "full") {
207
+ await this.clear(`sync_state_${calendarId}`);
208
+ }
209
+ }
210
+ }
211
+ catch (error) {
212
+ console.error(`Error in sync batch ${batchNumber} for calendar ${calendarId}:`, error);
213
+ throw error;
214
+ }
215
+ }
216
+ async processCalendarEvents(events, calendarId) {
217
+ for (const event of events) {
218
+ try {
219
+ if (event.status === "cancelled") {
220
+ // TODO: Handle event cancellation
221
+ continue;
222
+ }
223
+ // Check if this is a recurring event instance (exception)
224
+ if (event.recurringEventId && event.originalStartTime) {
225
+ await this.processEventException(event, calendarId);
226
+ }
227
+ else {
228
+ // Regular or master recurring event
229
+ const activityData = transformGoogleEvent(event, calendarId);
230
+ // Convert to full Activity and call callback
231
+ const callbackToken = await this.get("event_callback_token");
232
+ if (callbackToken && activityData.type) {
233
+ const activity = {
234
+ type: activityData.type,
235
+ start: activityData.start || null,
236
+ end: activityData.end || null,
237
+ recurrenceUntil: activityData.recurrenceUntil || null,
238
+ recurrenceCount: activityData.recurrenceCount || null,
239
+ doneAt: null,
240
+ note: activityData.note || null,
241
+ title: activityData.title || null,
242
+ parent: null,
243
+ links: null,
244
+ recurrenceRule: activityData.recurrenceRule || null,
245
+ recurrenceExdates: activityData.recurrenceExdates || null,
246
+ recurrenceDates: activityData.recurrenceDates || null,
247
+ recurrence: null,
248
+ occurrence: null,
249
+ meta: activityData.meta ?? null,
250
+ };
251
+ await this.run(callbackToken, activity);
252
+ }
253
+ }
254
+ }
255
+ catch (error) {
256
+ console.error(`Failed to process event ${event.id}:`, error);
257
+ // Continue processing other events
258
+ }
259
+ }
260
+ }
261
+ async processEventException(event, calendarId) {
262
+ // Similar to processCalendarEvents but for exceptions
263
+ // This would find the master recurring activity and create an exception
264
+ const originalStartTime = event.originalStartTime?.dateTime || event.originalStartTime?.date;
265
+ if (!originalStartTime) {
266
+ console.warn(`No original start time for exception: ${event.id}`);
267
+ return;
268
+ }
269
+ const activityData = transformGoogleEvent(event, calendarId);
270
+ const callbackToken = await this.get("event_callback_token");
271
+ if (callbackToken && activityData.type) {
272
+ const activity = {
273
+ type: activityData.type,
274
+ start: activityData.start || null,
275
+ end: activityData.end || null,
276
+ recurrenceUntil: activityData.recurrenceUntil || null,
277
+ recurrenceCount: activityData.recurrenceCount || null,
278
+ doneAt: null,
279
+ note: activityData.note || null,
280
+ title: activityData.title || null,
281
+ parent: null,
282
+ links: null,
283
+ recurrenceRule: null,
284
+ recurrenceExdates: null,
285
+ recurrenceDates: null,
286
+ recurrence: null, // Would need to find master activity
287
+ occurrence: new Date(originalStartTime),
288
+ meta: activityData.meta ?? null,
289
+ };
290
+ await this.run(callbackToken, activity);
291
+ }
292
+ }
293
+ async onCalendarWebhook(request, calendarId, authToken) {
294
+ console.log("Received calendar webhook notification", {
295
+ headers: request.headers,
296
+ params: request.params,
297
+ calendarId,
298
+ });
299
+ // Validate webhook authenticity
300
+ const channelId = request.headers["X-Goog-Channel-ID"];
301
+ const channelToken = request.headers["X-Goog-Channel-Token"];
302
+ if (!channelId || !channelToken) {
303
+ throw new Error("Invalid webhook headers");
304
+ }
305
+ const watchData = await this.get(`calendar_watch_${calendarId}`);
306
+ if (!watchData || watchData.watchId !== channelId) {
307
+ console.warn("Unknown or expired webhook notification");
308
+ return;
309
+ }
310
+ const params = new URLSearchParams(channelToken);
311
+ const secret = params.get("secret");
312
+ if (!watchData || watchData.secret !== secret) {
313
+ console.warn("Invalid webhook secret");
314
+ return;
315
+ }
316
+ // Trigger incremental sync
317
+ await this.startIncrementalSync(calendarId, authToken);
318
+ }
319
+ async startIncrementalSync(calendarId, authToken) {
320
+ const watchData = await this.get(`calendar_watch_${calendarId}`);
321
+ if (!watchData) {
322
+ console.error("No calendar watch data found");
323
+ return;
324
+ }
325
+ const incrementalState = {
326
+ calendarId: watchData.calendarId,
327
+ state: (await this.get(`last_sync_token_${calendarId}`)) || undefined,
328
+ };
329
+ await this.set(`sync_state_${calendarId}`, incrementalState);
330
+ const syncCallback = await this.callback(this.syncBatch, 1, "incremental", authToken, calendarId);
331
+ await this.run(syncCallback);
332
+ }
333
+ async onAuthSuccess(authResult, authToken, callback) {
334
+ // Store the actual auth token using opaque token as key
335
+ await this.set(`authorization:${authToken}`, authResult);
336
+ const authSuccessResult = {
337
+ authToken,
338
+ };
339
+ await this.run(callback, authSuccessResult);
340
+ // Clean up the callback token
341
+ await this.clear(`auth_callback_token:${authToken}`);
342
+ }
343
+ }
344
+ export default GoogleCalendar;
345
+ //# sourceMappingURL=google-calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-calendar.js","sourceRoot":"","sources":["../src/google-calendar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { default, GoogleCalendar } from "./google-calendar";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { default, GoogleCalendar } from "./google-calendar";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "description": "Sync with Google Calendar",
5
5
  "author": "Plot <team@plot.day> (https://plot.day)",
6
6
  "license": "MIT",
7
- "version": "0.2.1",
7
+ "version": "0.2.2",
8
8
  "type": "module",
9
9
  "main": "./dist/index.js",
10
10
  "types": "./dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "LICENSE"
21
21
  ],
22
22
  "dependencies": {
23
- "@plotday/agent": "^0.18.0"
23
+ "@plotday/agent": "^0.18.3"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "^5.9.3"