@plotday/tool-gmail 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.md +21 -0
- package/dist/gmail-api.d.ts +122 -0
- package/dist/gmail-api.js +319 -0
- package/dist/gmail-api.js.map +1 -0
- package/dist/gmail.d.ts +80 -0
- package/dist/gmail.js +350 -0
- package/dist/gmail.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/LICENSE.md
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.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { NewActivity } from "@plotday/twister";
|
|
2
|
+
export type GmailLabel = {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
type: "system" | "user";
|
|
6
|
+
messageListVisibility?: string;
|
|
7
|
+
labelListVisibility?: string;
|
|
8
|
+
messagesTotal?: number;
|
|
9
|
+
messagesUnread?: number;
|
|
10
|
+
};
|
|
11
|
+
export type GmailThread = {
|
|
12
|
+
id: string;
|
|
13
|
+
historyId: string;
|
|
14
|
+
messages: GmailMessage[];
|
|
15
|
+
};
|
|
16
|
+
export type GmailMessage = {
|
|
17
|
+
id: string;
|
|
18
|
+
threadId: string;
|
|
19
|
+
labelIds: string[];
|
|
20
|
+
snippet: string;
|
|
21
|
+
historyId: string;
|
|
22
|
+
internalDate: string;
|
|
23
|
+
payload: GmailMessagePart;
|
|
24
|
+
sizeEstimate: number;
|
|
25
|
+
};
|
|
26
|
+
export type GmailMessagePart = {
|
|
27
|
+
partId?: string;
|
|
28
|
+
mimeType: string;
|
|
29
|
+
filename?: string;
|
|
30
|
+
headers: GmailHeader[];
|
|
31
|
+
body?: {
|
|
32
|
+
attachmentId?: string;
|
|
33
|
+
size: number;
|
|
34
|
+
data?: string;
|
|
35
|
+
};
|
|
36
|
+
parts?: GmailMessagePart[];
|
|
37
|
+
};
|
|
38
|
+
export type GmailHeader = {
|
|
39
|
+
name: string;
|
|
40
|
+
value: string;
|
|
41
|
+
};
|
|
42
|
+
export type EmailAddress = {
|
|
43
|
+
name: string | null;
|
|
44
|
+
email: string;
|
|
45
|
+
};
|
|
46
|
+
export type SyncState = {
|
|
47
|
+
channelId: string;
|
|
48
|
+
pageToken?: string;
|
|
49
|
+
historyId?: string;
|
|
50
|
+
lastSyncTime?: Date;
|
|
51
|
+
watchExpiration?: Date;
|
|
52
|
+
};
|
|
53
|
+
export declare class GmailApi {
|
|
54
|
+
accessToken: string;
|
|
55
|
+
private baseUrl;
|
|
56
|
+
constructor(accessToken: string);
|
|
57
|
+
call(endpoint: string, options?: {
|
|
58
|
+
method?: string;
|
|
59
|
+
params?: {
|
|
60
|
+
[key: string]: any;
|
|
61
|
+
};
|
|
62
|
+
body?: any;
|
|
63
|
+
}): Promise<any>;
|
|
64
|
+
getLabels(): Promise<GmailLabel[]>;
|
|
65
|
+
getThreads(labelId: string, pageToken?: string, maxResults?: number, query?: string): Promise<{
|
|
66
|
+
threads: Array<{
|
|
67
|
+
id: string;
|
|
68
|
+
historyId: string;
|
|
69
|
+
}>;
|
|
70
|
+
nextPageToken?: string;
|
|
71
|
+
resultSizeEstimate: number;
|
|
72
|
+
}>;
|
|
73
|
+
getThread(threadId: string): Promise<GmailThread>;
|
|
74
|
+
setupWatch(labelId: string, topicName: string): Promise<{
|
|
75
|
+
historyId: string;
|
|
76
|
+
expiration: string;
|
|
77
|
+
}>;
|
|
78
|
+
stopWatch(): Promise<void>;
|
|
79
|
+
getHistory(startHistoryId: string, labelId?: string, pageToken?: string): Promise<{
|
|
80
|
+
history: Array<{
|
|
81
|
+
id: string;
|
|
82
|
+
messages?: GmailMessage[];
|
|
83
|
+
messagesAdded?: Array<{
|
|
84
|
+
message: GmailMessage;
|
|
85
|
+
}>;
|
|
86
|
+
messagesDeleted?: Array<{
|
|
87
|
+
message: {
|
|
88
|
+
id: string;
|
|
89
|
+
};
|
|
90
|
+
}>;
|
|
91
|
+
labelsAdded?: Array<{
|
|
92
|
+
message: GmailMessage;
|
|
93
|
+
}>;
|
|
94
|
+
labelsRemoved?: Array<{
|
|
95
|
+
message: {
|
|
96
|
+
id: string;
|
|
97
|
+
};
|
|
98
|
+
}>;
|
|
99
|
+
}>;
|
|
100
|
+
historyId: string;
|
|
101
|
+
nextPageToken?: string;
|
|
102
|
+
}>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Parses an email address header into name and email
|
|
106
|
+
* Handles formats like "John Doe <john@example.com>" or "john@example.com"
|
|
107
|
+
*/
|
|
108
|
+
export declare function parseEmailAddress(headerValue: string): EmailAddress;
|
|
109
|
+
/**
|
|
110
|
+
* Transforms a Gmail thread into an array of Activities
|
|
111
|
+
* The first message is the parent, subsequent messages are replies
|
|
112
|
+
*/
|
|
113
|
+
export declare function transformGmailThread(thread: GmailThread): NewActivity[];
|
|
114
|
+
/**
|
|
115
|
+
* Syncs threads from a Gmail label/query with pagination
|
|
116
|
+
* Returns threads and updated sync state
|
|
117
|
+
*/
|
|
118
|
+
export declare function syncGmailChannel(api: GmailApi, state: SyncState, batchSize?: number): Promise<{
|
|
119
|
+
threads: GmailThread[];
|
|
120
|
+
state: SyncState;
|
|
121
|
+
hasMore: boolean;
|
|
122
|
+
}>;
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { ActivityLinkType, ActivityType } from "@plotday/twister";
|
|
2
|
+
export class GmailApi {
|
|
3
|
+
constructor(accessToken) {
|
|
4
|
+
this.accessToken = accessToken;
|
|
5
|
+
this.baseUrl = "https://gmail.googleapis.com/gmail/v1/users/me";
|
|
6
|
+
}
|
|
7
|
+
async call(endpoint, options) {
|
|
8
|
+
const method = options?.method || "GET";
|
|
9
|
+
const params = options?.params || {};
|
|
10
|
+
const body = options?.body;
|
|
11
|
+
// Build URL with query parameters
|
|
12
|
+
const url = new URL(`${this.baseUrl}${endpoint}`);
|
|
13
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
14
|
+
if (value !== undefined && value !== null) {
|
|
15
|
+
url.searchParams.append(key, String(value));
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const headers = {
|
|
19
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
};
|
|
22
|
+
const response = await fetch(url.toString(), {
|
|
23
|
+
method,
|
|
24
|
+
headers,
|
|
25
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const errorText = await response.text();
|
|
29
|
+
throw new Error(`Gmail API error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
30
|
+
}
|
|
31
|
+
return await response.json();
|
|
32
|
+
}
|
|
33
|
+
async getLabels() {
|
|
34
|
+
const data = await this.call("/labels");
|
|
35
|
+
return data.labels || [];
|
|
36
|
+
}
|
|
37
|
+
async getThreads(labelId, pageToken, maxResults = 20, query) {
|
|
38
|
+
const params = {
|
|
39
|
+
labelIds: labelId,
|
|
40
|
+
maxResults,
|
|
41
|
+
};
|
|
42
|
+
if (pageToken) {
|
|
43
|
+
params.pageToken = pageToken;
|
|
44
|
+
}
|
|
45
|
+
if (query) {
|
|
46
|
+
params.q = query;
|
|
47
|
+
}
|
|
48
|
+
const data = await this.call("/threads", { params });
|
|
49
|
+
return {
|
|
50
|
+
threads: data.threads || [],
|
|
51
|
+
nextPageToken: data.nextPageToken,
|
|
52
|
+
resultSizeEstimate: data.resultSizeEstimate || 0,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async getThread(threadId) {
|
|
56
|
+
const data = await this.call(`/threads/${threadId}`, {
|
|
57
|
+
params: { format: "full" },
|
|
58
|
+
});
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
async setupWatch(labelId, topicName) {
|
|
62
|
+
const data = await this.call("/watch", {
|
|
63
|
+
method: "POST",
|
|
64
|
+
body: {
|
|
65
|
+
labelIds: [labelId],
|
|
66
|
+
topicName,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
historyId: data.historyId,
|
|
71
|
+
expiration: data.expiration,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
async stopWatch() {
|
|
75
|
+
await this.call("/stop", { method: "POST" });
|
|
76
|
+
}
|
|
77
|
+
async getHistory(startHistoryId, labelId, pageToken) {
|
|
78
|
+
const params = {
|
|
79
|
+
startHistoryId,
|
|
80
|
+
historyTypes: ["messageAdded", "messageDeleted"],
|
|
81
|
+
};
|
|
82
|
+
if (labelId) {
|
|
83
|
+
params.labelId = labelId;
|
|
84
|
+
}
|
|
85
|
+
if (pageToken) {
|
|
86
|
+
params.pageToken = pageToken;
|
|
87
|
+
}
|
|
88
|
+
const data = await this.call("/history", { params });
|
|
89
|
+
return {
|
|
90
|
+
history: data.history || [],
|
|
91
|
+
historyId: data.historyId,
|
|
92
|
+
nextPageToken: data.nextPageToken,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Parses an email address header into name and email
|
|
98
|
+
* Handles formats like "John Doe <john@example.com>" or "john@example.com"
|
|
99
|
+
*/
|
|
100
|
+
export function parseEmailAddress(headerValue) {
|
|
101
|
+
const match = headerValue.match(/^(?:"?([^"]*)"?\s)?<?([^@]+@[^>]+)>?$/);
|
|
102
|
+
if (match) {
|
|
103
|
+
return {
|
|
104
|
+
name: match[1]?.trim() || null,
|
|
105
|
+
email: match[2].trim(),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Fallback: treat entire string as email
|
|
109
|
+
return {
|
|
110
|
+
name: null,
|
|
111
|
+
email: headerValue.trim(),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Gets a specific header value from a message
|
|
116
|
+
*/
|
|
117
|
+
function getHeader(message, name) {
|
|
118
|
+
const header = message.payload.headers.find((h) => h.name.toLowerCase() === name.toLowerCase());
|
|
119
|
+
return header?.value || null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Extracts the body from a Gmail message (handles multipart messages)
|
|
123
|
+
*/
|
|
124
|
+
function extractBody(part) {
|
|
125
|
+
// If this part has a body with data, return it
|
|
126
|
+
if (part.body?.data) {
|
|
127
|
+
// Gmail API returns base64url-encoded data
|
|
128
|
+
const decoded = atob(part.body.data.replace(/-/g, "+").replace(/_/g, "/"));
|
|
129
|
+
return decoded;
|
|
130
|
+
}
|
|
131
|
+
// If multipart, recursively search parts
|
|
132
|
+
if (part.parts) {
|
|
133
|
+
// Prefer plain text over HTML
|
|
134
|
+
const textPart = part.parts.find((p) => p.mimeType === "text/plain");
|
|
135
|
+
if (textPart) {
|
|
136
|
+
return extractBody(textPart);
|
|
137
|
+
}
|
|
138
|
+
const htmlPart = part.parts.find((p) => p.mimeType === "text/html");
|
|
139
|
+
if (htmlPart) {
|
|
140
|
+
// For HTML, strip tags for plain text representation
|
|
141
|
+
const html = extractBody(htmlPart);
|
|
142
|
+
return stripHtmlTags(html);
|
|
143
|
+
}
|
|
144
|
+
// Try first part as fallback
|
|
145
|
+
if (part.parts.length > 0) {
|
|
146
|
+
return extractBody(part.parts[0]);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Strips HTML tags for plain text representation
|
|
153
|
+
* This is a simple implementation - could be enhanced with a proper HTML parser
|
|
154
|
+
*/
|
|
155
|
+
function stripHtmlTags(html) {
|
|
156
|
+
return html
|
|
157
|
+
.replace(/<style[^>]*>.*?<\/style>/gi, "")
|
|
158
|
+
.replace(/<script[^>]*>.*?<\/script>/gi, "")
|
|
159
|
+
.replace(/<[^>]+>/g, " ")
|
|
160
|
+
.replace(/\s+/g, " ")
|
|
161
|
+
.trim();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Extracts attachment information from a Gmail message
|
|
165
|
+
*/
|
|
166
|
+
function extractAttachments(message) {
|
|
167
|
+
const attachments = [];
|
|
168
|
+
function processPart(part) {
|
|
169
|
+
// Check if this part is an attachment
|
|
170
|
+
if (part.filename && part.body?.attachmentId) {
|
|
171
|
+
attachments.push({
|
|
172
|
+
filename: part.filename,
|
|
173
|
+
url: `https://mail.google.com/mail/u/0/#inbox/${message.id}`,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// Recursively process sub-parts
|
|
177
|
+
if (part.parts) {
|
|
178
|
+
part.parts.forEach(processPart);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
processPart(message.payload);
|
|
182
|
+
return attachments;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Transforms a Gmail thread into an array of Activities
|
|
186
|
+
* The first message is the parent, subsequent messages are replies
|
|
187
|
+
*/
|
|
188
|
+
export function transformGmailThread(thread) {
|
|
189
|
+
if (!thread.messages || thread.messages.length === 0)
|
|
190
|
+
return [];
|
|
191
|
+
const activities = [];
|
|
192
|
+
const parentMessage = thread.messages[0];
|
|
193
|
+
// Extract key headers
|
|
194
|
+
const from = getHeader(parentMessage, "From");
|
|
195
|
+
const subject = getHeader(parentMessage, "Subject");
|
|
196
|
+
const to = getHeader(parentMessage, "To");
|
|
197
|
+
const cc = getHeader(parentMessage, "Cc");
|
|
198
|
+
// Parse sender
|
|
199
|
+
const sender = from ? parseEmailAddress(from) : null;
|
|
200
|
+
// Extract body
|
|
201
|
+
const body = extractBody(parentMessage.payload);
|
|
202
|
+
// Create parent activity
|
|
203
|
+
const parentActivity = {
|
|
204
|
+
type: ActivityType.Task,
|
|
205
|
+
title: subject || parentMessage.snippet || "Email",
|
|
206
|
+
note: body || parentMessage.snippet,
|
|
207
|
+
noteType: "text",
|
|
208
|
+
start: new Date(parseInt(parentMessage.internalDate)),
|
|
209
|
+
meta: {
|
|
210
|
+
source: `gmail:${thread.id}:${parentMessage.id}`,
|
|
211
|
+
threadId: thread.id,
|
|
212
|
+
messageId: parentMessage.id,
|
|
213
|
+
from: sender,
|
|
214
|
+
to,
|
|
215
|
+
cc,
|
|
216
|
+
labels: parentMessage.labelIds,
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
// Initialize links array
|
|
220
|
+
parentActivity.links = [];
|
|
221
|
+
// Add Gmail URL as action link
|
|
222
|
+
parentActivity.links.push({
|
|
223
|
+
type: ActivityLinkType.external,
|
|
224
|
+
title: "Open in Gmail",
|
|
225
|
+
url: `https://mail.google.com/mail/u/0/#inbox/${thread.id}`,
|
|
226
|
+
});
|
|
227
|
+
// Add attachments as links
|
|
228
|
+
const attachments = extractAttachments(parentMessage);
|
|
229
|
+
attachments.forEach((att) => {
|
|
230
|
+
parentActivity.links.push({
|
|
231
|
+
type: ActivityLinkType.external,
|
|
232
|
+
title: `Attachment: ${att.filename}`,
|
|
233
|
+
url: att.url,
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
activities.push(parentActivity);
|
|
237
|
+
// Create activities for replies (messages after the first)
|
|
238
|
+
for (let i = 1; i < thread.messages.length; i++) {
|
|
239
|
+
const message = thread.messages[i];
|
|
240
|
+
const replyFrom = getHeader(message, "From");
|
|
241
|
+
const replySender = replyFrom ? parseEmailAddress(replyFrom) : null;
|
|
242
|
+
const replyBody = extractBody(message.payload);
|
|
243
|
+
const replyActivity = {
|
|
244
|
+
type: ActivityType.Task,
|
|
245
|
+
title: `Re: ${subject || "Email"}`,
|
|
246
|
+
note: replyBody || message.snippet,
|
|
247
|
+
noteType: "text",
|
|
248
|
+
start: new Date(parseInt(message.internalDate)),
|
|
249
|
+
parent: { id: `gmail:${thread.id}:${parentMessage.id}` },
|
|
250
|
+
meta: {
|
|
251
|
+
source: `gmail:${thread.id}:${message.id}`,
|
|
252
|
+
threadId: thread.id,
|
|
253
|
+
messageId: message.id,
|
|
254
|
+
from: replySender,
|
|
255
|
+
labels: message.labelIds,
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
// Initialize links array
|
|
259
|
+
replyActivity.links = [];
|
|
260
|
+
// Add Gmail URL as action link
|
|
261
|
+
replyActivity.links.push({
|
|
262
|
+
type: ActivityLinkType.external,
|
|
263
|
+
title: "Open in Gmail",
|
|
264
|
+
url: `https://mail.google.com/mail/u/0/#inbox/${thread.id}`,
|
|
265
|
+
});
|
|
266
|
+
// Add attachments as links
|
|
267
|
+
const replyAttachments = extractAttachments(message);
|
|
268
|
+
replyAttachments.forEach((att) => {
|
|
269
|
+
replyActivity.links.push({
|
|
270
|
+
type: ActivityLinkType.external,
|
|
271
|
+
title: `Attachment: ${att.filename}`,
|
|
272
|
+
url: att.url,
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
activities.push(replyActivity);
|
|
276
|
+
}
|
|
277
|
+
return activities;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Syncs threads from a Gmail label/query with pagination
|
|
281
|
+
* Returns threads and updated sync state
|
|
282
|
+
*/
|
|
283
|
+
export async function syncGmailChannel(api, state, batchSize = 20) {
|
|
284
|
+
// Extract query from channelId if it's a search filter
|
|
285
|
+
let labelId = state.channelId;
|
|
286
|
+
let query;
|
|
287
|
+
if (state.channelId.startsWith("search:")) {
|
|
288
|
+
query = state.channelId.substring(7);
|
|
289
|
+
labelId = "INBOX"; // Default to inbox for searches
|
|
290
|
+
}
|
|
291
|
+
const { threads: threadRefs, nextPageToken } = await api.getThreads(labelId, state.pageToken, batchSize, query);
|
|
292
|
+
// Fetch full thread details
|
|
293
|
+
const threads = [];
|
|
294
|
+
for (const threadRef of threadRefs) {
|
|
295
|
+
try {
|
|
296
|
+
const thread = await api.getThread(threadRef.id);
|
|
297
|
+
threads.push(thread);
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
console.error(`Failed to fetch thread ${threadRef.id}:`, error);
|
|
301
|
+
// Continue with other threads even if one fails
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const newState = {
|
|
305
|
+
channelId: state.channelId,
|
|
306
|
+
pageToken: nextPageToken,
|
|
307
|
+
lastSyncTime: new Date(),
|
|
308
|
+
};
|
|
309
|
+
// Update historyId from the last thread if available
|
|
310
|
+
if (threads.length > 0) {
|
|
311
|
+
newState.historyId = threads[threads.length - 1].historyId;
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
threads,
|
|
315
|
+
state: newState,
|
|
316
|
+
hasMore: !!nextPageToken,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=gmail-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmail-api.js","sourceRoot":"","sources":["../src/gmail-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA4DlE,MAAM,OAAO,QAAQ;IAGnB,YAAmB,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;QAF9B,YAAO,GAAG,gDAAgD,CAAC;IAE1B,CAAC;IAEnC,KAAK,CAAC,IAAI,CACf,QAAgB,EAChB,OAIC;QAED,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC;QAE3B,kCAAkC;QAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBAC1C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAgB;YAC3B,aAAa,EAAE,UAAU,IAAI,CAAC,WAAW,EAAE;YAC3C,cAAc,EAAE,kBAAkB;SACnC,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;YAC3C,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,MAAM,SAAS,EAAE,CAC5E,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAEM,KAAK,CAAC,SAAS;QACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,OAAe,EACf,SAAkB,EAClB,aAAqB,EAAE,EACvB,KAAc;QAMd,MAAM,MAAM,GAAQ;YAClB,QAAQ,EAAE,OAAO;YACjB,UAAU;SACX,CAAC;QAEF,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/B,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAErD,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,CAAC;SACjD,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,QAAgB;QACrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,QAAQ,EAAE,EAAE;YACnD,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;SAC3B,CAAC,CAAC;QACH,OAAO,IAAmB,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,OAAe,EACf,SAAiB;QAKjB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE;gBACJ,QAAQ,EAAE,CAAC,OAAO,CAAC;gBACnB,SAAS;aACV;SACF,CAAC,CAAC;QAEH,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,SAAS;QACpB,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAEM,KAAK,CAAC,UAAU,CACrB,cAAsB,EACtB,OAAgB,EAChB,SAAkB;QAalB,MAAM,MAAM,GAAQ;YAClB,cAAc;YACd,YAAY,EAAE,CAAC,cAAc,EAAE,gBAAgB,CAAC;SACjD,CAAC;QAEF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC3B,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;QAC/B,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAErD,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;YAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,IAAI,CAAC,aAAa;SAClC,CAAC;IACJ,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAEzE,IAAI,KAAK,EAAE,CAAC;QACV,OAAO;YACL,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI;YAC9B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;SACvB,CAAC;IACJ,CAAC;IAED,yCAAyC;IACzC,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE;KAC1B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,OAAqB,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CACzC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CACnD,CAAC;IACF,OAAO,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAsB;IACzC,+CAA+C;IAC/C,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QACpB,2CAA2C;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,yCAAyC;IACzC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC;QACrE,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,qDAAqD;YACrD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAED,6BAA6B;QAC7B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI;SACR,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;SACzC,OAAO,CAAC,8BAA8B,EAAE,EAAE,CAAC;SAC3C,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC;SACxB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,OAAqB;IAErB,MAAM,WAAW,GAA6C,EAAE,CAAC;IAEjE,SAAS,WAAW,CAAC,IAAsB;QACzC,sCAAsC;QACtC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;YAC7C,WAAW,CAAC,IAAI,CAAC;gBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,GAAG,EAAE,2CAA2C,OAAO,CAAC,EAAE,EAAE;aAC7D,CAAC,CAAC;QACL,CAAC;QAED,gCAAgC;QAChC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAmB;IACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEhE,MAAM,UAAU,GAAkB,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEzC,sBAAsB;IACtB,MAAM,IAAI,GAAG,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IACpD,MAAM,EAAE,GAAG,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAE1C,eAAe;IACf,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAErD,eAAe;IACf,MAAM,IAAI,GAAG,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAEhD,yBAAyB;IACzB,MAAM,cAAc,GAAgB;QAClC,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,KAAK,EAAE,OAAO,IAAI,aAAa,CAAC,OAAO,IAAI,OAAO;QAClD,IAAI,EAAE,IAAI,IAAI,aAAa,CAAC,OAAO;QACnC,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,EAAE;YACJ,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,EAAE;YAChD,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnB,SAAS,EAAE,aAAa,CAAC,EAAE;YAC3B,IAAI,EAAE,MAAM;YACZ,EAAE;YACF,EAAE;YACF,MAAM,EAAE,aAAa,CAAC,QAAQ;SAC/B;KACF,CAAC;IAEF,yBAAyB;IACzB,cAAc,CAAC,KAAK,GAAG,EAAE,CAAC;IAE1B,+BAA+B;IAC/B,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;QAC/B,KAAK,EAAE,eAAe;QACtB,GAAG,EAAE,2CAA2C,MAAM,CAAC,EAAE,EAAE;KAC5D,CAAC,CAAC;IAEH,2BAA2B;IAC3B,MAAM,WAAW,GAAG,kBAAkB,CAAC,aAAa,CAAC,CAAC;IACtD,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,cAAc,CAAC,KAAM,CAAC,IAAI,CAAC;YACzB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,KAAK,EAAE,eAAe,GAAG,CAAC,QAAQ,EAAE;YACpC,GAAG,EAAE,GAAG,CAAC,GAAG;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAEhC,2DAA2D;IAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACpE,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE/C,MAAM,aAAa,GAAgB;YACjC,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,KAAK,EAAE,OAAO,OAAO,IAAI,OAAO,EAAE;YAClC,IAAI,EAAE,SAAS,IAAI,OAAO,CAAC,OAAO;YAClC,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC/C,MAAM,EAAE,EAAE,EAAE,EAAE,SAAS,MAAM,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,EAAE,EAAE;YACxD,IAAI,EAAE;gBACJ,MAAM,EAAE,SAAS,MAAM,CAAC,EAAE,IAAI,OAAO,CAAC,EAAE,EAAE;gBAC1C,QAAQ,EAAE,MAAM,CAAC,EAAE;gBACnB,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,OAAO,CAAC,QAAQ;aACzB;SACF,CAAC;QAEF,yBAAyB;QACzB,aAAa,CAAC,KAAK,GAAG,EAAE,CAAC;QAEzB,+BAA+B;QAC/B,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC;YACvB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;YAC/B,KAAK,EAAE,eAAe;YACtB,GAAG,EAAE,2CAA2C,MAAM,CAAC,EAAE,EAAE;SAC5D,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACrD,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC/B,aAAa,CAAC,KAAM,CAAC,IAAI,CAAC;gBACxB,IAAI,EAAE,gBAAgB,CAAC,QAAQ;gBAC/B,KAAK,EAAE,eAAe,GAAG,CAAC,QAAQ,EAAE;gBACpC,GAAG,EAAE,GAAG,CAAC,GAAG;aACb,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAa,EACb,KAAgB,EAChB,YAAoB,EAAE;IAMtB,uDAAuD;IACvD,IAAI,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC;IAC9B,IAAI,KAAyB,CAAC;IAE9B,IAAI,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1C,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,GAAG,OAAO,CAAC,CAAC,gCAAgC;IACrD,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,MAAM,GAAG,CAAC,UAAU,CACjE,OAAO,EACP,KAAK,CAAC,SAAS,EACf,SAAS,EACT,KAAK,CACN,CAAC;IAEF,4BAA4B;IAC5B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YAChE,gDAAgD;QAClD,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAc;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,aAAa;QACxB,YAAY,EAAE,IAAI,IAAI,EAAE;KACzB,CAAC;IAEF,qDAAqD;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,CAAC;IAED,OAAO;QACL,OAAO;QACP,KAAK,EAAE,QAAQ;QACf,OAAO,EAAE,CAAC,CAAC,aAAa;KACzB,CAAC;AACJ,CAAC"}
|
package/dist/gmail.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { type Activity, type ActivityLink, Tool, type ToolBuilder } from "@plotday/twister";
|
|
2
|
+
import { type MessageChannel, type MessageSyncOptions, type MessagingAuth, type MessagingTool } from "@plotday/twister/common/messaging";
|
|
3
|
+
import { type Callback } from "@plotday/twister/tools/callbacks";
|
|
4
|
+
import { type Authorization, Integrations } from "@plotday/twister/tools/integrations";
|
|
5
|
+
import { Network, type WebhookRequest } from "@plotday/twister/tools/network";
|
|
6
|
+
import { Plot } from "@plotday/twister/tools/plot";
|
|
7
|
+
/**
|
|
8
|
+
* Gmail integration tool implementing the MessagingTool interface.
|
|
9
|
+
*
|
|
10
|
+
* Supports inbox, labels, and search filters as channels.
|
|
11
|
+
*
|
|
12
|
+
* **Required OAuth Scopes:**
|
|
13
|
+
* - `https://www.googleapis.com/auth/gmail.readonly` - Read emails
|
|
14
|
+
* - `https://www.googleapis.com/auth/gmail.modify` - Modify labels
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* class MessagesTwist extends Twist {
|
|
19
|
+
* private gmail: Gmail;
|
|
20
|
+
*
|
|
21
|
+
* constructor(id: string, tools: Tools) {
|
|
22
|
+
* super();
|
|
23
|
+
* this.gmail = tools.get(Gmail);
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* async activate() {
|
|
27
|
+
* const authLink = await this.gmail.requestAuth(this.onGmailAuth);
|
|
28
|
+
*
|
|
29
|
+
* await this.plot.createActivity({
|
|
30
|
+
* type: ActivityType.Task,
|
|
31
|
+
* title: "Connect Gmail",
|
|
32
|
+
* links: [authLink]
|
|
33
|
+
* });
|
|
34
|
+
* }
|
|
35
|
+
*
|
|
36
|
+
* async onGmailAuth(auth: MessagingAuth) {
|
|
37
|
+
* const channels = await this.gmail.getChannels(auth.authToken);
|
|
38
|
+
*
|
|
39
|
+
* // Start syncing inbox
|
|
40
|
+
* const inbox = channels.find(c => c.primary);
|
|
41
|
+
* if (inbox) {
|
|
42
|
+
* await this.gmail.startSync(
|
|
43
|
+
* auth.authToken,
|
|
44
|
+
* inbox.id,
|
|
45
|
+
* this.onGmailThread,
|
|
46
|
+
* {
|
|
47
|
+
* timeMin: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // Last 7 days
|
|
48
|
+
* }
|
|
49
|
+
* );
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* async onGmailThread(thread: Activity[]) {
|
|
54
|
+
* // Process Gmail email threads
|
|
55
|
+
* for (const message of thread) {
|
|
56
|
+
* await this.plot.createActivity(message);
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare class Gmail extends Tool<Gmail> implements MessagingTool {
|
|
63
|
+
build(build: ToolBuilder): {
|
|
64
|
+
integrations: Promise<Integrations>;
|
|
65
|
+
network: Promise<Network>;
|
|
66
|
+
plot: Promise<Plot>;
|
|
67
|
+
};
|
|
68
|
+
requestAuth<TCallback extends (auth: MessagingAuth, ...args: any[]) => any>(callback: TCallback, ...extraArgs: any[]): Promise<ActivityLink>;
|
|
69
|
+
private getApi;
|
|
70
|
+
getChannels(authToken: string): Promise<MessageChannel[]>;
|
|
71
|
+
startSync<TCallback extends (thread: Activity[], ...args: any[]) => any>(authToken: string, channelId: string, callback: TCallback, options?: MessageSyncOptions, ...extraArgs: any[]): Promise<void>;
|
|
72
|
+
stopSync(authToken: string, channelId: string): Promise<void>;
|
|
73
|
+
private setupChannelWebhook;
|
|
74
|
+
syncBatch(_args: any, batchNumber: number, mode: "full" | "incremental", authToken: string, channelId: string): Promise<void>;
|
|
75
|
+
private processEmailThreads;
|
|
76
|
+
onGmailWebhook(request: WebhookRequest, channelId: string, authToken: string): Promise<void>;
|
|
77
|
+
private startIncrementalSync;
|
|
78
|
+
onAuthSuccess(authResult: Authorization, authToken: string, callback: Callback): Promise<void>;
|
|
79
|
+
}
|
|
80
|
+
export default Gmail;
|
package/dist/gmail.js
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { Tool, } from "@plotday/twister";
|
|
2
|
+
import { AuthLevel, AuthProvider, Integrations, } from "@plotday/twister/tools/integrations";
|
|
3
|
+
import { Network } from "@plotday/twister/tools/network";
|
|
4
|
+
import { ActivityAccess, ContactAccess, Plot } from "@plotday/twister/tools/plot";
|
|
5
|
+
import { GmailApi, syncGmailChannel, transformGmailThread, } from "./gmail-api";
|
|
6
|
+
/**
|
|
7
|
+
* Gmail integration tool implementing the MessagingTool interface.
|
|
8
|
+
*
|
|
9
|
+
* Supports inbox, labels, and search filters as channels.
|
|
10
|
+
*
|
|
11
|
+
* **Required OAuth Scopes:**
|
|
12
|
+
* - `https://www.googleapis.com/auth/gmail.readonly` - Read emails
|
|
13
|
+
* - `https://www.googleapis.com/auth/gmail.modify` - Modify labels
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* class MessagesTwist extends Twist {
|
|
18
|
+
* private gmail: Gmail;
|
|
19
|
+
*
|
|
20
|
+
* constructor(id: string, tools: Tools) {
|
|
21
|
+
* super();
|
|
22
|
+
* this.gmail = tools.get(Gmail);
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* async activate() {
|
|
26
|
+
* const authLink = await this.gmail.requestAuth(this.onGmailAuth);
|
|
27
|
+
*
|
|
28
|
+
* await this.plot.createActivity({
|
|
29
|
+
* type: ActivityType.Task,
|
|
30
|
+
* title: "Connect Gmail",
|
|
31
|
+
* links: [authLink]
|
|
32
|
+
* });
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* async onGmailAuth(auth: MessagingAuth) {
|
|
36
|
+
* const channels = await this.gmail.getChannels(auth.authToken);
|
|
37
|
+
*
|
|
38
|
+
* // Start syncing inbox
|
|
39
|
+
* const inbox = channels.find(c => c.primary);
|
|
40
|
+
* if (inbox) {
|
|
41
|
+
* await this.gmail.startSync(
|
|
42
|
+
* auth.authToken,
|
|
43
|
+
* inbox.id,
|
|
44
|
+
* this.onGmailThread,
|
|
45
|
+
* {
|
|
46
|
+
* timeMin: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // Last 7 days
|
|
47
|
+
* }
|
|
48
|
+
* );
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* async onGmailThread(thread: Activity[]) {
|
|
53
|
+
* // Process Gmail email threads
|
|
54
|
+
* for (const message of thread) {
|
|
55
|
+
* await this.plot.createActivity(message);
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export class Gmail extends Tool {
|
|
62
|
+
build(build) {
|
|
63
|
+
return {
|
|
64
|
+
integrations: build(Integrations),
|
|
65
|
+
network: build(Network, {
|
|
66
|
+
urls: ["https://gmail.googleapis.com/gmail/v1/*"],
|
|
67
|
+
}),
|
|
68
|
+
plot: build(Plot, {
|
|
69
|
+
contact: {
|
|
70
|
+
access: ContactAccess.Write,
|
|
71
|
+
},
|
|
72
|
+
activity: {
|
|
73
|
+
access: ActivityAccess.Create,
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async requestAuth(callback, ...extraArgs) {
|
|
79
|
+
console.log("Requesting Gmail auth");
|
|
80
|
+
// Gmail OAuth scopes for read-only access
|
|
81
|
+
const gmailScopes = [
|
|
82
|
+
"https://www.googleapis.com/auth/gmail.readonly",
|
|
83
|
+
"https://www.googleapis.com/auth/gmail.modify",
|
|
84
|
+
];
|
|
85
|
+
// Generate opaque token for authorization
|
|
86
|
+
const authToken = crypto.randomUUID();
|
|
87
|
+
const callbackToken = await this.tools.callbacks.createFromParent(callback, ...extraArgs);
|
|
88
|
+
// Request auth and return the activity link
|
|
89
|
+
// Use User level for user-scoped Gmail authorization
|
|
90
|
+
return await this.tools.integrations.request({
|
|
91
|
+
provider: AuthProvider.Google,
|
|
92
|
+
level: AuthLevel.User,
|
|
93
|
+
scopes: gmailScopes,
|
|
94
|
+
}, this.onAuthSuccess, authToken, callbackToken);
|
|
95
|
+
}
|
|
96
|
+
async getApi(authToken) {
|
|
97
|
+
const authorization = await this.get(`authorization:${authToken}`);
|
|
98
|
+
if (!authorization) {
|
|
99
|
+
throw new Error("Authorization no longer available");
|
|
100
|
+
}
|
|
101
|
+
const token = await this.tools.integrations.get(authorization);
|
|
102
|
+
if (!token) {
|
|
103
|
+
throw new Error("Authorization no longer available");
|
|
104
|
+
}
|
|
105
|
+
return new GmailApi(token.token);
|
|
106
|
+
}
|
|
107
|
+
async getChannels(authToken) {
|
|
108
|
+
console.log("Fetching Gmail labels");
|
|
109
|
+
const api = await this.getApi(authToken);
|
|
110
|
+
const labels = await api.getLabels();
|
|
111
|
+
console.log("Got Gmail labels", labels);
|
|
112
|
+
const channels = [];
|
|
113
|
+
// Add standard labels as channels
|
|
114
|
+
for (const label of labels) {
|
|
115
|
+
// Filter out system labels that don't make sense as channels
|
|
116
|
+
if (label.type === "system" &&
|
|
117
|
+
!["INBOX", "SENT", "DRAFT", "IMPORTANT", "STARRED"].includes(label.id)) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
channels.push({
|
|
121
|
+
id: label.id,
|
|
122
|
+
name: label.name,
|
|
123
|
+
description: `${label.messagesTotal || 0} messages, ${label.messagesUnread || 0} unread`,
|
|
124
|
+
primary: label.id === "INBOX",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// Add a special "search" channel option
|
|
128
|
+
channels.push({
|
|
129
|
+
id: "search:from:important@example.com",
|
|
130
|
+
name: "Search (Custom Query)",
|
|
131
|
+
description: "Use custom Gmail search queries as channels",
|
|
132
|
+
primary: false,
|
|
133
|
+
});
|
|
134
|
+
return channels;
|
|
135
|
+
}
|
|
136
|
+
async startSync(authToken, channelId, callback, options, ...extraArgs) {
|
|
137
|
+
console.log("Starting Gmail sync for channel", channelId);
|
|
138
|
+
// Create callback token for parent
|
|
139
|
+
const callbackToken = await this.tools.callbacks.createFromParent(callback, ...extraArgs);
|
|
140
|
+
await this.set(`thread_callback_token_${channelId}`, callbackToken);
|
|
141
|
+
// Store auth token for channel
|
|
142
|
+
await this.set(`auth_token_${channelId}`, authToken);
|
|
143
|
+
// Setup webhook for this channel (Gmail Push Notifications)
|
|
144
|
+
await this.setupChannelWebhook(authToken, channelId);
|
|
145
|
+
const initialState = {
|
|
146
|
+
channelId,
|
|
147
|
+
lastSyncTime: options?.timeMin
|
|
148
|
+
? typeof options.timeMin === "string"
|
|
149
|
+
? new Date(options.timeMin)
|
|
150
|
+
: options.timeMin
|
|
151
|
+
: undefined,
|
|
152
|
+
};
|
|
153
|
+
await this.set(`sync_state_${channelId}`, initialState);
|
|
154
|
+
console.log("Starting initial Gmail sync");
|
|
155
|
+
// Start sync batch using run tool for long-running operation
|
|
156
|
+
const syncCallback = await this.callback(this.syncBatch, 1, "full", authToken, channelId);
|
|
157
|
+
await this.run(syncCallback);
|
|
158
|
+
}
|
|
159
|
+
async stopSync(authToken, channelId) {
|
|
160
|
+
console.log("Stopping Gmail sync for channel", channelId);
|
|
161
|
+
// Stop watching for push notifications
|
|
162
|
+
const api = await this.getApi(authToken);
|
|
163
|
+
try {
|
|
164
|
+
await api.stopWatch();
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
console.error("Failed to stop Gmail watch:", error);
|
|
168
|
+
}
|
|
169
|
+
// Clear webhook
|
|
170
|
+
await this.clear(`channel_webhook_${channelId}`);
|
|
171
|
+
// Clear sync state
|
|
172
|
+
await this.clear(`sync_state_${channelId}`);
|
|
173
|
+
// Clear callback token
|
|
174
|
+
await this.clear(`thread_callback_token_${channelId}`);
|
|
175
|
+
// Clear auth token
|
|
176
|
+
await this.clear(`auth_token_${channelId}`);
|
|
177
|
+
}
|
|
178
|
+
async setupChannelWebhook(authToken, channelId) {
|
|
179
|
+
// Retrieve the authorization for this auth token
|
|
180
|
+
const authorization = await this.get(`authorization:${authToken}`);
|
|
181
|
+
if (!authorization) {
|
|
182
|
+
throw new Error("Authorization not found for Gmail webhook setup");
|
|
183
|
+
}
|
|
184
|
+
// Create Gmail webhook (returns Pub/Sub topic name, not a URL)
|
|
185
|
+
// When provider is Google with Gmail scopes, createWebhook returns a Pub/Sub topic name
|
|
186
|
+
const topicName = await this.tools.network.createWebhook({
|
|
187
|
+
callback: this.onGmailWebhook,
|
|
188
|
+
extraArgs: [channelId, authToken],
|
|
189
|
+
provider: AuthProvider.Google,
|
|
190
|
+
authorization,
|
|
191
|
+
});
|
|
192
|
+
const api = await this.getApi(authToken);
|
|
193
|
+
try {
|
|
194
|
+
// Setup Gmail watch with the Pub/Sub topic name
|
|
195
|
+
// topicName format: projects/{project_id}/topics/{topic_name}
|
|
196
|
+
const watchResult = await api.setupWatch(channelId, topicName);
|
|
197
|
+
// Store webhook data including expiration
|
|
198
|
+
await this.set(`channel_webhook_${channelId}`, {
|
|
199
|
+
topicName,
|
|
200
|
+
channelId,
|
|
201
|
+
historyId: watchResult.historyId,
|
|
202
|
+
expiration: new Date(parseInt(watchResult.expiration)),
|
|
203
|
+
createdAt: new Date().toISOString(),
|
|
204
|
+
});
|
|
205
|
+
console.log("Gmail webhook setup complete", {
|
|
206
|
+
channelId,
|
|
207
|
+
topicName,
|
|
208
|
+
expiration: watchResult.expiration,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
console.error("Failed to setup Gmail webhook:", error);
|
|
213
|
+
console.log("Continuing without webhooks - only manual/scheduled syncs will work");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async syncBatch(_args, batchNumber, mode, authToken, channelId) {
|
|
217
|
+
console.log(`Starting Gmail sync batch ${batchNumber} (${mode}) for channel ${channelId}`);
|
|
218
|
+
try {
|
|
219
|
+
const state = await this.get(`sync_state_${channelId}`);
|
|
220
|
+
if (!state) {
|
|
221
|
+
throw new Error("No sync state found");
|
|
222
|
+
}
|
|
223
|
+
const api = await this.getApi(authToken);
|
|
224
|
+
// Use smaller batch size for Gmail (20 threads) to avoid timeouts
|
|
225
|
+
const result = await syncGmailChannel(api, state, 20);
|
|
226
|
+
if (result.threads.length > 0) {
|
|
227
|
+
await this.processEmailThreads(result.threads, channelId, authToken);
|
|
228
|
+
console.log(`Synced ${result.threads.length} threads in batch ${batchNumber} for channel ${channelId}`);
|
|
229
|
+
}
|
|
230
|
+
await this.set(`sync_state_${channelId}`, result.state);
|
|
231
|
+
if (result.hasMore) {
|
|
232
|
+
const syncCallback = await this.callback(this.syncBatch, batchNumber + 1, mode, authToken, channelId);
|
|
233
|
+
await this.run(syncCallback);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
console.log(`Gmail ${mode} sync completed after ${batchNumber} batches for channel ${channelId}`);
|
|
237
|
+
if (mode === "full") {
|
|
238
|
+
await this.clear(`sync_state_${channelId}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
console.error(`Error in sync batch ${batchNumber} for channel ${channelId}:`, error);
|
|
244
|
+
throw error;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async processEmailThreads(threads, channelId, authToken) {
|
|
248
|
+
for (const thread of threads) {
|
|
249
|
+
try {
|
|
250
|
+
// Transform Gmail thread to Activity array
|
|
251
|
+
const activities = transformGmailThread(thread);
|
|
252
|
+
if (activities.length === 0)
|
|
253
|
+
continue;
|
|
254
|
+
// Extract email addresses from all messages and create contacts
|
|
255
|
+
const emailAddresses = new Set();
|
|
256
|
+
for (const activity of activities) {
|
|
257
|
+
const meta = activity.meta;
|
|
258
|
+
if (meta?.from?.email) {
|
|
259
|
+
emailAddresses.add(meta.from.email);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Create contacts for all unique email addresses
|
|
263
|
+
if (emailAddresses.size > 0) {
|
|
264
|
+
const contacts = Array.from(emailAddresses).map((email) => {
|
|
265
|
+
// Try to find the name from the activity meta
|
|
266
|
+
const activity = activities.find((act) => act.meta?.from?.email === email);
|
|
267
|
+
const name = activity?.meta?.from?.name || null;
|
|
268
|
+
return {
|
|
269
|
+
email,
|
|
270
|
+
name: name || undefined,
|
|
271
|
+
};
|
|
272
|
+
});
|
|
273
|
+
await this.tools.plot.addContacts(contacts);
|
|
274
|
+
}
|
|
275
|
+
// Call parent callback with the thread
|
|
276
|
+
const callbackToken = await this.get(`thread_callback_token_${channelId}`);
|
|
277
|
+
if (callbackToken) {
|
|
278
|
+
// Pass activities as-is - the callback will handle conversion if needed
|
|
279
|
+
await this.run(callbackToken, activities);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
console.error(`Failed to process Gmail thread ${thread.id}:`, error);
|
|
284
|
+
// Continue processing other threads
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async onGmailWebhook(request, channelId, authToken) {
|
|
289
|
+
console.log("Received Gmail webhook notification", {
|
|
290
|
+
body: request.body,
|
|
291
|
+
channelId,
|
|
292
|
+
});
|
|
293
|
+
// Gmail sends push notifications via Cloud Pub/Sub
|
|
294
|
+
// The message body is base64-encoded
|
|
295
|
+
const message = request.body?.message;
|
|
296
|
+
if (!message) {
|
|
297
|
+
console.warn("No message in webhook body");
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// Decode the Pub/Sub message
|
|
301
|
+
let data;
|
|
302
|
+
try {
|
|
303
|
+
const decoded = atob(message.data);
|
|
304
|
+
data = JSON.parse(decoded);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
console.error("Failed to decode Gmail webhook message:", error);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
console.log("Decoded Gmail notification:", data);
|
|
311
|
+
// Gmail notifications contain historyId for incremental sync
|
|
312
|
+
if (data.historyId) {
|
|
313
|
+
await this.startIncrementalSync(channelId, authToken, data.historyId);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async startIncrementalSync(channelId, authToken, historyId) {
|
|
317
|
+
const webhookData = await this.get(`channel_webhook_${channelId}`);
|
|
318
|
+
if (!webhookData) {
|
|
319
|
+
console.error("No channel webhook data found");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
// Check if watch has expired and renew if needed
|
|
323
|
+
const expiration = new Date(webhookData.expiration);
|
|
324
|
+
if (expiration < new Date()) {
|
|
325
|
+
console.log("Gmail watch expired, renewing...");
|
|
326
|
+
await this.setupChannelWebhook(authToken, channelId);
|
|
327
|
+
}
|
|
328
|
+
// For incremental sync, use the historyId from the notification
|
|
329
|
+
const incrementalState = {
|
|
330
|
+
channelId,
|
|
331
|
+
historyId,
|
|
332
|
+
lastSyncTime: new Date(),
|
|
333
|
+
};
|
|
334
|
+
await this.set(`sync_state_${channelId}`, incrementalState);
|
|
335
|
+
const syncCallback = await this.callback(this.syncBatch, 1, "incremental", authToken, channelId);
|
|
336
|
+
await this.run(syncCallback);
|
|
337
|
+
}
|
|
338
|
+
async onAuthSuccess(authResult, authToken, callback) {
|
|
339
|
+
// Store the actual auth token using opaque token as key
|
|
340
|
+
await this.set(`authorization:${authToken}`, authResult);
|
|
341
|
+
const authSuccessResult = {
|
|
342
|
+
authToken,
|
|
343
|
+
};
|
|
344
|
+
await this.run(callback, authSuccessResult);
|
|
345
|
+
// Clean up the callback token
|
|
346
|
+
await this.clear(`auth_callback_token:${authToken}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
export default Gmail;
|
|
350
|
+
//# sourceMappingURL=gmail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmail.js","sourceRoot":"","sources":["../src/gmail.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default, Gmail } from "./gmail";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plotday/tool-gmail",
|
|
3
|
+
"displayName": "Gmail",
|
|
4
|
+
"description": "Sync with Gmail inbox and messages",
|
|
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/twister": "^0.20.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/gmail"
|
|
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
|
+
"gmail",
|
|
42
|
+
"messaging",
|
|
43
|
+
"email"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"clean": "rm -rf dist"
|
|
51
|
+
}
|
|
52
|
+
}
|