patchwork-os 0.2.0-beta.6.canary.21 → 0.2.0-beta.6.canary.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/connectorRoutes.js +384 -0
  2. package/dist/connectorRoutes.js.map +1 -1
  3. package/dist/connectors/airtable.d.ts +108 -0
  4. package/dist/connectors/airtable.js +396 -0
  5. package/dist/connectors/airtable.js.map +1 -0
  6. package/dist/connectors/connectorRegistry.js +63 -0
  7. package/dist/connectors/connectorRegistry.js.map +1 -1
  8. package/dist/connectors/elasticsearch.d.ts +141 -0
  9. package/dist/connectors/elasticsearch.js +601 -0
  10. package/dist/connectors/elasticsearch.js.map +1 -0
  11. package/dist/connectors/figma.d.ts +130 -0
  12. package/dist/connectors/figma.js +387 -0
  13. package/dist/connectors/figma.js.map +1 -0
  14. package/dist/connectors/gmail.js +9 -0
  15. package/dist/connectors/gmail.js.map +1 -1
  16. package/dist/connectors/googleDrive.d.ts +12 -0
  17. package/dist/connectors/googleDrive.js +27 -0
  18. package/dist/connectors/googleDrive.js.map +1 -1
  19. package/dist/connectors/mongodb.d.ts +139 -0
  20. package/dist/connectors/mongodb.js +455 -0
  21. package/dist/connectors/mongodb.js.map +1 -0
  22. package/dist/connectors/postgres.d.ts +127 -0
  23. package/dist/connectors/postgres.js +512 -0
  24. package/dist/connectors/postgres.js.map +1 -0
  25. package/dist/connectors/redis.d.ts +140 -0
  26. package/dist/connectors/redis.js +571 -0
  27. package/dist/connectors/redis.js.map +1 -0
  28. package/dist/connectors/sendgrid.d.ts +102 -0
  29. package/dist/connectors/sendgrid.js +423 -0
  30. package/dist/connectors/sendgrid.js.map +1 -0
  31. package/dist/connectors/twilio.d.ts +118 -0
  32. package/dist/connectors/twilio.js +475 -0
  33. package/dist/connectors/twilio.js.map +1 -0
  34. package/dist/connectors/webflow.d.ts +118 -0
  35. package/dist/connectors/webflow.js +393 -0
  36. package/dist/connectors/webflow.js.map +1 -0
  37. package/dist/recipes/tools/gmail.js +27 -5
  38. package/dist/recipes/tools/gmail.js.map +1 -1
  39. package/dist/recipes/tools/googleDrive.js +64 -0
  40. package/dist/recipes/tools/googleDrive.js.map +1 -1
  41. package/package.json +1 -1
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Webflow connector — read-only access to Webflow CMS via the Webflow v2 API.
3
+ *
4
+ * Auth: Site API Token via `Authorization: Bearer <token>` + `accept-version: 2.0.0`.
5
+ * - Env var: WEBFLOW_API_TOKEN (+ optional WEBFLOW_SITE_ID)
6
+ * - Stored: getSecretJsonSync("webflow") → WebflowTokens
7
+ *
8
+ * Tools: listSites, getSite, listCollections, getCollection, listCollectionItems,
9
+ * getCollectionItem, listForms, listFormSubmissions
10
+ *
11
+ * Extends BaseConnector for unified auth, retry, rate-limit, error handling.
12
+ */
13
+ import { type AuthContext, BaseConnector, type ConnectorError, type ConnectorStatus } from "./baseConnector.js";
14
+ export interface WebflowTokens {
15
+ accessToken: string;
16
+ siteId?: string;
17
+ siteName?: string;
18
+ connected_at: string;
19
+ }
20
+ export interface WebflowSite {
21
+ id: string;
22
+ displayName?: string;
23
+ shortName?: string;
24
+ workspaceId?: string;
25
+ createdOn?: string;
26
+ lastPublished?: string;
27
+ }
28
+ export interface WebflowCollection {
29
+ id: string;
30
+ displayName?: string;
31
+ singularName?: string;
32
+ slug?: string;
33
+ createdOn?: string;
34
+ lastUpdated?: string;
35
+ }
36
+ export interface WebflowCollectionItem {
37
+ id: string;
38
+ cmsLocaleId?: string;
39
+ lastPublished?: string | null;
40
+ lastUpdated?: string;
41
+ createdOn?: string;
42
+ isArchived?: boolean;
43
+ isDraft?: boolean;
44
+ fieldData?: Record<string, unknown>;
45
+ }
46
+ export interface WebflowForm {
47
+ id: string;
48
+ displayName?: string;
49
+ createdOn?: string;
50
+ lastUpdated?: string;
51
+ fields?: Record<string, unknown>;
52
+ }
53
+ export interface WebflowFormSubmission {
54
+ id: string;
55
+ displayName?: string;
56
+ siteId?: string;
57
+ formId?: string;
58
+ dateSubmitted?: string;
59
+ formResponse?: Record<string, unknown>;
60
+ }
61
+ export interface WebflowListResult<T> {
62
+ items: T[];
63
+ pagination?: {
64
+ limit?: number;
65
+ offset?: number;
66
+ total?: number;
67
+ };
68
+ }
69
+ export declare class WebflowConnector extends BaseConnector {
70
+ readonly providerName = "webflow";
71
+ private tokens;
72
+ protected getOAuthConfig(): null;
73
+ authenticate(): Promise<AuthContext>;
74
+ healthCheck(): Promise<{
75
+ ok: boolean;
76
+ error?: ConnectorError;
77
+ }>;
78
+ normalizeError(error: unknown): ConnectorError;
79
+ getStatus(): ConnectorStatus;
80
+ listSites(): Promise<WebflowListResult<WebflowSite>>;
81
+ getSite(siteId: string): Promise<WebflowSite>;
82
+ listCollections(siteId: string): Promise<WebflowListResult<WebflowCollection>>;
83
+ getCollection(collectionId: string): Promise<WebflowCollection>;
84
+ listCollectionItems(collectionId: string, params?: {
85
+ limit?: number;
86
+ offset?: number;
87
+ }): Promise<WebflowListResult<WebflowCollectionItem>>;
88
+ getCollectionItem(collectionId: string, itemId: string): Promise<WebflowCollectionItem>;
89
+ listForms(siteId: string): Promise<WebflowListResult<WebflowForm>>;
90
+ listFormSubmissions(formId: string, params?: {
91
+ limit?: number;
92
+ offset?: number;
93
+ }): Promise<WebflowListResult<WebflowFormSubmission>>;
94
+ private buildHeaders;
95
+ }
96
+ export declare function loadTokens(): WebflowTokens | null;
97
+ export declare function saveTokens(tokens: WebflowTokens): void;
98
+ export declare function clearTokens(): void;
99
+ export declare function getWebflowConnector(): WebflowConnector;
100
+ export { getWebflowConnector as webflow };
101
+ export interface ConnectorHandlerResult {
102
+ status: number;
103
+ body: string;
104
+ contentType?: string;
105
+ }
106
+ /**
107
+ * POST /connections/webflow/connect { accessToken }
108
+ * Validates by GET /v2/sites; captures first site's id + displayName.
109
+ */
110
+ export declare function handleWebflowConnect(body: string): Promise<ConnectorHandlerResult>;
111
+ /**
112
+ * POST /connections/webflow/test
113
+ */
114
+ export declare function handleWebflowTest(): Promise<ConnectorHandlerResult>;
115
+ /**
116
+ * DELETE /connections/webflow
117
+ */
118
+ export declare function handleWebflowDisconnect(): ConnectorHandlerResult;
@@ -0,0 +1,393 @@
1
+ /**
2
+ * Webflow connector — read-only access to Webflow CMS via the Webflow v2 API.
3
+ *
4
+ * Auth: Site API Token via `Authorization: Bearer <token>` + `accept-version: 2.0.0`.
5
+ * - Env var: WEBFLOW_API_TOKEN (+ optional WEBFLOW_SITE_ID)
6
+ * - Stored: getSecretJsonSync("webflow") → WebflowTokens
7
+ *
8
+ * Tools: listSites, getSite, listCollections, getCollection, listCollectionItems,
9
+ * getCollectionItem, listForms, listFormSubmissions
10
+ *
11
+ * Extends BaseConnector for unified auth, retry, rate-limit, error handling.
12
+ */
13
+ import { BaseConnector, } from "./baseConnector.js";
14
+ import { deleteSecretJsonSync, getSecretJsonSync, storeSecretJsonSync, } from "./tokenStorage.js";
15
+ const BASE_URL = "https://api.webflow.com/v2";
16
+ const MAX_LIMIT = 100;
17
+ export class WebflowConnector extends BaseConnector {
18
+ providerName = "webflow";
19
+ tokens = null;
20
+ getOAuthConfig() {
21
+ return null;
22
+ }
23
+ async authenticate() {
24
+ const tokens = loadTokens();
25
+ if (!tokens) {
26
+ throw new Error("Webflow not connected. Run: patchwork-os connect webflow or set WEBFLOW_API_TOKEN");
27
+ }
28
+ this.tokens = tokens;
29
+ return {
30
+ token: tokens.accessToken,
31
+ scopes: ["read"],
32
+ };
33
+ }
34
+ async healthCheck() {
35
+ try {
36
+ const result = await this.apiCall(async () => {
37
+ const res = await fetch(`${BASE_URL}/token/authorized_by`, {
38
+ headers: this.buildHeaders(),
39
+ });
40
+ if (!res.ok)
41
+ throw res;
42
+ return res.json();
43
+ });
44
+ if ("error" in result)
45
+ return { ok: false, error: result.error };
46
+ return { ok: true };
47
+ }
48
+ catch (err) {
49
+ return { ok: false, error: this.normalizeError(err) };
50
+ }
51
+ }
52
+ normalizeError(error) {
53
+ if (error instanceof Response) {
54
+ const s = error.status;
55
+ if (s === 400)
56
+ return {
57
+ code: "provider_error",
58
+ message: `Webflow API bad request (HTTP 400)`,
59
+ retryable: false,
60
+ };
61
+ if (s === 401)
62
+ return {
63
+ code: "auth_expired",
64
+ message: "Webflow authentication expired — reconnect",
65
+ retryable: false,
66
+ suggestedAction: "patchwork-os connect webflow",
67
+ };
68
+ if (s === 403)
69
+ return {
70
+ code: "permission_denied",
71
+ message: "Insufficient Webflow permissions",
72
+ retryable: false,
73
+ };
74
+ if (s === 404)
75
+ return {
76
+ code: "not_found",
77
+ message: "Webflow resource not found",
78
+ retryable: false,
79
+ };
80
+ if (s === 429)
81
+ return {
82
+ code: "rate_limited",
83
+ message: "Webflow API rate limit exceeded",
84
+ retryable: true,
85
+ suggestedAction: "Wait and retry",
86
+ };
87
+ return {
88
+ code: "provider_error",
89
+ message: `Webflow API error: HTTP ${s}`,
90
+ retryable: s >= 500,
91
+ };
92
+ }
93
+ if (error instanceof Error) {
94
+ if (error.message.includes("ENOTFOUND") ||
95
+ error.message.includes("ECONNREFUSED")) {
96
+ return {
97
+ code: "network_error",
98
+ message: `Cannot connect to Webflow: ${error.message}`,
99
+ retryable: true,
100
+ };
101
+ }
102
+ }
103
+ return {
104
+ code: "provider_error",
105
+ message: error instanceof Error ? error.message : String(error),
106
+ retryable: false,
107
+ };
108
+ }
109
+ getStatus() {
110
+ const tokens = loadTokens();
111
+ return {
112
+ id: "webflow",
113
+ status: tokens ? "connected" : "disconnected",
114
+ lastSync: tokens?.connected_at,
115
+ workspace: tokens?.siteName
116
+ ? `Webflow site ${tokens.siteName}`
117
+ : tokens?.siteId
118
+ ? `Webflow site ${tokens.siteId}`
119
+ : undefined,
120
+ };
121
+ }
122
+ // ── API Methods ────────────────────────────────────────────────────────────
123
+ async listSites() {
124
+ const result = await this.apiCall(async () => {
125
+ const res = await fetch(`${BASE_URL}/sites`, {
126
+ headers: this.buildHeaders(),
127
+ });
128
+ if (!res.ok)
129
+ throw res;
130
+ return res.json();
131
+ });
132
+ if ("error" in result)
133
+ throw new Error(result.error.message);
134
+ const data = result.data;
135
+ return { items: data.sites ?? [] };
136
+ }
137
+ async getSite(siteId) {
138
+ const result = await this.apiCall(async () => {
139
+ const res = await fetch(`${BASE_URL}/sites/${encodeURIComponent(siteId)}`, { headers: this.buildHeaders() });
140
+ if (!res.ok)
141
+ throw res;
142
+ return res.json();
143
+ });
144
+ if ("error" in result)
145
+ throw new Error(result.error.message);
146
+ return result.data;
147
+ }
148
+ async listCollections(siteId) {
149
+ const result = await this.apiCall(async () => {
150
+ const res = await fetch(`${BASE_URL}/sites/${encodeURIComponent(siteId)}/collections`, { headers: this.buildHeaders() });
151
+ if (!res.ok)
152
+ throw res;
153
+ return res.json();
154
+ });
155
+ if ("error" in result)
156
+ throw new Error(result.error.message);
157
+ const data = result.data;
158
+ return { items: data.collections ?? [] };
159
+ }
160
+ async getCollection(collectionId) {
161
+ const result = await this.apiCall(async () => {
162
+ const res = await fetch(`${BASE_URL}/collections/${encodeURIComponent(collectionId)}`, { headers: this.buildHeaders() });
163
+ if (!res.ok)
164
+ throw res;
165
+ return res.json();
166
+ });
167
+ if ("error" in result)
168
+ throw new Error(result.error.message);
169
+ return result.data;
170
+ }
171
+ async listCollectionItems(collectionId, params = {}) {
172
+ const limit = Math.min(params.limit ?? MAX_LIMIT, MAX_LIMIT);
173
+ const offset = params.offset ?? 0;
174
+ const result = await this.apiCall(async () => {
175
+ const qs = new URLSearchParams();
176
+ qs.set("limit", String(limit));
177
+ qs.set("offset", String(offset));
178
+ const res = await fetch(`${BASE_URL}/collections/${encodeURIComponent(collectionId)}/items?${qs}`, { headers: this.buildHeaders() });
179
+ if (!res.ok)
180
+ throw res;
181
+ return res.json();
182
+ });
183
+ if ("error" in result)
184
+ throw new Error(result.error.message);
185
+ const data = result.data;
186
+ return { items: data.items ?? [], pagination: data.pagination };
187
+ }
188
+ async getCollectionItem(collectionId, itemId) {
189
+ const result = await this.apiCall(async () => {
190
+ const res = await fetch(`${BASE_URL}/collections/${encodeURIComponent(collectionId)}/items/${encodeURIComponent(itemId)}`, { headers: this.buildHeaders() });
191
+ if (!res.ok)
192
+ throw res;
193
+ return res.json();
194
+ });
195
+ if ("error" in result)
196
+ throw new Error(result.error.message);
197
+ return result.data;
198
+ }
199
+ async listForms(siteId) {
200
+ const result = await this.apiCall(async () => {
201
+ const res = await fetch(`${BASE_URL}/sites/${encodeURIComponent(siteId)}/forms`, { headers: this.buildHeaders() });
202
+ if (!res.ok)
203
+ throw res;
204
+ return res.json();
205
+ });
206
+ if ("error" in result)
207
+ throw new Error(result.error.message);
208
+ const data = result.data;
209
+ return { items: data.forms ?? [] };
210
+ }
211
+ async listFormSubmissions(formId, params = {}) {
212
+ const limit = Math.min(params.limit ?? MAX_LIMIT, MAX_LIMIT);
213
+ const offset = params.offset ?? 0;
214
+ const result = await this.apiCall(async () => {
215
+ const qs = new URLSearchParams();
216
+ qs.set("limit", String(limit));
217
+ qs.set("offset", String(offset));
218
+ const res = await fetch(`${BASE_URL}/forms/${encodeURIComponent(formId)}/submissions?${qs}`, { headers: this.buildHeaders() });
219
+ if (!res.ok)
220
+ throw res;
221
+ return res.json();
222
+ });
223
+ if ("error" in result)
224
+ throw new Error(result.error.message);
225
+ const data = result.data;
226
+ return { items: data.formSubmissions ?? [], pagination: data.pagination };
227
+ }
228
+ // ── Helpers ────────────────────────────────────────────────────────────────
229
+ buildHeaders() {
230
+ const token = this.tokens?.accessToken ?? "";
231
+ return {
232
+ Authorization: `Bearer ${token}`,
233
+ Accept: "application/json",
234
+ "accept-version": "2.0.0",
235
+ };
236
+ }
237
+ }
238
+ // ── Token persistence ────────────────────────────────────────────────────────
239
+ export function loadTokens() {
240
+ const envToken = process.env.WEBFLOW_API_TOKEN;
241
+ if (envToken) {
242
+ return {
243
+ accessToken: envToken,
244
+ siteId: process.env.WEBFLOW_SITE_ID,
245
+ connected_at: new Date().toISOString(),
246
+ };
247
+ }
248
+ return getSecretJsonSync("webflow");
249
+ }
250
+ export function saveTokens(tokens) {
251
+ storeSecretJsonSync("webflow", tokens);
252
+ }
253
+ export function clearTokens() {
254
+ try {
255
+ deleteSecretJsonSync("webflow");
256
+ }
257
+ catch {
258
+ // ignore
259
+ }
260
+ }
261
+ // ── Singleton instance ───────────────────────────────────────────────────────
262
+ let _instance = null;
263
+ function resetWebflowConnector() {
264
+ _instance = null;
265
+ }
266
+ export function getWebflowConnector() {
267
+ if (!_instance) {
268
+ _instance = new WebflowConnector();
269
+ }
270
+ return _instance;
271
+ }
272
+ export { getWebflowConnector as webflow };
273
+ /**
274
+ * POST /connections/webflow/connect { accessToken }
275
+ * Validates by GET /v2/sites; captures first site's id + displayName.
276
+ */
277
+ export async function handleWebflowConnect(body) {
278
+ let accessToken;
279
+ try {
280
+ const parsed = JSON.parse(body);
281
+ if (typeof parsed.accessToken !== "string" || !parsed.accessToken) {
282
+ return {
283
+ status: 400,
284
+ contentType: "application/json",
285
+ body: JSON.stringify({ ok: false, error: "accessToken is required" }),
286
+ };
287
+ }
288
+ accessToken = parsed.accessToken;
289
+ }
290
+ catch {
291
+ return {
292
+ status: 400,
293
+ contentType: "application/json",
294
+ body: JSON.stringify({ ok: false, error: "Invalid JSON body" }),
295
+ };
296
+ }
297
+ try {
298
+ const res = await fetch(`${BASE_URL}/sites`, {
299
+ headers: {
300
+ Authorization: `Bearer ${accessToken}`,
301
+ Accept: "application/json",
302
+ "accept-version": "2.0.0",
303
+ },
304
+ });
305
+ if (!res.ok) {
306
+ return {
307
+ status: 401,
308
+ contentType: "application/json",
309
+ body: JSON.stringify({
310
+ ok: false,
311
+ error: `Credentials rejected by Webflow (HTTP ${res.status}) — check accessToken`,
312
+ }),
313
+ };
314
+ }
315
+ const data = (await res.json());
316
+ const firstSite = data.sites?.[0];
317
+ const siteId = firstSite?.id;
318
+ const siteName = firstSite?.displayName;
319
+ const tokens = {
320
+ accessToken,
321
+ siteId,
322
+ siteName,
323
+ connected_at: new Date().toISOString(),
324
+ };
325
+ saveTokens(tokens);
326
+ resetWebflowConnector();
327
+ return {
328
+ status: 200,
329
+ contentType: "application/json",
330
+ body: JSON.stringify({
331
+ ok: true,
332
+ siteId,
333
+ siteName,
334
+ connectedAt: tokens.connected_at,
335
+ }),
336
+ };
337
+ }
338
+ catch (err) {
339
+ return {
340
+ status: 500,
341
+ contentType: "application/json",
342
+ body: JSON.stringify({
343
+ ok: false,
344
+ error: err instanceof Error ? err.message : String(err),
345
+ }),
346
+ };
347
+ }
348
+ }
349
+ /**
350
+ * POST /connections/webflow/test
351
+ */
352
+ export async function handleWebflowTest() {
353
+ const tokens = loadTokens();
354
+ if (!tokens) {
355
+ return {
356
+ status: 400,
357
+ contentType: "application/json",
358
+ body: JSON.stringify({ ok: false, error: "Webflow not connected" }),
359
+ };
360
+ }
361
+ try {
362
+ const connector = getWebflowConnector();
363
+ const check = await connector.healthCheck();
364
+ return {
365
+ status: check.ok ? 200 : 401,
366
+ contentType: "application/json",
367
+ body: JSON.stringify(check.ok ? { ok: true } : { ok: false, error: check.error?.message }),
368
+ };
369
+ }
370
+ catch (err) {
371
+ return {
372
+ status: 500,
373
+ contentType: "application/json",
374
+ body: JSON.stringify({
375
+ ok: false,
376
+ error: err instanceof Error ? err.message : String(err),
377
+ }),
378
+ };
379
+ }
380
+ }
381
+ /**
382
+ * DELETE /connections/webflow
383
+ */
384
+ export function handleWebflowDisconnect() {
385
+ clearTokens();
386
+ resetWebflowConnector();
387
+ return {
388
+ status: 200,
389
+ contentType: "application/json",
390
+ body: JSON.stringify({ ok: true }),
391
+ };
392
+ }
393
+ //# sourceMappingURL=webflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webflow.js","sourceRoot":"","sources":["../../src/connectors/webflow.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,13 @@ async function gmailSearch(query, max, deps) {
47
47
  const ids = listJson.messages ?? [];
