@squadbase/vite-server 0.1.3-dev.0 → 0.1.3-dev.10

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 (70) hide show
  1. package/dist/cli/index.js +82859 -9645
  2. package/dist/connectors/airtable-oauth.js +77 -3
  3. package/dist/connectors/airtable.js +85 -2
  4. package/dist/connectors/amplitude.js +85 -2
  5. package/dist/connectors/anthropic.js +85 -2
  6. package/dist/connectors/{slack.d.ts → asana.d.ts} +1 -1
  7. package/dist/connectors/asana.js +744 -0
  8. package/dist/connectors/attio.js +85 -2
  9. package/dist/connectors/{microsoft-teams-oauth.d.ts → customerio.d.ts} +1 -1
  10. package/dist/connectors/customerio.js +716 -0
  11. package/dist/connectors/dbt.js +85 -2
  12. package/dist/connectors/gemini.js +86 -3
  13. package/dist/connectors/{microsoft-teams.d.ts → gmail-oauth.d.ts} +1 -1
  14. package/dist/connectors/gmail-oauth.js +713 -0
  15. package/dist/connectors/gmail.d.ts +5 -0
  16. package/dist/connectors/gmail.js +875 -0
  17. package/dist/connectors/google-ads-oauth.js +78 -4
  18. package/dist/connectors/google-ads.d.ts +5 -0
  19. package/dist/connectors/google-ads.js +867 -0
  20. package/dist/connectors/google-analytics-oauth.js +90 -8
  21. package/dist/connectors/google-analytics.js +85 -2
  22. package/dist/connectors/google-calendar-oauth.d.ts +5 -0
  23. package/dist/connectors/google-calendar-oauth.js +817 -0
  24. package/dist/connectors/google-calendar.d.ts +5 -0
  25. package/dist/connectors/google-calendar.js +991 -0
  26. package/dist/connectors/google-sheets-oauth.js +144 -33
  27. package/dist/connectors/google-sheets.d.ts +5 -0
  28. package/dist/connectors/google-sheets.js +707 -0
  29. package/dist/connectors/grafana.d.ts +5 -0
  30. package/dist/connectors/grafana.js +638 -0
  31. package/dist/connectors/hubspot-oauth.js +77 -3
  32. package/dist/connectors/hubspot.js +89 -6
  33. package/dist/connectors/intercom-oauth.d.ts +5 -0
  34. package/dist/connectors/intercom-oauth.js +584 -0
  35. package/dist/connectors/intercom.d.ts +5 -0
  36. package/dist/connectors/intercom.js +710 -0
  37. package/dist/connectors/jira-api-key.d.ts +5 -0
  38. package/dist/connectors/jira-api-key.js +598 -0
  39. package/dist/connectors/kintone-api-token.js +77 -3
  40. package/dist/connectors/kintone.js +86 -3
  41. package/dist/connectors/linkedin-ads-oauth.d.ts +5 -0
  42. package/dist/connectors/linkedin-ads-oauth.js +848 -0
  43. package/dist/connectors/linkedin-ads.d.ts +5 -0
  44. package/dist/connectors/linkedin-ads.js +865 -0
  45. package/dist/connectors/mailchimp-oauth.d.ts +5 -0
  46. package/dist/connectors/mailchimp-oauth.js +613 -0
  47. package/dist/connectors/mailchimp.d.ts +5 -0
  48. package/dist/connectors/mailchimp.js +729 -0
  49. package/dist/connectors/notion-oauth.d.ts +5 -0
  50. package/dist/connectors/notion-oauth.js +567 -0
  51. package/dist/connectors/notion.d.ts +5 -0
  52. package/dist/connectors/notion.js +663 -0
  53. package/dist/connectors/openai.js +85 -2
  54. package/dist/connectors/shopify-oauth.js +77 -3
  55. package/dist/connectors/shopify.js +85 -2
  56. package/dist/connectors/stripe-api-key.d.ts +5 -0
  57. package/dist/connectors/stripe-api-key.js +600 -0
  58. package/dist/connectors/stripe-oauth.js +77 -3
  59. package/dist/connectors/wix-store.js +85 -2
  60. package/dist/connectors/zendesk-oauth.d.ts +5 -0
  61. package/dist/connectors/zendesk-oauth.js +579 -0
  62. package/dist/connectors/zendesk.d.ts +5 -0
  63. package/dist/connectors/zendesk.js +714 -0
  64. package/dist/index.js +83024 -7099
  65. package/dist/main.js +82988 -7063
  66. package/dist/vite-plugin.js +82862 -6974
  67. package/package.json +86 -2
  68. package/dist/connectors/microsoft-teams-oauth.js +0 -479
  69. package/dist/connectors/microsoft-teams.js +0 -381
  70. package/dist/connectors/slack.js +0 -362
