@squadbase/vite-server 0.1.3-dev.7 → 0.1.3-dev.8

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 (48) hide show
  1. package/dist/cli/index.js +1532 -1335
  2. package/dist/connectors/airtable-oauth.js +74 -1
  3. package/dist/connectors/airtable.js +74 -1
  4. package/dist/connectors/amplitude.js +74 -1
  5. package/dist/connectors/anthropic.js +74 -1
  6. package/dist/connectors/asana.js +74 -1
  7. package/dist/connectors/attio.js +74 -1
  8. package/dist/connectors/customerio.js +74 -1
  9. package/dist/connectors/dbt.js +74 -1
  10. package/dist/connectors/gemini.js +74 -1
  11. package/dist/connectors/gmail-oauth.js +74 -1
  12. package/dist/connectors/gmail.js +74 -1
  13. package/dist/connectors/google-ads-oauth.js +74 -1
  14. package/dist/connectors/google-ads.js +74 -1
  15. package/dist/connectors/google-analytics-oauth.js +87 -6
  16. package/dist/connectors/google-analytics.js +117 -46
  17. package/dist/connectors/google-calendar-oauth.js +74 -1
  18. package/dist/connectors/google-calendar.d.ts +1 -8
  19. package/dist/connectors/google-calendar.js +316 -64
  20. package/dist/connectors/google-sheets-oauth.js +85 -18
  21. package/dist/connectors/google-sheets.js +75 -2
  22. package/dist/connectors/grafana.js +74 -1
  23. package/dist/connectors/hubspot-oauth.js +74 -1
  24. package/dist/connectors/hubspot.js +74 -1
  25. package/dist/connectors/intercom-oauth.js +74 -1
  26. package/dist/connectors/intercom.js +74 -1
  27. package/dist/connectors/jira-api-key.js +74 -1
  28. package/dist/connectors/kintone-api-token.js +74 -1
  29. package/dist/connectors/kintone.js +74 -1
  30. package/dist/connectors/linkedin-ads-oauth.js +74 -1
  31. package/dist/connectors/linkedin-ads.js +74 -1
  32. package/dist/connectors/mailchimp-oauth.js +74 -1
  33. package/dist/connectors/mailchimp.js +74 -1
  34. package/dist/connectors/notion-oauth.js +74 -1
  35. package/dist/connectors/notion.js +74 -1
  36. package/dist/connectors/openai.js +74 -1
  37. package/dist/connectors/shopify-oauth.js +74 -1
  38. package/dist/connectors/shopify.js +74 -1
  39. package/dist/connectors/stripe-api-key.js +74 -1
  40. package/dist/connectors/stripe-oauth.js +74 -1
  41. package/dist/connectors/wix-store.js +74 -1
  42. package/dist/connectors/zendesk-oauth.js +74 -1
  43. package/dist/connectors/zendesk.js +74 -1
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.js +1484 -1288
  46. package/dist/main.js +1483 -1286
  47. package/dist/vite-plugin.js +1483 -1286
  48. package/package.json +1 -1
@@ -58,8 +58,8 @@ var parameters = {
58
58
  }),
