@plotday/tool-google-calendar 0.1.1

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Plot Technologies Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Google Calendar Tool
2
+
3
+ A Plot tool for syncing with Google Calendar.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @plotday/tool-google-calendar @plotday/sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { Agent, Tools } from "@plotday/sdk";
15
+ import { GoogleCalendar } from "@plotday/tool-google-calendar";
16
+ import { Auth, AuthLevel, AuthProvider } from "@plotday/sdk/tools/auth";
17
+
18
+ export default class extends Agent {
19
+ private googleCalendar: GoogleCalendar;
20
+ private auth: Auth;
21
+
22
+ constructor(tools: Tools) {
23
+ super();
24
+ this.googleCalendar = tools.get(GoogleCalendar);
25
+ this.auth = tools.get(Auth);
26
+ }
27
+
28
+ async activate(priority: { id: string }) {
29
+ // Request Google Calendar access
30
+ const authLink = await this.auth.request(
31
+ {
32
+ provider: AuthProvider.Google,
33
+ level: AuthLevel.User,
34
+ scopes: ["https://www.googleapis.com/auth/calendar.readonly"],
35
+ },
36
+ {
37
+ functionName: "onAuthComplete",
38
+ context: { priorityId: priority.id },
39
+ }
40
+ );
41
+
42
+ // User will authenticate via authLink
43
+ }
44
+
45
+ async onAuthComplete(authorization: any, context: any) {
46
+ const authToken = await this.auth.get(authorization);
47
+
48
+ // Get available calendars
49
+ const calendars = await this.googleCalendar.getCalendars(authToken);
50
+
51
+ // Start syncing a calendar
52
+ await this.googleCalendar.startSync(
53
+ authToken,
54
+ calendars[0].id,
55
+ "onCalendarEvent"
56
+ );
57
+ }
58
+
59
+ async onCalendarEvent(event: any) {
60
+ // Handle calendar events
61
+ console.log("New calendar event:", event.summary);
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## API
67
+
68
+ ### `getCalendars(authToken: string)`
69
+
70
+ Retrieves the list of calendars available to the authenticated user.
71
+
72
+ ### `startSync(authToken: string, calendarId: string, callbackName: string, options?: object)`
73
+
74
+ Starts syncing events from a Google Calendar.
75
+
76
+ ### `stopSync(authToken: string, calendarId: string)`
77
+
78
+ Stops syncing events from a Google Calendar.
79
+
80
+ ## License
81
+
82
+ MIT © Plot Technologies Inc.
@@ -0,0 +1,71 @@
1
+ import type { Activity } from "@plotday/sdk";
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
+ }>;
71
+ //# sourceMappingURL=google-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-api.d.ts","sourceRoot":"","sources":["../src/google-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ import { ActivityType } from "@plotday/sdk";
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
+ source: {
123
+ type: "google-calendar-event",
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,102 @@
1
+ import { type ActivityLink, Tool, type Tools } from "@plotday/sdk";
2
+ import { type Authorization } from "@plotday/sdk/tools/auth";
3
+ import { type Calendar, type CalendarTool, type SyncOptions } from "@plotday/sdk/common/calendar";
4
+ import { type Callback } from "@plotday/sdk/tools/callback";
5
+ import { type WebhookRequest } from "@plotday/sdk/tools/webhook";
6
+ type AuthSuccessContext = {
7
+ authToken: string;
8
+ callbackToken: Callback;
9
+ };
10
+ /**
11
+ * Google Calendar integration tool.
12
+ *
13
+ * Provides seamless integration with Google Calendar, supporting event
14
+ * synchronization, real-time updates via webhooks, and comprehensive
15
+ * recurrence pattern handling.
16
+ *
17
+ * **Features:**
18
+ * - OAuth 2.0 authentication with Google
19
+ * - Real-time event synchronization
20
+ * - Webhook-based change notifications
21
+ * - Support for recurring events and exceptions
22
+ * - Batch processing for large calendars
23
+ * - Automatic retry on failures
24
+ *
25
+ * **Required OAuth Scopes:**
26
+ * - `https://www.googleapis.com/auth/calendar.calendarlist.readonly` - Read calendar list
27
+ * - `https://www.googleapis.com/auth/calendar.events` - Read/write calendar events
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * class EventsAgent extends Agent {
32
+ * private googleCalendar: GoogleCalendar;
33
+ *
34
+ * constructor(tools: Tools) {
35
+ * super();
36
+ * this.googleCalendar = tools.get(GoogleCalendar);
37
+ * }
38
+ *
39
+ * async activate() {
40
+ * const authLink = await this.googleCalendar.requestAuth("onGoogleAuth", {
41
+ * provider: "google"
42
+ * });
43
+ *
44
+ * await this.plot.createActivity({
45
+ * type: ActivityType.Task,
46
+ * title: "Connect Google Calendar",
47
+ * links: [authLink]
48
+ * });
49
+ * }
50
+ *
51
+ * async onGoogleAuth(auth: CalendarAuth, context: any) {
52
+ * const calendars = await this.googleCalendar.getCalendars(auth.authToken);
53
+ *
54
+ * // Start syncing primary calendar
55
+ * const primary = calendars.find(c => c.primary);
56
+ * if (primary) {
57
+ * await this.googleCalendar.startSync(
58
+ * auth.authToken,
59
+ * primary.id,
60
+ * "onCalendarEvent",
61
+ * {
62
+ * options: {
63
+ * timeMin: new Date(), // Only sync future events
64
+ * }
65
+ * }
66
+ * );
67
+ * }
68
+ * }
69
+ *
70
+ * async onCalendarEvent(activity: Activity, context: any) {
71
+ * // Process Google Calendar events
72
+ * await this.plot.createActivity(activity);
73
+ * }
74
+ * }
75
+ * ```
76
+ */
77
+ export declare class GoogleCalendar extends Tool implements CalendarTool {
78
+ protected tools: Tools;
79
+ static readonly id = "google-calendar";
80
+ private auth;
81
+ private webhook;
82
+ constructor(tools: Tools);
83
+ requestAuth(callback: Callback): Promise<ActivityLink>;
84
+ private getApi;
85
+ getCalendars(authToken: string): Promise<Calendar[]>;
86
+ startSync(authToken: string, calendarId: string, callback: Callback, options?: SyncOptions): Promise<void>;
87
+ stopSync(authToken: string, calendarId: string): Promise<void>;
88
+ private setupCalendarWatch;
89
+ syncBatch({ calendarId, batchNumber, mode, authToken, }: {
90
+ calendarId: string;
91
+ batchNumber: number;
92
+ mode: "full" | "incremental";
93
+ authToken: string;
94
+ }): Promise<void>;
95
+ private processCalendarEvents;
96
+ private processEventException;
97
+ onCalendarWebhook(request: WebhookRequest, context: any): Promise<void>;
98
+ private startIncrementalSync;
99
+ onAuthSuccess(authResult: Authorization, context: AuthSuccessContext): Promise<void>;
100
+ }
101
+ export default GoogleCalendar;
102
+ //# sourceMappingURL=google-calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google-calendar.d.ts","sourceRoot":"","sources":["../src/google-calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAEjB,IAAI,EACJ,KAAK,KAAK,EACX,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,QAAQ,EAEb,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAS1E,KAAK,kBAAkB,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,QAAQ,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkEG;AACH,qBAAa,cAAe,SAAQ,IAAK,YAAW,YAAY;IAMlD,SAAS,CAAC,KAAK,EAAE,KAAK;IALlC,MAAM,CAAC,QAAQ,CAAC,EAAE,qBAAqB;IAEvC,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,OAAO,CAAU;gBAEH,KAAK,EAAE,KAAK;IAM5B,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;YA6B9C,MAAM;IAgBd,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAsBpD,SAAS,CACb,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,IAAI,CAAC;IA+BV,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAYtD,kBAAkB;IA4C1B,SAAS,CAAC,EACd,UAAU,EACV,WAAW,EACX,IAAI,EACJ,SAAS,GACV,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,IAAI,CAAC;YAyDH,qBAAqB;YAoDrB,qBAAqB;IA0C7B,iBAAiB,CACrB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,IAAI,CAAC;YAoCF,oBAAoB;IA2B5B,aAAa,CACjB,UAAU,EAAE,aAAa,EACzB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC;CAYjB;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,365 @@
1
+ import { Tool, } from "@plotday/sdk";
2
+ import { Auth, AuthLevel, AuthProvider, } from "@plotday/sdk/tools/auth";
3
+ import { Webhook } from "@plotday/sdk/tools/webhook";
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(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
+ tools;
74
+ static id = "google-calendar";
75
+ auth;
76
+ webhook;
77
+ constructor(tools) {
78
+ super(tools);
79
+ this.tools = tools;
80
+ this.auth = tools.get(Auth);
81
+ this.webhook = tools.get(Webhook);
82
+ }
83
+ async requestAuth(callback) {
84
+ const calendarScopes = [
85
+ "https://www.googleapis.com/auth/calendar.calendarlist.readonly",
86
+ "https://www.googleapis.com/auth/calendar.events",
87
+ ];
88
+ // Generate opaque token for this authorization
89
+ const authToken = crypto.randomUUID();
90
+ // Use the provided callback token
91
+ const callbackToken = callback;
92
+ // Create callback for auth completion
93
+ const authCallback = await this.callback("onAuthSuccess", {
94
+ authToken,
95
+ callbackToken,
96
+ });
97
+ // Request auth and return the activity link
98
+ return await this.auth.request({
99
+ provider: AuthProvider.Google,
100
+ level: AuthLevel.User,
101
+ scopes: calendarScopes,
102
+ }, authCallback);
103
+ }
104
+ async getApi(authToken) {
105
+ const authorization = await this.get(`authorization:${authToken}`);
106
+ if (!authorization) {
107
+ throw new Error("Authorization no longer available");
108
+ }
109
+ const token = await this.auth.get(authorization);
110
+ if (!token) {
111
+ throw new Error("Authorization no longer available");
112
+ }
113
+ return new GoogleApi(token.token);
114
+ }
115
+ async getCalendars(authToken) {
116
+ const api = await this.getApi(authToken);
117
+ const data = (await api.call("GET", "https://www.googleapis.com/calendar/v3/users/me/calendarList"));
118
+ return data.items.map((item) => ({
119
+ id: item.id,
120
+ name: item.summary,
121
+ description: item.description || null,
122
+ primary: item.primary || false,
123
+ }));
124
+ }
125
+ async startSync(authToken, calendarId, callback, options) {
126
+ // Store the callback token
127
+ await this.set("event_callback_token", callback);
128
+ // Setup webhook for this calendar
129
+ await this.setupCalendarWatch(authToken, calendarId, authToken);
130
+ // Start initial sync
131
+ const now = new Date();
132
+ const min = options?.timeMin || new Date(now.getFullYear() - 2, 0, 1);
133
+ const max = options?.timeMax || new Date(now.getFullYear() + 1, 11, 31);
134
+ const initialState = {
135
+ calendarId,
136
+ min,
137
+ max,
138
+ sequence: 1,
139
+ };
140
+ await this.set(`sync_state_${calendarId}`, initialState);
141
+ // Start sync batch using run tool for long-running operation
142
+ const syncCallback = await this.callback("syncBatch", {
143
+ calendarId,
144
+ batchNumber: 1,
145
+ mode: "full",
146
+ authToken,
147
+ });
148
+ await this.run(syncCallback);
149
+ }
150
+ async stopSync(authToken, calendarId) {
151
+ // Stop webhook
152
+ const watchData = await this.get(`calendar_watch_${calendarId}`);
153
+ if (watchData) {
154
+ // Cancel the watch (would need Google API call)
155
+ await this.clear(`calendar_watch_${calendarId}`);
156
+ }
157
+ // Clear sync state
158
+ await this.clear(`sync_state_${calendarId}`);
159
+ }
160
+ async setupCalendarWatch(authToken, calendarId, opaqueAuthToken) {
161
+ const webhookUrl = await this.webhook.create("onCalendarWebhook", {
162
+ calendarId,
163
+ authToken: opaqueAuthToken,
164
+ });
165
+ // Check if webhook URL is localhost
166
+ if (URL.parse(webhookUrl)?.hostname === "localhost") {
167
+ console.log("Skipping webhook setup for localhost URL");
168
+ return;
169
+ }
170
+ const api = await this.getApi(authToken);
171
+ // Setup watch for calendar
172
+ const watchId = crypto.randomUUID();
173
+ const secret = crypto.randomUUID();
174
+ const watchData = (await api.call("POST", `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/watch`, undefined, {
175
+ id: watchId,
176
+ type: "web_hook",
177
+ address: webhookUrl,
178
+ token: new URLSearchParams({ secret }).toString(),
179
+ }));
180
+ await this.set(`calendar_watch_${calendarId}`, {
181
+ watchId,
182
+ secret,
183
+ calendarId,
184
+ expiry: new Date(parseInt(watchData.expiration)),
185
+ });
186
+ console.log("Calendar watch setup complete", { watchId, calendarId });
187
+ }
188
+ async syncBatch({ calendarId, batchNumber, mode, authToken, }) {
189
+ console.log(`Starting Google Calendar sync batch ${batchNumber} (${mode}) for calendar ${calendarId}`);
190
+ try {
191
+ const state = await this.get(`sync_state_${calendarId}`);
192
+ if (!state) {
193
+ throw new Error("No sync state found");
194
+ }
195
+ // Convert date strings back to Date objects after deserialization
196
+ if (state.min && typeof state.min === "string") {
197
+ state.min = new Date(state.min);
198
+ }
199
+ if (state.max && typeof state.max === "string") {
200
+ state.max = new Date(state.max);
201
+ }
202
+ const api = await this.getApi(authToken);
203
+ const result = await syncGoogleCalendar(api, calendarId, state);
204
+ if (result.events.length > 0) {
205
+ await this.processCalendarEvents(result.events, calendarId);
206
+ console.log(`Synced ${result.events.length} events in batch ${batchNumber} for calendar ${calendarId}`);
207
+ }
208
+ await this.set(`sync_state_${calendarId}`, result.state);
209
+ if (result.state.more) {
210
+ const syncCallback = await this.callback("syncBatch", {
211
+ calendarId,
212
+ batchNumber: batchNumber + 1,
213
+ mode,
214
+ authToken,
215
+ });
216
+ await this.run(syncCallback);
217
+ }
218
+ else {
219
+ console.log(`Google Calendar ${mode} sync completed after ${batchNumber} batches for calendar ${calendarId}`);
220
+ if (mode === "full") {
221
+ await this.clear(`sync_state_${calendarId}`);
222
+ }
223
+ }
224
+ }
225
+ catch (error) {
226
+ console.error(`Error in sync batch ${batchNumber} for calendar ${calendarId}:`, error);
227
+ throw error;
228
+ }
229
+ }
230
+ async processCalendarEvents(events, calendarId) {
231
+ for (const event of events) {
232
+ try {
233
+ if (event.status === "cancelled") {
234
+ // TODO: Handle event cancellation
235
+ continue;
236
+ }
237
+ // Check if this is a recurring event instance (exception)
238
+ if (event.recurringEventId && event.originalStartTime) {
239
+ await this.processEventException(event, calendarId);
240
+ }
241
+ else {
242
+ // Regular or master recurring event
243
+ const activityData = transformGoogleEvent(event, calendarId);
244
+ // Convert to full Activity and call callback
245
+ const callbackToken = await this.get("event_callback_token");
246
+ if (callbackToken && activityData.type) {
247
+ const activity = {
248
+ type: activityData.type,
249
+ start: activityData.start || null,
250
+ end: activityData.end || null,
251
+ recurrenceUntil: activityData.recurrenceUntil || null,
252
+ recurrenceCount: activityData.recurrenceCount || null,
253
+ doneAt: null,
254
+ note: activityData.note || null,
255
+ title: activityData.title || null,
256
+ parent: null,
257
+ links: null,
258
+ recurrenceRule: activityData.recurrenceRule || null,
259
+ recurrenceExdates: activityData.recurrenceExdates || null,
260
+ recurrenceDates: activityData.recurrenceDates || null,
261
+ recurrence: null,
262
+ occurrence: null,
263
+ source: activityData.source || null,
264
+ };
265
+ await this.call(callbackToken, activity);
266
+ }
267
+ }
268
+ }
269
+ catch (error) {
270
+ console.error(`Failed to process event ${event.id}:`, error);
271
+ // Continue processing other events
272
+ }
273
+ }
274
+ }
275
+ async processEventException(event, calendarId) {
276
+ // Similar to processCalendarEvents but for exceptions
277
+ // This would find the master recurring activity and create an exception
278
+ const originalStartTime = event.originalStartTime?.dateTime || event.originalStartTime?.date;
279
+ if (!originalStartTime) {
280
+ console.warn(`No original start time for exception: ${event.id}`);
281
+ return;
282
+ }
283
+ const activityData = transformGoogleEvent(event, calendarId);
284
+ const callbackToken = await this.get("event_callback_token");
285
+ if (callbackToken && activityData.type) {
286
+ const activity = {
287
+ type: activityData.type,
288
+ start: activityData.start || null,
289
+ end: activityData.end || null,
290
+ recurrenceUntil: activityData.recurrenceUntil || null,
291
+ recurrenceCount: activityData.recurrenceCount || null,
292
+ doneAt: null,
293
+ note: activityData.note || null,
294
+ title: activityData.title || null,
295
+ parent: null,
296
+ links: null,
297
+ recurrenceRule: null,
298
+ recurrenceExdates: null,
299
+ recurrenceDates: null,
300
+ recurrence: null, // Would need to find master activity
301
+ occurrence: new Date(originalStartTime),
302
+ source: activityData.source || null,
303
+ };
304
+ await this.call(callbackToken, activity);
305
+ }
306
+ }
307
+ async onCalendarWebhook(request, context) {
308
+ console.log("Received calendar webhook notification", {
309
+ headers: request.headers,
310
+ params: request.params,
311
+ calendarId: context.calendarId,
312
+ });
313
+ // Validate webhook authenticity
314
+ const channelId = request.headers["X-Goog-Channel-ID"];
315
+ const channelToken = request.headers["X-Goog-Channel-Token"];
316
+ if (!channelId || !channelToken) {
317
+ throw new Error("Invalid webhook headers");
318
+ }
319
+ const watchData = await this.get(`calendar_watch_${context.calendarId}`);
320
+ if (!watchData || watchData.watchId !== channelId) {
321
+ console.warn("Unknown or expired webhook notification");
322
+ return;
323
+ }
324
+ const params = new URLSearchParams(channelToken);
325
+ const secret = params.get("secret");
326
+ if (!watchData || watchData.secret !== secret) {
327
+ console.warn("Invalid webhook secret");
328
+ return;
329
+ }
330
+ // Trigger incremental sync
331
+ await this.startIncrementalSync(context.calendarId, context.authToken);
332
+ }
333
+ async startIncrementalSync(calendarId, authToken) {
334
+ const watchData = await this.get(`calendar_watch_${calendarId}`);
335
+ if (!watchData) {
336
+ console.error("No calendar watch data found");
337
+ return;
338
+ }
339
+ const incrementalState = {
340
+ calendarId: watchData.calendarId,
341
+ state: (await this.get(`last_sync_token_${calendarId}`)) ||
342
+ undefined,
343
+ };
344
+ await this.set(`sync_state_${calendarId}`, incrementalState);
345
+ const syncCallback = await this.callback("syncBatch", {
346
+ calendarId,
347
+ batchNumber: 1,
348
+ mode: "incremental",
349
+ authToken,
350
+ });
351
+ await this.run(syncCallback);
352
+ }
353
+ async onAuthSuccess(authResult, context) {
354
+ // Store the actual auth token using opaque token as key
355
+ await this.set(`authorization:${context.authToken}`, authResult);
356
+ const authSuccessResult = {
357
+ authToken: context.authToken,
358
+ };
359
+ await this.call(context.callbackToken, authSuccessResult);
360
+ // Clean up the callback token
361
+ await this.clear(`auth_callback_token:${context.authToken}`);
362
+ }
363
+ }
364
+ export default GoogleCalendar;
365
+ //# 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,2 @@
1
+ export { default, GoogleCalendar } from "./google-calendar";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
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 ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@plotday/tool-google-calendar",
3
+ "displayName": "Google Calendar",
4
+ "description": "Sync with Google Calendar",
5
+ "author": "Plot <team@plot.day> (https://plot.day)",
6
+ "license": "MIT",
7
+ "version": "0.1.1",
8
+ "type": "module",
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "dependencies": {
23
+ "@plotday/sdk": "^0.10.0"
24
+ },
25
+ "devDependencies": {
26
+ "typescript": "^5.9.3"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/plotday/plot.git",
31
+ "directory": "tools/google-calendar"
32
+ },
33
+ "homepage": "https://plot.day",
34
+ "bugs": {
35
+ "url": "https://github.com/plotday/plot/issues"
36
+ },
37
+ "keywords": [
38
+ "plot",
39
+ "agent",
40
+ "tool",
41
+ "google-calendar",
42
+ "calendar"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc --project tsconfig.build.json",
49
+ "clean": "rm -rf dist"
50
+ }
51
+ }