48
48
  // 2. Fetch details for each message
49
49
  const messages = await Promise.all(ids.slice(0, max).map(async (m) => {
50
- const detailUrl = `https://www.googleapis.com/gmail/v1/users/me/messages/${m.id}?format=metadata&metadataHeaders=Subject,From,Date`;
50
+ // Gmail's metadataHeaders param must be REPEATED per header, not
51
+ // comma-joined. `metadataHeaders=Subject,From,Date` is silently
52
+ // dropped server-side — the response then carries an empty
53
+ // headers array and every {subject,from,date} field returns "",
54
+ // which made downstream tools that branch on the subject (e.g.
55
+ // resolveMeetingNotes) silently no-op against real emails.
56
+ const detailUrl = `https://www.googleapis.com/gmail/v1/users/me/messages/${m.id}?format=metadata&metadataHeaders=Subject&metadataHeaders=From&metadataHeaders=Date`;
51
57
  const detailRes = await fetch(detailUrl, {
52
58
  headers: { Authorization: `Bearer ${token}` },
53
59
  });
@@ -365,7 +371,14 @@ registerTool({
365
371
  const results = [];
366
372
  for (const msg of messages) {
367
373
  const subject = msg.subject ?? "";
368
- const isGemini = /notes by gemini|document shared with you|shared a document|invited you to (?:edit|view|comment)/i.test(subject) ||
374
+ // Gemini's notification email format changed at least once. Earlier
375
+ // emails said "Notes by Gemini" in the subject; the current format
376
+ // (as of 2026) is `Notes: "<meeting title>" <date>` from
377
+ // gemini-notes@google.com — no "by Gemini" anywhere. Match both, plus
378
+ // the generic Drive-share variants Drive uses when the Doc is shared
379
+ // separately. Also accept any subject that already references a
380
+ // docs.google.com URL via the snippet.
381
+ const isGemini = /notes by gemini|^notes:\s|document shared with you|shared a document|invited you to (?:edit|view|comment)/i.test(subject) ||
369
382
  /notes by gemini|docs\.google\.com\/document/i.test(msg.snippet ?? "");
370
383
  if (!isGemini) {
371
384
  // Direct Meet summary — use snippet as content
@@ -377,16 +390,21 @@ registerTool({
377
390
  });
378
391
  continue;
379
392
  }
380
- // Gemini notes — fetch full message to get Drive URL
393
+ // Gemini notes — fetch full message and look for either a Doc URL OR
394
+ // an inlined-body. Newer Gemini emails (2026+) inline the full notes
395
+ // directly in the email body and DON'T include a docs.google.com URL.
396
+ // Older Gemini / Meet emails just link to a Drive doc.
381
397
  let driveUrl = "";
398
+ let emailBody = "";
382
399
  try {
383
400
  const fullMsg = await gmailGetMessage(msg.id, deps);
384
401
  const parsed = JSON.parse(fullMsg);
402
+ emailBody = parsed.body ?? "";
385
403
  const links = parsed.links ?? [];
386
404
  driveUrl = links.find(isDocsGoogleHost) ?? "";
387
405
  if (!driveUrl) {
388
406
  // Try extracting from body text
389
- const bodyMatch = /https?:\/\/docs\.google\.com\/[^\s"'<>]+/.exec(parsed.body ?? "");
407
+ const bodyMatch = /https?:\/\/docs\.google\.com\/[^\s"'<>]+/.exec(emailBody);
390
408
  driveUrl = bodyMatch?.[0] ?? "";
391
409
  }
392
410
  }
@@ -400,11 +418,15 @@ registerTool({
400
418
  continue;
401
419
  }
402
420
  if (!driveUrl) {
421
+ // No linked Doc — use the email body itself as the meeting content.
422
+ // Gemini's inlined-notes format is what the parser already expects:
423
+ // a "Summary" section, topical sections, etc. Fall back to snippet
424
+ // only when even the body is empty (rare).
403
425
  results.push({
404
426
  emailId: msg.id,
405
427
  subject,
406
428
  source: "email",
407
- content: msg.snippet ?? "",
429
+ content: emailBody.length > 0 ? emailBody : (msg.snippet ?? ""),
408
430
  });
409
431
  continue;
410
432
  }