@@ -0,0 +1,713 @@
1
+ // ../connectors/src/connectors/gmail-oauth/sdk/index.ts
2
+ var BASE_URL = "https://gmail.googleapis.com/gmail/v1/users";
3
+ function createClient(_params, fetchFn = fetch) {
4
+ function request(path2, init) {
5
+ const url = `${BASE_URL}${path2.startsWith("/") ? "" : "/"}${path2}`;
6
+ return fetchFn(url, init);
7
+ }
8
+ async function getProfile() {
9
+ const response = await request("/me/profile");
10
+ if (!response.ok) {
11
+ const body = await response.text();
12
+ throw new Error(
13
+ `gmail: getProfile failed (${response.status}): ${body}`
14
+ );
15
+ }
16
+ return await response.json();
17
+ }
18
+ async function listLabels() {
19
+ const response = await request("/me/labels");
20
+ if (!response.ok) {
21
+ const body = await response.text();
22
+ throw new Error(
23
+ `gmail: listLabels failed (${response.status}): ${body}`
24
+ );
25
+ }
26
+ return await response.json();
27
+ }
28
+ async function listMessages(options) {
29
+ const params = new URLSearchParams();
30
+ if (options?.q) params.set("q", options.q);
31
+ if (options?.maxResults) params.set("maxResults", String(options.maxResults));
32
+ if (options?.pageToken) params.set("pageToken", options.pageToken);
33
+ if (options?.labelIds) {
34
+ for (const labelId of options.labelIds) {
35
+ params.append("labelIds", labelId);
36
+ }
37
+ }
38
+ const qs = params.toString();
39
+ const response = await request(`/me/messages${qs ? `?${qs}` : ""}`);
40
+ if (!response.ok) {
41
+ const body = await response.text();
42
+ throw new Error(
43
+ `gmail: listMessages failed (${response.status}): ${body}`
44
+ );
45
+ }
46
+ return await response.json();
47
+ }
48
+ async function getMessage(messageId, format) {
49
+ const params = new URLSearchParams();
50
+ if (format) params.set("format", format);
51
+ const qs = params.toString();
52
+ const response = await request(
53
+ `/me/messages/${encodeURIComponent(messageId)}${qs ? `?${qs}` : ""}`
54
+ );
55
+ if (!response.ok) {
56
+ const body = await response.text();
57
+ throw new Error(
58
+ `gmail: getMessage failed (${response.status}): ${body}`
59
+ );
60
+ }
61
+ return await response.json();
62
+ }
63
+ async function listThreads(options) {
64
+ const params = new URLSearchParams();
65
+ if (options?.q) params.set("q", options.q);
66
+ if (options?.maxResults) params.set("maxResults", String(options.maxResults));
67
+ if (options?.pageToken) params.set("pageToken", options.pageToken);
68
+ if (options?.labelIds) {
69
+ for (const labelId of options.labelIds) {
70
+ params.append("labelIds", labelId);
71
+ }
72
+ }
73
+ const qs = params.toString();
74
+ const response = await request(`/me/threads${qs ? `?${qs}` : ""}`);
75
+ if (!response.ok) {
76
+ const body = await response.text();
77
+ throw new Error(
78
+ `gmail: listThreads failed (${response.status}): ${body}`
79
+ );
80
+ }
81
+ return await response.json();
82
+ }
83
+ async function getThread(threadId, format) {
84
+ const params = new URLSearchParams();
85
+ if (format) params.set("format", format);
86
+ const qs = params.toString();
87
+ const response = await request(
88
+ `/me/threads/${encodeURIComponent(threadId)}${qs ? `?${qs}` : ""}`
89
+ );
90
+ if (!response.ok) {
91
+ const body = await response.text();
92
+ throw new Error(
93
+ `gmail: getThread failed (${response.status}): ${body}`
94
+ );
95
+ }
96
+ return await response.json();
97
+ }
98
+ return {
99
+ request,
100
+ getProfile,
101
+ listLabels,
102
+ listMessages,
103
+ getMessage,
104
+ listThreads,
105
+ getThread
106
+ };
107
+ }
108
+
109
+ // ../connectors/src/connector-onboarding.ts
110
+ var ConnectorOnboarding = class {
111
+ /** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
112
+ connectionSetupInstructions;
113
+ /** Phase 2: Data overview instructions */
114
+ dataOverviewInstructions;
115
+ constructor(config) {
116
+ this.connectionSetupInstructions = config.connectionSetupInstructions;
117
+ this.dataOverviewInstructions = config.dataOverviewInstructions;
118
+ }
119
+ getConnectionSetupPrompt(language) {
120
+ return this.connectionSetupInstructions?.[language] ?? null;
121
+ }
122
+ getDataOverviewInstructions(language) {
123
+ return this.dataOverviewInstructions[language];
124
+ }
125
+ };
126
+
127
+ // ../connectors/src/connector-tool.ts
128
+ var ConnectorTool = class {
129
+ name;
130
+ description;
131
+ inputSchema;
132
+ outputSchema;
133
+ _execute;
134
+ constructor(config) {
135
+ this.name = config.name;
136
+ this.description = config.description;
137
+ this.inputSchema = config.inputSchema;
138
+ this.outputSchema = config.outputSchema;
139
+ this._execute = config.execute;
140
+ }
141
+ createTool(connections, config) {
142
+ return {
143
+ description: this.description,
144
+ inputSchema: this.inputSchema,
145
+ outputSchema: this.outputSchema,
146
+ execute: (input) => this._execute(input, connections, config)
147
+ };
148
+ }
149
+ };
150
+
151
+ // ../connectors/src/connector-plugin.ts
152
+ var ConnectorPlugin = class _ConnectorPlugin {
153
+ slug;
154
+ authType;
155
+ name;
156
+ description;
157
+ iconUrl;
158
+ parameters;
159
+ releaseFlag;
160
+ proxyPolicy;
161
+ experimentalAttributes;
162
+ onboarding;
163
+ systemPrompt;
164
+ tools;
165
+ query;
166
+ checkConnection;
167
+ constructor(config) {
168
+ this.slug = config.slug;
169
+ this.authType = config.authType;
170
+ this.name = config.name;
171
+ this.description = config.description;
172
+ this.iconUrl = config.iconUrl;
173
+ this.parameters = config.parameters;
174
+ this.releaseFlag = config.releaseFlag;
175
+ this.proxyPolicy = config.proxyPolicy;
176
+ this.experimentalAttributes = config.experimentalAttributes;
177
+ this.onboarding = config.onboarding;
178
+ this.systemPrompt = config.systemPrompt;
179
+ this.tools = config.tools;
180
+ this.query = config.query;
181
+ this.checkConnection = config.checkConnection;
182
+ }
183
+ get connectorKey() {
184
+ return _ConnectorPlugin.deriveKey(this.slug, this.authType);
185
+ }
186
+ /**
187
+ * Create tools for connections that belong to this connector.
188
+ * Filters connections by connectorKey internally.
189
+ * Returns tools keyed as `${connectorKey}_${toolName}`.
190
+ */
191
+ createTools(connections, config) {
192
+ const myConnections = connections.filter(
193
+ (c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
194
+ );
195
+ const result = {};
196
+ for (const t of Object.values(this.tools)) {
197
+ result[`${this.connectorKey}_${t.name}`] = t.createTool(
198
+ myConnections,
199
+ config
200
+ );
201
+ }
202
+ return result;
203
+ }
204
+ static deriveKey(slug, authType) {
205
+ return authType ? `${slug}-${authType}` : slug;
206
+ }
207
+ };
208
+
209
+ // ../connectors/src/auth-types.ts
210
+ var AUTH_TYPES = {
211
+ OAUTH: "oauth",
212
+ API_KEY: "api-key",
213
+ JWT: "jwt",
214
+ SERVICE_ACCOUNT: "service-account",
215
+ PAT: "pat",
216
+ USER_PASSWORD: "user-password"
217
+ };
218
+
219
+ // ../connectors/src/connectors/gmail-oauth/tools/request.ts
220
+ import { z } from "zod";
221
+ var BASE_URL2 = "https://gmail.googleapis.com/gmail/v1/users";
222
+ var REQUEST_TIMEOUT_MS = 6e4;
223
+ var cachedToken = null;
224
+ async function getProxyToken(config) {
225
+ if (cachedToken && cachedToken.expiresAt > Date.now() + 6e4) {
226
+ return cachedToken.token;
227
+ }
228
+ const url = `${config.appApiBaseUrl}/v0/database/${config.projectId}/environment/${config.environmentId}/oauth-request-proxy-token`;
229
+ const res = await fetch(url, {
230
+ method: "POST",
231
+ headers: {
232
+ "Content-Type": "application/json",
233
+ "x-api-key": config.appApiKey,
234
+ "project-id": config.projectId
235
+ },
236
+ body: JSON.stringify({
237
+ sandboxId: config.sandboxId,
238
+ issuedBy: "coding-agent"
239
+ })
240
+ });
241
+ if (!res.ok) {
242
+ const errorText = await res.text().catch(() => res.statusText);
243
+ throw new Error(
244
+ `Failed to get proxy token: HTTP ${res.status} ${errorText}`
245
+ );
246
+ }
247
+ const data = await res.json();
248
+ cachedToken = {
249
+ token: data.token,
250
+ expiresAt: new Date(data.expiresAt).getTime()
251
+ };
252
+ return data.token;
253
+ }
254
+ var inputSchema = z.object({
255
+ toolUseIntent: z.string().optional().describe(
256
+ "Brief description of what you intend to accomplish with this tool call"
257
+ ),
258
+ connectionId: z.string().describe("ID of the Gmail OAuth connection to use"),
259
+ method: z.enum(["GET"]).describe("HTTP method (read-only, GET only)"),
260
+ path: z.string().describe(
261
+ "API path appended to https://gmail.googleapis.com/gmail/v1/users (e.g., '/me/messages', '/me/messages/{id}', '/me/labels'). Use '/me' as the userId."
262
+ ),
263
+ queryParams: z.record(z.string(), z.string()).optional().describe(
264
+ "Query parameters to append to the URL (e.g., { q: 'from:example@gmail.com', maxResults: '10' })"
265
+ )
266
+ });
267
+ var outputSchema = z.discriminatedUnion("success", [
268
+ z.object({
269
+ success: z.literal(true),
270
+ status: z.number(),
271
+ data: z.record(z.string(), z.unknown())
272
+ }),
273
+ z.object({
274
+ success: z.literal(false),
275
+ error: z.string()
276
+ })
277
+ ]);
278
+ var requestTool = new ConnectorTool({
279
+ name: "request",
280
+ description: `Send authenticated GET requests to the Gmail API v1.
281
+ Authentication is handled automatically via OAuth proxy.
282
+ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me' as the userId prefix (e.g., '/me/messages').`,
283
+ inputSchema,
284
+ outputSchema,
285
+ async execute({ connectionId, method, path: path2, queryParams }, connections, config) {
286
+ const connection2 = connections.find((c) => c.id === connectionId);
287
+ if (!connection2) {
288
+ return {
289
+ success: false,
290
+ error: `Connection ${connectionId} not found`
291
+ };
292
+ }
293
+ console.log(
294
+ `[connector-request] gmail-oauth/${connection2.name}: ${method} ${path2}`
295
+ );
296
+ try {
297
+ let url = `${BASE_URL2}${path2.startsWith("/") ? "" : "/"}${path2}`;
298
+ if (queryParams) {
299
+ const searchParams = new URLSearchParams(queryParams);
300
+ url += `?${searchParams.toString()}`;
301
+ }
302
+ const token = await getProxyToken(config.oauthProxy);
303
+ const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
304
+ const controller = new AbortController();
305
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
306
+ try {
307
+ const response = await fetch(proxyUrl, {
308
+ method: "POST",
309
+ headers: {
310
+ "Content-Type": "application/json",
311
+ Authorization: `Bearer ${token}`
312
+ },
313
+ body: JSON.stringify({
314
+ url,
315
+ method
316
+ }),
317
+ signal: controller.signal
318
+ });
319
+ const data = await response.json();
320
+ if (!response.ok) {
321
+ const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
322
+ return { success: false, error: errorMessage };
323
+ }
324
+ return { success: true, status: response.status, data };
325
+ } finally {
326
+ clearTimeout(timeout);
327
+ }
328
+ } catch (err) {
329
+ const msg = err instanceof Error ? err.message : String(err);
330
+ return { success: false, error: msg };
331
+ }
332
+ }
333
+ });
334
+
335
+ // ../connectors/src/connectors/gmail-oauth/setup.ts
336
+ var requestToolName = `gmail-oauth_${requestTool.name}`;
337
+ var gmailOnboarding = new ConnectorOnboarding({
338
+ connectionSetupInstructions: {
339
+ ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Gmail\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
340
+
341
+ 1. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\u3059\u308B:
342
+ - \`method\`: \`"GET"\`
343
+ - \`path\`: \`"/me/profile"\`
344
+ 2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001OAuth\u306E\u8A8D\u8A3C\u304C\u6B63\u3057\u304F\u5B8C\u4E86\u3057\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3059\u308B\u3088\u3046\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u308B
345
+ 3. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
346
+ - \`method\`: \`"GET"\`
347
+ - \`path\`: \`"/me/labels"\`
348
+ 4. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
349
+ - \`email\`: \u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
350
+ - \`labels\`: \u4E3B\u8981\u306A\u30E9\u30D9\u30EB\u540D\u4E00\u89A7\uFF08\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3001INBOX, SENT, DRAFT, SPAM, TRASH\u7B49\u306E\u30B7\u30B9\u30C6\u30E0\u30E9\u30D9\u30EB\u3092\u542B\u3080\uFF09
351
+ - \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
352
+
353
+ #### \u5236\u7D04
354
+ - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u672C\u6587\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u53D6\u5F97\u3068\u30E9\u30D9\u30EB\u4E00\u89A7\u53D6\u5F97\u306E\u307F
355
+ - \u30C4\u30FC\u30EB\u9593\u306F1\u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u3002\u4E0D\u8981\u306A\u8AAC\u660E\u306F\u7701\u7565\u3057\u3001\u52B9\u7387\u7684\u306B\u9032\u3081\u308B`,
356
+ en: `Follow these steps to set up the Gmail connection.
357
+
358
+ 1. Call \`${requestToolName}\` to get the user's profile:
359
+ - \`method\`: \`"GET"\`
360
+ - \`path\`: \`"/me/profile"\`
361
+ 2. If an error is returned, ask the user to verify that OAuth authentication completed correctly
362
+ 3. Call \`${requestToolName}\` to get the label list:
363
+ - \`method\`: \`"GET"\`
364
+ - \`path\`: \`"/me/labels"\`
365
+ 4. Call \`updateConnectionContext\`:
366
+ - \`email\`: The user's email address
367
+ - \`labels\`: Key label names (comma-separated, including system labels like INBOX, SENT, DRAFT, SPAM, TRASH)
368
+ - \`note\`: Brief description of the setup
369
+
370
+ #### Constraints
371
+ - **Do NOT read message bodies during setup**. Only the profile and label list requests specified above are allowed
372
+ - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
373
+ },
374
+ dataOverviewInstructions: {
375
+ en: `1. Call gmail-oauth_request with GET /me/labels to list all labels
376
+ 2. Call gmail-oauth_request with GET /me/messages?maxResults=5 to get recent message IDs
377
+ 3. Call gmail-oauth_request with GET /me/messages/{id}?format=metadata for each message to see subjects and senders`,
378
+ ja: `1. gmail-oauth_request \u3067 GET /me/labels \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
379
+ 2. gmail-oauth_request \u3067 GET /me/messages?maxResults=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8ID\u3092\u53D6\u5F97
380
+ 3. \u5404\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 gmail-oauth_request \u3067 GET /me/messages/{id}?format=metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u4EF6\u540D\u3068\u9001\u4FE1\u8005\u3092\u78BA\u8A8D`
381
+ }
382
+ });
383
+
384
+ // ../connectors/src/connectors/gmail-oauth/parameters.ts
385
+ var parameters = {};
386
+
387
+ // ../connectors/src/connectors/gmail-oauth/index.ts
388
+ var tools = { request: requestTool };
389
+ var gmailOauthConnector = new ConnectorPlugin({
390
+ slug: "gmail",
391
+ authType: AUTH_TYPES.OAUTH,
392
+ name: "Gmail",
393
+ description: "Connect to Gmail for email data access using OAuth. Read-only access to messages, threads, and labels.",
394
+ iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4V3rfaSc1ksFIt2eHBNIwJ/7f3be41a154a6d96dcf229ed0e5858c9/Gmail_icon__2020_.svg.png",
395
+ parameters,
396
+ releaseFlag: { dev1: true, dev2: false, prod: false },
397
+ onboarding: gmailOnboarding,
398
+ proxyPolicy: {
399
+ allowlist: [
400
+ {
401
+ host: "gmail.googleapis.com",
402
+ methods: ["GET"]
403
+ }
404
+ ]
405
+ },
406
+ systemPrompt: {
407
+ en: `### Tools
408
+
409
+ - \`gmail-oauth_request\`: The only way to call the Gmail API (read-only). Use it to list messages, get message details, list labels, list threads, and get user profile. Authentication is configured automatically via OAuth.
410
+
411
+ ### Gmail API Reference
412
+
413
+ #### Available Endpoints
414
+ - GET \`/me/profile\` \u2014 Get the authenticated user's profile (email address, total messages/threads)
415
+ - GET \`/me/labels\` \u2014 List all labels in the mailbox
416
+ - GET \`/me/labels/{id}\` \u2014 Get details for a specific label
417
+ - GET \`/me/messages\` \u2014 List messages (returns IDs only; use format param on individual messages)
418
+ - GET \`/me/messages/{id}\` \u2014 Get a specific message
419
+ - GET \`/me/threads\` \u2014 List threads
420
+ - GET \`/me/threads/{id}\` \u2014 Get a specific thread with all its messages
421
+
422
+ #### Key Query Parameters
423
+ - \`q\` \u2014 Gmail search query (same syntax as Gmail search box). Examples:
424
+ - \`from:user@example.com\` \u2014 Messages from a specific sender
425
+ - \`subject:meeting\` \u2014 Messages with "meeting" in the subject
426
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 Messages within a date range
427
+ - \`label:INBOX is:unread\` \u2014 Unread messages in inbox
428
+ - \`has:attachment\` \u2014 Messages with attachments
429
+ - \`maxResults\` \u2014 Maximum number of results (default 100, max 500)
430
+ - \`pageToken\` \u2014 Token for pagination (from nextPageToken in response)
431
+ - \`labelIds\` \u2014 Filter by label IDs (e.g., \`INBOX\`, \`SENT\`, \`DRAFT\`)
432
+ - \`format\` \u2014 Message format for /messages/{id} and /threads/{id}:
433
+ - \`full\` \u2014 Complete message with parsed payload (default)
434
+ - \`metadata\` \u2014 Only headers (Subject, From, To, Date) without body
435
+ - \`minimal\` \u2014 Only IDs, labels, and snippet
436
+ - \`raw\` \u2014 Full RFC 2822 formatted message in base64url
437
+
438
+ #### Tips
439
+ - Always use \`/me\` as the userId \u2014 it refers to the authenticated user
440
+ - List endpoints return only IDs; fetch individual resources for details
441
+ - Use \`format=metadata\` to efficiently get subject/sender without full body
442
+ - Message body content is base64url encoded in \`payload.body.data\` or nested \`payload.parts[].body.data\`
443
+ - Use \`q\` parameter for powerful search filtering (same as Gmail search syntax)
444
+ - System labels include: INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
445
+
446
+ ### Business Logic
447
+
448
+ The business logic type for this connector is "typescript". Write handler code using the connector SDK shown below. Do NOT access credentials directly from environment variables.
449
+
450
+ #### Example
451
+
452
+ \`\`\`ts
453
+ import { connection } from "@squadbase/vite-server/connectors/gmail-oauth";
454
+
455
+ const gmail = connection("<connectionId>");
456
+
457
+ // Get user profile
458
+ const profile = await gmail.getProfile();
459
+ console.log(profile.emailAddress, profile.messagesTotal);
460
+
461
+ // List recent messages
462
+ const messages = await gmail.listMessages({ maxResults: 10 });
463
+ for (const msg of messages.messages) {
464
+ const detail = await gmail.getMessage(msg.id, "metadata");
465
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
466
+ console.log(subject, detail.snippet);
467
+ }
468
+
469
+ // Search messages
470
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
471
+
472
+ // List labels
473
+ const labels = await gmail.listLabels();
474
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
475
+
476
+ // Get a thread
477
+ const thread = await gmail.getThread("<threadId>");
478
+ thread.messages.forEach(m => console.log(m.snippet));
479
+ \`\`\``,
480
+ ja: `### \u30C4\u30FC\u30EB
481
+
482
+ - \`gmail-oauth_request\`: Gmail API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF09\u3002\u30E1\u30C3\u30BB\u30FC\u30B8\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30E1\u30C3\u30BB\u30FC\u30B8\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u30E9\u30D9\u30EB\u4E00\u89A7\u3001\u30B9\u30EC\u30C3\u30C9\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u306E\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
483
+
484
+ ### Gmail API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
485
+
486
+ #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
487
+ - GET \`/me/profile\` \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\uFF08\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3001\u30E1\u30C3\u30BB\u30FC\u30B8/\u30B9\u30EC\u30C3\u30C9\u7DCF\u6570\uFF09
488
+ - GET \`/me/labels\` \u2014 \u30E1\u30FC\u30EB\u30DC\u30C3\u30AF\u30B9\u306E\u5168\u30E9\u30D9\u30EB\u3092\u4E00\u89A7
489
+ - GET \`/me/labels/{id}\` \u2014 \u7279\u5B9A\u30E9\u30D9\u30EB\u306E\u8A73\u7D30\u3092\u53D6\u5F97
490
+ - GET \`/me/messages\` \u2014 \u30E1\u30C3\u30BB\u30FC\u30B8\u4E00\u89A7\uFF08ID\u306E\u307F\u8FD4\u5374\u3002\u500B\u5225\u30E1\u30C3\u30BB\u30FC\u30B8\u3067format\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\uFF09
491
+ - GET \`/me/messages/{id}\` \u2014 \u7279\u5B9A\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
492
+ - GET \`/me/threads\` \u2014 \u30B9\u30EC\u30C3\u30C9\u4E00\u89A7
493
+ - GET \`/me/threads/{id}\` \u2014 \u7279\u5B9A\u30B9\u30EC\u30C3\u30C9\u306E\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
494
+
495
+ #### \u4E3B\u8981\u306A\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF
496
+ - \`q\` \u2014 Gmail\u691C\u7D22\u30AF\u30A8\u30EA\uFF08Gmail\u691C\u7D22\u30DC\u30C3\u30AF\u30B9\u3068\u540C\u3058\u69CB\u6587\uFF09\u3002\u4F8B\uFF1A
497
+ - \`from:user@example.com\` \u2014 \u7279\u5B9A\u306E\u9001\u4FE1\u8005\u304B\u3089\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
498
+ - \`subject:meeting\` \u2014 \u4EF6\u540D\u306B\u300Cmeeting\u300D\u3092\u542B\u3080\u30E1\u30C3\u30BB\u30FC\u30B8
499
+ - \`after:2025/01/01 before:2025/02/01\` \u2014 \u65E5\u4ED8\u7BC4\u56F2\u5185\u306E\u30E1\u30C3\u30BB\u30FC\u30B8
500
+ - \`label:INBOX is:unread\` \u2014 \u53D7\u4FE1\u30C8\u30EC\u30A4\u306E\u672A\u8AAD\u30E1\u30C3\u30BB\u30FC\u30B8
501
+ - \`has:attachment\` \u2014 \u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u4ED8\u304D\u30E1\u30C3\u30BB\u30FC\u30B8
502
+ - \`maxResults\` \u2014 \u6700\u5927\u7D50\u679C\u6570\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8100\u3001\u6700\u5927500\uFF09
503
+ - \`pageToken\` \u2014 \u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u7528\u30C8\u30FC\u30AF\u30F3\uFF08\u30EC\u30B9\u30DD\u30F3\u30B9\u306EnextPageToken\u304B\u3089\u53D6\u5F97\uFF09
504
+ - \`labelIds\` \u2014 \u30E9\u30D9\u30EBID\u3067\u30D5\u30A3\u30EB\u30BF\uFF08\u4F8B\uFF1A\`INBOX\`, \`SENT\`, \`DRAFT\`\uFF09
505
+ - \`format\` \u2014 /messages/{id} \u3068 /threads/{id} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\uFF1A
506
+ - \`full\` \u2014 \u30D1\u30FC\u30B9\u6E08\u307F\u30DA\u30A4\u30ED\u30FC\u30C9\u4ED8\u304D\u306E\u5B8C\u5168\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\uFF09
507
+ - \`metadata\` \u2014 \u30D8\u30C3\u30C0\u30FC\u306E\u307F\uFF08Subject, From, To, Date\uFF09\u3001\u672C\u6587\u306A\u3057
508
+ - \`minimal\` \u2014 ID\u3001\u30E9\u30D9\u30EB\u3001\u30B9\u30CB\u30DA\u30C3\u30C8\u306E\u307F
509
+ - \`raw\` \u2014 base64url\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u305F\u5B8C\u5168\u306ARFC 2822\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8\u30E1\u30C3\u30BB\u30FC\u30B8
510
+
511
+ #### \u30D2\u30F3\u30C8
512
+ - userId\u306B\u306F\u5E38\u306B \`/me\` \u3092\u4F7F\u7528 \u2014 \u8A8D\u8A3C\u6E08\u307F\u30E6\u30FC\u30B6\u30FC\u3092\u6307\u3057\u307E\u3059
513
+ - \u4E00\u89A7\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306FID\u306E\u307F\u8FD4\u5374\u3057\u307E\u3059\u3002\u8A73\u7D30\u306F\u500B\u5225\u30EA\u30BD\u30FC\u30B9\u3092\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044
514
+ - \u4EF6\u540D/\u9001\u4FE1\u8005\u3092\u52B9\u7387\u7684\u306B\u53D6\u5F97\u3059\u308B\u306B\u306F \`format=metadata\` \u3092\u4F7F\u7528\u3057\u307E\u3059
515
+ - \u30E1\u30C3\u30BB\u30FC\u30B8\u672C\u6587\u306F \`payload.body.data\` \u307E\u305F\u306F\u30CD\u30B9\u30C8\u3055\u308C\u305F \`payload.parts[].body.data\` \u306Bbase64url\u30A8\u30F3\u30B3\u30FC\u30C9\u3067\u683C\u7D0D\u3055\u308C\u3066\u3044\u307E\u3059
516
+ - \u5F37\u529B\u306A\u691C\u7D22\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\u306B\u306F \`q\` \u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\uFF08Gmail\u691C\u7D22\u3068\u540C\u3058\u69CB\u6587\uFF09
517
+ - \u30B7\u30B9\u30C6\u30E0\u30E9\u30D9\u30EB: INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
518
+
519
+ ### Business Logic
520
+
521
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u4EE5\u4E0B\u306B\u793A\u3059\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u30CF\u30F3\u30C9\u30E9\u30B3\u30FC\u30C9\u3092\u8A18\u8FF0\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u76F4\u63A5\u8A8D\u8A3C\u60C5\u5831\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
522
+
523
+ #### Example
524
+
525
+ \`\`\`ts
526
+ import { connection } from "@squadbase/vite-server/connectors/gmail-oauth";
527
+
528
+ const gmail = connection("<connectionId>");
529
+
530
+ // Get user profile
531
+ const profile = await gmail.getProfile();
532
+ console.log(profile.emailAddress, profile.messagesTotal);
533
+
534
+ // List recent messages
535
+ const messages = await gmail.listMessages({ maxResults: 10 });
536
+ for (const msg of messages.messages) {
537
+ const detail = await gmail.getMessage(msg.id, "metadata");
538
+ const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
539
+ console.log(subject, detail.snippet);
540
+ }
541
+
542
+ // Search messages
543
+ const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
544
+
545
+ // List labels
546
+ const labels = await gmail.listLabels();
547
+ labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
548
+
549
+ // Get a thread
550
+ const thread = await gmail.getThread("<threadId>");
551
+ thread.messages.forEach(m => console.log(m.snippet));
552
+ \`\`\``
553
+ },
554
+ tools,
555
+ async checkConnection(_params, config) {
556
+ const { proxyFetch } = config;
557
+ const url = "https://gmail.googleapis.com/gmail/v1/users/me/profile";
558
+ try {
559
+ const res = await proxyFetch(url, { method: "GET" });
560
+ if (!res.ok) {
561
+ const errorText = await res.text().catch(() => res.statusText);
562
+ return {
563
+ success: false,
564
+ error: `Gmail API failed: HTTP ${res.status} ${errorText}`
565
+ };
566
+ }
567
+ return { success: true };
568
+ } catch (error) {
569
+ return {
570
+ success: false,
571
+ error: error instanceof Error ? error.message : String(error)
572
+ };
573
+ }
574
+ }
575
+ });
576
+
577
+ // src/connectors/create-connector-sdk.ts
578
+ import { readFileSync } from "fs";
579
+ import path from "path";
580
+
581
+ // src/connector-client/env.ts
582
+ function resolveEnvVar(entry, key, connectionId) {
583
+ const envVarName = entry.envVars[key];
584
+ if (!envVarName) {
585
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
586
+ }
587
+ const value = process.env[envVarName];
588
+ if (!value) {
589
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
590
+ }
591
+ return value;
592
+ }
593
+ function resolveEnvVarOptional(entry, key) {
594
+ const envVarName = entry.envVars[key];
595
+ if (!envVarName) return void 0;
596
+ return process.env[envVarName] || void 0;
597
+ }
598
+
599
+ // src/connector-client/proxy-fetch.ts
600
+ import { getContext } from "hono/context-storage";
601
+ import { getCookie } from "hono/cookie";
602
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
603
+ function createSandboxProxyFetch(connectionId) {
604
+ return async (input, init) => {
605
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
606
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
607
+ if (!token || !sandboxId) {
608
+ throw new Error(
609
+ "Connection proxy is not configured. Please check your deployment settings."
610
+ );
611
+ }
612
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
613
+ const originalMethod = init?.method ?? "GET";
614
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
615
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
616
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
617
+ return fetch(proxyUrl, {
618
+ method: "POST",
619
+ headers: {
620
+ "Content-Type": "application/json",
621
+ Authorization: `Bearer ${token}`
622
+ },
623
+ body: JSON.stringify({
624
+ url: originalUrl,
625
+ method: originalMethod,
626
+ body: originalBody
627
+ })
628
+ });
629
+ };
630
+ }
631
+ function createDeployedAppProxyFetch(connectionId) {
632
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
633
+ if (!projectId) {
634
+ throw new Error(
635
+ "Connection proxy is not configured. Please check your deployment settings."
636
+ );
637
+ }
638
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
639
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
640
+ return async (input, init) => {
641
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
642
+ const originalMethod = init?.method ?? "GET";
643
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
644
+ const c = getContext();
645
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
646
+ if (!appSession) {
647
+ throw new Error(
648
+ "No authentication method available for connection proxy."
649
+ );
650
+ }
651
+ return fetch(proxyUrl, {
652
+ method: "POST",
653
+ headers: {
654
+ "Content-Type": "application/json",
655
+ Authorization: `Bearer ${appSession}`
656
+ },
657
+ body: JSON.stringify({
658
+ url: originalUrl,
659
+ method: originalMethod,
660
+ body: originalBody
661
+ })
662
+ });
663
+ };
664
+ }
665
+ function createProxyFetch(connectionId) {
666
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
667
+ return createSandboxProxyFetch(connectionId);
668
+ }
669
+ return createDeployedAppProxyFetch(connectionId);
670
+ }
671
+
672
+ // src/connectors/create-connector-sdk.ts
673
+ function loadConnectionsSync() {
674
+ const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
675
+ try {
676
+ const raw = readFileSync(filePath, "utf-8");
677
+ return JSON.parse(raw);
678
+ } catch {
679
+ return {};
680
+ }
681
+ }
682
+ function createConnectorSdk(plugin, createClient2) {
683
+ return (connectionId) => {
684
+ const connections = loadConnectionsSync();
685
+ const entry = connections[connectionId];
686
+ if (!entry) {
687
+ throw new Error(
688
+ `Connection "${connectionId}" not found in .squadbase/connections.json`
689
+ );
690
+ }
691
+ if (entry.connector.slug !== plugin.slug) {
692
+ throw new Error(
693
+ `Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
694
+ );
695
+ }
696
+ const params = {};
697
+ for (const param of Object.values(plugin.parameters)) {
698
+ if (param.required) {
699
+ params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
700
+ } else {
701
+ const val = resolveEnvVarOptional(entry, param.slug);
702
+ if (val !== void 0) params[param.slug] = val;
703
+ }
704
+ }
705
+ return createClient2(params, createProxyFetch(connectionId));
706
+ };
707
+ }
708
+
709
+ // src/connectors/entries/gmail-oauth.ts
710
+ var connection = createConnectorSdk(gmailOauthConnector, createClient);
711
+ export {
712
+ connection
713
+ };