@squadbase/vite-server 0.1.8-dev.d378524 → 0.1.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.
@@ -2805,22 +2805,22 @@ var require_nacl_fast = __commonJS({
2805
2805
  randombytes = fn;
2806
2806
  };
2807
2807
  (function() {
2808
- var crypto9 = typeof self !== "undefined" ? self.crypto || self.msCrypto : null;
2809
- if (crypto9 && crypto9.getRandomValues) {
2808
+ var crypto8 = typeof self !== "undefined" ? self.crypto || self.msCrypto : null;
2809
+ if (crypto8 && crypto8.getRandomValues) {
2810
2810
  var QUOTA = 65536;
2811
2811
  nacl.setPRNG(function(x6, n6) {
2812
2812
  var i6, v7 = new Uint8Array(n6);
2813
2813
  for (i6 = 0; i6 < n6; i6 += QUOTA) {
2814
- crypto9.getRandomValues(v7.subarray(i6, i6 + Math.min(n6 - i6, QUOTA)));
2814
+ crypto8.getRandomValues(v7.subarray(i6, i6 + Math.min(n6 - i6, QUOTA)));
2815
2815
  }
2816
2816
  for (i6 = 0; i6 < n6; i6++) x6[i6] = v7[i6];
2817
2817
  cleanup(v7);
2818
2818
  });
2819
2819
  } else if (typeof __require !== "undefined") {
2820
- crypto9 = __require("crypto");
2821
- if (crypto9 && crypto9.randomBytes) {
2820
+ crypto8 = __require("crypto");
2821
+ if (crypto8 && crypto8.randomBytes) {
2822
2822
  nacl.setPRNG(function(x6, n6) {
2823
- var i6, v7 = crypto9.randomBytes(n6);
2823
+ var i6, v7 = crypto8.randomBytes(n6);
2824
2824
  for (i6 = 0; i6 < n6; i6++) x6[i6] = v7[i6];
2825
2825
  cleanup(v7);
2826
2826
  });
@@ -4117,7 +4117,7 @@ var require_lib2 = __commonJS({
4117
4117
  var require_constants = __commonJS({
4118
4118
  "../../node_modules/ssh2/lib/protocol/constants.js"(exports2, module) {
4119
4119
  "use strict";
4120
- var crypto9 = __require("crypto");
4120
+ var crypto8 = __require("crypto");
4121
4121
  var cpuInfo;
4122
4122
  try {
4123
4123
  cpuInfo = require_lib2()();
@@ -4125,21 +4125,21 @@ var require_constants = __commonJS({
4125
4125
  }
4126
4126
  var { bindingAvailable, CIPHER_INFO, MAC_INFO } = require_crypto();
4127
4127
  var eddsaSupported = (() => {
4128
- if (typeof crypto9.sign === "function" && typeof crypto9.verify === "function") {
4128
+ if (typeof crypto8.sign === "function" && typeof crypto8.verify === "function") {
4129
4129
  const key = "-----BEGIN PRIVATE KEY-----\r\nMC4CAQAwBQYDK2VwBCIEIHKj+sVa9WcD/q2DJUJaf43Kptc8xYuUQA4bOFj9vC8T\r\n-----END PRIVATE KEY-----";
4130
4130
  const data = Buffer.from("a");
4131
4131
  let sig;
4132
4132
  let verified;
4133
4133
  try {
4134
- sig = crypto9.sign(null, data, key);
4135
- verified = crypto9.verify(null, data, key, sig);
4134
+ sig = crypto8.sign(null, data, key);
4135
+ verified = crypto8.verify(null, data, key, sig);
4136
4136
  } catch {
4137
4137
  }
4138
4138
  return Buffer.isBuffer(sig) && sig.length === 64 && verified === true;
4139
4139
  }
4140
4140
  return false;
4141
4141
  })();
4142
- var curve25519Supported = typeof crypto9.diffieHellman === "function" && typeof crypto9.generateKeyPairSync === "function" && typeof crypto9.createPublicKey === "function";
4142
+ var curve25519Supported = typeof crypto8.diffieHellman === "function" && typeof crypto8.generateKeyPairSync === "function" && typeof crypto8.createPublicKey === "function";
4143
4143
  var DEFAULT_KEX = [
4144
4144
  // https://tools.ietf.org/html/rfc5656#section-10.1
4145
4145
  "ecdh-sha2-nistp256",
@@ -4182,7 +4182,7 @@ var require_constants = __commonJS({
4182
4182
  "ssh-dss"
4183
4183
  ]);
4184
4184
  var canUseCipher = (() => {
4185
- const ciphers = crypto9.getCiphers();
4185
+ const ciphers = crypto8.getCiphers();
4186
4186
  return (name) => ciphers.includes(CIPHER_INFO[name].sslName);
4187
4187
  })();
4188
4188
  var DEFAULT_CIPHER = [
@@ -4220,7 +4220,7 @@ var require_constants = __commonJS({
4220
4220
  "arcfour"
4221
4221
  ].filter(canUseCipher));
4222
4222
  var canUseMAC = (() => {
4223
- const hashes = crypto9.getHashes();
4223
+ const hashes = crypto8.getHashes();
4224
4224
  return (name) => hashes.includes(MAC_INFO[name].sslName);
4225
4225
  })();
4226
4226
  var DEFAULT_MAC = [
@@ -4826,7 +4826,7 @@ var require_utils = __commonJS({
4826
4826
  var sshcrypto_default;
4827
4827
  var init_sshcrypto = __esm({
4828
4828
  "../../node_modules/ssh2/lib/protocol/crypto/build/Release/sshcrypto.node"() {
4829
- sshcrypto_default = "./sshcrypto-VVJOJ3LR.node";
4829
+ sshcrypto_default = "./sshcrypto-P3UBA7BP.node";
4830
4830
  }
4831
4831
  });
4832
4832
 
@@ -6604,7 +6604,7 @@ var require_keyParser = __commonJS({
6604
6604
  createECDH,
6605
6605
  createHash: createHash4,
6606
6606
  createHmac: createHmac2,
6607
- createSign: createSign2,
6607
+ createSign,
6608
6608
  createVerify,
6609
6609
  getCiphers,
6610
6610
  sign: sign_,
@@ -6905,7 +6905,7 @@ ${formatted}-----END ${type} KEY-----`;
6905
6905
  return new Error("No private key available");
6906
6906
  if (!algo || typeof algo !== "string")
6907
6907
  algo = this[SYM_HASH_ALGO];
6908
- const signature = createSign2(algo);
6908
+ const signature = createSign(algo);
6909
6909
  signature.update(data);
6910
6910
  try {
6911
6911
  return signature.sign(pem);
@@ -20414,8 +20414,8 @@ var require_bson = __commonJS({
20414
20414
  return crypto.getRandomValues(nodeJsByteUtils.allocate(byteLength));
20415
20415
  }
20416
20416
  var nodejsRandomBytes = (() => {
20417
- const { crypto: crypto9 } = globalThis;
20418
- if (crypto9 != null && typeof crypto9.getRandomValues === "function") {
20417
+ const { crypto: crypto8 } = globalThis;
20418
+ if (crypto8 != null && typeof crypto8.getRandomValues === "function") {
20419
20419
  return nodejsSecureRandomBytes;
20420
20420
  } else {
20421
20421
  return nodejsMathRandomBytes;
@@ -20520,10 +20520,10 @@ var require_bson = __commonJS({
20520
20520
  return webByteUtils.fromNumberArray(Array.from({ length: byteLength }, () => Math.floor(Math.random() * 256)));
20521
20521
  }
20522
20522
  var webRandomBytes = (() => {
20523
- const { crypto: crypto9 } = globalThis;
20524
- if (crypto9 != null && typeof crypto9.getRandomValues === "function") {
20523
+ const { crypto: crypto8 } = globalThis;
20524
+ if (crypto8 != null && typeof crypto8.getRandomValues === "function") {
20525
20525
  return (byteLength) => {
20526
- return crypto9.getRandomValues(webByteUtils.allocate(byteLength));
20526
+ return crypto8.getRandomValues(webByteUtils.allocate(byteLength));
20527
20527
  };
20528
20528
  } else {
20529
20529
  if (isReactNative()) {
@@ -27025,7 +27025,7 @@ var require_utils3 = __commonJS({
27025
27025
  exports2.decorateDecryptionResult = decorateDecryptionResult;
27026
27026
  exports2.addAbortListener = addAbortListener;
27027
27027
  exports2.abortable = abortable;
27028
- var crypto9 = __require("crypto");
27028
+ var crypto8 = __require("crypto");
27029
27029
  var fs_1 = __require("fs");
27030
27030
  var http2 = __require("http");
27031
27031
  var process2 = __require("process");
@@ -27185,7 +27185,7 @@ var require_utils3 = __commonJS({
27185
27185
  }
27186
27186
  }
27187
27187
  function uuidV4() {
27188
- const result = crypto9.randomBytes(16);
27188
+ const result = crypto8.randomBytes(16);
27189
27189
  result[6] = result[6] & 15 | 64;
27190
27190
  result[8] = result[8] & 63 | 128;
27191
27191
  return result;
@@ -27737,7 +27737,7 @@ var require_utils3 = __commonJS({
27737
27737
  }
27738
27738
  var randomBytes = (size) => {
27739
27739
  return new Promise((resolve, reject) => {
27740
- crypto9.randomBytes(size, (error2, buf) => {
27740
+ crypto8.randomBytes(size, (error2, buf) => {
27741
27741
  if (error2)
27742
27742
  return reject(error2);
27743
27743
  resolve(buf);
@@ -39490,12 +39490,12 @@ var init_date_utils = __esm({
39490
39490
  });
39491
39491
 
39492
39492
  // ../../node_modules/@smithy/uuid/dist-es/randomUUID.js
39493
- import crypto4 from "crypto";
39493
+ import crypto3 from "crypto";
39494
39494
  var randomUUID;
39495
39495
  var init_randomUUID = __esm({
39496
39496
  "../../node_modules/@smithy/uuid/dist-es/randomUUID.js"() {
39497
39497
  "use strict";
39498
- randomUUID = crypto4.randomUUID.bind(crypto4);
39498
+ randomUUID = crypto3.randomUUID.bind(crypto3);
39499
39499
  }
39500
39500
  });
39501
39501
 
@@ -61429,10 +61429,10 @@ var require_retry = __commonJS({
61429
61429
  });
61430
61430
 
61431
61431
  // ../../node_modules/gaxios/node_modules/uuid/dist/esm-node/rng.js
61432
- import crypto5 from "crypto";
61432
+ import crypto4 from "crypto";
61433
61433
  function rng() {
61434
61434
  if (poolPtr > rnds8Pool.length - 16) {
61435
- crypto5.randomFillSync(rnds8Pool);
61435
+ crypto4.randomFillSync(rnds8Pool);
61436
61436
  poolPtr = 0;
61437
61437
  }
61438
61438
  return rnds8Pool.slice(poolPtr, poolPtr += 16);
@@ -61643,14 +61643,14 @@ var init_v35 = __esm({
61643
61643
  });
61644
61644
 
61645
61645
  // ../../node_modules/gaxios/node_modules/uuid/dist/esm-node/md5.js
61646
- import crypto6 from "crypto";
61646
+ import crypto5 from "crypto";
61647
61647
  function md5(bytes) {
61648
61648
  if (Array.isArray(bytes)) {
61649
61649
  bytes = Buffer.from(bytes);
61650
61650
  } else if (typeof bytes === "string") {
61651
61651
  bytes = Buffer.from(bytes, "utf8");
61652
61652
  }
61653
- return crypto6.createHash("md5").update(bytes).digest();
61653
+ return crypto5.createHash("md5").update(bytes).digest();
61654
61654
  }
61655
61655
  var md5_default;
61656
61656
  var init_md5 = __esm({
@@ -61673,13 +61673,13 @@ var init_v3 = __esm({
61673
61673
  });
61674
61674
 
61675
61675
  // ../../node_modules/gaxios/node_modules/uuid/dist/esm-node/native.js
61676
- import crypto7 from "crypto";
61676
+ import crypto6 from "crypto";
61677
61677
  var native_default;
61678
61678
  var init_native = __esm({
61679
61679
  "../../node_modules/gaxios/node_modules/uuid/dist/esm-node/native.js"() {
61680
61680
  "use strict";
61681
61681
  native_default = {
61682
- randomUUID: crypto7.randomUUID
61682
+ randomUUID: crypto6.randomUUID
61683
61683
  };
61684
61684
  }
61685
61685
  });
@@ -61714,14 +61714,14 @@ var init_v42 = __esm({
61714
61714
  });
61715
61715
 
61716
61716
  // ../../node_modules/gaxios/node_modules/uuid/dist/esm-node/sha1.js
61717
- import crypto8 from "crypto";
61717
+ import crypto7 from "crypto";
61718
61718
  function sha1(bytes) {
61719
61719
  if (Array.isArray(bytes)) {
61720
61720
  bytes = Buffer.from(bytes);
61721
61721
  } else if (typeof bytes === "string") {
61722
61722
  bytes = Buffer.from(bytes, "utf8");
61723
61723
  }
61724
- return crypto8.createHash("sha1").update(bytes).digest();
61724
+ return crypto7.createHash("sha1").update(bytes).digest();
61725
61725
  }
61726
61726
  var sha1_default;
61727
61727
  var init_sha1 = __esm({
@@ -82405,7 +82405,7 @@ var require_scram = __commonJS({
82405
82405
  Object.defineProperty(exports2, "__esModule", { value: true });
82406
82406
  exports2.ScramSHA256 = exports2.ScramSHA1 = void 0;
82407
82407
  var saslprep_1 = require_node2();
82408
- var crypto9 = __require("crypto");
82408
+ var crypto8 = __require("crypto");
82409
82409
  var bson_1 = require_bson2();
82410
82410
  var error_1 = require_error();
82411
82411
  var utils_1 = require_utils3();
@@ -82558,9 +82558,9 @@ var require_scram = __commonJS({
82558
82558
  }
82559
82559
  let md52;
82560
82560
  try {
82561
- md52 = crypto9.createHash("md5");
82561
+ md52 = crypto8.createHash("md5");
82562
82562
  } catch (err) {
82563
- if (crypto9.getFips()) {
82563
+ if (crypto8.getFips()) {
82564
82564
  throw new Error("Auth mechanism SCRAM-SHA-1 is not supported in FIPS mode");
82565
82565
  }
82566
82566
  throw err;
@@ -82583,10 +82583,10 @@ var require_scram = __commonJS({
82583
82583
  return Buffer.from(res).toString("base64");
82584
82584
  }
82585
82585
  function H2(method, text) {
82586
- return crypto9.createHash(method).update(text).digest();
82586
+ return crypto8.createHash(method).update(text).digest();
82587
82587
  }
82588
82588
  function HMAC(method, key, text) {
82589
- return crypto9.createHmac(method, key).update(text).digest();
82589
+ return crypto8.createHmac(method, key).update(text).digest();
82590
82590
  }
82591
82591
  var _hiCache = {};
82592
82592
  var _hiCacheCount = 0;
@@ -82603,7 +82603,7 @@ var require_scram = __commonJS({
82603
82603
  if (_hiCache[key] != null) {
82604
82604
  return _hiCache[key];
82605
82605
  }
82606
- const saltedData = crypto9.pbkdf2Sync(data, salt, iterations, hiLengthMap[cryptoMethod], cryptoMethod);
82606
+ const saltedData = crypto8.pbkdf2Sync(data, salt, iterations, hiLengthMap[cryptoMethod], cryptoMethod);
82607
82607
  if (_hiCacheCount >= 200) {
82608
82608
  _hiCachePurge();
82609
82609
  }
@@ -82615,8 +82615,8 @@ var require_scram = __commonJS({
82615
82615
  if (lhs.length !== rhs.length) {
82616
82616
  return false;
82617
82617
  }
82618
- if (typeof crypto9.timingSafeEqual === "function") {
82619
- return crypto9.timingSafeEqual(lhs, rhs);
82618
+ if (typeof crypto8.timingSafeEqual === "function") {
82619
+ return crypto8.timingSafeEqual(lhs, rhs);
82620
82620
  }
82621
82621
  let result = 0;
82622
82622
  for (let i6 = 0; i6 < lhs.length; i6++) {
@@ -91268,8 +91268,7 @@ const realtime = await ga.runRealtimeReport({
91268
91268
  }
91269
91269
  });
91270
91270
 
91271
- // ../connectors/src/connectors/google-calendar/tools/list-calendars.ts
91272
- import * as crypto3 from "crypto";
91271
+ // ../connectors/src/connectors/google-calendar/tools/request.ts
91273
91272
  import { z as z21 } from "zod";
91274
91273
 
91275
91274
  // ../connectors/src/connectors/google-calendar/parameters.ts
@@ -91277,121 +91276,54 @@ var parameters14 = {
91277
91276
  serviceAccountKeyJsonBase64: new ParameterDefinition({
91278
91277
  slug: "service-account-key-json-base64",
91279
91278
  name: "Google Cloud Service Account JSON",
91280
- description: "The service account JSON key used to authenticate with Google Cloud Platform. Ensure that the service account has the necessary permissions to access Google Calendar, and that calendars are shared with the service account email.",
91279
+ description: "The service account JSON key. Used for both Domain-wide Delegation (impersonating a Workspace user) and direct service-account access (calendars explicitly shared with the SA email). The authentication path is selected per call by the tool used.",
91281
91280
  envVarBaseKey: "GOOGLE_CALENDAR_SERVICE_ACCOUNT_JSON_BASE64",
91282
91281
  type: "base64EncodedJson",
91283
91282
  secret: true,
91284
91283
  required: true
91285
91284
  })
91286
91285
  };
91287
- var impersonateEmailParameter = new ParameterDefinition({
91288
- slug: "impersonate-email",
91289
- name: "User Email Address(es)",
91290
- description: "The email address(es) of the Google Workspace user(s) whose calendar is accessed via Domain-wide Delegation. Collected during the setup flow.",
91291
- envVarBaseKey: "GOOGLE_CALENDAR_IMPERSONATE_EMAIL",
91292
- type: "text",
91293
- secret: false,
91294
- required: false
91295
- });
91296
- var calendarIdParameter = new ParameterDefinition({
91297
- slug: "calendar-id",
91298
- name: "Default Calendar ID",
91299
- description: "The default Google Calendar ID to use (e.g., 'primary' or an email address like 'user@example.com'). If not set, 'primary' is used.",
91300
- envVarBaseKey: "GOOGLE_CALENDAR_CALENDAR_ID",
91301
- type: "text",
91302
- secret: false,
91303
- required: false
91304
- });
91305
-
91306
- // ../connectors/src/connectors/google-calendar/tools/list-calendars.ts
91307
- var TOKEN_URL = "https://oauth2.googleapis.com/token";
91286
+
91287
+ // ../connectors/src/connectors/google-calendar/tools/request.ts
91308
91288
  var BASE_URL6 = "https://www.googleapis.com/calendar/v3";
91309
- var SCOPE = "https://www.googleapis.com/auth/calendar.readonly https://www.googleapis.com/auth/calendar.events.readonly";
91310
91289
  var REQUEST_TIMEOUT_MS11 = 6e4;
91311
- function base64url(input) {
91312
- const buf = typeof input === "string" ? Buffer.from(input) : input;
91313
- return buf.toString("base64url");
91314
- }
91315
- function buildJwt(clientEmail, privateKey, nowSec, subject) {
91316
- const header = base64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
91317
- const payload = base64url(
91318
- JSON.stringify({
91319
- iss: clientEmail,
91320
- sub: subject,
91321
- scope: SCOPE,
91322
- aud: TOKEN_URL,
91323
- iat: nowSec,
91324
- exp: nowSec + 3600
91325
- })
91326
- );
91327
- const signingInput = `${header}.${payload}`;
91328
- const sign2 = crypto3.createSign("RSA-SHA256");
91329
- sign2.update(signingInput);
91330
- sign2.end();
91331
- const signature = base64url(sign2.sign(privateKey));
91332
- return `${signingInput}.${signature}`;
91333
- }
91334
- async function getAccessToken(serviceAccount, subject) {
91335
- const nowSec = Math.floor(Date.now() / 1e3);
91336
- const jwt = buildJwt(
91337
- serviceAccount.client_email,
91338
- serviceAccount.private_key,
91339
- nowSec,
91340
- subject
91341
- );
91342
- const response = await fetch(TOKEN_URL, {
91343
- method: "POST",
91344
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
91345
- body: new URLSearchParams({
91346
- grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
91347
- assertion: jwt
91348
- })
91349
- });
91350
- if (!response.ok) {
91351
- const text = await response.text();
91352
- throw new Error(
91353
- `token exchange failed for ${subject} (${response.status}): ${text}`
91354
- );
91355
- }
91356
- const data = await response.json();
91357
- return data.access_token;
91290
+ function decodeServiceAccount(keyJsonBase64) {
91291
+ const decoded = Buffer.from(keyJsonBase64, "base64").toString("utf-8");
91292
+ return JSON.parse(decoded);
91358
91293
  }
91359
91294
  var inputSchema21 = z21.object({
91360
91295
  toolUseIntent: z21.string().optional().describe(
91361
91296
  "Brief description of what you intend to accomplish with this tool call"
91362
91297
  ),
91363
- connectionId: z21.string().describe("ID of the Google Calendar connection to use")
91298
+ connectionId: z21.string().describe("ID of the Google Calendar connection to use"),
91299
+ method: z21.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
91300
+ path: z21.string().describe(
91301
+ "API path appended to https://www.googleapis.com/calendar/v3 (e.g., '/users/me/calendarList', '/calendars/team@example.com/events'). Write the calendar ID directly into the path \u2014 there is no placeholder substitution."
91302
+ ),
91303
+ scopes: z21.array(z21.string()).describe(
91304
+ "OAuth scopes the token must include. This connector currently supports read-only operations only \u2014 pass one of ['https://www.googleapis.com/auth/calendar.readonly'] (calendars + events read), ['https://www.googleapis.com/auth/calendar.events.readonly'] (events read only), or ['https://www.googleapis.com/auth/calendar.freebusy'] (busy/free queries only). Per-endpoint scope reference: https://developers.google.com/calendar/api/auth"
91305
+ ),
91306
+ queryParams: z21.record(z21.string(), z21.string()).optional().describe("Query parameters to append to the URL"),
91307
+ body: z21.record(z21.string(), z21.unknown()).optional().describe("JSON request body for POST/PUT/PATCH")
91364
91308
  });
91365
91309
  var outputSchema21 = z21.discriminatedUnion("success", [
91366
91310
  z21.object({
91367
91311
  success: z21.literal(true),
91368
- calendars: z21.array(
91369
- z21.object({
91370
- impersonateEmail: z21.string(),
91371
- id: z21.string(),
91372
- summary: z21.string(),
91373
- primary: z21.boolean().optional(),
91374
- accessRole: z21.string()
91375
- })
91376
- ),
91377
- errors: z21.array(
91378
- z21.object({
91379
- impersonateEmail: z21.string(),
91380
- error: z21.string()
91381
- })
91382
- )
91312
+ status: z21.number(),
91313
+ data: z21.record(z21.string(), z21.unknown())
91383
91314
  }),
91384
91315
  z21.object({
91385
91316
  success: z21.literal(false),
91386
- error: z21.string()
91317
+ error: z21.string(),
91318
+ serviceAccountEmail: z21.string().optional()
91387
91319
  })
91388
91320
  ]);
91389
- var listCalendarsTool = new ConnectorTool({
91390
- name: "listCalendars",
91391
- 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.",
91321
+ var requestTool5 = new ConnectorTool({
91322
+ name: "request",
91323
+ description: "Call the Google Calendar API as the service account itself (no delegation). Read-only operations only. Only calendars explicitly shared with the service account email are accessible. Pass `scopes` as a read-only Calendar scope (e.g., ['https://www.googleapis.com/auth/calendar.readonly']). Use this tool when the project knowledge records the calendar with `(service-account, ...)` (no `subject`).",
91392
91324
  inputSchema: inputSchema21,
91393
91325
  outputSchema: outputSchema21,
91394
- async execute({ connectionId }, connections) {
91326
+ async execute({ connectionId, method, path: path4, scopes, queryParams, body }, connections) {
91395
91327
  const connection = connections.find((c6) => c6.id === connectionId);
91396
91328
  if (!connection) {
91397
91329
  return {
@@ -91399,144 +91331,89 @@ var listCalendarsTool = new ConnectorTool({
91399
91331
  error: `Connection ${connectionId} not found`
91400
91332
  };
91401
91333
  }
91402
- const impersonateEmailRaw = impersonateEmailParameter.getValue(connection);
91403
- const emails = impersonateEmailRaw.split(",").map((e6) => e6.trim()).filter((e6) => e6.length > 0);
91404
- if (emails.length === 0) {
91405
- return {
91406
- success: false,
91407
- error: "impersonate-email parameter is empty"
91408
- };
91409
- }
91410
- console.log(
91411
- `[connector-request] google-calendar/${connection.name}: listCalendars for ${emails.join(",")}`
91412
- );
91334
+ const keyJsonBase64 = parameters14.serviceAccountKeyJsonBase64.getValue(connection);
91413
91335
  let serviceAccount;
91414
91336
  try {
91415
- const keyJsonBase64 = parameters14.serviceAccountKeyJsonBase64.getValue(connection);
91416
- const decoded = Buffer.from(keyJsonBase64, "base64").toString("utf-8");
91417
- serviceAccount = JSON.parse(decoded);
91337
+ serviceAccount = decodeServiceAccount(keyJsonBase64);
91418
91338
  } catch (err) {
91419
91339
  const msg = err instanceof Error ? err.message : String(err);
91420
91340
  return {
91421
91341
  success: false,
91422
- error: `failed to decode service account key: ${msg}`
91342
+ error: `Failed to decode service account key: ${msg}`
91423
91343
  };
91424
91344
  }
91425
- if (!serviceAccount.client_email || !serviceAccount.private_key) {
91426
- return {
91427
- success: false,
91428
- error: "service account key JSON must contain client_email and private_key"
91429
- };
91430
- }
91431
- const aggregated = [];
91432
- const errors2 = [];
91433
- for (const email of emails) {
91345
+ const serviceAccountEmail = serviceAccount.client_email;
91346
+ console.log(
91347
+ `[connector-request] google-calendar/${connection.name}: ${method} ${path4} (service account)`
91348
+ );
91349
+ try {
91350
+ const { GoogleAuth } = await import("google-auth-library");
91351
+ const auth = new GoogleAuth({
91352
+ credentials: {
91353
+ client_email: serviceAccount.client_email,
91354
+ private_key: serviceAccount.private_key
91355
+ },
91356
+ scopes
91357
+ });
91358
+ const token = await auth.getAccessToken();
91359
+ if (!token) {
91360
+ return {
91361
+ success: false,
91362
+ error: "Failed to obtain access token",
91363
+ serviceAccountEmail
91364
+ };
91365
+ }
91366
+ let url = `${BASE_URL6}${path4.startsWith("/") ? "" : "/"}${path4}`;
91367
+ if (queryParams) {
91368
+ const searchParams = new URLSearchParams(queryParams);
91369
+ url += `?${searchParams.toString()}`;
91370
+ }
91434
91371
  const controller = new AbortController();
91435
91372
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS11);
91436
91373
  try {
91437
- const token = await getAccessToken(serviceAccount, email);
91438
- const response = await fetch(`${BASE_URL6}/users/me/calendarList`, {
91439
- method: "GET",
91440
- headers: { Authorization: `Bearer ${token}` },
91374
+ const hasBody = body != null && ["POST", "PUT", "PATCH"].includes(method);
91375
+ const response = await fetch(url, {
91376
+ method,
91377
+ headers: {
91378
+ Authorization: `Bearer ${token}`,
91379
+ "Content-Type": "application/json"
91380
+ },
91381
+ body: hasBody ? JSON.stringify(body) : void 0,
91441
91382
  signal: controller.signal
91442
91383
  });
91443
- const data = await response.json();
91384
+ const data = await response.json().catch(() => ({}));
91444
91385
  if (!response.ok) {
91445
91386
  const errorObj = data?.error;
91446
- errors2.push({
91447
- impersonateEmail: email,
91448
- error: errorObj?.message ?? `HTTP ${response.status} ${response.statusText}`
91449
- });
91450
- continue;
91451
- }
91452
- const items = data.items ?? [];
91453
- for (const c6 of items) {
91454
- aggregated.push({
91455
- impersonateEmail: email,
91456
- id: c6.id,
91457
- summary: c6.summary,
91458
- primary: c6.primary,
91459
- accessRole: c6.accessRole
91460
- });
91387
+ const errorMessage = errorObj?.message ?? (typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`);
91388
+ return {
91389
+ success: false,
91390
+ error: errorMessage,
91391
+ serviceAccountEmail
91392
+ };
91461
91393
  }
91462
- } catch (err) {
91463
- const msg = err instanceof Error ? err.message : String(err);
91464
- errors2.push({ impersonateEmail: email, error: msg });
91394
+ return { success: true, status: response.status, data };
91465
91395
  } finally {
91466
91396
  clearTimeout(timeout);
91467
91397
  }
91398
+ } catch (err) {
91399
+ const msg = err instanceof Error ? err.message : String(err);
91400
+ return {
91401
+ success: false,
91402
+ error: msg,
91403
+ serviceAccountEmail
91404
+ };
91468
91405
  }
91469
- return {
91470
- success: true,
91471
- calendars: aggregated,
91472
- errors: errors2
91473
- };
91474
91406
  }
91475
91407
  });
91476
91408
 
91477
- // ../connectors/src/connectors/google-calendar/setup.ts
91478
- var listCalendarsToolName = `google-calendar-service-account_${listCalendarsTool.name}`;
91479
- var googleCalendarOnboarding = new ConnectorOnboarding({
91480
- connectionSetupInstructions: {
91481
- 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\u63A5\u7D9A\u4F5C\u6210\u6642\u306B\u306F\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8JSON\u306E\u307F\u304C\u8A2D\u5B9A\u6E08\u307F\u3067\u3001\u5BFE\u8C61\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3084\u30AB\u30EC\u30F3\u30C0\u30FCID\u306F\u3053\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u53D6\u5F97\u3057\u307E\u3059\u3002
91482
-
91483
- 1. \`askUserQuestion\` \u3067\u30E6\u30FC\u30B6\u30FC\u306B\u3001\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u304CDomain-wide Delegation\u3067\u4EE3\u7406\u30A2\u30AF\u30BB\u30B9\u3059\u308BGoogle Workspace\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u30D2\u30A2\u30EA\u30F3\u30B0\u3059\u308B:
91484
- - \`type\`: \`"freeText"\`
91485
- - \`question\`: \u300C\u30A2\u30AF\u30BB\u30B9\u3057\u305F\u3044\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u6301\u3064\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u3042\u308B\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\u3067\u5165\u529B\u53EF\uFF09\u300D
91486
- - \`placeholder\`: \`"user@example.com, admin@example.com"\`
91487
- 2. \u30E6\u30FC\u30B6\u30FC\u304B\u3089\u53D7\u3051\u53D6\u3063\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\uFF08\u30AB\u30F3\u30DE\u533A\u5207\u308A\u5BFE\u5FDC\uFF09\u3092 \`updateConnectionParameters\` \u3067\u4FDD\u5B58\u3059\u308B:
91488
- - \`parameterSlug\`: \`"impersonate-email"\`
91489
- - \`options\`: \`[{ value: <\u5165\u529B\u3055\u308C\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u6587\u5B57\u5217>, label: <\u540C\u3058\u5024> }]\`\uFF081\u4EF6\u306E\u307F\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u81EA\u52D5\u9078\u629E\u3055\u308C\u308B\uFF09
91490
- 3. \`${listCalendarsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3001\u4FDD\u5B58\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B\u3002
91491
- - \`errors\` \u306B\u30A8\u30E9\u30FC\u304C\u3042\u308A \`calendars\` \u304C\u7A7A\u306E\u5834\u5408\uFF08\u3059\u3079\u3066\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3067\u5931\u6557\uFF09\u3001\u5165\u529B\u3055\u308C\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u5B58\u5728\u3057\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308B\u3002\`askUserQuestion\` \u3067\u300C{\u5165\u529B\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9} \u306E\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A2\u30C9\u30EC\u30B9\u306B\u8AA4\u308A\u304C\u3042\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u4F3C\u305F\u30A2\u30C9\u30EC\u30B9\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u304B\uFF1F\u300D\u3068\u805E\u304D\u8FD4\u3057\u3001\u30B9\u30C6\u30C3\u30D72\u304B\u3089\u518D\u5EA6\u5B9F\u884C\u3059\u308B
91492
- 4. \u8FD4\u5374\u3055\u308C\u305F \`calendars\` \u914D\u5217\uFF08\u5404\u8981\u7D20: \`{ impersonateEmail, id, summary, primary, accessRole }\`\uFF09\u3092\u5143\u306B\u300C\u4F7F\u7528\u3059\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u300D\u3068\u77ED\u304F\u4F1D\u3048\u305F\u4E0A\u3067\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
91493
- - \`parameterSlug\`: \`"calendar-id"\`
91494
- - \`options\`: \u5404 option \u306E \`label\` \u306F \`\u30AB\u30EC\u30F3\u30C0\u30FC\u540D (owner: impersonateEmail)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30AB\u30EC\u30F3\u30C0\u30FCID
91495
- - \`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
91496
- 5. \u30E6\u30FC\u30B6\u30FC\u304C\u9078\u629E\u3057\u305F\u30AB\u30EC\u30F3\u30C0\u30FC\u306E \`label\` \u304B\u3089 owner \u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u62BD\u51FA\u3057\u3001\`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3057\u3066 \`impersonate-email\` \u3092\u6700\u7D42\u5024\u3067\u4E0A\u66F8\u304D\u3059\u308B:
91497
- - \`parameterSlug\`: \`"impersonate-email"\`
91498
- - \`options\`: \`[{ value: <ownerEmail>, label: <ownerEmail> }]\`
91499
-
91500
- #### \u5236\u7D04
91501
- - **\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
91502
- - \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`,
91503
- en: `Follow these steps to set up the Google Calendar connection. Only the service account JSON is provided at connection creation time \u2014 the target user email and calendar ID are collected during this setup flow.
91504
-
91505
- 1. Call \`askUserQuestion\` to ask the user for the Google Workspace user email the service account will impersonate via Domain-wide Delegation:
91506
- - \`type\`: \`"freeText"\`
91507
- - \`question\`: "Please enter the email address of the user whose calendar you want to access (comma-separated list allowed for multiple users)"
91508
- - \`placeholder\`: \`"user@example.com, admin@example.com"\`
91509
- 2. Save the email(s) the user provided (comma-separated supported) via \`updateConnectionParameters\`:
91510
- - \`parameterSlug\`: \`"impersonate-email"\`
91511
- - \`options\`: \`[{ value: <the email string entered>, label: <same value> }]\` (a single option is auto-selected)
91512
- 3. Call \`${listCalendarsToolName}\` to list calendars accessible via the saved email(s).
91513
- - If \`errors\` is non-empty and \`calendars\` is empty (all emails failed), the entered address may not exist. Use \`askUserQuestion\` to ask: "Could not access the calendar for {entered email}. The address may be incorrect \u2014 did you mean a similar address?" Then re-run from step 2 with the new input
91514
- 4. Using the returned \`calendars\` array (each item: \`{ impersonateEmail, id, summary, primary, accessRole }\`), briefly say "Please select a calendar." then call \`updateConnectionParameters\`:
91515
- - \`parameterSlug\`: \`"calendar-id"\`
91516
- - \`options\`: Each option's \`label\` should be \`Calendar Name (owner: impersonateEmail)\`, \`value\` should be the calendar ID
91517
- - If \`errors\` contains failing email addresses, briefly mention them
91518
- 5. Extract the owner email from the \`label\` of the user's selected calendar, then call \`updateConnectionParameters\` to overwrite \`impersonate-email\` with the final value:
91519
- - \`parameterSlug\`: \`"impersonate-email"\`
91520
- - \`options\`: \`[{ value: <ownerEmail>, label: <ownerEmail> }]\`
91521
-
91522
- #### Constraints
91523
- - **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
91524
- - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
91525
- },
91526
- dataOverviewInstructions: {
91527
- en: `1. Call google-calendar-service-account_request with GET /calendars/{calendarId} to get the default calendar's metadata
91528
- 2. Call google-calendar-service-account_request with GET /users/me/calendarList to list all accessible calendars
91529
- 3. Call google-calendar-service-account_request with GET /calendars/{calendarId}/events with query params timeMin (RFC3339) and maxResults=10 to sample upcoming events`,
91530
- ja: `1. google-calendar-service-account_request \u3067 GET /calendars/{calendarId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
91531
- 2. google-calendar-service-account_request \u3067 GET /users/me/calendarList \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u3092\u53D6\u5F97
91532
- 3. google-calendar-service-account_request \u3067 GET /calendars/{calendarId}/events \u3092\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF timeMin\uFF08RFC3339\u5F62\u5F0F\uFF09\u3068 maxResults=10 \u3067\u547C\u3073\u51FA\u3057\u3001\u76F4\u8FD1\u306E\u30A4\u30D9\u30F3\u30C8\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
91533
- }
91534
- });
91535
-
91536
- // ../connectors/src/connectors/google-calendar/tools/request.ts
91409
+ // ../connectors/src/connectors/google-calendar/tools/request-with-delegation.ts
91537
91410
  import { z as z22 } from "zod";
91538
91411
  var BASE_URL7 = "https://www.googleapis.com/calendar/v3";
91539
91412
  var REQUEST_TIMEOUT_MS12 = 6e4;
91413
+ function decodeServiceAccount2(keyJsonBase64) {
91414
+ const decoded = Buffer.from(keyJsonBase64, "base64").toString("utf-8");
91415
+ return JSON.parse(decoded);
91416
+ }
91540
91417
  var inputSchema22 = z22.object({
91541
91418
  toolUseIntent: z22.string().optional().describe(
91542
91419
  "Brief description of what you intend to accomplish with this tool call"
@@ -91544,13 +91421,18 @@ var inputSchema22 = z22.object({
91544
91421
  connectionId: z22.string().describe("ID of the Google Calendar connection to use"),
91545
91422
  method: z22.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
91546
91423
  path: z22.string().describe(
91547
- "API path appended to https://www.googleapis.com/calendar/v3 (e.g., '/calendars/{calendarId}/events'). {calendarId} is automatically replaced."
91424
+ "API path appended to https://www.googleapis.com/calendar/v3 (e.g., '/users/me/calendarList', '/calendars/alice@example.com/events'). Write the calendar ID directly into the path \u2014 there is no placeholder substitution."
91548
91425
  ),
91549
- queryParams: z22.record(z22.string(), z22.string()).optional().describe("Query parameters to append to the URL"),
91550
- body: z22.record(z22.string(), z22.unknown()).optional().describe("Request body (JSON) for POST/PUT/PATCH methods"),
91551
- subject: z22.string().optional().describe(
91552
- "Override the email address of the user to impersonate via Domain-wide Delegation. If omitted, the connection's configured user email is used."
91553
- )
91426
+ subject: z22.string().describe(
91427
+ "Email of the Workspace user to impersonate via Domain-wide Delegation. The token will be issued as this user."
91428
+ ),
91429
+ scopes: z22.array(z22.string()).describe(
91430
+ "OAuth scopes the token must include. This connector currently supports read-only operations only \u2014 pass one of ['https://www.googleapis.com/auth/calendar.readonly'] (calendars + events read), ['https://www.googleapis.com/auth/calendar.events.readonly'] (events read only), or ['https://www.googleapis.com/auth/calendar.freebusy'] (busy/free queries only). Per-endpoint scope reference: https://developers.google.com/calendar/api/auth"
91431
+ ),
91432
+ queryParams: z22.record(z22.string(), z22.string()).optional().describe(
91433
+ "Query parameters to append to the URL (e.g., { timeMin: '2025-01-01T00:00:00Z', maxResults: '10' })"
91434
+ ),
91435
+ body: z22.record(z22.string(), z22.unknown()).optional().describe("JSON request body for POST/PUT/PATCH")
91554
91436
  });
91555
91437
  var outputSchema22 = z22.discriminatedUnion("success", [
91556
91438
  z22.object({
@@ -91560,17 +91442,16 @@ var outputSchema22 = z22.discriminatedUnion("success", [
91560
91442
  }),
91561
91443
  z22.object({
91562
91444
  success: z22.literal(false),
91563
- error: z22.string()
91445
+ error: z22.string(),
91446
+ serviceAccountEmail: z22.string().optional()
91564
91447
  })
91565
91448
  ]);
91566
- var requestTool5 = new ConnectorTool({
91567
- name: "request",
91568
- description: `Send authenticated requests to the Google Calendar API v3.
91569
- Authentication is handled automatically using a service account.
91570
- {calendarId} in the path is automatically replaced with the connection's default calendar ID.`,
91449
+ var requestWithDelegationTool = new ConnectorTool({
91450
+ name: "request_with_delegation",
91451
+ description: "Call the Google Calendar API on behalf of the specified Workspace user via Domain-wide Delegation. Read-only operations only. Pass `subject` as the target user email and `scopes` as a read-only Calendar scope (e.g., ['https://www.googleapis.com/auth/calendar.readonly']). Use this tool when the project knowledge records the calendar with `(delegation, subject: <email>, ...)`. Requires Domain-wide Delegation to be authorized for the service account in the Workspace admin console.",
91571
91452
  inputSchema: inputSchema22,
91572
91453
  outputSchema: outputSchema22,
91573
- async execute({ connectionId, method, path: path4, queryParams, body, subject }, connections) {
91454
+ async execute({ connectionId, method, path: path4, subject, scopes, queryParams, body }, connections) {
91574
91455
  const connection = connections.find((c6) => c6.id === connectionId);
91575
91456
  if (!connection) {
91576
91457
  return {
@@ -91578,41 +91459,40 @@ Authentication is handled automatically using a service account.
91578
91459
  error: `Connection ${connectionId} not found`
91579
91460
  };
91580
91461
  }
91462
+ const keyJsonBase64 = parameters14.serviceAccountKeyJsonBase64.getValue(connection);
91463
+ let serviceAccount;
91464
+ try {
91465
+ serviceAccount = decodeServiceAccount2(keyJsonBase64);
91466
+ } catch (err) {
91467
+ const msg = err instanceof Error ? err.message : String(err);
91468
+ return {
91469
+ success: false,
91470
+ error: `Failed to decode service account key: ${msg}`
91471
+ };
91472
+ }
91473
+ const serviceAccountEmail = serviceAccount.client_email;
91581
91474
  console.log(
91582
- `[connector-request] google-calendar/${connection.name}: ${method} ${path4}`
91475
+ `[connector-request] google-calendar/${connection.name}: ${method} ${path4} subject=${subject}`
91583
91476
  );
91584
91477
  try {
91585
91478
  const { GoogleAuth } = await import("google-auth-library");
91586
- const keyJsonBase64 = parameters14.serviceAccountKeyJsonBase64.getValue(connection);
91587
- const impersonateEmail = impersonateEmailParameter.tryGetValue(connection);
91588
- const calendarId = calendarIdParameter.tryGetValue(connection) ?? "primary";
91589
- const resolvedSubject = subject ?? impersonateEmail;
91590
- if (!resolvedSubject) {
91591
- return {
91592
- success: false,
91593
- error: `Missing required parameter: ${impersonateEmailParameter.slug}. Configure the user email for this connection.`
91594
- };
91595
- }
91596
- const credentials = JSON.parse(
91597
- Buffer.from(keyJsonBase64, "base64").toString("utf-8")
91598
- );
91599
91479
  const auth = new GoogleAuth({
91600
- credentials,
91601
- scopes: [
91602
- "https://www.googleapis.com/auth/calendar.readonly",
91603
- "https://www.googleapis.com/auth/calendar.events.readonly"
91604
- ],
91605
- clientOptions: { subject: resolvedSubject }
91480
+ credentials: {
91481
+ client_email: serviceAccount.client_email,
91482
+ private_key: serviceAccount.private_key
91483
+ },
91484
+ scopes,
91485
+ clientOptions: { subject }
91606
91486
  });
91607
91487
  const token = await auth.getAccessToken();
91608
91488
  if (!token) {
91609
91489
  return {
91610
91490
  success: false,
91611
- error: "Failed to obtain access token"
91491
+ error: "Failed to obtain access token",
91492
+ serviceAccountEmail
91612
91493
  };
91613
91494
  }
91614
- const resolvedPath = path4.replace(/\{calendarId\}/g, calendarId);
91615
- let url = `${BASE_URL7}${resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
91495
+ let url = `${BASE_URL7}${path4.startsWith("/") ? "" : "/"}${path4}`;
91616
91496
  if (queryParams) {
91617
91497
  const searchParams = new URLSearchParams(queryParams);
91618
91498
  url += `?${searchParams.toString()}`;
@@ -91620,28 +91500,24 @@ Authentication is handled automatically using a service account.
91620
91500
  const controller = new AbortController();
91621
91501
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS12);
91622
91502
  try {
91503
+ const hasBody = body != null && ["POST", "PUT", "PATCH"].includes(method);
91623
91504
  const response = await fetch(url, {
91624
91505
  method,
91625
91506
  headers: {
91626
91507
  Authorization: `Bearer ${token}`,
91627
91508
  "Content-Type": "application/json"
91628
91509
  },
91629
- body: body && ["POST", "PUT", "PATCH"].includes(method) ? JSON.stringify(body) : void 0,
91510
+ body: hasBody ? JSON.stringify(body) : void 0,
91630
91511
  signal: controller.signal
91631
91512
  });
91632
- if (method === "DELETE" && response.status === 204) {
91633
- return {
91634
- success: true,
91635
- status: 204,
91636
- data: { message: "Deleted successfully" }
91637
- };
91638
- }
91639
- const data = await response.json();
91513
+ const data = await response.json().catch(() => ({}));
91640
91514
  if (!response.ok) {
91641
91515
  const errorObj = data?.error;
91516
+ const errorMessage = errorObj?.message ?? (typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`);
91642
91517
  return {
91643
91518
  success: false,
91644
- error: errorObj?.message ?? `HTTP ${response.status} ${response.statusText}`
91519
+ error: errorMessage,
91520
+ serviceAccountEmail
91645
91521
  };
91646
91522
  }
91647
91523
  return { success: true, status: response.status, data };
@@ -91650,13 +91526,200 @@ Authentication is handled automatically using a service account.
91650
91526
  }
91651
91527
  } catch (err) {
91652
91528
  const msg = err instanceof Error ? err.message : String(err);
91653
- return { success: false, error: msg };
91529
+ return {
91530
+ success: false,
91531
+ error: msg,
91532
+ serviceAccountEmail
91533
+ };
91654
91534
  }
91655
91535
  }
91656
91536
  });
91657
91537
 
91538
+ // ../connectors/src/connectors/google-calendar/setup.ts
91539
+ var requestToolName = `google-calendar-service-account_${requestTool5.name}`;
91540
+ var requestWithDelegationToolName = `google-calendar-service-account_${requestWithDelegationTool.name}`;
91541
+ var READONLY_SCOPES = '["https://www.googleapis.com/auth/calendar.readonly"]';
91542
+ var SERVICE_ACCOUNT_KEY_PARAM_SLUG = parameters14.serviceAccountKeyJsonBase64.slug;
91543
+ var googleCalendarOnboarding = new ConnectorOnboarding({
91544
+ connectionSetupInstructions: {
91545
+ ja: `Google Calendar \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u3092\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3057\u307E\u3059\u3002\u30A2\u30AF\u30BB\u30B9\u65B9\u6CD5\u3092\u9078\u3093\u3067\u3082\u3089\u3044\u3001\u5BFE\u8C61\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u767A\u898B\u30FB\u9078\u629E\u3057\u3066 Project Knowledge \u306B\u8A18\u9332\u3057\u307E\u3059\u3002
91546
+
91547
+ ## \u30B9\u30C6\u30C3\u30D7 1: \u30A2\u30AF\u30BB\u30B9\u65B9\u6CD5\u3092\u9078\u629E
91548
+
91549
+ \`askUserQuestion\` \u3067\u6B21\u306E 3 \u629E\u3092\u63D0\u793A\u3059\u308B:
91550
+ - \`type\`: \`"select"\`
91551
+ - \`question\`: \u300C\u3069\u306E\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3057\u307E\u3059\u304B\uFF1F\u300D
91552
+ - \`options\`:
91553
+ - \`{ label: "\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u5171\u6709\u3055\u308C\u3066\u3044\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u4F7F\u3046", value: "service-account" }\`
91554
+ - \`{ label: "\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3067\u7D44\u7E54\u306E\u30E6\u30FC\u30B6\u30FC\u306E\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u30A2\u30AF\u30BB\u30B9\u3059\u308B", value: "delegation" }\`
91555
+ - \`{ label: "\u4E21\u65B9\u3092\u7D44\u307F\u5408\u308F\u305B\u308B", value: "both" }\`
91556
+
91557
+ ## \u30B9\u30C6\u30C3\u30D7 2: \u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u7D4C\u8DEF\u306E\u767A\u898B\u3068\u9078\u629E (\`"service-account"\` \u307E\u305F\u306F \`"both"\` \u306E\u5834\u5408)
91558
+
91559
+ 1. \`${requestToolName}\` \u3092\u547C\u3093\u3067\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
91560
+ - \`method\`: \`"GET"\`
91561
+ - \`path\`: \`"/users/me/calendarList"\`
91562
+ - \`scopes\`: \`${READONLY_SCOPES}\`
91563
+
91564
+ 2. \u53D6\u5F97\u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
91565
+ - \u7D50\u679C\u304C\u7A7A: \u30A2\u30AF\u30BB\u30B9\u65B9\u6CD5\u304C \`"service-account"\` \u3060\u3051\u306A\u3089\u30B9\u30C6\u30C3\u30D7 5 (\u30A8\u30B9\u30AB\u30EC\u30FC\u30B7\u30E7\u30F3) \u3078\u3002\`"both"\` \u306E\u5834\u5408\u306F\u305D\u306E\u307E\u307E\u30B9\u30C6\u30C3\u30D7 3 \u3078\u9032\u3080
91566
+ - \u7D50\u679C\u304C\u3042\u308B: \`askUserQuestion\` \u3067\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u3070\u305B\u308B
91567
+ - \`type\`: \`"multiSelect"\`
91568
+ - \`question\`: \u300C\u4F7F\u7528\u3059\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u53EF\uFF09\u300D
91569
+ - \`options\`: \u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u3064\u3044\u3066 \`label\`: \`"<\u30AB\u30EC\u30F3\u30C0\u30FC\u540D>"\`\u3001\`value\`: \`"<calendarId>"\`
91570
+
91571
+ ## \u30B9\u30C6\u30C3\u30D7 3: \u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u7D4C\u8DEF\u306E\u767A\u898B\u3068\u9078\u629E (\`"delegation"\` \u307E\u305F\u306F \`"both"\` \u306E\u5834\u5408)
91572
+
91573
+ 1. \`askUserQuestion\` \u3067\u5BFE\u8C61\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u805E\u304F:
91574
+ - \`type\`: \`"freeText"\`
91575
+ - \`question\`: \u300C\u30A2\u30AF\u30BB\u30B9\u3057\u305F\u3044\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u6240\u6709\u3059\u308B Google Workspace \u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u53EF\u3001\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09\u3002Workspace \u7BA1\u7406\u8005\u304C\u3001\u3053\u306E\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u5BFE\u3057\u3066\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3092\u3042\u3089\u304B\u3058\u3081\u627F\u8A8D\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08[\u7BA1\u7406\u8005\u5411\u3051\u8A2D\u5B9A\u30AC\u30A4\u30C9](https://support.google.com/a/answer/162106)\uFF09\u3002\u300D
91576
+ - \`placeholder\`: \`"alice@example.com, bob@example.com"\`
91577
+
91578
+ 2. \u30E6\u30FC\u30B6\u30FC\u304B\u3089\u53D7\u3051\u53D6\u3063\u305F\u6587\u5B57\u5217\u304B\u3089\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u62BD\u51FA\u3057\u3001\u5404 \`<email>\` \u306B\u3064\u3044\u3066 \`${requestWithDelegationToolName}\` \u3092\u547C\u3076:
91579
+ - \`method\`: \`"GET"\`
91580
+ - \`path\`: \`"/users/me/calendarList"\`
91581
+ - \`subject\`: \`<email>\`
91582
+ - \`scopes\`: \`${READONLY_SCOPES}\`
91583
+
91584
+ 3. \u53D6\u5F97\u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
91585
+ - \u5168 email \u3067\u53D6\u5F97\u5931\u6557: \u30A2\u30AF\u30BB\u30B9\u65B9\u6CD5\u304C \`"delegation"\` \u3060\u3051\u3001\u3082\u3057\u304F\u306F \`"both"\` \u3067\u30B9\u30C6\u30C3\u30D7 2 \u3067\u3082 0 \u4EF6\u306E\u5834\u5408\u306F\u30B9\u30C6\u30C3\u30D7 5 \u3078\u3002\`"both"\` \u3067\u30B9\u30C6\u30C3\u30D7 2 \u306B\u30AB\u30EC\u30F3\u30C0\u30FC\u304C\u3042\u3063\u305F\u5834\u5408\u306F\u305D\u306E\u307E\u307E\u30B9\u30C6\u30C3\u30D7 4 \u3078
91586
+ - \u4E00\u90E8\u307E\u305F\u306F\u5168\u4EF6\u6210\u529F: \`askUserQuestion\` \u3067\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u3070\u305B\u308B
91587
+ - \`type\`: \`"multiSelect"\`
91588
+ - \`question\`: \u300C\u4F7F\u7528\u3059\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u53EF\uFF09\u300D
91589
+ - \`options\`: \u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u3064\u3044\u3066 \`label\`: \`"<\u30AB\u30EC\u30F3\u30C0\u30FC\u540D> (\u6240\u6709\u8005: <\u305D\u306E\u3068\u304D\u306E subject>)"\`\u3001\`value\`: \`"<calendarId>"\`
91590
+ - \u4E00\u90E8\u5931\u6557\u304C\u3042\u308C\u3070\u3001\u305D\u306E\u65E8\u3092 1 \u6587\u3067\u77ED\u304F\u4F1D\u3048\u308B
91591
+
91592
+ ## \u30B9\u30C6\u30C3\u30D7 4: Project Knowledge \u306B\u8A18\u9332
91593
+
91594
+ \u30B9\u30C6\u30C3\u30D7 2 \u3068 3 \u3067\u9078\u3070\u308C\u305F calendarId \u96C6\u5408\u3092\u30C7\u30A3\u30B9\u30AB\u30D0\u30EA\u7D50\u679C\u3068\u7A81\u304D\u5408\u308F\u305B\u3066\u3001\u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u7D4C\u8DEF\u3068 subject \u3092\u7279\u5B9A\u3059\u308B\u3002\`finalizeSetup\` \u3092\u547C\u3073\u3001\`projectKnowledge\` \u306E \`#### \u30B9\u30B3\u30FC\u30D7\` \u7BC0\u306B\u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u3092 1 \u884C\u305A\u3064\u5217\u6319\u3059\u308B:
91595
+ - \u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u7D4C\u7531: \`- calendar: <calendarId> (delegation, subject: <subject>, name: "<\u30AB\u30EC\u30F3\u30C0\u30FC\u540D>")\`
91596
+ - \u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u7D4C\u8DEF: \`- calendar: <calendarId> (service-account, name: "<\u30AB\u30EC\u30F3\u30C0\u30FC\u540D>")\`
91597
+
91598
+ ## \u30B9\u30C6\u30C3\u30D7 5: \u6700\u7D42\u7684\u306B\u30AB\u30EC\u30F3\u30C0\u30FC\u304C 0 \u4EF6\u306E\u5834\u5408\u306E\u30A8\u30B9\u30AB\u30EC\u30FC\u30B7\u30E7\u30F3
91599
+
91600
+ \u6700\u7D42\u7684\u306B\u9078\u629E\u30AB\u30EC\u30F3\u30C0\u30FC\u304C 1 \u4EF6\u3082\u7121\u3044\u5834\u5408 (\u5404\u7D4C\u8DEF\u306E\u767A\u898B\u304C\u7A7A\u3001\u307E\u305F\u306F\u9078\u629E\u3055\u308C\u306A\u304B\u3063\u305F)\u3001\u30A8\u30E9\u30FC\u30EC\u30B9\u30DD\u30F3\u30B9\u304B\u3089 \`serviceAccountEmail\` \u3092\u53D6\u308A\u51FA\u3057\u3001\`askUserQuestion\` \u3067\u6B21\u306E\u3088\u3046\u306B\u6848\u5185\u3059\u308B:
91601
+
91602
+ - \`question\`: \u300C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6B21\u306E\u3044\u305A\u308C\u304B\u3092\u884C\u3063\u3066\u304B\u3089\u7D9A\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8: \`<serviceAccountEmail>\`\u3002\u300D
91603
+ - \`options\`: \u3053\u3053\u307E\u3067\u306B\u8A66\u3057\u305F\u7D4C\u8DEF\u306B\u5FDC\u3058\u3066\u4EE5\u4E0B\u3092\u7D44\u307F\u5408\u308F\u305B\u308B:
91604
+ - \u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u7D4C\u8DEF\u3092\u8A66\u3057\u305F\u5834\u5408: \`{ label: "\u5BFE\u8C61\u30AB\u30EC\u30F3\u30C0\u30FC\u3092\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u5171\u6709\u3057\u305F\u306E\u3067\u30EA\u30C8\u30E9\u30A4", value: "retry" }\`
91605
+ - \u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u7D4C\u8DEF\u3092\u8A66\u3057\u305F\u5834\u5408: \`{ label: "\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3092\u627F\u8A8D\u3057\u305F\u306E\u3067\u30EA\u30C8\u30E9\u30A4", value: "retry" }\`
91606
+ - \u5E38\u306B: \`{ label: "\u30A2\u30AF\u30BB\u30B9\u65B9\u6CD5\u3092\u5909\u66F4\u3059\u308B", value: "restart" }\`
91607
+ - \u5E38\u306B: \`{ label: "\u5225\u306E\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u3067\u8A2D\u5B9A\u3057\u76F4\u3059", value: "change-service-account" }\`
91608
+
91609
+ \u9078\u629E\u7D50\u679C\u306B\u5FDC\u3058\u305F\u6319\u52D5:
91610
+ - "retry": \u76F4\u524D\u306E\u7D4C\u8DEF\u3092\u518D probe (\u5177\u4F53\u7684\u306A\u3084\u308A\u76F4\u3057\u65B9\u306F\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306B\u4EFB\u305B\u308B)
91611
+ - "restart": \u30B9\u30C6\u30C3\u30D7 1 \u304B\u3089\u518D\u5B9F\u884C
91612
+ - "change-service-account": \`updateConnectionParameters\` \u3092\u547C\u3093\u3067\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8 JSON \u3092\u518D\u5165\u529B\u3055\u305B\u308B:
91613
+ - \`parameterSlug\`: \`"${SERVICE_ACCOUNT_KEY_PARAM_SLUG}"\`
91614
+ - \u5B8C\u4E86\u5F8C\u3001\u30B9\u30C6\u30C3\u30D7 1 \u304B\u3089\u518D\u5B9F\u884C
91615
+
91616
+ ## \u5236\u7D04
91617
+
91618
+ - \u4E0A\u8A18\u4EE5\u5916\u306E API \u547C\u3073\u51FA\u3057\u3092 setup \u4E2D\u306B\u884C\u308F\u306A\u3044
91619
+ - \u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u306E\u9593\u306F 1 \u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057`,
91620
+ en: `Set up the Google Calendar connection. Ask the user how they want to access calendars, discover and select the target calendars, and record them in Project Knowledge.
91621
+
91622
+ ## Step 1: Choose the access method
91623
+
91624
+ Call \`askUserQuestion\`:
91625
+ - \`type\`: \`"select"\`
91626
+ - \`question\`: "Which calendars do you want to access?"
91627
+ - \`options\`:
91628
+ - \`{ label: "Calendars shared with this service account", value: "service-account" }\`
91629
+ - \`{ label: "Calendars of users in your organization (via Domain-wide Delegation)", value: "delegation" }\`
91630
+ - \`{ label: "Both", value: "both" }\`
91631
+
91632
+ ## Step 2: Discover and select via the service-account path (when \`"service-account"\` or \`"both"\`)
91633
+
91634
+ 1. Call \`${requestToolName}\`:
91635
+ - \`method\`: \`"GET"\`
91636
+ - \`path\`: \`"/users/me/calendarList"\`
91637
+ - \`scopes\`: \`${READONLY_SCOPES}\`
91638
+
91639
+ 2. Branch on the result:
91640
+ - Empty: if the access method is \`"service-account"\` only, jump to Step 5. If \`"both"\`, continue to Step 3.
91641
+ - Non-empty: ask the user to pick:
91642
+ - \`type\`: \`"multiSelect"\`
91643
+ - \`question\`: "Select the calendars to use (multiple allowed)"
91644
+ - \`options\`: For each calendar, \`label\`: \`"<calendar name>"\`, \`value\`: \`"<calendarId>"\`
91645
+
91646
+ ## Step 3: Discover and select via the Domain-wide Delegation path (when \`"delegation"\` or \`"both"\`)
91647
+
91648
+ 1. Ask the user for target emails:
91649
+ - \`type\`: \`"freeText"\`
91650
+ - \`question\`: "Enter the email addresses of the Google Workspace users whose calendars you want to access (comma-separated for multiple). Your Workspace admin must have authorized Domain-wide Delegation for this service account in advance ([admin setup guide](https://support.google.com/a/answer/162106))."
91651
+ - \`placeholder\`: \`"alice@example.com, bob@example.com"\`
91652
+
91653
+ 2. Extract individual emails and, for each \`<email>\`, call \`${requestWithDelegationToolName}\`:
91654
+ - \`method\`: \`"GET"\`
91655
+ - \`path\`: \`"/users/me/calendarList"\`
91656
+ - \`subject\`: \`<email>\`
91657
+ - \`scopes\`: \`${READONLY_SCOPES}\`
91658
+
91659
+ 3. Branch on the results:
91660
+ - All emails failed: if the access method is \`"delegation"\` only, or it's \`"both"\` but Step 2 also produced 0 calendars, jump to Step 5. If \`"both"\` and Step 2 had calendars, proceed to Step 4.
91661
+ - Any success: ask the user to pick:
91662
+ - \`type\`: \`"multiSelect"\`
91663
+ - \`question\`: "Select the calendars to use (multiple allowed)"
91664
+ - \`options\`: For each calendar, \`label\`: \`"<calendar name> (owner: <the subject used>)"\`, \`value\`: \`"<calendarId>"\`
91665
+ - If some emails failed, mention that briefly in one sentence.
91666
+
91667
+ ## Step 4: Record in Project Knowledge
91668
+
91669
+ Aggregate the calendarIds selected in Steps 2 and 3, cross-reference the discovery results to recover each calendar's access path and subject, and call \`finalizeSetup\`. Under \`#### \u30B9\u30B3\u30FC\u30D7\` in \`projectKnowledge\`, list each calendar on its own line:
91670
+ - Via Domain-wide Delegation: \`- calendar: <calendarId> (delegation, subject: <subject>, name: "<calendar name>")\`
91671
+ - Via service account: \`- calendar: <calendarId> (service-account, name: "<calendar name>")\`
91672
+
91673
+ ## Step 5: Escalation when zero calendars are selected
91674
+
91675
+ If the final selected calendar set is empty (every attempted path returned nothing, or the user picked nothing), take \`serviceAccountEmail\` from any failed tool response and call \`askUserQuestion\`:
91676
+
91677
+ - \`question\`: "No accessible calendars found. Please do one of the following before continuing. Service account: \`<serviceAccountEmail>\`."
91678
+ - \`options\`: Combine these based on which paths were attempted:
91679
+ - Service-account path attempted: \`{ label: "Shared the calendar with the service account \u2014 retry", value: "retry" }\`
91680
+ - Domain-wide Delegation path attempted: \`{ label: "Authorized Domain-wide Delegation \u2014 retry", value: "retry" }\`
91681
+ - Always: \`{ label: "Change the access method", value: "restart" }\`
91682
+ - Always: \`{ label: "Use a different service account", value: "change-service-account" }\`
91683
+
91684
+ Behavior per selection:
91685
+ - "retry": re-probe the path that was just attempted (leave the exact retry plan to the agent)
91686
+ - "restart": re-run from Step 1
91687
+ - "change-service-account": call \`updateConnectionParameters\` to have the user re-upload the service account JSON:
91688
+ - \`parameterSlug\`: \`"${SERVICE_ACCOUNT_KEY_PARAM_SLUG}"\`
91689
+ - After it completes, re-run from Step 1
91690
+
91691
+ ## Constraints
91692
+
91693
+ - Do not call any other API endpoints during setup
91694
+ - Write at most 1 sentence between tool calls`
91695
+ },
91696
+ dataOverviewInstructions: {
91697
+ en: `For each calendar recorded under \`#### \u30B9\u30B3\u30FC\u30D7\`, fetch metadata and a small sample of upcoming events. The annotation on each line tells you which tool to use:
91698
+ - \`(delegation, subject: <email>, ...)\` \u2192 \`${requestWithDelegationToolName}\` with \`subject: <email>\`
91699
+ - \`(service-account, ...)\` \u2192 \`${requestToolName}\`
91700
+
91701
+ Pass \`scopes: ${READONLY_SCOPES}\` for every call.
91702
+
91703
+ For each calendar:
91704
+ 1. \`method=GET\`, \`path=/calendars/<id>\` to fetch metadata.
91705
+ 2. \`method=GET\`, \`path=/calendars/<id>/events\`, \`queryParams={ timeMin: <RFC3339 now>, maxResults: "10", singleEvents: "true", orderBy: "startTime" }\`.`,
91706
+ ja: `\`#### \u30B9\u30B3\u30FC\u30D7\` \u306E\u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u3064\u3044\u3066\u3001\u30E1\u30BF\u30C7\u30FC\u30BF\u3068\u76F4\u8FD1\u306E\u30A4\u30D9\u30F3\u30C8\u3092\u5C11\u91CF\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u5404\u884C\u306E\u6CE8\u91C8\u3067\u4F7F\u7528\u3059\u308B\u30C4\u30FC\u30EB\u3092\u9078\u3073\u307E\u3059:
91707
+ - \`(delegation, subject: <email>, ...)\` \u2192 \`${requestWithDelegationToolName}\` \u3092 \`subject: <email>\` \u4ED8\u304D\u3067\u547C\u3076
91708
+ - \`(service-account, ...)\` \u2192 \`${requestToolName}\` \u3092\u547C\u3076
91709
+
91710
+ \`scopes\` \u306F\u6BCE\u56DE \`${READONLY_SCOPES}\` \u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
91711
+
91712
+ \u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306B\u3064\u3044\u3066:
91713
+ 1. \`method=GET\`\u3001\`path=/calendars/<id>\` \u3067\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
91714
+ 2. \`method=GET\`\u3001\`path=/calendars/<id>/events\`\u3001\`queryParams={ timeMin: <RFC3339 \u306E\u73FE\u5728\u6642\u523B>, maxResults: "10", singleEvents: "true", orderBy: "startTime" }\``
91715
+ }
91716
+ });
91717
+
91658
91718
  // ../connectors/src/connectors/google-calendar/index.ts
91659
- var tools14 = { request: requestTool5, listCalendars: listCalendarsTool };
91719
+ var tools14 = {
91720
+ request: requestTool5,
91721
+ request_with_delegation: requestWithDelegationTool
91722
+ };
91660
91723
  var googleCalendarConnector = new ConnectorPlugin({
91661
91724
  slug: "google-calendar",
91662
91725
  authType: AUTH_TYPES.SERVICE_ACCOUNT,
@@ -91669,58 +91732,45 @@ var googleCalendarConnector = new ConnectorPlugin({
91669
91732
  systemPrompt: {
91670
91733
  en: `### Tools
91671
91734
 
91672
- - \`google-calendar-service-account_request\`: The only way to call the Google Calendar API. Use it to list calendars, get events, and manage calendar data. Authentication is handled automatically using a service account with Domain-wide Delegation \u2014 the service account impersonates the user configured on the connection (\`impersonate-email\` parameter). The {calendarId} placeholder in paths is automatically replaced with the configured default calendar ID. Pass an optional \`subject\` only if you need to override the configured user for a specific request.
91735
+ This connector exposes two request tools that correspond to the two ways a Service Account can authenticate against the Google Calendar API:
91673
91736
 
91674
- ### Business Logic
91737
+ - \`google-calendar-service-account_request_with_delegation\`: Call the Calendar API on behalf of the specified Workspace user via Domain-wide Delegation. Pass \`subject\` as the target user email. Requires Domain-wide Delegation to be authorized for the service account in the Workspace admin console.
91738
+ - \`google-calendar-service-account_request\`: Call the Calendar API as the service account itself (no delegation). Only calendars explicitly shared with the service account email are accessible.
91675
91739
 
91676
- The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
91740
+ Both tools require a \`scopes\` argument.
91677
91741
 
91678
- SDK methods (client created via \`connection(connectionId)\` \u2014 the connection's \`impersonate-email\` parameter is used automatically for Domain-wide Delegation):
91679
- - \`client.listCalendars()\` \u2014 list all accessible calendars
91680
- - \`client.listEvents(options?, calendarId?)\` \u2014 list events with optional filters
91681
- - \`client.getEvent(eventId, calendarId?)\` \u2014 get a single event by ID
91682
- - \`client.request(path, init?)\` \u2014 low-level authenticated fetch
91742
+ ### OAuth Scopes (pass as \`scopes\` argument)
91683
91743
 
91684
- #### Domain-wide Delegation
91744
+ This connector is currently read-only. Pass one of:
91685
91745
 
91686
- The target user email is configured on the connection (\`impersonate-email\` parameter), so \`connection()\` automatically uses it. Pass \`subject\` only to override it:
91746
+ - \`https://www.googleapis.com/auth/calendar.readonly\` \u2014 read-only on calendars and events
91747
+ - \`https://www.googleapis.com/auth/calendar.events.readonly\` \u2014 read-only on events (no calendar metadata)
91748
+ - \`https://www.googleapis.com/auth/calendar.freebusy\` \u2014 busy/free time queries only
91687
91749
 
91688
- \`\`\`ts
91689
- const calendar = connection("<connectionId>", { subject: "other-user@example.com" });
91690
- \`\`\`
91750
+ For \`request_with_delegation\`, the Workspace admin must have authorized the requested scope for the service account in the Domain-wide Delegation settings, otherwise token issuance will fail with \`unauthorized_client\`.
91691
91751
 
91692
- \`\`\`ts
91693
- import type { Context } from "hono";
91694
- import { connection } from "@squadbase/vite-server/connectors/google-calendar";
91752
+ Per-endpoint scope reference: https://developers.google.com/calendar/api/auth
91695
91753
 
91696
- const calendar = connection("<connectionId>");
91754
+ ### Choosing the right tool
91697
91755
 
91698
- export default async function handler(c: Context) {
91699
- const now = new Date().toISOString();
91700
- const { items } = await calendar.listEvents({
91701
- timeMin: now,
91702
- maxResults: 10,
91703
- singleEvents: true,
91704
- orderBy: "startTime",
91705
- });
91756
+ Read \`#### \u30B9\u30B3\u30FC\u30D7\` in the project knowledge for this connection. Each calendar appears as a \`- calendar: <id> (...)\` line whose annotation tells you which tool to use:
91706
91757
 
91707
- return c.json(
91708
- items.map((event) => ({
91709
- id: event.id,
91710
- summary: event.summary,
91711
- start: event.start.dateTime ?? event.start.date,
91712
- end: event.end.dateTime ?? event.end.date,
91713
- location: event.location,
91714
- })),
91715
- );
91716
- }
91717
- \`\`\`
91758
+ - \`(delegation, subject: <email>, name: "...")\` \u2192 use \`request_with_delegation\` and pass \`subject: <email>\`
91759
+ - \`(service-account, name: "...")\` \u2192 use \`request\` (no \`subject\`)
91760
+
91761
+ ### Path conventions
91762
+
91763
+ Write the calendar ID directly into the path \u2014 there is no placeholder substitution. Examples:
91764
+
91765
+ - \`/users/me/calendarList\` \u2014 list calendars accessible to the authenticated identity
91766
+ - \`/calendars/alice@example.com/events\` \u2014 events on alice's primary calendar
91767
+ - \`/calendars/c_abc123@group.calendar.google.com/events\` \u2014 events on a secondary calendar
91718
91768
 
91719
91769
  ### Google Calendar API v3 Reference
91720
91770
 
91721
91771
  #### Available Endpoints
91722
91772
  - GET \`/calendars/{calendarId}\` \u2014 Get calendar metadata
91723
- - GET \`/users/me/calendarList\` \u2014 List all calendars accessible by the authenticated user
91773
+ - GET \`/users/me/calendarList\` \u2014 List all calendars accessible by the authenticated identity
91724
91774
  - GET \`/calendars/{calendarId}/events\` \u2014 List events on a calendar
91725
91775
  - GET \`/calendars/{calendarId}/events/{eventId}\` \u2014 Get a single event
91726
91776
 
@@ -91732,66 +91782,93 @@ export default async function handler(c: Context) {
91732
91782
  - \`orderBy=startTime\` \u2014 Order by start time (requires singleEvents=true)
91733
91783
  - \`q\` \u2014 Free text search terms
91734
91784
 
91735
- #### Tips
91736
- - Use \`{calendarId}\` placeholder in paths \u2014 it is automatically replaced with the configured default calendar ID
91737
- - Set \`singleEvents=true\` to expand recurring events into individual instances
91738
- - When using \`orderBy=startTime\`, you must also set \`singleEvents=true\`
91739
- - Use RFC3339 format for time parameters (e.g., "2024-01-15T09:00:00Z" or "2024-01-15T09:00:00+09:00")
91740
- - The default calendar ID is "primary" if not configured`,
91741
- ja: `### \u30C4\u30FC\u30EB
91742
-
91743
- - \`google-calendar-service-account_request\`: Google Calendar API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u53D6\u5F97\u3001\u30A4\u30D9\u30F3\u30C8\u306E\u53D6\u5F97\u3001\u30AB\u30EC\u30F3\u30C0\u30FC\u30C7\u30FC\u30BF\u306E\u7BA1\u7406\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\uFF0BDomain-wide Delegation\u3067\u8A8D\u8A3C\u304C\u81EA\u52D5\u7684\u306B\u51E6\u7406\u3055\u308C\u3001\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306B\u8A2D\u5B9A\u3055\u308C\u305F\u30E6\u30FC\u30B6\u30FC\uFF08\`impersonate-email\`\u30D1\u30E9\u30E1\u30FC\u30BF\uFF09\u3068\u3057\u3066\u52D5\u4F5C\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{calendarId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002\u7279\u5B9A\u30EA\u30AF\u30A8\u30B9\u30C8\u3067\u8A2D\u5B9A\u30E6\u30FC\u30B6\u30FC\u3092\u4E0A\u66F8\u304D\u3057\u305F\u3044\u5834\u5408\u306E\u307F\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\`subject\`\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
91744
-
91745
91785
  ### Business Logic
91746
91786
 
91747
- \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
91787
+ The business logic type for this connector is "typescript". Use the connector SDK in your handler. Do NOT read credentials from environment variables.
91748
91788
 
91749
- SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8 \u2014 \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\`impersonate-email\`\u30D1\u30E9\u30E1\u30FC\u30BF\u304C\u81EA\u52D5\u7684\u306BDomain-wide Delegation\u306Esubject\u3068\u3057\u3066\u4F7F\u308F\u308C\u307E\u3059):
91750
- - \`client.listCalendars()\` \u2014 \u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7\u53D6\u5F97
91751
- - \`client.listEvents(options?, calendarId?)\` \u2014 \u30D5\u30A3\u30EB\u30BF\u30FC\u4ED8\u304D\u30A4\u30D9\u30F3\u30C8\u4E00\u89A7\u53D6\u5F97
91752
- - \`client.getEvent(eventId, calendarId?)\` \u2014 ID\u306B\u3088\u308B\u5358\u4E00\u30A4\u30D9\u30F3\u30C8\u53D6\u5F97
91753
- - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304Dfetch
91789
+ SDK methods (client created via \`connection(connectionId)\`):
91754
91790
 
91755
- #### Domain-wide Delegation
91791
+ - \`client.requestWithDelegation(path, { subject, scopes, init? })\` \u2014 call the API as the impersonated Workspace user via Domain-wide Delegation
91792
+ - \`client.request(path, { scopes, init? })\` \u2014 call the API as the service account itself (only calendars shared with the SA email are accessible)
91756
91793
 
91757
- \u5BFE\u8C61\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\uFF08\`impersonate-email\`\u30D1\u30E9\u30E1\u30FC\u30BF\uFF09\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\`connection()\`\u306F\u81EA\u52D5\u7684\u306B\u305D\u308C\u3092\u4F7F\u3044\u307E\u3059\u3002\u4E0A\u66F8\u304D\u3057\u305F\u3044\u5834\u5408\u306E\u307F\`subject\`\u3092\u6E21\u3057\u307E\u3059\uFF1A
91794
+ Both methods take \`scopes\` \u2014 pass the minimum scope(s) for the endpoint. Both return a standard \`Response\`. Read the body with \`.json()\`. Same path conventions as the tools.
91758
91795
 
91759
- \`\`\`ts
91760
- const calendar = connection("<connectionId>", { subject: "other-user@example.com" });
91761
- \`\`\`
91796
+ #### Example
91762
91797
 
91763
91798
  \`\`\`ts
91764
91799
  import type { Context } from "hono";
91765
91800
  import { connection } from "@squadbase/vite-server/connectors/google-calendar";
91766
91801
 
91767
91802
  const calendar = connection("<connectionId>");
91803
+ const READ = ["https://www.googleapis.com/auth/calendar.readonly"];
91768
91804
 
91769
91805
  export default async function handler(c: Context) {
91770
91806
  const now = new Date().toISOString();
91771
- const { items } = await calendar.listEvents({
91807
+ const qs = new URLSearchParams({
91772
91808
  timeMin: now,
91773
- maxResults: 10,
91774
- singleEvents: true,
91809
+ maxResults: "10",
91810
+ singleEvents: "true",
91775
91811
  orderBy: "startTime",
91776
91812
  });
91777
91813
 
91778
- return c.json(
91779
- items.map((event) => ({
91780
- id: event.id,
91781
- summary: event.summary,
91782
- start: event.start.dateTime ?? event.start.date,
91783
- end: event.end.dateTime ?? event.end.date,
91784
- location: event.location,
91785
- })),
91814
+ // Project knowledge says: alice@example.com is reachable via delegation
91815
+ const aliceRes = await calendar.requestWithDelegation(
91816
+ \`/calendars/alice@example.com/events?\${qs}\`,
91817
+ { subject: "alice@example.com", scopes: READ },
91818
+ );
91819
+ const alice = await aliceRes.json();
91820
+
91821
+ // Project knowledge says: team@example.com is shared with the SA
91822
+ const teamRes = await calendar.request(
91823
+ \`/calendars/team@example.com/events?\${qs}\`,
91824
+ { scopes: READ },
91786
91825
  );
91826
+ const team = await teamRes.json();
91827
+
91828
+ return c.json({ alice: alice.items, team: team.items });
91787
91829
  }
91788
- \`\`\`
91830
+ \`\`\``,
91831
+ ja: `### \u30C4\u30FC\u30EB
91832
+
91833
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u30FC\u306F\u3001Service Account \u304C Google Calendar API \u306B\u8A8D\u8A3C\u3059\u308B 2 \u3064\u306E\u65B9\u6CD5\u306B\u5BFE\u5FDC\u3059\u308B 2 \u3064\u306E request \u30C4\u30FC\u30EB\u3092\u516C\u958B\u3057\u307E\u3059:
91834
+
91835
+ - \`google-calendar-service-account_request_with_delegation\`: \u6307\u5B9A\u3055\u308C\u305F Workspace \u30E6\u30FC\u30B6\u30FC\u306B\u4EE3\u308F\u3063\u3066 Domain-wide Delegation \u7D4C\u7531\u3067 Calendar API \u3092\u547C\u3073\u51FA\u3057\u307E\u3059\u3002\u4EE3\u7406\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092 \`subject\` \u3068\u3057\u3066\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002Workspace \u7BA1\u7406\u30B3\u30F3\u30BD\u30FC\u30EB\u3067 Service Account \u306E Domain-wide Delegation \u304C\u627F\u8A8D\u3055\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
91836
+ - \`google-calendar-service-account_request\`: Service Account \u81EA\u8EAB\u3068\u3057\u3066 Calendar API \u3092\u547C\u3073\u51FA\u3057\u307E\u3059 (Domain-wide Delegation \u3092\u4F7F\u308F\u306A\u3044\u7D4C\u8DEF)\u3002Service Account \u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306B\u660E\u793A\u7684\u306B\u5171\u6709\u3055\u308C\u3066\u3044\u308B\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u307F\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u3067\u3059\u3002
91837
+
91838
+ \u4E21\u30C4\u30FC\u30EB\u3068\u3082 \`scopes\` \u5F15\u6570\u304C\u5FC5\u9808\u3067\u3059\u3002
91839
+
91840
+ ### OAuth \u30B9\u30B3\u30FC\u30D7 (\`scopes\` \u5F15\u6570\u3067\u6E21\u3059)
91841
+
91842
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u30FC\u306F\u73FE\u72B6\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u3067\u3059\u3002\u6B21\u306E\u3044\u305A\u308C\u304B\u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044:
91843
+
91844
+ - \`https://www.googleapis.com/auth/calendar.readonly\` \u2014 \u30AB\u30EC\u30F3\u30C0\u30FC\u3068\u30A4\u30D9\u30F3\u30C8\u306E\u8AAD\u307F\u53D6\u308A
91845
+ - \`https://www.googleapis.com/auth/calendar.events.readonly\` \u2014 \u30A4\u30D9\u30F3\u30C8\u306E\u307F\u8AAD\u307F\u53D6\u308A\uFF08\u30AB\u30EC\u30F3\u30C0\u30FC\u30E1\u30BF\u30C7\u30FC\u30BF\u4E0D\u53EF\uFF09
91846
+ - \`https://www.googleapis.com/auth/calendar.freebusy\` \u2014 \u7A7A\u304D\u72B6\u6CC1\u30AF\u30A8\u30EA\u306E\u307F
91847
+
91848
+ \`request_with_delegation\` \u306E\u5834\u5408\u3001\u8981\u6C42\u3059\u308B scope \u306F Workspace \u7BA1\u7406\u8005\u304C Domain-wide Delegation \u8A2D\u5B9A\u3067\u5F53\u8A72 Service Account \u306B\u5BFE\u3057\u3066\u627F\u8A8D\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u627F\u8A8D\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u30C8\u30FC\u30AF\u30F3\u767A\u884C\u304C \`unauthorized_client\` \u3067\u5931\u6557\u3057\u307E\u3059\u3002
91849
+
91850
+ \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u5225\u306E\u6B63\u78BA\u306A scope \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9: https://developers.google.com/calendar/api/auth
91851
+
91852
+ ### \u9069\u5207\u306A\u30C4\u30FC\u30EB\u306E\u9078\u3073\u65B9
91853
+
91854
+ \u3053\u306E\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E Project Knowledge \u306E \`#### \u30B9\u30B3\u30FC\u30D7\` \u3092\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044\u3002\u5404\u30AB\u30EC\u30F3\u30C0\u30FC\u306F \`- calendar: <id> (...)\` \u5F62\u5F0F\u306E\u884C\u3068\u3057\u3066\u8A18\u9332\u3055\u308C\u3066\u304A\u308A\u3001\u6CE8\u91C8\u304C\u3069\u3061\u3089\u306E\u30C4\u30FC\u30EB\u3092\u4F7F\u3046\u3079\u304D\u304B\u3092\u793A\u3057\u307E\u3059:
91855
+
91856
+ - \`(delegation, subject: <email>, name: "...")\` \u2192 \`request_with_delegation\` \u3092\u4F7F\u3044\u3001\`subject: <email>\` \u3092\u6E21\u3059
91857
+ - \`(service-account, name: "...")\` \u2192 \`request\` \u3092\u4F7F\u3046\uFF08\`subject\` \u4E0D\u8981\uFF09
91858
+
91859
+ ### \u30D1\u30B9\u306E\u66F8\u304D\u65B9
91860
+
91861
+ calendar ID \u3092\u30D1\u30B9\u306B\u76F4\u63A5\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\u3002\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306E\u7F6E\u63DB\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u4F8B:
91862
+
91863
+ - \`/users/me/calendarList\` \u2014 \u8A8D\u8A3C\u3055\u308C\u305F\u8B58\u5225\u5B50\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7
91864
+ - \`/calendars/alice@example.com/events\` \u2014 alice \u306E\u30D7\u30E9\u30A4\u30DE\u30EA\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30A4\u30D9\u30F3\u30C8
91865
+ - \`/calendars/c_abc123@group.calendar.google.com/events\` \u2014 \u4E8C\u6B21\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30A4\u30D9\u30F3\u30C8
91789
91866
 
91790
91867
  ### Google Calendar API v3 \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
91791
91868
 
91792
91869
  #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
91793
91870
  - GET \`/calendars/{calendarId}\` \u2014 \u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
91794
- - GET \`/users/me/calendarList\` \u2014 \u8A8D\u8A3C\u30E6\u30FC\u30B6\u30FC\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7
91871
+ - GET \`/users/me/calendarList\` \u2014 \u8A8D\u8A3C\u3055\u308C\u305F\u8B58\u5225\u5B50\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u5168\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u4E00\u89A7
91795
91872
  - GET \`/calendars/{calendarId}/events\` \u2014 \u30AB\u30EC\u30F3\u30C0\u30FC\u4E0A\u306E\u30A4\u30D9\u30F3\u30C8\u4E00\u89A7
91796
91873
  - GET \`/calendars/{calendarId}/events/{eventId}\` \u2014 \u5358\u4E00\u30A4\u30D9\u30F3\u30C8\u306E\u53D6\u5F97
91797
91874
 
@@ -91803,12 +91880,52 @@ export default async function handler(c: Context) {
91803
91880
  - \`orderBy=startTime\` \u2014 \u958B\u59CB\u6642\u9593\u9806\u306B\u4E26\u3079\u66FF\u3048\uFF08singleEvents=true\u304C\u5FC5\u8981\uFF09
91804
91881
  - \`q\` \u2014 \u30D5\u30EA\u30FC\u30C6\u30AD\u30B9\u30C8\u691C\u7D22\u8A9E
91805
91882
 
91806
- #### \u30D2\u30F3\u30C8
91807
- - \u30D1\u30B9\u306B \`{calendarId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u3092\u4F7F\u7528 \u2014 \u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059
91808
- - \`singleEvents=true\` \u3092\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u7E70\u308A\u8FD4\u3057\u30A4\u30D9\u30F3\u30C8\u304C\u500B\u5225\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u306B\u5C55\u958B\u3055\u308C\u307E\u3059
91809
- - \`orderBy=startTime\` \u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u3001\`singleEvents=true\` \u3082\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
91810
- - \u6642\u9593\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u306FRFC3339\u5F62\u5F0F\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B: "2024-01-15T09:00:00Z" \u3084 "2024-01-15T09:00:00+09:00"\uFF09
91811
- - \u30C7\u30D5\u30A9\u30EB\u30C8\u30AB\u30EC\u30F3\u30C0\u30FCID\u306F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408 "primary" \u304C\u4F7F\u7528\u3055\u308C\u307E\u3059`
91883
+ ### Business Logic
91884
+
91885
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "typescript" \u3067\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u30B3\u30CD\u30AF\u30BFSDK\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u74B0\u5883\u5909\u6570\u304B\u3089\u8A8D\u8A3C\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u3089\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
91886
+
91887
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
91888
+
91889
+ - \`client.requestWithDelegation(path, { subject, scopes, init? })\` \u2014 Domain-wide Delegation \u3067\u6307\u5B9A Workspace \u30E6\u30FC\u30B6\u30FC\u306B\u4EE3\u308F\u3063\u3066 API \u3092\u547C\u3076
91890
+ - \`client.request(path, { scopes, init? })\` \u2014 SA \u81EA\u8EAB\u3068\u3057\u3066 API \u3092\u547C\u3076\uFF08SA \u306B\u5171\u6709\u3055\u308C\u305F\u30AB\u30EC\u30F3\u30C0\u30FC\u306E\u307F\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\uFF09
91891
+
91892
+ \u4E21\u30E1\u30BD\u30C3\u30C9\u3068\u3082 \`scopes\` \u3092\u53D7\u3051\u53D6\u308A\u307E\u3059\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u5FC5\u8981\u306A\u6700\u5C0F scope \u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u6A19\u6E96\u306E \`Response\` \u3092\u8FD4\u3059\u306E\u3067 \`response.json()\` \u3067\u30DC\u30C7\u30A3\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\u30D1\u30B9\u306E\u66F8\u304D\u65B9\u306F\u30C4\u30FC\u30EB\u3068\u540C\u3058\u3002
91893
+
91894
+ #### Example
91895
+
91896
+ \`\`\`ts
91897
+ import type { Context } from "hono";
91898
+ import { connection } from "@squadbase/vite-server/connectors/google-calendar";
91899
+
91900
+ const calendar = connection("<connectionId>");
91901
+ const READ = ["https://www.googleapis.com/auth/calendar.readonly"];
91902
+
91903
+ export default async function handler(c: Context) {
91904
+ const now = new Date().toISOString();
91905
+ const qs = new URLSearchParams({
91906
+ timeMin: now,
91907
+ maxResults: "10",
91908
+ singleEvents: "true",
91909
+ orderBy: "startTime",
91910
+ });
91911
+
91912
+ // Project Knowledge: alice@example.com \u306F delegation \u7D4C\u8DEF\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD
91913
+ const aliceRes = await calendar.requestWithDelegation(
91914
+ \`/calendars/alice@example.com/events?\${qs}\`,
91915
+ { subject: "alice@example.com", scopes: READ },
91916
+ );
91917
+ const alice = await aliceRes.json();
91918
+
91919
+ // Project Knowledge: team@example.com \u306F SA \u306B\u5171\u6709\u3055\u308C\u3066\u3044\u308B
91920
+ const teamRes = await calendar.request(
91921
+ \`/calendars/team@example.com/events?\${qs}\`,
91922
+ { scopes: READ },
91923
+ );
91924
+ const team = await teamRes.json();
91925
+
91926
+ return c.json({ alice: alice.items, team: team.items });
91927
+ }
91928
+ \`\`\``
91812
91929
  },
91813
91930
  tools: tools14
91814
91931
  });
@@ -91871,7 +91988,7 @@ var outputSchema23 = z23.discriminatedUnion("success", [
91871
91988
  error: z23.string()
91872
91989
  })
91873
91990
  ]);
91874
- var listCalendarsTool2 = new ConnectorTool({
91991
+ var listCalendarsTool = new ConnectorTool({
91875
91992
  name: "listCalendars",
91876
91993
  description: "List all Google Calendars accessible with the OAuth credentials. Use during setup to discover available calendars.",
91877
91994
  inputSchema: inputSchema23,
@@ -91932,12 +92049,12 @@ var listCalendarsTool2 = new ConnectorTool({
91932
92049
  });
91933
92050
 
91934
92051
  // ../connectors/src/connectors/google-calendar-oauth/setup.ts
91935
- var listCalendarsToolName2 = `google-calendar-oauth_${listCalendarsTool2.name}`;
92052
+ var listCalendarsToolName = `google-calendar-oauth_${listCalendarsTool.name}`;
91936
92053
  var googleCalendarOauthOnboarding = new ConnectorOnboarding({
91937
92054
  connectionSetupInstructions: {
91938
92055
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Calendar (OAuth) \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
91939
92056
 
91940
- 1. \`${listCalendarsToolName2}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
92057
+ 1. \`${listCalendarsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
91941
92058
  2. \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\`askUserQuestion\` \u3092\u547C\u3073\u51FA\u3059:
91942
92059
  - \`options\`: \u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30AB\u30EC\u30F3\u30C0\u30FC\u540D (id: \u30AB\u30EC\u30F3\u30C0\u30FCID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30AB\u30EC\u30F3\u30C0\u30FCID
91943
92060
  3. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
@@ -91949,7 +92066,7 @@ var googleCalendarOauthOnboarding = new ConnectorOnboarding({
91949
92066
  - \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`,
91950
92067
  en: `Follow these steps to set up the Google Calendar (OAuth) connection.
91951
92068
 
91952
- 1. Call \`${listCalendarsToolName2}\` to get the list of calendars accessible with the OAuth credentials
92069
+ 1. Call \`${listCalendarsToolName}\` to get the list of calendars accessible with the OAuth credentials
91953
92070
  2. Tell the user "Please select a calendar.", then call \`askUserQuestion\`:
91954
92071
  - \`options\`: The calendar list. Each option's \`label\` should be \`Calendar Name (id: calendarId)\`, \`value\` should be the calendar ID
91955
92072
  3. Call \`updateConnectionParameters\`:
@@ -92105,7 +92222,7 @@ Authentication is handled automatically via OAuth proxy.
92105
92222
  // ../connectors/src/connectors/google-calendar-oauth/index.ts
92106
92223
  var tools15 = {
92107
92224
  request: requestTool6,
92108
- listCalendars: listCalendarsTool2
92225
+ listCalendars: listCalendarsTool
92109
92226
  };
92110
92227
  var googleCalendarOauthConnector = new ConnectorPlugin({
92111
92228
  slug: "google-calendar",
@@ -93141,7 +93258,7 @@ Authentication is handled automatically via OAuth proxy.`,
93141
93258
  });
93142
93259
 
93143
93260
  // ../connectors/src/connectors/google-sheets/setup.ts
93144
- var requestToolName = `google-sheets-oauth_${requestTool9.name}`;
93261
+ var requestToolName2 = `google-sheets-oauth_${requestTool9.name}`;
93145
93262
  var googleSheetsOnboarding = new ConnectorOnboarding({
93146
93263
  connectionSetupInstructions: {
93147
93264
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Google Sheets (OAuth) \u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306F\u8AAD\u307F\u66F8\u304D\u53EF\u80FD\u306A\u30B9\u30B3\u30FC\u30D7 (\`spreadsheets\`) \u3067\u63A5\u7D9A\u3055\u308C\u3001OAuth\u8A8D\u8A3C\u3057\u305FGoogle\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u6A29\u9650\u3092\u6301\u3064\u4EFB\u610F\u306E\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306B\u5BFE\u3057\u3066\u8AAD\u307F\u66F8\u304D\u3067\u304D\u307E\u3059\u3002
@@ -93151,12 +93268,12 @@ var googleSheetsOnboarding = new ConnectorOnboarding({
93151
93268
  - \`question\`: \u300C\u64CD\u4F5C\u3057\u305F\u3044Google Sheets\u306EURL\u3092\u8CBC\u308A\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\uFF08\u8AAD\u307F\u53D6\u308A\u30FB\u7DE8\u96C6\u3069\u3061\u3089\u3082\u53EF\u80FD\u3067\u3059\uFF09\u300D
93152
93269
  - \`placeholder\`: \`"https://docs.google.com/spreadsheets/d/.../edit"\`
93153
93270
  2. \u53D7\u3051\u53D6\u3063\u305FURL\u304B\u3089\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u3092\u62BD\u51FA\u3059\u308B\u3002URL\u306E \`/d/\` \u3068 \`/edit\`\uFF08\u307E\u305F\u306F\u672B\u5C3E\uFF09\u306E\u9593\u306B\u3042\u308B\u6587\u5B57\u5217\u304C\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u3067\u3059\uFF08\u4F8B: \`https://docs.google.com/spreadsheets/d/1AbCxyz.../edit\` \u2192 \`1AbCxyz...\`\uFF09\u3002URL\u3067\u306F\u306A\u304FID\u3060\u3051\u304C\u6E21\u3055\u308C\u305F\u5834\u5408\u306F\u305D\u306E\u307E\u307E\u5229\u7528\u3057\u307E\u3059\u3002
93154
- 3. \`${requestToolName}\` \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u6027\u3092\u78BA\u8A8D\u3059\u308B:
93271
+ 3. \`${requestToolName2}\` \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u6027\u3092\u78BA\u8A8D\u3059\u308B:
93155
93272
  - \`method\`: \`"GET"\`
93156
93273
  - \`path\`: \`"/<\u62BD\u51FA\u3057\u305FspreadsheetId>"\`
93157
93274
  4. **\u691C\u8A3C\u5931\u6557\u6642\u306E\u518D\u30D2\u30A2\u30EA\u30F3\u30B0**: \u30B9\u30C6\u30C3\u30D73\u304C \`success: false\` \u3092\u8FD4\u3057\u305F\u5834\u5408\uFF08404/403/\u898B\u3064\u304B\u3089\u306A\u3044\u7B49\uFF09\u3001\u4EE5\u4E0B\u306E\u624B\u9806\u3067\u518D\u8A66\u884C\u3059\u308B:
93158
93275
  a. \u30E6\u30FC\u30B6\u30FC\u306B\u539F\u56E0\u306E\u53EF\u80FD\u6027\u3092\u4F1D\u3048\u308B\uFF08URL\u304C\u9593\u9055\u3063\u3066\u3044\u308B\u3001OAuth\u9023\u643A\u3057\u305FGoogle\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u30A2\u30AF\u30BB\u30B9\u6A29\u9650\u304C\u306A\u3044\u3001\u30D7\u30E9\u30A4\u30D9\u30FC\u30C8\u30B7\u30FC\u30C8\u3067\u5225\u30A2\u30AB\u30A6\u30F3\u30C8\u3068\u5171\u6709\u3055\u308C\u3066\u3044\u308B \u7B49\uFF09
93159
- b. \`askUserQuestion\` \u3067\u3082\u3046\u4E00\u5EA6URL\u3092\u805E\u304D\u76F4\u3057\u3001\u518D\u5EA6 \`${requestToolName}\` \u3067\u691C\u8A3C
93276
+ b. \`askUserQuestion\` \u3067\u3082\u3046\u4E00\u5EA6URL\u3092\u805E\u304D\u76F4\u3057\u3001\u518D\u5EA6 \`${requestToolName2}\` \u3067\u691C\u8A3C
93160
93277
  c. \u6210\u529F\u3059\u308B\u307E\u3067\uFF08\u307E\u305F\u306F\u30E6\u30FC\u30B6\u30FC\u304C\u4E2D\u65AD\u3059\u308B\u307E\u3067\uFF09\u3053\u306E\u30EB\u30FC\u30D7\u3092\u7E70\u308A\u8FD4\u3059
93161
93278
 
93162
93279
  #### \u5236\u7D04
@@ -93170,12 +93287,12 @@ var googleSheetsOnboarding = new ConnectorOnboarding({
93170
93287
  - \`question\`: "Please paste the URL of the Google Sheet you want to work with (both read and edit are supported)."
93171
93288
  - \`placeholder\`: \`"https://docs.google.com/spreadsheets/d/.../edit"\`
93172
93289
  2. Extract the spreadsheet ID from the URL. It is the segment between \`/d/\` and \`/edit\` (or the end of the URL), e.g. \`https://docs.google.com/spreadsheets/d/1AbCxyz.../edit\` \u2192 \`1AbCxyz...\`. If the user pasted just the ID, use it as-is.
93173
- 3. Verify accessibility by calling \`${requestToolName}\`:
93290
+ 3. Verify accessibility by calling \`${requestToolName2}\`:
93174
93291
  - \`method\`: \`"GET"\`
93175
93292
  - \`path\`: \`"/<extracted spreadsheetId>"\`
93176
93293
  4. **Retry on verification failure**: If step 3 returns \`success: false\` (404/403/not found or any other error):
93177
93294
  a. Tell the user the likely causes (wrong URL, OAuth-connected Google account lacks access, private sheet shared with a different account, etc.)
93178
- b. Call \`askUserQuestion\` again to re-ask for the URL and re-verify with \`${requestToolName}\`
93295
+ b. Call \`askUserQuestion\` again to re-ask for the URL and re-verify with \`${requestToolName2}\`
93179
93296
  c. Repeat until verification succeeds (or the user aborts)
93180
93297
 
93181
93298
  #### Constraints
@@ -93184,10 +93301,10 @@ var googleSheetsOnboarding = new ConnectorOnboarding({
93184
93301
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently.`
93185
93302
  },
93186
93303
  dataOverviewInstructions: {
93187
- en: `1. Call ${requestToolName} with GET /<spreadsheetId> to fetch spreadsheet metadata (sheet names, grid properties)
93188
- 2. For each sheet of interest, call ${requestToolName} with GET /<spreadsheetId>/values/<SheetName>!A1:Z5 to sample the first rows and understand the column layout`,
93189
- ja: `1. ${requestToolName} \u3067 GET /<spreadsheetId> \u3092\u547C\u3073\u51FA\u3057\u3001\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\uFF08\u30B7\u30FC\u30C8\u540D\u3001\u30B0\u30EA\u30C3\u30C9\u30D7\u30ED\u30D1\u30C6\u30A3\uFF09\u3092\u53D6\u5F97
93190
- 2. \u4E3B\u8981\u306A\u30B7\u30FC\u30C8\u306B\u3064\u3044\u3066 ${requestToolName} \u3067 GET /<spreadsheetId>/values/<\u30B7\u30FC\u30C8\u540D>!A1:Z5 \u3092\u547C\u3073\u51FA\u3057\u3001\u5148\u982D\u6570\u884C\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3057\u3066\u30AB\u30E9\u30E0\u69CB\u9020\u3092\u628A\u63E1`
93304
+ en: `1. Call ${requestToolName2} with GET /<spreadsheetId> to fetch spreadsheet metadata (sheet names, grid properties)
93305
+ 2. For each sheet of interest, call ${requestToolName2} with GET /<spreadsheetId>/values/<SheetName>!A1:Z5 to sample the first rows and understand the column layout`,
93306
+ ja: `1. ${requestToolName2} \u3067 GET /<spreadsheetId> \u3092\u547C\u3073\u51FA\u3057\u3001\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\uFF08\u30B7\u30FC\u30C8\u540D\u3001\u30B0\u30EA\u30C3\u30C9\u30D7\u30ED\u30D1\u30C6\u30A3\uFF09\u3092\u53D6\u5F97
93307
+ 2. \u4E3B\u8981\u306A\u30B7\u30FC\u30C8\u306B\u3064\u3044\u3066 ${requestToolName2} \u3067 GET /<spreadsheetId>/values/<\u30B7\u30FC\u30C8\u540D>!A1:Z5 \u3092\u547C\u3073\u51FA\u3057\u3001\u5148\u982D\u6570\u884C\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3057\u3066\u30AB\u30E9\u30E0\u69CB\u9020\u3092\u628A\u63E1`
93191
93308
  }
93192
93309
  });
93193
93310
 
@@ -93803,12 +93920,12 @@ Authentication is handled automatically via OAuth proxy.`,
93803
93920
  });
93804
93921
 
93805
93922
  // ../connectors/src/connectors/hubspot-oauth/setup.ts
93806
- var requestToolName2 = `hubspot-oauth_${requestTool11.name}`;
93923
+ var requestToolName3 = `hubspot-oauth_${requestTool11.name}`;
93807
93924
  var hubspotOnboarding = new ConnectorOnboarding({
93808
93925
  connectionSetupInstructions: {
93809
93926
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067HubSpot\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
93810
93927
 
93811
- 1. \`${requestToolName2}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
93928
+ 1. \`${requestToolName3}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
93812
93929
  - \`method\`: \`"GET"\`
93813
93930
  - \`path\`: \`"/account-info/v3/details"\`
93814
93931
  2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306BOAuth\u63A5\u7D9A\u306E\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
@@ -93818,7 +93935,7 @@ var hubspotOnboarding = new ConnectorOnboarding({
93818
93935
  - \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`,
93819
93936
  en: `Follow these steps to set up the HubSpot connection.
93820
93937
 
93821
- 1. Call \`${requestToolName2}\` to fetch account info:
93938
+ 1. Call \`${requestToolName3}\` to fetch account info:
93822
93939
  - \`method\`: \`"GET"\`
93823
93940
  - \`path\`: \`"/account-info/v3/details"\`
93824
93941
  2. If an error is returned, ask the user to check the OAuth connection settings
@@ -94092,12 +94209,12 @@ Authentication is handled automatically via OAuth proxy.`,
94092
94209
  });
94093
94210
 
94094
94211
  // ../connectors/src/connectors/stripe-oauth/setup.ts
94095
- var requestToolName3 = `stripe-oauth_${requestTool12.name}`;
94212
+ var requestToolName4 = `stripe-oauth_${requestTool12.name}`;
94096
94213
  var stripeOnboarding = new ConnectorOnboarding({
94097
94214
  connectionSetupInstructions: {
94098
94215
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Stripe\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
94099
94216
 
94100
- 1. \`${requestToolName3}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
94217
+ 1. \`${requestToolName4}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
94101
94218
  - \`method\`: \`"GET"\`
94102
94219
  - \`path\`: \`"/v1/accounts"\`
94103
94220
  2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306BOAuth\u63A5\u7D9A\u306E\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
@@ -94107,7 +94224,7 @@ var stripeOnboarding = new ConnectorOnboarding({
94107
94224
  - \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`,
94108
94225
  en: `Follow these steps to set up the Stripe connection.
94109
94226
 
94110
- 1. Call \`${requestToolName3}\` to fetch account info:
94227
+ 1. Call \`${requestToolName4}\` to fetch account info:
94111
94228
  - \`method\`: \`"GET"\`
94112
94229
  - \`path\`: \`"/v1/accounts"\`
94113
94230
  2. If an error is returned, ask the user to check the OAuth connection settings
@@ -94382,12 +94499,12 @@ Use this tool for all Stripe API interactions: querying charges, customers, invo
94382
94499
  });
94383
94500
 
94384
94501
  // ../connectors/src/connectors/stripe-api-key/setup.ts
94385
- var requestToolName4 = `stripe-api-key_${requestTool13.name}`;
94502
+ var requestToolName5 = `stripe-api-key_${requestTool13.name}`;
94386
94503
  var stripeApiKeyOnboarding = new ConnectorOnboarding({
94387
94504
  connectionSetupInstructions: {
94388
94505
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Stripe\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
94389
94506
 
94390
- 1. \`${requestToolName4}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u6B8B\u9AD8\u3092\u53D6\u5F97\u3059\u308B:
94507
+ 1. \`${requestToolName5}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u6B8B\u9AD8\u3092\u53D6\u5F97\u3059\u308B:
94391
94508
  - \`method\`: \`"GET"\`
94392
94509
  - \`path\`: \`"/v1/balance"\`
94393
94510
  2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306BAPI\u30AD\u30FC\u306E\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B\uFF08Secret API Key\u307E\u305F\u306FRestricted API Key\u304C\u6B63\u3057\u304F\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u304B\uFF09
@@ -94397,7 +94514,7 @@ var stripeApiKeyOnboarding = new ConnectorOnboarding({
94397
94514
  - \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`,
94398
94515
  en: `Follow these steps to set up the Stripe connection.
94399
94516
 
94400
- 1. Call \`${requestToolName4}\` to fetch account balance:
94517
+ 1. Call \`${requestToolName5}\` to fetch account balance:
94401
94518
  - \`method\`: \`"GET"\`
94402
94519
  - \`path\`: \`"/v1/balance"\`
94403
94520
  2. If an error is returned, ask the user to check the API key settings (verify that the Secret API Key or Restricted API Key is configured correctly)
@@ -94407,11 +94524,11 @@ var stripeApiKeyOnboarding = new ConnectorOnboarding({
94407
94524
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
94408
94525
  },
94409
94526
  dataOverviewInstructions: {
94410
- en: `1. Call ${requestToolName4} with GET /v1/customers?limit=5 to explore customers structure
94411
- 2. Call ${requestToolName4} with GET /v1/charges?limit=5 to explore charges structure
94527
+ en: `1. Call ${requestToolName5} with GET /v1/customers?limit=5 to explore customers structure
94528
+ 2. Call ${requestToolName5} with GET /v1/charges?limit=5 to explore charges structure
94412
94529
  3. Explore other endpoints (invoices, subscriptions, products) as needed`,
94413
- ja: `1. ${requestToolName4} \u3067 GET /v1/customers?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u9867\u5BA2\u306E\u69CB\u9020\u3092\u78BA\u8A8D
94414
- 2. ${requestToolName4} \u3067 GET /v1/charges?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u8AB2\u91D1\u306E\u69CB\u9020\u3092\u78BA\u8A8D
94530
+ ja: `1. ${requestToolName5} \u3067 GET /v1/customers?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u9867\u5BA2\u306E\u69CB\u9020\u3092\u78BA\u8A8D
94531
+ 2. ${requestToolName5} \u3067 GET /v1/charges?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u8AB2\u91D1\u306E\u69CB\u9020\u3092\u78BA\u8A8D
94415
94532
  3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\u8ACB\u6C42\u66F8\u3001\u30B5\u30D6\u30B9\u30AF\u30EA\u30D7\u30B7\u30E7\u30F3\u3001\u5546\u54C1\uFF09\u3092\u63A2\u7D22`
94416
94533
  }
94417
94534
  });
@@ -94696,7 +94813,7 @@ Authentication is handled automatically via OAuth proxy.
94696
94813
  });
94697
94814
 
94698
94815
  // ../connectors/src/connectors/airtable-oauth/setup.ts
94699
- var requestToolName5 = `airtable-oauth_${requestTool14.name}`;
94816
+ var requestToolName6 = `airtable-oauth_${requestTool14.name}`;
94700
94817
  var airtableOauthOnboarding = new ConnectorOnboarding({
94701
94818
  connectionSetupInstructions: {
94702
94819
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Airtable OAuth\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
@@ -94706,7 +94823,7 @@ var airtableOauthOnboarding = new ConnectorOnboarding({
94706
94823
  3. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3059:
94707
94824
  - \`parameterSlug\`: \`"base-id"\`
94708
94825
  - \`value\`: \u62BD\u51FA\u3057\u305F\u30D9\u30FC\u30B9ID
94709
- 4. \`${requestToolName5}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30D9\u30FC\u30B9\u306E\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
94826
+ 4. \`${requestToolName6}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30D9\u30FC\u30B9\u306E\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
94710
94827
  - \`method\`: \`"GET"\`
94711
94828
  - \`path\`: \`"/meta/bases/{baseId}/tables"\`
94712
94829
  5. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u30D9\u30FC\u30B9\u306E\u5171\u6709\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
@@ -94721,7 +94838,7 @@ var airtableOauthOnboarding = new ConnectorOnboarding({
94721
94838
  3. Call \`updateConnectionParameters\`:
94722
94839
  - \`parameterSlug\`: \`"base-id"\`
94723
94840
  - \`value\`: The extracted base ID
94724
- 4. Call \`${requestToolName5}\` to fetch the base's table list:
94841
+ 4. Call \`${requestToolName6}\` to fetch the base's table list:
94725
94842
  - \`method\`: \`"GET"\`
94726
94843
  - \`path\`: \`"/meta/bases/{baseId}/tables"\`
94727
94844
  5. If an error is returned, ask the user to check the base sharing settings
@@ -97623,12 +97740,12 @@ Authentication is handled automatically via OAuth proxy.`,
97623
97740
  });
97624
97741
 
97625
97742
  // ../connectors/src/connectors/shopify-oauth/setup.ts
97626
- var requestToolName6 = `shopify-oauth_${requestTool22.name}`;
97743
+ var requestToolName7 = `shopify-oauth_${requestTool22.name}`;
97627
97744
  var shopifyOauthOnboarding = new ConnectorOnboarding({
97628
97745
  connectionSetupInstructions: {
97629
97746
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Shopify\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
97630
97747
 
97631
- 1. \`${requestToolName6}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B7\u30E7\u30C3\u30D7\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
97748
+ 1. \`${requestToolName7}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B7\u30E7\u30C3\u30D7\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
97632
97749
  - \`method\`: \`"GET"\`
97633
97750
  - \`path\`: \`"/admin/api/2024-10/shop.json"\`
97634
97751
  2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306BOAuth\u63A5\u7D9A\u306E\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
@@ -97638,7 +97755,7 @@ var shopifyOauthOnboarding = new ConnectorOnboarding({
97638
97755
  - \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`,
97639
97756
  en: `Follow these steps to set up the Shopify connection.
97640
97757
 
97641
- 1. Call \`${requestToolName6}\` to fetch shop info:
97758
+ 1. Call \`${requestToolName7}\` to fetch shop info:
97642
97759
  - \`method\`: \`"GET"\`
97643
97760
  - \`path\`: \`"/admin/api/2024-10/shop.json"\`
97644
97761
  2. If an error is returned, ask the user to check the OAuth connection settings
@@ -99895,12 +100012,12 @@ Pagination uses cursor-based start_cursor and page_size (max 100).`,
99895
100012
  });
99896
100013
 
99897
100014
  // ../connectors/src/connectors/notion-oauth/setup.ts
99898
- var requestToolName7 = `notion-oauth_${requestTool28.name}`;
100015
+ var requestToolName8 = `notion-oauth_${requestTool28.name}`;
99899
100016
  var notionOauthOnboarding = new ConnectorOnboarding({
99900
100017
  connectionSetupInstructions: {
99901
100018
  ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Notion\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002
99902
100019
 
99903
- 1. \`${requestToolName7}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30DC\u30C3\u30C8\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
100020
+ 1. \`${requestToolName8}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30DC\u30C3\u30C8\u30E6\u30FC\u30B6\u30FC\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B:
99904
100021
  - \`method\`: \`"GET"\`
99905
100022
  - \`path\`: \`"/users/me"\`
99906
100023
  2. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u30E6\u30FC\u30B6\u30FC\u306BOAuth\u63A5\u7D9A\u306E\u8A2D\u5B9A\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u4F1D\u3048\u308B
@@ -99910,7 +100027,7 @@ var notionOauthOnboarding = new ConnectorOnboarding({
99910
100027
  - \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`,
99911
100028
  en: `Follow these steps to set up the Notion connection.
99912
100029
 
99913
- 1. Call \`${requestToolName7}\` to fetch bot user info:
100030
+ 1. Call \`${requestToolName8}\` to fetch bot user info:
99914
100031
  - \`method\`: \`"GET"\`
99915
100032
  - \`path\`: \`"/users/me"\`
99916
100033
  2. If an error is returned, ask the user to check the OAuth connection settings
@@ -102353,7 +102470,7 @@ export default async function handler(c: Context) {
102353
102470
  tools: tools49
102354
102471
  });
102355
102472
 
102356
- // ../connectors/src/connectors/gmail/tools/request.ts
102473
+ // ../connectors/src/connectors/gmail/tools/request-with-delegation.ts
102357
102474
  import { z as z63 } from "zod";
102358
102475
 
102359
102476
  // ../connectors/src/connectors/gmail/parameters.ts
@@ -102361,38 +102478,40 @@ var parameters50 = {
102361
102478
  serviceAccountKeyJsonBase64: new ParameterDefinition({
102362
102479
  slug: "service-account-key-json-base64",
102363
102480
  name: "Google Cloud Service Account JSON",
102364
- description: "The service account JSON key used to authenticate with Google Cloud Platform. The service account must have domain-wide delegation enabled and be granted the Gmail API scope in Google Workspace admin.",
102481
+ description: "The service account JSON key. Domain-wide Delegation must be authorized in the Google Workspace admin console for the Gmail API scope. The user to impersonate is supplied per call as the `subject` argument.",
102365
102482
  envVarBaseKey: "GMAIL_SERVICE_ACCOUNT_JSON_BASE64",
102366
102483
  type: "base64EncodedJson",
102367
102484
  secret: true,
102368
102485
  required: true
102369
102486
  })
102370
102487
  };
102371
- var delegatedUserEmailParameter = new ParameterDefinition({
102372
- slug: "delegated-user-email",
102373
- name: "Delegated User Email",
102374
- description: "The email address of the Google Workspace user whose Gmail mailbox the service account will access via domain-wide delegation. Collected during the setup flow.",
102375
- envVarBaseKey: "GMAIL_DELEGATED_USER_EMAIL",
102376
- type: "text",
102377
- secret: false,
102378
- required: false
102379
- });
102380
102488
 
102381
- // ../connectors/src/connectors/gmail/tools/request.ts
102489
+ // ../connectors/src/connectors/gmail/tools/request-with-delegation.ts
102382
102490
  var BASE_URL28 = "https://gmail.googleapis.com/gmail/v1/users";
102383
102491
  var REQUEST_TIMEOUT_MS46 = 6e4;
102492
+ function decodeServiceAccount3(keyJsonBase64) {
102493
+ const decoded = Buffer.from(keyJsonBase64, "base64").toString("utf-8");
102494
+ return JSON.parse(decoded);
102495
+ }
102384
102496
  var inputSchema61 = z63.object({
102385
102497
  toolUseIntent: z63.string().optional().describe(
102386
102498
  "Brief description of what you intend to accomplish with this tool call"
102387
102499
  ),
102388
102500
  connectionId: z63.string().describe("ID of the Gmail service account connection to use"),
102389
- method: z63.enum(["GET"]).describe("HTTP method (read-only, GET only)"),
102501
+ method: z63.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).describe("HTTP method"),
102390
102502
  path: z63.string().describe(
102391
- "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."
102503
+ "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 \u2014 the impersonated user."
102504
+ ),
102505
+ subject: z63.string().describe(
102506
+ "Email of the Workspace user to impersonate via Domain-wide Delegation. The token will be issued as this user."
102507
+ ),
102508
+ scopes: z63.array(z63.string()).describe(
102509
+ "OAuth scopes the token must include. This connector currently supports read-only operations only \u2014 pass ['https://www.googleapis.com/auth/gmail.readonly']. Per-endpoint scope reference: https://developers.google.com/gmail/api/auth/scopes"
102392
102510
  ),
102393
102511
  queryParams: z63.record(z63.string(), z63.string()).optional().describe(
102394
102512
  "Query parameters to append to the URL (e.g., { q: 'from:example@gmail.com', maxResults: '10' })"
102395
- )
102513
+ ),
102514
+ body: z63.record(z63.string(), z63.unknown()).optional().describe("JSON request body for POST/PUT/PATCH")
102396
102515
  });
102397
102516
  var outputSchema61 = z63.discriminatedUnion("success", [
102398
102517
  z63.object({
@@ -102402,17 +102521,16 @@ var outputSchema61 = z63.discriminatedUnion("success", [
102402
102521
  }),
102403
102522
  z63.object({
102404
102523
  success: z63.literal(false),
102405
- error: z63.string()
102524
+ error: z63.string(),
102525
+ serviceAccountEmail: z63.string().optional()
102406
102526
  })
102407
102527
  ]);
102408
- var requestTool35 = new ConnectorTool({
102409
- name: "request",
102410
- description: `Send authenticated GET requests to the Gmail API v1.
102411
- Authentication is handled automatically using a service account with domain-wide delegation.
102412
- All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me' as the userId prefix (e.g., '/me/messages').`,
102528
+ var requestWithDelegationTool2 = new ConnectorTool({
102529
+ name: "request_with_delegation",
102530
+ description: "Call the Gmail API on behalf of the specified Workspace user via Domain-wide Delegation. Read-only operations only. Pass `subject` as the target user email and `scopes` as ['https://www.googleapis.com/auth/gmail.readonly']. Paths are relative to https://gmail.googleapis.com/gmail/v1/users \u2014 use '/me' as the userId prefix (e.g., '/me/messages'). Requires Domain-wide Delegation to be authorized for the service account in the Workspace admin console.",
102413
102531
  inputSchema: inputSchema61,
102414
102532
  outputSchema: outputSchema61,
102415
- async execute({ connectionId, method, path: path4, queryParams }, connections) {
102533
+ async execute({ connectionId, method, path: path4, subject, scopes, queryParams, body }, connections) {
102416
102534
  const connection = connections.find((c6) => c6.id === connectionId);
102417
102535
  if (!connection) {
102418
102536
  return {
@@ -102420,28 +102538,37 @@ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me'
102420
102538
  error: `Connection ${connectionId} not found`
102421
102539
  };
102422
102540
  }
102541
+ const keyJsonBase64 = parameters50.serviceAccountKeyJsonBase64.getValue(connection);
102542
+ let serviceAccount;
102543
+ try {
102544
+ serviceAccount = decodeServiceAccount3(keyJsonBase64);
102545
+ } catch (err) {
102546
+ const msg = err instanceof Error ? err.message : String(err);
102547
+ return {
102548
+ success: false,
102549
+ error: `Failed to decode service account key: ${msg}`
102550
+ };
102551
+ }
102552
+ const serviceAccountEmail = serviceAccount.client_email;
102423
102553
  console.log(
102424
- `[connector-request] gmail/${connection.name}: ${method} ${path4}`
102554
+ `[connector-request] gmail/${connection.name}: ${method} ${path4} subject=${subject}`
102425
102555
  );
102426
102556
  try {
102427
102557
  const { GoogleAuth } = await import("google-auth-library");
102428
- const keyJsonBase64 = parameters50.serviceAccountKeyJsonBase64.getValue(connection);
102429
- const delegatedUserEmail = delegatedUserEmailParameter.getValue(connection);
102430
- const credentials = JSON.parse(
102431
- Buffer.from(keyJsonBase64, "base64").toString("utf-8")
102432
- );
102433
102558
  const auth = new GoogleAuth({
102434
- credentials,
102435
- scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
102436
- clientOptions: {
102437
- subject: delegatedUserEmail
102438
- }
102559
+ credentials: {
102560
+ client_email: serviceAccount.client_email,
102561
+ private_key: serviceAccount.private_key
102562
+ },
102563
+ scopes,
102564
+ clientOptions: { subject }
102439
102565
  });
102440
102566
  const token = await auth.getAccessToken();
102441
102567
  if (!token) {
102442
102568
  return {
102443
102569
  success: false,
102444
- error: "Failed to obtain access token"
102570
+ error: "Failed to obtain access token",
102571
+ serviceAccountEmail
102445
102572
  };
102446
102573
  }
102447
102574
  let url = `${BASE_URL28}${path4.startsWith("/") ? "" : "/"}${path4}`;
@@ -102452,18 +102579,25 @@ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me'
102452
102579
  const controller = new AbortController();
102453
102580
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS46);
102454
102581
  try {
102582
+ const hasBody = body != null && ["POST", "PUT", "PATCH"].includes(method);
102455
102583
  const response = await fetch(url, {
102456
102584
  method,
102457
102585
  headers: {
102458
102586
  Authorization: `Bearer ${token}`,
102459
102587
  "Content-Type": "application/json"
102460
102588
  },
102589
+ body: hasBody ? JSON.stringify(body) : void 0,
102461
102590
  signal: controller.signal
102462
102591
  });
102463
- const data = await response.json();
102592
+ const data = await response.json().catch(() => ({}));
102464
102593
  if (!response.ok) {
102465
- const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
102466
- return { success: false, error: errorMessage };
102594
+ const errorObj = data?.error;
102595
+ const errorMessage = errorObj?.message ?? (typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`);
102596
+ return {
102597
+ success: false,
102598
+ error: errorMessage,
102599
+ serviceAccountEmail
102600
+ };
102467
102601
  }
102468
102602
  return { success: true, status: response.status, data };
102469
102603
  } finally {
@@ -102471,79 +102605,92 @@ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me'
102471
102605
  }
102472
102606
  } catch (err) {
102473
102607
  const msg = err instanceof Error ? err.message : String(err);
102474
- return { success: false, error: msg };
102608
+ return {
102609
+ success: false,
102610
+ error: msg,
102611
+ serviceAccountEmail
102612
+ };
102475
102613
  }
102476
102614
  }
102477
102615
  });
102478
102616
 
102479
102617
  // ../connectors/src/connectors/gmail/setup.ts
102480
- var requestToolName8 = `gmail-service-account_${requestTool35.name}`;
102618
+ var requestWithDelegationToolName2 = `gmail-service-account_${requestWithDelegationTool2.name}`;
102619
+ var READONLY_SCOPES2 = '["https://www.googleapis.com/auth/gmail.readonly"]';
102481
102620
  var gmailOnboarding = new ConnectorOnboarding({
102482
102621
  connectionSetupInstructions: {
102483
- ja: `\u4EE5\u4E0B\u306E\u624B\u9806\u3067Gmail\uFF08\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\uFF09\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002\u63A5\u7D9A\u4F5C\u6210\u6642\u306B\u306F\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8JSON\u306E\u307F\u304C\u8A2D\u5B9A\u6E08\u307F\u3067\u3001\u59D4\u4EFB\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u3053\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u53D6\u5F97\u3057\u307E\u3059\u3002
102622
+ ja: `Gmail\uFF08\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\uFF09\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306E\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3092\u884C\u3044\u307E\u3059\u3002\u30A2\u30AF\u30BB\u30B9\u5BFE\u8C61\u306E Workspace \u30E6\u30FC\u30B6\u30FC\u3092\u30E6\u30FC\u30B6\u30FC\u304B\u3089\u805E\u304D\u3001Project Knowledge \u306B\u8A18\u9332\u3057\u307E\u3059\u3002
102484
102623
 
102485
- 1. \`askUserQuestion\` \u3067\u3001\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u304CDomain-wide Delegation\u3067\u4EE3\u7406\u30A2\u30AF\u30BB\u30B9\u3059\u308BGoogle Workspace\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u30D2\u30A2\u30EA\u30F3\u30B0\u3059\u308B:
102624
+ 1. \`askUserQuestion\` \u3067\u5BFE\u8C61\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u805E\u304F:
102486
102625
  - \`type\`: \`"freeText"\`
102487
- - \`question\`: \u300CGmail\u3092\u53C2\u7167\u3059\u308BGoogle Workspace\u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u300D
102488
- - \`placeholder\`: \`"user@example.com"\`
102489
- 2. \u53D7\u3051\u53D6\u3063\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092 \`updateConnectionParameters\` \u3067\u4FDD\u5B58\u3059\u308B:
102490
- - \`parameterSlug\`: \`"delegated-user-email"\`
102491
- - \`options\`: \`[{ value: <\u5165\u529B\u3055\u308C\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9>, label: <\u540C\u3058\u5024> }]\`\uFF081\u4EF6\u306E\u307F\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u81EA\u52D5\u9078\u629E\u3055\u308C\u308B\uFF09
102492
- 3. \`${requestToolName8}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u53D6\u5F97\u3059\u308B:
102626
+ - \`question\`: \u300CGmail \u3092\u53C2\u7167\u3059\u308B Google Workspace \u30E6\u30FC\u30B6\u30FC\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u8907\u6570\u53EF\u3001\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09\u300D
102627
+ - \`placeholder\`: \`"alice@example.com, bob@example.com"\`
102628
+
102629
+ 2. \u30E6\u30FC\u30B6\u30FC\u304B\u3089\u53D7\u3051\u53D6\u3063\u305F\u6587\u5B57\u5217\u304B\u3089\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u62BD\u51FA\u3059\u308B\u3002\u5404 \`<email>\` \u306B\u3064\u3044\u3066 \`${requestWithDelegationToolName2}\` \u3092\u4EE5\u4E0B\u306E\u5F15\u6570\u3067\u547C\u3073\u3001Domain-wide Delegation \u7D4C\u7531\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u304B\u3092\u78BA\u8A8D\u3059\u308B:
102493
102630
  - \`method\`: \`"GET"\`
102494
102631
  - \`path\`: \`"/me/profile"\`
102495
- 4. \u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u3001\u4EE5\u4E0B\u3092\u78BA\u8A8D\u3059\u308B\u3088\u3046\u30E6\u30FC\u30B6\u30FC\u306B\u4F1D\u3048\u308B:
102496
- - \u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u304C\u6709\u52B9\u304B
102497
- - Google Workspace\u7BA1\u7406\u30B3\u30F3\u30BD\u30FC\u30EB\u3067Gmail API\u30B9\u30B3\u30FC\u30D7\u304C\u8A31\u53EF\u3055\u308C\u3066\u3044\u308B\u304B
102498
- - \u5165\u529B\u3055\u308C\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u6B63\u3057\u3044\u304B
102499
- 5. \`${requestToolName8}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B:
102500
- - \`method\`: \`"GET"\`
102501
- - \`path\`: \`"/me/labels"\`
102632
+ - \`subject\`: \`<email>\`
102633
+ - \`scopes\`: \`${READONLY_SCOPES2}\`
102634
+
102635
+ 3. \u5931\u6557\u3057\u305F\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u304C\u3042\u308C\u3070\u3001\u30A8\u30E9\u30FC\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`serviceAccountEmail\` \u30D5\u30A3\u30FC\u30EB\u30C9\u304B\u3089\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u53D6\u308A\u51FA\u3057\u3001\`askUserQuestion\` \u3067\u6B21\u306E\u9078\u629E\u80A2\u3092\u63D0\u793A\u3059\u308B\u3002\`question\` \u306B\u306F\u6B21\u306E\u6848\u5185\u6587\u3092\u542B\u3081\u308B: \u300C\u6B21\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: {\u5931\u6557\u30A2\u30C9\u30EC\u30B9\u4E00\u89A7}\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8 \`<serviceAccountEmail>\` \u306E Domain-wide Delegation \u304C Workspace \u7BA1\u7406\u30B3\u30F3\u30BD\u30FC\u30EB\u3067\u627F\u8A8D\u3055\u308C\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF08[\u8A2D\u5B9A\u30AC\u30A4\u30C9](https://support.google.com/a/answer/162106)\uFF09\u300D\u3002
102636
+ - \`options\`: \`[{ label: "\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3092\u627F\u8A8D\u3057\u305F\u306E\u3067\u30EA\u30C8\u30E9\u30A4", value: "retry" }, { label: "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u76F4\u3059", value: "restart" }]\`
102637
+ - \u300C\u30EA\u30C8\u30E9\u30A4\u300D: \u76F4\u524D\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u30EA\u30B9\u30C8\u3067\u30B9\u30C6\u30C3\u30D7 2 \u3092\u518D\u5B9F\u884C
102638
+ - \u300C\u5165\u529B\u3057\u76F4\u3059\u300D: \u30B9\u30C6\u30C3\u30D7 1 \u304B\u3089\u518D\u5B9F\u884C
102639
+
102640
+ 4. \u5168\u30A2\u30C9\u30EC\u30B9\u304C\u6210\u529F\u3057\u305F\u3089 \`finalizeSetup\` \u3092\u547C\u3076\u3002\`projectKnowledge\` \u306E \`#### \u30B9\u30B3\u30FC\u30D7\` \u7BC0\u306B\u5404\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092 1 \u884C\u305A\u3064\u5217\u6319\u3059\u308B:
102641
+ - \`- subject: alice@example.com\`
102642
+ - \`- subject: bob@example.com\`
102502
102643
 
102503
102644
  #### \u5236\u7D04
102504
- - **\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
102505
- - \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`,
102506
- en: `Follow these steps to set up the Gmail (Service Account) connection. Only the service account JSON is provided at connection creation time \u2014 the delegated user email is collected during this setup flow.
102645
+ - \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\u8A31\u53EF\u3055\u308C\u3066\u3044\u308B\u306E\u306F\u30B9\u30C6\u30C3\u30D7 2 \u306E \`/me/profile\` \u78BA\u8A8D\u306E\u307F
102646
+ - \u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u306E\u9593\u306F 1 \u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057`,
102647
+ en: `Set up the Gmail (Service Account) connection. Ask the user which Workspace users to access, verify each via Domain-wide Delegation, and record them in Project Knowledge.
102507
102648
 
102508
- 1. Call \`askUserQuestion\` to ask the user for the Google Workspace user email the service account will impersonate via Domain-wide Delegation:
102649
+ 1. Call \`askUserQuestion\` to collect target emails:
102509
102650
  - \`type\`: \`"freeText"\`
102510
- - \`question\`: "Please enter the email address of the Google Workspace user whose Gmail mailbox you want to access"
102511
- - \`placeholder\`: \`"user@example.com"\`
102512
- 2. Save the email via \`updateConnectionParameters\`:
102513
- - \`parameterSlug\`: \`"delegated-user-email"\`
102514
- - \`options\`: \`[{ value: <entered email>, label: <same value> }]\` (a single option is auto-selected)
102515
- 3. Call \`${requestToolName8}\` to get the user's profile:
102651
+ - \`question\`: "Enter the Google Workspace user email(s) whose Gmail mailbox you want to access (comma-separated for multiple)"
102652
+ - \`placeholder\`: \`"alice@example.com, bob@example.com"\`
102653
+
102654
+ 2. Extract individual emails from the response. For each \`<email>\`, verify Domain-wide Delegation access by calling \`${requestWithDelegationToolName2}\`:
102516
102655
  - \`method\`: \`"GET"\`
102517
102656
  - \`path\`: \`"/me/profile"\`
102518
- 4. If an error is returned, ask the user to verify:
102519
- - Domain-wide delegation is enabled for the service account
102520
- - Gmail API scope is authorized in Google Workspace admin console
102521
- - The entered email address is correct
102522
- 5. Call \`${requestToolName8}\` to get the label list:
102523
- - \`method\`: \`"GET"\`
102524
- - \`path\`: \`"/me/labels"\`
102657
+ - \`subject\`: \`<email>\`
102658
+ - \`scopes\`: \`${READONLY_SCOPES2}\`
102659
+
102660
+ 3. For any failed email, take \`serviceAccountEmail\` from the error response and call \`askUserQuestion\`. Include this guidance in \`question\`: "Could not access Gmail for {failed emails}. Verify Domain-wide Delegation for service account \`<serviceAccountEmail>\` in the Workspace admin console ([setup guide](https://support.google.com/a/answer/162106))".
102661
+ - \`options\`: \`[{ label: "Authorized Domain-wide Delegation \u2014 retry", value: "retry" }, { label: "Re-enter the email addresses", value: "restart" }]\`
102662
+ - On "retry" \u2192 re-run step 2 with the previously entered email list
102663
+ - On "Re-enter" \u2192 re-run step 1
102664
+
102665
+ 4. Once every email succeeds, call \`finalizeSetup\`. Under \`#### \u30B9\u30B3\u30FC\u30D7\` in \`projectKnowledge\`, list each email on its own line:
102666
+ - \`- subject: alice@example.com\`
102667
+ - \`- subject: bob@example.com\`
102525
102668
 
102526
102669
  #### Constraints
102527
- - **Do NOT read message bodies during setup**. Only the profile and label list requests specified above are allowed
102528
- - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
102670
+ - Do NOT read message bodies during setup. Only the \`/me/profile\` verification is permitted
102671
+ - Write at most 1 sentence between tool calls`
102529
102672
  },
102530
102673
  dataOverviewInstructions: {
102531
- en: `1. Call gmail-service-account_request with GET /me/labels to list all labels
102532
- 2. Call gmail-service-account_request with GET /me/messages?maxResults=5 to get recent message IDs
102533
- 3. Call gmail-service-account_request with GET /me/messages/{id}?format=metadata for each message to see subjects and senders`,
102534
- ja: `1. gmail-service-account_request \u3067 GET /me/labels \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
102535
- 2. gmail-service-account_request \u3067 GET /me/messages?maxResults=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8ID\u3092\u53D6\u5F97
102536
- 3. \u5404\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 gmail-service-account_request \u3067 GET /me/messages/{id}?format=metadata \u3092\u547C\u3073\u51FA\u3057\u3001\u4EF6\u540D\u3068\u9001\u4FE1\u8005\u3092\u78BA\u8A8D`
102674
+ en: `Pick ONE email from \`#### \u30B9\u30B3\u30FC\u30D7\` (a \`- subject: <email>\` line) and use it as \`subject\` for every call below. Pass \`scopes: ${READONLY_SCOPES2}\` every time.
102675
+
102676
+ 1. \`method=GET\`, \`path=/me/labels\` to list labels.
102677
+ 2. \`method=GET\`, \`path=/me/messages?maxResults=5\` to fetch recent message IDs.
102678
+ 3. For each message id, \`method=GET\`, \`path=/me/messages/{id}?format=metadata\`.`,
102679
+ ja: `\`#### \u30B9\u30B3\u30FC\u30D7\` \u306E \`- subject: <email>\` \u884C\u304B\u3089 1 \u3064\u9078\u3073\u3001\u4EE5\u4E0B\u306E\u30B9\u30C6\u30C3\u30D7\u3067 \`subject\` \u5F15\u6570\u3068\u3057\u3066\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002\`scopes\` \u306F\u6BCE\u56DE \`${READONLY_SCOPES2}\` \u3092\u6E21\u3057\u307E\u3059\u3002
102680
+
102681
+ 1. \`method=GET\`\u3001\`path=/me/labels\` \u3067\u30E9\u30D9\u30EB\u4E00\u89A7\u3092\u53D6\u5F97
102682
+ 2. \`method=GET\`\u3001\`path=/me/messages?maxResults=5\` \u3067\u6700\u8FD1\u306E\u30E1\u30C3\u30BB\u30FC\u30B8 ID \u3092\u53D6\u5F97
102683
+ 3. \u5404\u30E1\u30C3\u30BB\u30FC\u30B8 ID \u306B\u3064\u3044\u3066 \`method=GET\`\u3001\`path=/me/messages/{id}?format=metadata\``
102537
102684
  }
102538
102685
  });
102539
102686
 
102540
102687
  // ../connectors/src/connectors/gmail/index.ts
102541
- var tools50 = { request: requestTool35 };
102688
+ var tools50 = { request_with_delegation: requestWithDelegationTool2 };
102542
102689
  var gmailConnector = new ConnectorPlugin({
102543
102690
  slug: "gmail",
102544
102691
  authType: AUTH_TYPES.SERVICE_ACCOUNT,
102545
102692
  name: "Gmail",
102546
- description: "Connect to Gmail for email data access using a service account with domain-wide delegation. Read-only access to messages, threads, and labels.",
102693
+ description: "Connect to Gmail for email data access using a service account with domain-wide delegation. Currently read-only (messages, threads, labels).",
102547
102694
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/4V3rfaSc1ksFIt2eHBNIwJ/7f3be41a154a6d96dcf229ed0e5858c9/Gmail_icon__2020_.svg.png",
102548
102695
  parameters: parameters50,
102549
102696
  releaseFlag: { dev1: true, dev2: true, prod: true },
@@ -102551,12 +102698,22 @@ var gmailConnector = new ConnectorPlugin({
102551
102698
  systemPrompt: {
102552
102699
  en: `### Tools
102553
102700
 
102554
- - \`gmail-service-account_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 handled automatically using a service account with domain-wide delegation.
102701
+ - \`gmail-service-account_request_with_delegation\`: Call the Gmail API on behalf of the specified Workspace user via Domain-wide Delegation. Pass \`subject\` as the target user email; the token will be issued as that user. The set of users this connection works with is recorded in the project knowledge under "#### \u30B9\u30B3\u30FC\u30D7" as \`- subject: <email>\` lines \u2014 read those and pick a subject before calling. Always pass \`scopes\`.
102702
+
102703
+ ### OAuth Scopes (pass as \`scopes\` argument)
102704
+
102705
+ This connector is currently read-only. Pass:
102706
+
102707
+ - \`https://www.googleapis.com/auth/gmail.readonly\` \u2014 read-only access (profile, labels, messages, threads)
102708
+
102709
+ The Workspace admin must have authorized this scope for the service account in the Domain-wide Delegation settings, otherwise token issuance will fail with \`unauthorized_client\`.
102710
+
102711
+ Per-endpoint scope reference: https://developers.google.com/gmail/api/auth/scopes
102555
102712
 
102556
102713
  ### Gmail API Reference
102557
102714
 
102558
102715
  #### Available Endpoints
102559
- - GET \`/me/profile\` \u2014 Get the delegated user's profile (email address, total messages/threads)
102716
+ - GET \`/me/profile\` \u2014 Get the impersonated user's profile (email address, total messages/threads)
102560
102717
  - GET \`/me/labels\` \u2014 List all labels in the mailbox
102561
102718
  - GET \`/me/labels/{id}\` \u2014 Get details for a specific label
102562
102719
  - GET \`/me/messages\` \u2014 List messages (returns IDs only; use format param on individual messages)
@@ -102581,7 +102738,7 @@ var gmailConnector = new ConnectorPlugin({
102581
102738
  - \`raw\` \u2014 Full RFC 2822 formatted message in base64url
102582
102739
 
102583
102740
  #### Tips
102584
- - Always use \`/me\` as the userId \u2014 it refers to the delegated user
102741
+ - Always use \`/me\` as the userId in the path \u2014 it refers to the user you passed as \`subject\`
102585
102742
  - List endpoints return only IDs; fetch individual resources for details
102586
102743
  - Use \`format=metadata\` to efficiently get subject/sender without full body
102587
102744
  - Message body content is base64url encoded in \`payload.body.data\` or nested \`payload.parts[].body.data\`
@@ -102592,6 +102749,12 @@ var gmailConnector = new ConnectorPlugin({
102592
102749
 
102593
102750
  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.
102594
102751
 
102752
+ SDK methods (client created via \`connection(connectionId)\`):
102753
+
102754
+ - \`client.requestWithDelegation(path, { subject, scopes, init? })\` \u2014 call the Gmail API as the impersonated Workspace user via Domain-wide Delegation. Pass the minimum scopes required by the endpoint.
102755
+
102756
+ The method returns a standard \`Response\`. Read the body with \`.json()\`. Same path conventions as the tool.
102757
+
102595
102758
  #### Example
102596
102759
 
102597
102760
  \`\`\`ts
@@ -102599,37 +102762,51 @@ import { connection } from "@squadbase/vite-server/connectors/gmail";
102599
102762
 
102600
102763
  const gmail = connection("<connectionId>");
102601
102764
 
102602
- // Get user profile
102603
- const profile = await gmail.getProfile();
102765
+ // Pick the impersonated user from project knowledge ("#### \u30B9\u30B3\u30FC\u30D7").
102766
+ const subject = "alice@example.com";
102767
+ const READ = ["https://www.googleapis.com/auth/gmail.readonly"];
102768
+
102769
+ const profileRes = await gmail.requestWithDelegation("/me/profile", {
102770
+ subject,
102771
+ scopes: READ,
102772
+ });
102773
+ const profile = await profileRes.json();
102604
102774
  console.log(profile.emailAddress, profile.messagesTotal);
102605
102775
 
102606
- // List recent messages
102607
- const messages = await gmail.listMessages({ maxResults: 10 });
102608
- for (const msg of messages.messages) {
102609
- const detail = await gmail.getMessage(msg.id, "metadata");
102610
- const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
102611
- console.log(subject, detail.snippet);
102776
+ const messagesRes = await gmail.requestWithDelegation(
102777
+ "/me/messages?maxResults=10",
102778
+ { subject, scopes: READ },
102779
+ );
102780
+ const messages = await messagesRes.json();
102781
+
102782
+ for (const msg of messages.messages ?? []) {
102783
+ const detailRes = await gmail.requestWithDelegation(
102784
+ \`/me/messages/\${msg.id}?format=metadata\`,
102785
+ { subject, scopes: READ },
102786
+ );
102787
+ const detail = await detailRes.json();
102788
+ const subjectHeader = detail.payload.headers.find(h => h.name === "Subject")?.value;
102789
+ console.log(subjectHeader, detail.snippet);
102612
102790
  }
102791
+ \`\`\``,
102792
+ ja: `### \u30C4\u30FC\u30EB
102613
102793
 
102614
- // Search messages
102615
- const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
102794
+ - \`gmail-service-account_request_with_delegation\`: \u6307\u5B9A\u3055\u308C\u305F Workspace \u30E6\u30FC\u30B6\u30FC\u306B\u4EE3\u308F\u3063\u3066 Domain-wide Delegation \u7D4C\u7531\u3067 Gmail API \u3092\u547C\u3073\u51FA\u3057\u307E\u3059\u3002\u4EE3\u7406\u5BFE\u8C61\u306E\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u3092 \`subject\` \u3068\u3057\u3066\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30C8\u30FC\u30AF\u30F3\u306F\u305D\u306E\u30E6\u30FC\u30B6\u30FC\u3068\u3057\u3066\u767A\u884C\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u304C\u5BFE\u8C61\u3068\u3059\u308B\u30E6\u30FC\u30B6\u30FC\u306F Project Knowledge \u306E "#### \u30B9\u30B3\u30FC\u30D7" \u306B \`- subject: <email>\` \u5F62\u5F0F\u3067\u8A18\u9332\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u547C\u3073\u51FA\u3057\u524D\u306B\u305D\u3053\u3092\u8AAD\u3093\u3067 subject \u3092\u6C7A\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\`scopes\` \u3082\u6BCE\u56DE\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
102616
102795
 
102617
- // List labels
102618
- const labels = await gmail.listLabels();
102619
- labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
102796
+ ### OAuth \u30B9\u30B3\u30FC\u30D7 (\`scopes\` \u5F15\u6570\u3067\u6E21\u3059)
102620
102797
 
102621
- // Get a thread
102622
- const thread = await gmail.getThread("<threadId>");
102623
- thread.messages.forEach(m => console.log(m.snippet));
102624
- \`\`\``,
102625
- ja: `### \u30C4\u30FC\u30EB
102798
+ \u3053\u306E\u30B3\u30CD\u30AF\u30BF\u30FC\u306F\u73FE\u72B6\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u3067\u3059\u3002\u6B21\u3092\u6E21\u3057\u3066\u304F\u3060\u3055\u3044:
102799
+
102800
+ - \`https://www.googleapis.com/auth/gmail.readonly\` \u2014 \u8AAD\u307F\u53D6\u308A\uFF08\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3001\u30E9\u30D9\u30EB\u3001\u30E1\u30C3\u30BB\u30FC\u30B8\u3001\u30B9\u30EC\u30C3\u30C9\uFF09
102801
+
102802
+ \u8981\u6C42\u3059\u308B scope \u306F Workspace \u7BA1\u7406\u8005\u304C Domain-wide Delegation \u8A2D\u5B9A\u3067\u5F53\u8A72 Service Account \u306B\u5BFE\u3057\u3066\u627F\u8A8D\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u627F\u8A8D\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u30C8\u30FC\u30AF\u30F3\u767A\u884C\u304C \`unauthorized_client\` \u3067\u5931\u6557\u3057\u307E\u3059\u3002
102626
102803
 
102627
- - \`gmail-service-account_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\u3002\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u306E\u30C9\u30E1\u30A4\u30F3\u5168\u4F53\u306E\u59D4\u4EFB\u3092\u4F7F\u7528\u3057\u3066\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u51E6\u7406\u3055\u308C\u307E\u3059\u3002
102804
+ \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u5225\u306E\u6B63\u78BA\u306A scope \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9: https://developers.google.com/gmail/api/auth/scopes
102628
102805
 
102629
102806
  ### Gmail API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
102630
102807
 
102631
102808
  #### \u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8
102632
- - GET \`/me/profile\` \u2014 \u59D4\u4EFB\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
102809
+ - GET \`/me/profile\` \u2014 \u4EE3\u7406\u5BFE\u8C61\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
102633
102810
  - GET \`/me/labels\` \u2014 \u30E1\u30FC\u30EB\u30DC\u30C3\u30AF\u30B9\u306E\u5168\u30E9\u30D9\u30EB\u3092\u4E00\u89A7
102634
102811
  - GET \`/me/labels/{id}\` \u2014 \u7279\u5B9A\u30E9\u30D9\u30EB\u306E\u8A73\u7D30\u3092\u53D6\u5F97
102635
102812
  - 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
@@ -102654,7 +102831,7 @@ thread.messages.forEach(m => console.log(m.snippet));
102654
102831
  - \`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
102655
102832
 
102656
102833
  #### \u30D2\u30F3\u30C8
102657
- - userId\u306B\u306F\u5E38\u306B \`/me\` \u3092\u4F7F\u7528 \u2014 \u59D4\u4EFB\u30E6\u30FC\u30B6\u30FC\u3092\u6307\u3057\u307E\u3059
102834
+ - \u30D1\u30B9\u306E userId \u306B\u306F\u5E38\u306B \`/me\` \u3092\u4F7F\u7528 \u2014 \`subject\` \u306B\u6E21\u3057\u305F\u30E6\u30FC\u30B6\u30FC\u3092\u6307\u3057\u307E\u3059
102658
102835
  - \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
102659
102836
  - \u4EF6\u540D/\u9001\u4FE1\u8005\u3092\u52B9\u7387\u7684\u306B\u53D6\u5F97\u3059\u308B\u306B\u306F \`format=metadata\` \u3092\u4F7F\u7528\u3057\u307E\u3059
102660
102837
  - \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
@@ -102665,6 +102842,12 @@ thread.messages.forEach(m => console.log(m.snippet));
102665
102842
 
102666
102843
  \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
102667
102844
 
102845
+ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8):
102846
+
102847
+ - \`client.requestWithDelegation(path, { subject, scopes, init? })\` \u2014 Domain-wide Delegation \u3067\u6307\u5B9A Workspace \u30E6\u30FC\u30B6\u30FC\u306B\u4EE3\u308F\u3063\u3066 Gmail API \u3092\u547C\u3076\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u5FC5\u8981\u306A\u6700\u5C0F scope \u3092\u6E21\u3059\u3002
102848
+
102849
+ \u30E1\u30BD\u30C3\u30C9\u306F\u6A19\u6E96\u306E \`Response\` \u3092\u8FD4\u3057\u307E\u3059\u3002\`response.json()\` \u3067\u30DC\u30C7\u30A3\u3092\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30D1\u30B9\u306E\u66F8\u304D\u65B9\u306F\u30C4\u30FC\u30EB\u3068\u540C\u3058\u3002
102850
+
102668
102851
  #### Example
102669
102852
 
102670
102853
  \`\`\`ts
@@ -102672,86 +102855,35 @@ import { connection } from "@squadbase/vite-server/connectors/gmail";
102672
102855
 
102673
102856
  const gmail = connection("<connectionId>");
102674
102857
 
102675
- // Get user profile
102676
- const profile = await gmail.getProfile();
102677
- console.log(profile.emailAddress, profile.messagesTotal);
102858
+ // \u4EE3\u7406\u5BFE\u8C61\u30E6\u30FC\u30B6\u30FC\u306F Project Knowledge ("#### \u30B9\u30B3\u30FC\u30D7") \u304B\u3089\u9078\u3076
102859
+ const subject = "alice@example.com";
102860
+ const READ = ["https://www.googleapis.com/auth/gmail.readonly"];
102678
102861
 
102679
- // List recent messages
102680
- const messages = await gmail.listMessages({ maxResults: 10 });
102681
- for (const msg of messages.messages) {
102682
- const detail = await gmail.getMessage(msg.id, "metadata");
102683
- const subject = detail.payload.headers.find(h => h.name === "Subject")?.value;
102684
- console.log(subject, detail.snippet);
102685
- }
102686
-
102687
- // Search messages
102688
- const results = await gmail.listMessages({ q: "from:boss@company.com is:unread" });
102862
+ const profileRes = await gmail.requestWithDelegation("/me/profile", {
102863
+ subject,
102864
+ scopes: READ,
102865
+ });
102866
+ const profile = await profileRes.json();
102867
+ console.log(profile.emailAddress, profile.messagesTotal);
102689
102868
 
102690
- // List labels
102691
- const labels = await gmail.listLabels();
102692
- labels.labels.forEach(l => console.log(l.name, l.messagesTotal));
102869
+ const messagesRes = await gmail.requestWithDelegation(
102870
+ "/me/messages?maxResults=10",
102871
+ { subject, scopes: READ },
102872
+ );
102873
+ const messages = await messagesRes.json();
102693
102874
 
102694
- // Get a thread
102695
- const thread = await gmail.getThread("<threadId>");
102696
- thread.messages.forEach(m => console.log(m.snippet));
102875
+ for (const msg of messages.messages ?? []) {
102876
+ const detailRes = await gmail.requestWithDelegation(
102877
+ \`/me/messages/\${msg.id}?format=metadata\`,
102878
+ { subject, scopes: READ },
102879
+ );
102880
+ const detail = await detailRes.json();
102881
+ const subjectHeader = detail.payload.headers.find(h => h.name === "Subject")?.value;
102882
+ console.log(subjectHeader, detail.snippet);
102883
+ }
102697
102884
  \`\`\``
102698
102885
  },
102699
- tools: tools50,
102700
- async checkConnection(params, _config) {
102701
- const { GoogleAuth } = await import("google-auth-library");
102702
- const credentials = JSON.parse(
102703
- Buffer.from(
102704
- params[parameters50.serviceAccountKeyJsonBase64.slug],
102705
- "base64"
102706
- ).toString("utf-8")
102707
- );
102708
- const delegatedUserEmail = params[delegatedUserEmailParameter.slug];
102709
- if (!delegatedUserEmail) {
102710
- if (!credentials.client_email || !credentials.private_key) {
102711
- return {
102712
- success: false,
102713
- error: "Service account JSON must contain client_email and private_key"
102714
- };
102715
- }
102716
- return { success: true };
102717
- }
102718
- const auth = new GoogleAuth({
102719
- credentials,
102720
- scopes: ["https://www.googleapis.com/auth/gmail.readonly"],
102721
- clientOptions: {
102722
- subject: delegatedUserEmail
102723
- }
102724
- });
102725
- try {
102726
- const token = await auth.getAccessToken();
102727
- if (!token) {
102728
- return {
102729
- success: false,
102730
- error: "Failed to obtain access token"
102731
- };
102732
- }
102733
- const res = await fetch(
102734
- "https://gmail.googleapis.com/gmail/v1/users/me/profile",
102735
- {
102736
- method: "GET",
102737
- headers: { Authorization: `Bearer ${token}` }
102738
- }
102739
- );
102740
- if (!res.ok) {
102741
- const errorText = await res.text().catch(() => res.statusText);
102742
- return {
102743
- success: false,
102744
- error: `Gmail API failed: HTTP ${res.status} ${errorText}`
102745
- };
102746
- }
102747
- return { success: true };
102748
- } catch (error2) {
102749
- return {
102750
- success: false,
102751
- error: error2 instanceof Error ? error2.message : String(error2)
102752
- };
102753
- }
102754
- }
102886
+ tools: tools50
102755
102887
  });
102756
102888
 
102757
102889
  // ../connectors/src/connectors/gmail-oauth/tools/request.ts
@@ -102813,7 +102945,7 @@ var outputSchema62 = z64.discriminatedUnion("success", [
102813
102945
  error: z64.string()
102814
102946
  })
102815
102947
  ]);
102816
- var requestTool36 = new ConnectorTool({
102948
+ var requestTool35 = new ConnectorTool({
102817
102949
  name: "request",
102818
102950
  description: `Send authenticated GET requests to the Gmail API v1.
102819
102951
  Authentication is handled automatically via OAuth proxy.
@@ -102871,7 +103003,7 @@ All paths are relative to https://gmail.googleapis.com/gmail/v1/users. Use '/me'
102871
103003
  });
102872
103004
 
102873
103005
  // ../connectors/src/connectors/gmail-oauth/setup.ts
102874
- var requestToolName9 = `gmail-oauth_${requestTool36.name}`;
103006
+ var requestToolName9 = `gmail-oauth_${requestTool35.name}`;
102875
103007
  var gmailOnboarding2 = new ConnectorOnboarding({
102876
103008
  connectionSetupInstructions: {
102877
103009
  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
@@ -102915,7 +103047,7 @@ var gmailOnboarding2 = new ConnectorOnboarding({
102915
103047
  var parameters51 = {};
102916
103048
 
102917
103049
  // ../connectors/src/connectors/gmail-oauth/index.ts
102918
- var tools51 = { request: requestTool36 };
103050
+ var tools51 = { request: requestTool35 };
102919
103051
  var gmailOauthConnector = new ConnectorPlugin({
102920
103052
  slug: "gmail",
102921
103053
  authType: AUTH_TYPES.OAUTH,
@@ -103350,7 +103482,7 @@ var outputSchema64 = z66.discriminatedUnion("success", [
103350
103482
  error: z66.string()
103351
103483
  })
103352
103484
  ]);
103353
- var requestTool37 = new ConnectorTool({
103485
+ var requestTool36 = new ConnectorTool({
103354
103486
  name: "request",
103355
103487
  description: `Send authenticated requests to the LinkedIn Marketing API (REST).
103356
103488
  Authentication is handled automatically via OAuth proxy.
@@ -103426,7 +103558,7 @@ Required headers (LinkedIn-Version, X-Restli-Protocol-Version) are set automatic
103426
103558
 
103427
103559
  // ../connectors/src/connectors/linkedin-ads/index.ts
103428
103560
  var tools52 = {
103429
- request: requestTool37,
103561
+ request: requestTool36,
103430
103562
  listAdAccounts: listAdAccountsTool3
103431
103563
  };
103432
103564
  var linkedinAdsConnector = new ConnectorPlugin({
@@ -103735,7 +103867,7 @@ var outputSchema65 = z67.discriminatedUnion("success", [
103735
103867
  error: z67.string()
103736
103868
  })
103737
103869
  ]);
103738
- var requestTool38 = new ConnectorTool({
103870
+ var requestTool37 = new ConnectorTool({
103739
103871
  name: "request",
103740
103872
  description: `Send authenticated requests to the Zendesk Support API.
103741
103873
  Authentication is handled automatically using email/token Basic auth.
@@ -103791,7 +103923,7 @@ Zendesk uses cursor-based pagination with page[size] and page[after] parameters.
103791
103923
  });
103792
103924
 
103793
103925
  // ../connectors/src/connectors/zendesk/index.ts
103794
- var tools53 = { request: requestTool38 };
103926
+ var tools53 = { request: requestTool37 };
103795
103927
  var zendeskConnector = new ConnectorPlugin({
103796
103928
  slug: "zendesk",
103797
103929
  authType: AUTH_TYPES.API_KEY,
@@ -104035,7 +104167,7 @@ var outputSchema66 = z68.discriminatedUnion("success", [
104035
104167
  error: z68.string()
104036
104168
  })
104037
104169
  ]);
104038
- var requestTool39 = new ConnectorTool({
104170
+ var requestTool38 = new ConnectorTool({
104039
104171
  name: "request",
104040
104172
  description: `Send authenticated requests to the Zendesk Support API.
104041
104173
  Authentication is handled automatically via OAuth proxy.
@@ -104096,7 +104228,7 @@ Zendesk uses cursor-based pagination with page[size] and page[after] parameters.
104096
104228
  });
104097
104229
 
104098
104230
  // ../connectors/src/connectors/zendesk-oauth/setup.ts
104099
- var requestToolName10 = `zendesk-oauth_${requestTool39.name}`;
104231
+ var requestToolName10 = `zendesk-oauth_${requestTool38.name}`;
104100
104232
  var zendeskOauthOnboarding = new ConnectorOnboarding({
104101
104233
  connectionSetupInstructions: {
104102
104234
  en: `Follow these steps to set up the Zendesk connection.
@@ -104136,7 +104268,7 @@ var zendeskOauthOnboarding = new ConnectorOnboarding({
104136
104268
  var parameters54 = {};
104137
104269
 
104138
104270
  // ../connectors/src/connectors/zendesk-oauth/index.ts
104139
- var tools54 = { request: requestTool39 };
104271
+ var tools54 = { request: requestTool38 };
104140
104272
  var zendeskOauthConnector = new ConnectorPlugin({
104141
104273
  slug: "zendesk",
104142
104274
  authType: AUTH_TYPES.OAUTH,
@@ -104352,7 +104484,7 @@ var outputSchema67 = z69.discriminatedUnion("success", [
104352
104484
  error: z69.string()
104353
104485
  })
104354
104486
  ]);
104355
- var requestTool40 = new ConnectorTool({
104487
+ var requestTool39 = new ConnectorTool({
104356
104488
  name: "request",
104357
104489
  description: `Send authenticated requests to the Intercom API.
104358
104490
  Authentication is handled automatically using the Access Token (Bearer token).
@@ -104408,7 +104540,7 @@ The Intercom-Version header is set to 2.11 automatically.`,
104408
104540
  });
104409
104541
 
104410
104542
  // ../connectors/src/connectors/intercom/index.ts
104411
- var tools55 = { request: requestTool40 };
104543
+ var tools55 = { request: requestTool39 };
104412
104544
  var intercomConnector = new ConnectorPlugin({
104413
104545
  slug: "intercom",
104414
104546
  authType: AUTH_TYPES.API_KEY,
@@ -104673,7 +104805,7 @@ var outputSchema68 = z70.discriminatedUnion("success", [
104673
104805
  error: z70.string()
104674
104806
  })
104675
104807
  ]);
104676
- var requestTool41 = new ConnectorTool({
104808
+ var requestTool40 = new ConnectorTool({
104677
104809
  name: "request",
104678
104810
  description: `Send authenticated requests to the Intercom API.
104679
104811
  Authentication is handled automatically via OAuth proxy.
@@ -104736,7 +104868,7 @@ Search endpoints (contacts/search, conversations/search) use POST with a query o
104736
104868
  });
104737
104869
 
104738
104870
  // ../connectors/src/connectors/intercom-oauth/setup.ts
104739
- var requestToolName11 = `intercom-oauth_${requestTool41.name}`;
104871
+ var requestToolName11 = `intercom-oauth_${requestTool40.name}`;
104740
104872
  var intercomOauthOnboarding = new ConnectorOnboarding({
104741
104873
  connectionSetupInstructions: {
104742
104874
  en: `Follow these steps to set up the Intercom connection.
@@ -104776,7 +104908,7 @@ var intercomOauthOnboarding = new ConnectorOnboarding({
104776
104908
  var parameters56 = {};
104777
104909
 
104778
104910
  // ../connectors/src/connectors/intercom-oauth/index.ts
104779
- var tools56 = { request: requestTool41 };
104911
+ var tools56 = { request: requestTool40 };
104780
104912
  var intercomOauthConnector = new ConnectorPlugin({
104781
104913
  slug: "intercom",
104782
104914
  authType: AUTH_TYPES.OAUTH,
@@ -105028,7 +105160,7 @@ var outputSchema69 = z71.discriminatedUnion("success", [
105028
105160
  error: z71.string()
105029
105161
  })
105030
105162
  ]);
105031
- var requestTool42 = new ConnectorTool({
105163
+ var requestTool41 = new ConnectorTool({
105032
105164
  name: "request",
105033
105165
  description: `Send authenticated requests to the Mixpanel REST API.
105034
105166
  Authentication is handled automatically using Basic auth (Service Account username + secret).
@@ -105122,7 +105254,7 @@ Rate limit: 60 queries/hour, 5 concurrent queries for Query API.`,
105122
105254
  });
105123
105255
 
105124
105256
  // ../connectors/src/connectors/mixpanel/index.ts
105125
- var tools57 = { request: requestTool42 };
105257
+ var tools57 = { request: requestTool41 };
105126
105258
  var mixpanelConnector = new ConnectorPlugin({
105127
105259
  slug: "mixpanel",
105128
105260
  authType: AUTH_TYPES.API_KEY,
@@ -105316,7 +105448,7 @@ var outputSchema70 = z72.discriminatedUnion("success", [
105316
105448
  error: z72.string()
105317
105449
  })
105318
105450
  ]);
105319
- var requestTool43 = new ConnectorTool({
105451
+ var requestTool42 = new ConnectorTool({
105320
105452
  name: "request",
105321
105453
  description: `Send authenticated requests to the Grafana HTTP API.
105322
105454
  Authentication is handled automatically using the configured API Key or Service Account Token via Bearer token.
@@ -105372,7 +105504,7 @@ The path must start with '/' and is appended to the configured Grafana instance
105372
105504
  });
105373
105505
 
105374
105506
  // ../connectors/src/connectors/grafana/index.ts
105375
- var tools58 = { request: requestTool43 };
105507
+ var tools58 = { request: requestTool42 };
105376
105508
  var grafanaConnector = new ConnectorPlugin({
105377
105509
  slug: "grafana",
105378
105510
  authType: AUTH_TYPES.API_KEY,
@@ -105560,7 +105692,7 @@ var outputSchema71 = z73.discriminatedUnion("success", [
105560
105692
  error: z73.string()
105561
105693
  })
105562
105694
  ]);
105563
- var requestTool44 = new ConnectorTool({
105695
+ var requestTool43 = new ConnectorTool({
105564
105696
  name: "request",
105565
105697
  description: `Send authenticated requests to the Backlog REST API (v2).
105566
105698
  Authentication is handled automatically by appending the apiKey query parameter to every request.
@@ -105617,7 +105749,7 @@ Do NOT include the apiKey parameter yourself; it is injected automatically.`,
105617
105749
  });
105618
105750
 
105619
105751
  // ../connectors/src/connectors/backlog/index.ts
105620
- var tools59 = { request: requestTool44 };
105752
+ var tools59 = { request: requestTool43 };
105621
105753
  var backlogConnector = new ConnectorPlugin({
105622
105754
  slug: "backlog",
105623
105755
  authType: AUTH_TYPES.API_KEY,
@@ -105827,7 +105959,7 @@ var outputSchema72 = z74.discriminatedUnion("success", [
105827
105959
  error: z74.string()
105828
105960
  })
105829
105961
  ]);
105830
- var requestTool45 = new ConnectorTool({
105962
+ var requestTool44 = new ConnectorTool({
105831
105963
  name: "request",
105832
105964
  description: `Send authenticated requests to the Gamma REST API.
105833
105965
  Authentication is handled automatically using the API Key (X-API-KEY header).
@@ -106055,7 +106187,7 @@ Gamma does NOT support image uploads. To visualize data, embed raw numbers direc
106055
106187
  });
106056
106188
 
106057
106189
  // ../connectors/src/connectors/gamma/index.ts
106058
- var tools60 = { request: requestTool45, generate: generateTool };
106190
+ var tools60 = { request: requestTool44, generate: generateTool };
106059
106191
  var gammaConnector = new ConnectorPlugin({
106060
106192
  slug: "gamma",
106061
106193
  authType: AUTH_TYPES.API_KEY,
@@ -106278,7 +106410,7 @@ var outputSchema74 = z76.discriminatedUnion("success", [
106278
106410
  error: z76.string()
106279
106411
  })
106280
106412
  ]);
106281
- var requestTool46 = new ConnectorTool({
106413
+ var requestTool45 = new ConnectorTool({
106282
106414
  name: "request",
106283
106415
  description: `Send authenticated requests to the Sentry API.
106284
106416
  Supports GET, POST, PUT, and DELETE methods.
@@ -106335,7 +106467,7 @@ Authentication is handled automatically via Bearer token.
106335
106467
  });
106336
106468
 
106337
106469
  // ../connectors/src/connectors/sentry/index.ts
106338
- var tools61 = { request: requestTool46 };
106470
+ var tools61 = { request: requestTool45 };
106339
106471
  var sentryConnector = new ConnectorPlugin({
106340
106472
  slug: "sentry",
106341
106473
  authType: AUTH_TYPES.API_KEY,
@@ -106624,7 +106756,7 @@ function normalizeInstanceUrl(raw) {
106624
106756
  }
106625
106757
  return trimmed;
106626
106758
  }
106627
- var requestTool47 = new ConnectorTool({
106759
+ var requestTool46 = new ConnectorTool({
106628
106760
  name: "request",
106629
106761
  description: `Send authenticated requests to the Salesforce REST API.
106630
106762
  Authentication is handled automatically using the OAuth 2.0 Client Credentials Flow (External Client App or Connected App Consumer Key + Secret). An access token is obtained on each request, so the tool user only provides the API path.
@@ -106721,7 +106853,7 @@ Prefer SOQL via the /query endpoint for filtered, joined, or aggregated reads ra
106721
106853
  });
106722
106854
 
106723
106855
  // ../connectors/src/connectors/salesforce/index.ts
106724
- var tools62 = { request: requestTool47 };
106856
+ var tools62 = { request: requestTool46 };
106725
106857
  var salesforceConnector = new ConnectorPlugin({
106726
106858
  slug: "salesforce",
106727
106859
  authType: AUTH_TYPES.API_KEY,
@@ -107008,7 +107140,7 @@ var outputSchema76 = z78.discriminatedUnion("success", [
107008
107140
  error: z78.string()
107009
107141
  })
107010
107142
  ]);
107011
- var requestTool48 = new ConnectorTool({
107143
+ var requestTool47 = new ConnectorTool({
107012
107144
  name: "request",
107013
107145
  description: `Send authenticated requests to the InfluxDB HTTP API.
107014
107146
  Authentication is handled automatically using the API token (\`Authorization: Token {token}\`). The instance URL is resolved from the connection.
@@ -107086,7 +107218,7 @@ For read-only data exploration prefer SQL (InfluxDB 3) or InfluxQL queries \u201
107086
107218
  });
107087
107219
 
107088
107220
  // ../connectors/src/connectors/influxdb/index.ts
107089
- var tools63 = { request: requestTool48 };
107221
+ var tools63 = { request: requestTool47 };
107090
107222
  var influxdbConnector = new ConnectorPlugin({
107091
107223
  slug: "influxdb",
107092
107224
  authType: AUTH_TYPES.API_KEY,