59
59
  impersonateEmail: new ParameterDefinition({
60
60
  slug: "impersonate-email",
61
- name: "User Email Address",
62
- description: "The email address of the Google Workspace user whose calendar will be accessed via Domain-wide Delegation (e.g., 'user@example.com'). The service account will act on behalf of this user.",
61
+ name: "User Email Address(es)",
62
+ description: "The email address(es) of the Google Workspace user(s) whose calendar will be accessed via Domain-wide Delegation. Multiple addresses can be provided as a comma-separated list (e.g., 'user1@example.com, user2@example.com') to aggregate accessible calendars across users during setup. After setup completes, this value is overwritten with the owner email of the selected calendar.",
63
63
  envVarBaseKey: "GOOGLE_CALENDAR_IMPERSONATE_EMAIL",
64
64
  type: "text",
65
65
  secret: false,
@@ -104,7 +104,7 @@ function buildJwt(clientEmail, privateKey, nowSec, subject) {
104
104
  const signature = base64url(sign.sign(privateKey));
105
105
  return `${signingInput}.${signature}`;
106
106
  }
107
- function createClient(params, options) {
107
+ function createClient(params) {
108
108
  const serviceAccountKeyJsonBase64 = params[parameters.serviceAccountKeyJsonBase64.slug];
109
109
  const impersonateEmail = params[parameters.impersonateEmail.slug];
110
110
  const defaultCalendarId = params[parameters.calendarId.slug] ?? "primary";
@@ -113,7 +113,7 @@ function createClient(params, options) {
113
113
  `google-calendar: missing required parameter: ${parameters.serviceAccountKeyJsonBase64.slug}`
114
114
  );
115
115
  }
116
- if (!impersonateEmail && !options?.subject) {
116
+ if (!impersonateEmail) {
117
117
  throw new Error(
118
118
  `google-calendar: missing required parameter: ${parameters.impersonateEmail.slug}`
119
119
  );
@@ -135,10 +135,10 @@ function createClient(params, options) {
135
135
  "google-calendar: service account key JSON must contain client_email and private_key"
136
136
  );
137
137
  }
138
- const subject = options?.subject ?? impersonateEmail;
138
+ const subject = impersonateEmail;
139
139
  let cachedToken = null;
140
140
  let tokenExpiresAt = 0;
141
- async function getAccessToken() {
141
+ async function getAccessToken2() {
142
142
  const nowSec = Math.floor(Date.now() / 1e3);
143
143
  if (cachedToken && nowSec < tokenExpiresAt - 60) {
144
144
  return cachedToken;
@@ -173,7 +173,7 @@ function createClient(params, options) {
173
173
  }
174
174
  return {
175
175
  async request(path2, init) {
176
- const accessToken = await getAccessToken();
176
+ const accessToken = await getAccessToken2();
177
177
  const resolvedPath = path2.replace(
178
178
  /\{calendarId\}/g,
179
179
  defaultCalendarId
@@ -196,18 +196,18 @@ function createClient(params, options) {
196
196
  const data = await response.json();
197
197
  return data.items ?? [];
198
198
  },
199
- async listEvents(options2, calendarId) {
199
+ async listEvents(options, calendarId) {
200
200
  const cid = resolveCalendarId(calendarId);
201
201
  const searchParams = new URLSearchParams();
202
- if (options2?.timeMin) searchParams.set("timeMin", options2.timeMin);
203
- if (options2?.timeMax) searchParams.set("timeMax", options2.timeMax);
204
- if (options2?.maxResults)
205
- searchParams.set("maxResults", String(options2.maxResults));
206
- if (options2?.q) searchParams.set("q", options2.q);
207
- if (options2?.singleEvents != null)
208
- searchParams.set("singleEvents", String(options2.singleEvents));
209
- if (options2?.orderBy) searchParams.set("orderBy", options2.orderBy);
210
- if (options2?.pageToken) searchParams.set("pageToken", options2.pageToken);
202
+ if (options?.timeMin) searchParams.set("timeMin", options.timeMin);
203
+ if (options?.timeMax) searchParams.set("timeMax", options.timeMax);
204
+ if (options?.maxResults)
205
+ searchParams.set("maxResults", String(options.maxResults));
206
+ if (options?.q) searchParams.set("q", options.q);
207
+ if (options?.singleEvents != null)
208
+ searchParams.set("singleEvents", String(options.singleEvents));
209
+ if (options?.orderBy) searchParams.set("orderBy", options.orderBy);
210
+ if (options?.pageToken) searchParams.set("pageToken", options.pageToken);
211
211
  const qs = searchParams.toString();
212
212
  const path2 = `/calendars/${encodeURIComponent(cid)}/events${qs ? `?${qs}` : ""}`;
213
213
  const response = await this.request(path2, { method: "GET" });
@@ -344,34 +344,222 @@ var AUTH_TYPES = {
344
344
  USER_PASSWORD: "user-password"
345
345
  };
346
346
 
347
+ // ../connectors/src/connectors/google-calendar/tools/list-calendars.ts
348
+ import * as crypto2 from "crypto";
349
+ import { z } from "zod";
350
+ var TOKEN_URL2 = "https://oauth2.googleapis.com/token";
351
+ var BASE_URL2 = "https://www.googleapis.com/calendar/v3";
352
+ var SCOPE2 = "https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.events.readonly";
353
+ var REQUEST_TIMEOUT_MS = 6e4;
354
+ function base64url2(input) {
355
+ const buf = typeof input === "string" ? Buffer.from(input) : input;
356
+ return buf.toString("base64url");
357
+ }
358
+ function buildJwt2(clientEmail, privateKey, nowSec, subject) {
359
+ const header = base64url2(JSON.stringify({ alg: "RS256", typ: "JWT" }));
360
+ const payload = base64url2(
361
+ JSON.stringify({
362
+ iss: clientEmail,
363
+ sub: subject,
364
+ scope: SCOPE2,
365
+ aud: TOKEN_URL2,
366
+ iat: nowSec,
367
+ exp: nowSec + 3600
368
+ })
369
+ );
370
+ const signingInput = `${header}.${payload}`;
371
+ const sign = crypto2.createSign("RSA-SHA256");
372
+ sign.update(signingInput);
373
+ sign.end();
374
+ const signature = base64url2(sign.sign(privateKey));
375
+ return `${signingInput}.${signature}`;
376
+ }
377
+ async function getAccessToken(serviceAccount, subject) {
378
+ const nowSec = Math.floor(Date.now() / 1e3);
379
+ const jwt = buildJwt2(
380
+ serviceAccount.client_email,
381
+ serviceAccount.private_key,
382
+ nowSec,
383
+ subject
384
+ );
385
+ const response = await fetch(TOKEN_URL2, {
386
+ method: "POST",
387
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
388
+ body: new URLSearchParams({
389
+ grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
390
+ assertion: jwt
391
+ })
392
+ });
393
+ if (!response.ok) {
394
+ const text = await response.text();
395
+ throw new Error(
396
+ `token exchange failed for ${subject} (${response.status}): ${text}`
397
+ );
398
+ }
399
+ const data = await response.json();
400
+ return data.access_token;
401
+ }
402
+ var inputSchema = z.object({
403
+ toolUseIntent: z.string().optional().describe(
404
+ "Brief description of what you intend to accomplish with this tool call"
405
+ ),
406
+ connectionId: z.string().describe("ID of the Google Calendar connection to use")
407
+ });
408
+ var outputSchema = z.discriminatedUnion("success", [
409
+ z.object({
410
+ success: z.literal(true),
411
+ calendars: z.array(
412
+ z.object({
413
+ impersonateEmail: z.string(),
414
+ id: z.string(),
415
+ summary: z.string(),
416
+ primary: z.boolean().optional(),
417
+ accessRole: z.string()
418
+ })
419
+ ),
420
+ errors: z.array(
421
+ z.object({
422
+ impersonateEmail: z.string(),
423
+ error: z.string()
424
+ })
425
+ )
426
+ }),
427
+ z.object({
428
+ success: z.literal(false),
429
+ error: z.string()
430
+ })
431
+ ]);
432
+ var listCalendarsTool = new ConnectorTool({
433
+ name: "listCalendars",
434
+ description: "List Google Calendars accessible via Domain-wide Delegation by impersonating the Google Workspace user(s) configured on the connection's `impersonate-email` parameter (comma-separated list supported). Use during setup to aggregate calendars across the configured emails.",
435
+ inputSchema,
436
+ outputSchema,
437
+ async execute({ connectionId }, connections) {
438
+ const connection2 = connections.find((c) => c.id === connectionId);
439
+ if (!connection2) {
440
+ return {
441
+ success: false,
442
+ error: `Connection ${connectionId} not found`
443
+ };
444
+ }
445
+ const impersonateEmailRaw = parameters.impersonateEmail.getValue(connection2);
446
+ const emails = impersonateEmailRaw.split(",").map((e) => e.trim()).filter((e) => e.length > 0);
447
+ if (emails.length === 0) {
448
+ return {
449
+ success: false,
450
+ error: "impersonate-email parameter is empty"
451
+ };
452
+ }
453
+ console.log(
454
+ `[connector-request] google-calendar/${connection2.name}: listCalendars for ${emails.join(",")}`
455
+ );
456
+ let serviceAccount;
457
+ try {
458
+ const keyJsonBase64 = parameters.serviceAccountKeyJsonBase64.getValue(connection2);
459
+ const decoded = Buffer.from(keyJsonBase64, "base64").toString("utf-8");
460
+ serviceAccount = JSON.parse(decoded);
461
+ } catch (err) {
462
+ const msg = err instanceof Error ? err.message : String(err);
463
+ return {
464
+ success: false,
465
+ error: `failed to decode service account key: ${msg}`
466
+ };
467
+ }
468
+ if (!serviceAccount.client_email || !serviceAccount.private_key) {
469
+ return {
470
+ success: false,
471
+ error: "service account key JSON must contain client_email and private_key"
472
+ };
473
+ }
474
+ const aggregated = [];
475
+ const errors = [];
476
+ for (const email of emails) {
477
+ const controller = new AbortController();
478
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
479
+ try {
480
+ const token = await getAccessToken(serviceAccount, email);
481
+ const response = await fetch(`${BASE_URL2}/users/me/calendarList`, {
482
+ method: "GET",
483
+ headers: { Authorization: `Bearer ${token}` },
484
+ signal: controller.signal
485
+ });
486
+ const data = await response.json();
487
+ if (!response.ok) {
488
+ const errorObj = data?.error;
489
+ errors.push({
490
+ impersonateEmail: email,
491
+ error: errorObj?.message ?? `HTTP ${response.status} ${response.statusText}`
492
+ });
493
+ continue;
494
+ }
495
+ const items = data.items ?? [];
496
+ for (const c of items) {
497
+ aggregated.push({
498
+ impersonateEmail: email,
499
+ id: c.id,
500
+ summary: c.summary,
501
+ primary: c.primary,
502
+ accessRole: c.accessRole
503
+ });
504
+ }
505
+ } catch (err) {
506
+ const msg = err instanceof Error ? err.message : String(err);
507
+ errors.push({ impersonateEmail: email, error: msg });
508
+ } finally {
509
+ clearTimeout(timeout);
510
+ }
511
+ }
512
+ return {
513
+ success: true,
514
+ calendars: aggregated,
515
+ errors
516
+ };
517
+ }
518
+ });
519
+
347
520
  // ../connectors/src/connectors/google-calendar/setup.ts
521
+ var listCalendarsToolName = `google-calendar_${listCalendarsTool.name}`;
348
522
  var googleCalendarOnboarding = new ConnectorOnboarding({
349
523
  connectionSetupInstructions: {
350
524
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Calendar\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
351
525
 
352
- 1. \u30E6\u30FC\u30B6\u30FC\u306B\u300C\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u305F\u3044Google Workspace\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u6559\u3048\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: user@example.com\uFF09\u300D\u3068\u4F1D\u3048\u308B
353
- 2. \u30E6\u30FC\u30B6\u30FC\u304C\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u63D0\u4F9B\u3057\u305F\u3089\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
526
+ 1. \`${listCalendarsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E \`impersonate-email\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u8A2D\u5B9A\u3055\u308C\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\uFF08\u30AB\u30F3\u30DE\u533A\u5207\u308A\u5BFE\u5FDC\uFF09\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
527
+ 2. \u8FD4\u5374\u3055\u308C\u305F \`calendars\` \u914D\u5217\uFF08\u5404\u8981\u7D20: \`{ impersonateEmail, id, summary, primary, accessRole }\`\uFF09\u3092\u5143\u306B\u3001\u300C\u4F7F\u7528\u3059\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u300D\u3068\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u305F\u4E0A\u3067\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
528
+ - \`parameterSlug\`: \`"calendar-id"\`
529
+ - \`options\`: \u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30AB\u30EC\u30F3\u30C0\u30FC\u540D (owner: impersonateEmail)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30AB\u30EC\u30F3\u30C0\u30FCID
530
+ - \`errors\` \u306B\u5931\u6557\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u3042\u308B\u5834\u5408\u306F\u3001\u305D\u306E\u65E8\u3092\u77ED\u304F\u4F1D\u3048\u308B
531
+ 3. \u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3057\u305F\u30AB\u30EC\u30F3\u30C0\u30FC\u306E \`label\` \u304C\u30E1\u30C3\u30BB\u30FC\u30B8\u3068\u3057\u3066\u5C4A\u304F\u3002\u305D\u306E label \u304B\u3089 owner \u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u62BD\u51FA\u3057\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
354
532
  - \`parameterSlug\`: \`"impersonate-email"\`
355
- - \`value\`: \u30E6\u30FC\u30B6\u30FC\u304C\u63D0\u4F9B\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
356
- 3. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u5BFE\u8C61\u30E6\u30FC\u30B6\u30FC\u306E\u60C5\u5831\u3092\u8A18\u9332\u3059\u308B:
533
+ - \`options\`: \`[{ value: <ownerEmail>, label: <ownerEmail> }]\`\uFF08\u9078\u629E\u6E08\u307F\u30AB\u30EC\u30F3\u30C0\u30FC\u306E owner email \u3092\u5358\u4E00\u30AA\u30D7\u30B7\u30E7\u30F3\u3068\u3057\u3066\u6E21\u3059\uFF09
534
+ 4. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u5BFE\u8C61\u60C5\u5831\u3092\u8A18\u9332\u3059\u308B:
357
535
  - \`user\`: \u8A2D\u5B9A\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9
358
- - \`note\`: \u300CDomain-wide Delegation\u3067 {email} \u306E\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u300D\u306A\u3069\u306E\u8AAC\u660E
536
+ - \`calendar\`: \u9078\u629E\u3055\u308C\u305F\u30AB\u30EC\u30F3\u30C0\u30FC\u540D
537
+ - \`calendarId\`: \u9078\u629E\u3055\u308C\u305F\u30AB\u30EC\u30F3\u30C0\u30FCID
538
+ - \`note\`: \u300CDomain-wide Delegation\u3067 {email} \u306E {calendar} \u306B\u30A2\u30AF\u30BB\u30B9\u300D\u306A\u3069\u306E\u8AAC\u660E
359
539
 
360
540
  #### \u5236\u7D04
361
- - **\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u8A2D\u5B9A\u304C\u5FC5\u8981\u3067\u3059**\u3002\u30A2\u30AF\u30BB\u30B9\u6A29\u9650\u30A8\u30E9\u30FC\u304C\u51FA\u308B\u5834\u5408\u3001Google Workspace\u7BA1\u7406\u8005\u306BDomain-wide Delegation\u306E\u8A2D\u5B9A\u78BA\u8A8D\u3092\u4FC3\u3057\u3066\u304F\u3060\u3055\u3044
541
+ - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30E6\u30FC\u30B6\u30FC\u3078\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u7B49\u306E\u5165\u529B\u3092\u6C42\u3081\u306A\u3044\u3053\u3068**\u3002\u5FC5\u8981\u306A\u5024\u306F\u63A5\u7D9A\u4F5C\u6210\u6642\u306E\u30D1\u30E9\u30E1\u30FC\u30BF\uFF08\`impersonate-email\`\uFF09\u304B\u3089\u53D6\u5F97\u3059\u308B
542
+ - **\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u8A2D\u5B9A\u304C\u5FC5\u8981\u3067\u3059**\u3002\`${listCalendarsToolName}\` \u306E \`errors\` \u306B\u6A29\u9650\u30A8\u30E9\u30FC\u304C\u51FA\u308B\u5834\u5408\u3001Google Workspace\u7BA1\u7406\u8005\u306BDomain-wide Delegation\u306E\u8A2D\u5B9A\u78BA\u8A8D\u3092\u4FC3\u3057\u3066\u304F\u3060\u3055\u3044
362
543
  - \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`,
363
544
  en: `Follow these steps to set up the Google Calendar connection.
364
545
 
365
- 1. Ask the user for the Google Workspace email address whose calendar should be accessed (e.g., user@example.com)
366
- 2. When the user provides an email, call \`updateConnectionParameters\`:
546
+ 1. Call \`${listCalendarsToolName}\` to list calendars accessible via the email address(es) configured in the connection's \`impersonate-email\` parameter (comma-separated list supported)
547
+ 2. Using the returned \`calendars\` array (each item: \`{ impersonateEmail, id, summary, primary, accessRole }\`), tell the user "Please select a calendar.", then call \`updateConnectionParameters\`:
548
+ - \`parameterSlug\`: \`"calendar-id"\`
549
+ - \`options\`: The calendar list. Each option's \`label\` should be \`Calendar Name (owner: impersonateEmail)\`, \`value\` should be the calendar ID
550
+ - If \`errors\` contains failing email addresses, briefly mention them
551
+ 3. The \`label\` of the user's selected calendar will arrive as a message. Extract the owner email from that label and call \`updateConnectionParameters\`:
367
552
  - \`parameterSlug\`: \`"impersonate-email"\`
368
- - \`value\`: The email provided by the user
369
- 3. Call \`updateConnectionContext\` to record the target user:
553
+ - \`options\`: \`[{ value: <ownerEmail>, label: <ownerEmail> }]\` (pass the selected calendar's owner email as a single option)
554
+ 4. Call \`updateConnectionContext\` to record the target:
370
555
  - \`user\`: The configured email address
371
- - \`note\`: A description such as "Accessing {email}'s calendar via Domain-wide Delegation"
556
+ - \`calendar\`: The selected calendar's name
557
+ - \`calendarId\`: The selected calendar ID
558
+ - \`note\`: A description such as "Accessing {email}'s {calendar} via Domain-wide Delegation"
372
559
 
373
560
  #### Constraints
374
- - **Domain-wide Delegation must be configured on the service account**. If access errors occur, ask the user to verify the Domain-wide Delegation setup with their Google Workspace administrator
561
+ - **Do NOT prompt the user for any input (e.g., email addresses) during setup**. The required values come from the connection parameters (\`impersonate-email\`) filled in at connection creation time
562
+ - **Domain-wide Delegation must be configured on the service account**. If \`${listCalendarsToolName}\` returns permission errors in the \`errors\` field, ask the user to verify the Domain-wide Delegation setup with their Google Workspace administrator
375
563
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
376
564
  },
377
565
  dataOverviewInstructions: {
@@ -385,33 +573,33 @@ var googleCalendarOnboarding = new ConnectorOnboarding({
385
573
  });
386
574
 
387
575
  // ../connectors/src/connectors/google-calendar/tools/request.ts
388
- import { z } from "zod";
389
- var BASE_URL2 = "https://www.googleapis.com/calendar/v3";
390
- var REQUEST_TIMEOUT_MS = 6e4;
391
- var inputSchema = z.object({
392
- toolUseIntent: z.string().optional().describe(
576
+ import { z as z2 } from "zod";
577
+ var BASE_URL3 = "https://www.googleapis.com/calendar/v3";
578
+ var REQUEST_TIMEOUT_MS2 = 6e4;
579
+ var inputSchema2 = z2.object({
580
+ toolUseIntent: z2.string().optional().describe(
393
581
  "Brief description of what you intend to accomplish with this tool call"
394
582
  ),
395
- connectionId: z.string().describe("ID of the Google Calendar connection to use"),
396
- method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
397
- path: z.string().describe(
583
+ connectionId: z2.string().describe("ID of the Google Calendar connection to use"),
584
+ method: z2.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
585
+ path: z2.string().describe(
398
586
  "API path appended to https://www.googleapis.com/calendar/v3 (e.g., '/calendars/{calendarId}/events'). {calendarId} is automatically replaced."
399
587
  ),
400
- queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL"),
401
- body: z.record(z.string(), z.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH methods"),
402
- subject: z.string().optional().describe(
588
+ queryParams: z2.record(z2.string(), z2.string()).optional().describe("Query parameters to append to the URL"),
589
+ body: z2.record(z2.string(), z2.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH methods"),
590
+ subject: z2.string().optional().describe(
403
591
  "Override the email address of the user to impersonate via Domain-wide Delegation. If omitted, the connection's configured user email is used."
404
592
  )
405
593
  });
406
- var outputSchema = z.discriminatedUnion("success", [
407
- z.object({
408
- success: z.literal(true),
409
- status: z.number(),
410
- data: z.record(z.string(), z.unknown())
594
+ var outputSchema2 = z2.discriminatedUnion("success", [
595
+ z2.object({
596
+ success: z2.literal(true),
597
+ status: z2.number(),
598
+ data: z2.record(z2.string(), z2.unknown())
411
599
  }),
412
- z.object({
413
- success: z.literal(false),
414
- error: z.string()
600
+ z2.object({
601
+ success: z2.literal(false),
602
+ error: z2.string()
415
603
  })
416
604
  ]);
417
605
  var requestTool = new ConnectorTool({
@@ -419,8 +607,8 @@ var requestTool = new ConnectorTool({
419
607
  description: `Send authenticated requests to the Google Calendar API v3.
420
608
  Authentication is handled automatically using a service account.
421
609
  {calendarId} in the path is automatically replaced with the connection's default calendar ID.`,
422
- inputSchema,
423
- outputSchema,
610
+ inputSchema: inputSchema2,
611
+ outputSchema: outputSchema2,
424
612
  async execute({ connectionId, method, path: path2, queryParams, body, subject }, connections) {
425
613
  const connection2 = connections.find((c) => c.id === connectionId);
426
614
  if (!connection2) {
@@ -463,13 +651,13 @@ Authentication is handled automatically using a service account.
463
651
  };
464
652
  }
465
653
  const resolvedPath = path2.replace(/\{calendarId\}/g, calendarId);
466
- let url = `${BASE_URL2}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
654
+ let url = `${BASE_URL3}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
467
655
  if (queryParams) {
468
656
  const searchParams = new URLSearchParams(queryParams);
469
657
  url += `?${searchParams.toString()}`;
470
658
  }
471
659
  const controller = new AbortController();
472
- const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
660
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
473
661
  try {
474
662
  const response = await fetch(url, {
475
663
  method,
@@ -507,7 +695,7 @@ Authentication is handled automatically using a service account.
507
695
  });
508
696
 
509
697
  // ../connectors/src/connectors/google-calendar/index.ts
510
- var tools = { request: requestTool };
698
+ var tools = { request: requestTool, listCalendars: listCalendarsTool };
511
699
  var googleCalendarConnector = new ConnectorPlugin({
512
700
  slug: "google-calendar",
513
701
  authType: AUTH_TYPES.SERVICE_ACCOUNT,
@@ -686,6 +874,79 @@ function resolveEnvVarOptional(entry, key) {
686
874
  return process.env[envVarName] || void 0;
687
875
  }
688
876
 
877
+ // src/connector-client/proxy-fetch.ts
878
+ import { getContext } from "hono/context-storage";
879
+ import { getCookie } from "hono/cookie";
880
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
881
+ function createSandboxProxyFetch(connectionId) {
882
+ return async (input, init) => {
883
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
884
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
885
+ if (!token || !sandboxId) {
886
+ throw new Error(
887
+ "Connection proxy is not configured. Please check your deployment settings."
888
+ );
889
+ }
890
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
891
+ const originalMethod = init?.method ?? "GET";
892
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
893
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
894
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
895
+ return fetch(proxyUrl, {
896
+ method: "POST",
897
+ headers: {
898
+ "Content-Type": "application/json",
899
+ Authorization: `Bearer ${token}`
900
+ },
901
+ body: JSON.stringify({
902
+ url: originalUrl,
903
+ method: originalMethod,
904
+ body: originalBody
905
+ })
906
+ });
907
+ };
908
+ }
909
+ function createDeployedAppProxyFetch(connectionId) {
910
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
911
+ if (!projectId) {
912
+ throw new Error(
913
+ "Connection proxy is not configured. Please check your deployment settings."
914
+ );
915
+ }
916
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
917
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
918
+ return async (input, init) => {
919
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
920
+ const originalMethod = init?.method ?? "GET";
921
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
922
+ const c = getContext();
923
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
924
+ if (!appSession) {
925
+ throw new Error(
926
+ "No authentication method available for connection proxy."
927
+ );
928
+ }
929
+ return fetch(proxyUrl, {
930
+ method: "POST",
931
+ headers: {
932
+ "Content-Type": "application/json",
933
+ Authorization: `Bearer ${appSession}`
934
+ },
935
+ body: JSON.stringify({
936
+ url: originalUrl,
937
+ method: originalMethod,
938
+ body: originalBody
939
+ })
940
+ });
941
+ };
942
+ }
943
+ function createProxyFetch(connectionId) {
944
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
945
+ return createSandboxProxyFetch(connectionId);
946
+ }
947
+ return createDeployedAppProxyFetch(connectionId);
948
+ }
949
+
689
950
  // src/connectors/create-connector-sdk.ts
690
951
  function loadConnectionsSync() {
691
952
  const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
@@ -719,21 +980,12 @@ function createConnectorSdk(plugin, createClient2) {
719
980
  if (val !== void 0) params[param.slug] = val;
720
981
  }
721
982
  }
722
- return createClient2(params);
983
+ return createClient2(params, createProxyFetch(connectionId));
723
984
  };
724
985
  }
725
986
 
726
987
  // src/connectors/entries/google-calendar.ts
727
- var baseConnection = createConnectorSdk(googleCalendarConnector, createClient);
728
- var connection = (connectionId, options) => {
729
- if (options) {
730
- return createConnectorSdk(
731
- googleCalendarConnector,
732
- (params) => createClient(params, options)
733
- )(connectionId);
734
- }
735
- return baseConnection(connectionId);
736
- };
988
+ var connection = createConnectorSdk(googleCalendarConnector, createClient);
737
989
  export {
738
990
  connection
739
991
  };
@@ -90,7 +90,7 @@ var parameters = {
90
90
  envVarBaseKey: "GOOGLE_SHEETS_OAUTH_SPREADSHEET_URL",
91
91
  type: "text",
92
92
  secret: false,
93
- required: false
93
+ required: true
94
94
  })
95
95
  };
96
96
 
@@ -394,41 +394,35 @@ Authentication is handled automatically via OAuth proxy.
394
394
  var requestToolName = `google-sheets-oauth_${requestTool.name}`;
395
395
  var googleSheetsOnboarding = new ConnectorOnboarding({
396
396
  connectionSetupInstructions: {
397
- ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Sheets\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
397
+ ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Sheets\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8URL\u306F\u63A5\u7D9A\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u65E2\u306B\u767B\u9332\u6E08\u307F\u3067\u3059\u3002\u30E6\u30FC\u30B6\u30FC\u306B\u805E\u304D\u8FD4\u3055\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
398
398
 
399
- 1. \u30E6\u30FC\u30B6\u30FC\u306B\u300C\u4F7F\u7528\u3059\u308BGoogle Sheets\u306EURL\u3092\u8CBC\u308A\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: https://docs.google.com/spreadsheets/d/xxxxx/edit\uFF09\u300D\u3068\u4F1D\u3048\u308B
400
- 2. \u30E6\u30FC\u30B6\u30FC\u304CURL\u3092\u63D0\u4F9B\u3057\u305F\u3089\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
401
- - \`parameterSlug\`: \`"spreadsheet-url"\`
402
- - \`value\`: \u30E6\u30FC\u30B6\u30FC\u304C\u63D0\u4F9B\u3057\u305FURL\uFF08\u305D\u306E\u307E\u307E\u4FDD\u5B58\u3002ID\u306E\u62BD\u51FA\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u307E\u3059\uFF09
403
- 3. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3059\u308B:
399
+ 1. \`${requestToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3059\u308B:
404
400
  - \`method\`: \`"GET"\`
405
401
  - \`path\`: \`"/{spreadsheetId}?fields=spreadsheetId,properties.title,sheets.properties.title"\`
406
- 4. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u5171\u6709\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
407
- 5. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
402
+ 2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u5171\u6709\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
403
+ 3. \`updateConnectionContext\` \u3092\u547C\u3073\u51FA\u3059:
408
404
  - \`spreadsheet\`: \u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30BF\u30A4\u30C8\u30EB
409
405
  - \`sheets\`: \u30B7\u30FC\u30C8\u540D\u4E00\u89A7\uFF08\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09
410
406
  - \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
411
407
 
412
408
  #### \u5236\u7D04
413
409
  - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30B7\u30FC\u30C8\u306E\u30C7\u30FC\u30BF\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\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u30EA\u30AF\u30A8\u30B9\u30C8\u306E\u307F
410
+ - \u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8URL\u3092\u30E6\u30FC\u30B6\u30FC\u306B\u805E\u304D\u8FD4\u3055\u306A\u3044\u3053\u3068\uFF08\u767B\u9332\u6E08\u307F\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u305D\u306E\u307E\u307E\u4F7F\u7528\u3059\u308B\uFF09
414
411
  - \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`,
415
- en: `Follow these steps to set up the Google Sheets connection.
412
+ en: `Follow these steps to set up the Google Sheets connection. The spreadsheet URL is already registered as a connection parameter \u2014 do NOT ask the user for it again.
416
413
 
417
- 1. Ask the user to paste the Google Sheets URL (e.g., https://docs.google.com/spreadsheets/d/xxxxx/edit)
418
- 2. When the user provides a URL, call \`updateConnectionParameters\`:
419
- - \`parameterSlug\`: \`"spreadsheet-url"\`
420
- - \`value\`: The URL provided by the user (save as-is; the spreadsheet ID is extracted automatically)
421
- 3. Call \`${requestToolName}\` to fetch spreadsheet metadata:
414
+ 1. Call \`${requestToolName}\` to fetch spreadsheet metadata:
422
415
  - \`method\`: \`"GET"\`
423
416
  - \`path\`: \`"/{spreadsheetId}?fields=spreadsheetId,properties.title,sheets.properties.title"\`
424
- 4. If an error is returned, ask the user to check the spreadsheet sharing settings
425
- 5. Call \`updateConnectionContext\`:
417
+ 2. If an error is returned, ask the user to check the spreadsheet sharing settings
418
+ 3. Call \`updateConnectionContext\`:
426
419
  - \`spreadsheet\`: The spreadsheet title
427
420
  - \`sheets\`: Sheet names (comma-separated)
428
421
  - \`note\`: Brief description of the setup
429
422
 
430
423
  #### Constraints
431
424
  - **Do NOT read sheet data during setup**. Only the metadata request specified in the steps above is allowed
425
+ - Do NOT ask the user for the spreadsheet URL \u2014 it is already stored as a connection parameter
432
426
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
433
427
  },
434
428
  dataOverviewInstructions: {
@@ -607,6 +601,79 @@ function resolveEnvVarOptional(entry, key) {
607
601
  return process.env[envVarName] || void 0;
608
602
  }
609
603
 
604
+ // src/connector-client/proxy-fetch.ts
605
+ import { getContext } from "hono/context-storage";
606
+ import { getCookie } from "hono/cookie";
607
+ var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
608
+ function createSandboxProxyFetch(connectionId) {
609
+ return async (input, init) => {
610
+ const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
611
+ const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
612
+ if (!token || !sandboxId) {
613
+ throw new Error(
614
+ "Connection proxy is not configured. Please check your deployment settings."
615
+ );
616
+ }
617
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
618
+ const originalMethod = init?.method ?? "GET";
619
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
620
+ const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
621
+ const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
622
+ return fetch(proxyUrl, {
623
+ method: "POST",
624
+ headers: {
625
+ "Content-Type": "application/json",
626
+ Authorization: `Bearer ${token}`
627
+ },
628
+ body: JSON.stringify({
629
+ url: originalUrl,
630
+ method: originalMethod,
631
+ body: originalBody
632
+ })
633
+ });
634
+ };
635
+ }
636
+ function createDeployedAppProxyFetch(connectionId) {
637
+ const projectId = process.env["SQUADBASE_PROJECT_ID"];
638
+ if (!projectId) {
639
+ throw new Error(
640
+ "Connection proxy is not configured. Please check your deployment settings."
641
+ );
642
+ }
643
+ const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
644
+ const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
645
+ return async (input, init) => {
646
+ const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
647
+ const originalMethod = init?.method ?? "GET";
648
+ const originalBody = init?.body ? JSON.parse(init.body) : void 0;
649
+ const c = getContext();
650
+ const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
651
+ if (!appSession) {
652
+ throw new Error(
653
+ "No authentication method available for connection proxy."
654
+ );
655
+ }
656
+ return fetch(proxyUrl, {
657
+ method: "POST",
658
+ headers: {
659
+ "Content-Type": "application/json",
660
+ Authorization: `Bearer ${appSession}`
661
+ },
662
+ body: JSON.stringify({
663
+ url: originalUrl,
664
+ method: originalMethod,
665
+ body: originalBody
666
+ })
667
+ });
668
+ };
669
+ }
670
+ function createProxyFetch(connectionId) {
671
+ if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
672
+ return createSandboxProxyFetch(connectionId);
673
+ }
674
+ return createDeployedAppProxyFetch(connectionId);
675
+ }
676
+
610
677
  // src/connectors/create-connector-sdk.ts
611
678
  function loadConnectionsSync() {
612
679
  const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
@@ -640,7 +707,7 @@ function createConnectorSdk(plugin, createClient2) {
640
707
  if (val !== void 0) params[param.slug] = val;
641
708
  }
642
709
  }
643
- return createClient2(params);
710
+ return createClient2(params, createProxyFetch(connectionId));
644
711
  };
645
712
  }
646
713