@squadbase/vite-server 0.1.7-dev.3 → 0.1.7-dev.5

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.
@@ -42,78 +42,85 @@ var ParameterDefinition = class {
42
42
  }
43
43
  };
44
44
 
45
- // ../connectors/src/connectors/google-sheets/parameters.ts
46
- var parameters = {
47
- spreadsheetId: new ParameterDefinition({
48
- slug: "spreadsheet-id",
49
- name: "Google Sheets Spreadsheet ID",
50
- description: "The spreadsheet ID from the Google Sheets URL (the segment between /d/ and /edit in https://docs.google.com/spreadsheets/d/{spreadsheetId}/edit). Collected during the setup flow.",
51
- envVarBaseKey: "GOOGLE_SHEETS_SPREADSHEET_ID",
52
- type: "text",
53
- secret: false,
54
- required: true
55
- })
56
- };
57
-
58
45
  // ../connectors/src/connectors/google-sheets/sdk/index.ts
59
46
  var SHEETS_BASE_URL = "https://sheets.googleapis.com/v4/spreadsheets";
60
- function createClient(params, fetchFn = fetch) {
61
- const spreadsheetId = params[parameters.spreadsheetId.slug];
62
- if (!spreadsheetId) {
63
- throw new Error(
64
- `google-sheets: parameter "${parameters.spreadsheetId.slug}" is not configured for this connection`
65
- );
66
- }
67
- function resolvePath(path2) {
68
- const replaced = path2.replace(/\{spreadsheetId\}/g, spreadsheetId);
69
- return `${SHEETS_BASE_URL}${replaced === "" || replaced.startsWith("/") ? "" : "/"}${replaced}`;
47
+ function createClient(_params, fetchFn = fetch) {
48
+ function buildUrl(path2) {
49
+ return `${SHEETS_BASE_URL}${path2 === "" || path2.startsWith("/") ? "" : "/"}${path2}`;
70
50
  }
71
51
  async function request(path2, init) {
72
- return fetchFn(resolvePath(path2), init);
52
+ return fetchFn(buildUrl(path2), init);
73
53
  }
74
- async function getSpreadsheet() {
75
- const url = `${SHEETS_BASE_URL}/${spreadsheetId}?fields=spreadsheetId,properties,sheets.properties`;
76
- const response = await fetchFn(url);
54
+ async function asJson(response, operation) {
77
55
  if (!response.ok) {
78
56
  const body = await response.text();
79
57
  throw new Error(
80
- `google-sheets: getSpreadsheet failed (${response.status}): ${body}`
58
+ `google-sheets: ${operation} failed (${response.status}): ${body}`
81
59
  );
82
60
  }
83
61
  return await response.json();
84
62
  }
85
- async function getValues(range) {
63
+ async function getSpreadsheet(spreadsheetId) {
64
+ const url = `${SHEETS_BASE_URL}/${spreadsheetId}?fields=spreadsheetId,properties,sheets.properties`;
65
+ return asJson(await fetchFn(url), "getSpreadsheet");
66
+ }
67
+ async function getValues(spreadsheetId, range) {
86
68
  const url = `${SHEETS_BASE_URL}/${spreadsheetId}/values/${encodeURIComponent(range)}`;
87
- const response = await fetchFn(url);
88
- if (!response.ok) {
89
- const body = await response.text();
90
- throw new Error(
91
- `google-sheets: getValues failed (${response.status}): ${body}`
92
- );
93
- }
94
- return await response.json();
69
+ return asJson(await fetchFn(url), "getValues");
95
70
  }
96
- async function batchGetValues(ranges) {
71
+ async function batchGetValues(spreadsheetId, ranges) {
97
72
  const searchParams = new URLSearchParams();
98
73
  for (const range of ranges) {
99
74
  searchParams.append("ranges", range);
100
75
  }
101
76
  const url = `${SHEETS_BASE_URL}/${spreadsheetId}/values:batchGet?${searchParams.toString()}`;
102
- const response = await fetchFn(url);
103
- if (!response.ok) {
104
- const body = await response.text();
105
- throw new Error(
106
- `google-sheets: batchGetValues failed (${response.status}): ${body}`
107
- );
108
- }
109
- return await response.json();
77
+ return asJson(await fetchFn(url), "batchGetValues");
78
+ }
79
+ async function updateValues(spreadsheetId, range, values, valueInputOption = "USER_ENTERED") {
80
+ const url = `${SHEETS_BASE_URL}/${spreadsheetId}/values/${encodeURIComponent(range)}?valueInputOption=${valueInputOption}`;
81
+ const response = await fetchFn(url, {
82
+ method: "PUT",
83
+ headers: { "Content-Type": "application/json" },
84
+ body: JSON.stringify({ range, majorDimension: "ROWS", values })
85
+ });
86
+ return asJson(response, "updateValues");
87
+ }
88
+ async function appendValues(spreadsheetId, range, values, valueInputOption = "USER_ENTERED") {
89
+ const url = `${SHEETS_BASE_URL}/${spreadsheetId}/values/${encodeURIComponent(range)}:append?valueInputOption=${valueInputOption}`;
90
+ const response = await fetchFn(url, {
91
+ method: "POST",
92
+ headers: { "Content-Type": "application/json" },
93
+ body: JSON.stringify({ range, majorDimension: "ROWS", values })
94
+ });
95
+ return asJson(response, "appendValues");
96
+ }
97
+ async function clearValues(spreadsheetId, range) {
98
+ const url = `${SHEETS_BASE_URL}/${spreadsheetId}/values/${encodeURIComponent(range)}:clear`;
99
+ const response = await fetchFn(url, {
100
+ method: "POST",
101
+ headers: { "Content-Type": "application/json" },
102
+ body: JSON.stringify({})
103
+ });
104
+ return asJson(response, "clearValues");
105
+ }
106
+ async function batchUpdate(spreadsheetId, requests) {
107
+ const url = `${SHEETS_BASE_URL}/${spreadsheetId}:batchUpdate`;
108
+ const response = await fetchFn(url, {
109
+ method: "POST",
110
+ headers: { "Content-Type": "application/json" },
111
+ body: JSON.stringify({ requests })
112
+ });
113
+ return asJson(response, "batchUpdate");
110
114
  }
111
115
  return {
112
- spreadsheetId,
113
116
  request,
114
117
  getSpreadsheet,
115
118
  getValues,
116
- batchGetValues
119
+ batchGetValues,
120
+ updateValues,
121
+ appendValues,
122
+ clearValues,
123
+ batchUpdate
117
124
  };
118
125
  }
119
126
 
@@ -304,11 +311,16 @@ var inputSchema = z.object({
304
311
  "Brief description of what you intend to accomplish with this tool call"
305
312
  ),
306
313
  connectionId: z.string().describe("ID of the Google Sheets connection to use"),
307
- method: z.enum(["GET"]).describe("HTTP method. Only GET is supported (read-only analysis)."),
314
+ method: z.enum(["GET", "POST", "PUT"]).describe(
315
+ "HTTP method. GET for reads, PUT for values.update, POST for values.append / values:batchUpdate / values:batchGet / values:clear / values:batchClear."
316
+ ),
308
317
  path: z.string().describe(
309
- "API path appended to https://sheets.googleapis.com/v4/spreadsheets (e.g., '/{spreadsheetId}', '/{spreadsheetId}/values/Sheet1!A1:D10'). The `{spreadsheetId}` placeholder is automatically replaced with the connection's configured spreadsheet ID."
318
+ "API path appended to https://sheets.googleapis.com/v4/spreadsheets. The caller must provide the target spreadsheetId explicitly in the path (e.g., '/1AbCxyz...', '/1AbCxyz.../values/Sheet1!A1:D10')."
310
319
  ),
311
- queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL")
320
+ queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters to append to the URL"),
321
+ body: z.unknown().optional().describe(
322
+ "Request body for POST/PUT. Will be JSON-serialized. Omit for GET."
323
+ )
312
324
  });
313
325
  var outputSchema = z.discriminatedUnion("success", [
314
326
  z.object({
@@ -323,12 +335,13 @@ var outputSchema = z.discriminatedUnion("success", [
323
335
  ]);
324
336
  var requestTool = new ConnectorTool({
325
337
  name: "request",
326
- description: `Send authenticated GET requests to the Google Sheets API v4 for read-only analysis.
327
- The \`{spreadsheetId}\` placeholder in the path is automatically replaced with the connection's configured spreadsheet ID.
338
+ description: `Send authenticated requests to the Google Sheets API v4.
339
+ Supports GET (read) and POST/PUT (write: update/append/batchUpdate/clear).
340
+ The caller must include the target spreadsheetId in the path explicitly.
328
341
  Authentication is handled automatically via OAuth proxy.`,
329
342
  inputSchema,
330
343
  outputSchema,
331
- async execute({ connectionId, method, path: path2, queryParams }, connections, config) {
344
+ async execute({ connectionId, method, path: path2, queryParams, body }, connections, config) {
332
345
  const connection2 = connections.find((c) => c.id === connectionId);
333
346
  if (!connection2) {
334
347
  return {
@@ -340,15 +353,7 @@ Authentication is handled automatically via OAuth proxy.`,
340
353
  `[connector-request] google-sheets/${connection2.name}: ${method} ${path2}`
341
354
  );
342
355
  try {
343
- const spreadsheetId = parameters.spreadsheetId.tryGetValue(connection2);
344
- if (!spreadsheetId) {
345
- return {
346
- success: false,
347
- error: `Spreadsheet ID is not configured for connection "${connection2.name}". Ask the user for a Google Sheets URL and save it with updateConnectionParameters (parameterSlug: "spreadsheet-id") before calling this tool.`
348
- };
349
- }
350
- const resolvedPath = path2.replace(/\{spreadsheetId\}/g, spreadsheetId);
351
- let url = `${SHEETS_BASE_URL2}${resolvedPath === "" || resolvedPath.startsWith("/") ? "" : "/"}${resolvedPath}`;
356
+ let url = `${SHEETS_BASE_URL2}${path2 === "" || path2.startsWith("/") ? "" : "/"}${path2}`;
352
357
  if (queryParams) {
353
358
  const searchParams = new URLSearchParams(queryParams);
354
359
  url += `?${searchParams.toString()}`;
@@ -358,16 +363,17 @@ Authentication is handled automatically via OAuth proxy.`,
358
363
  const controller = new AbortController();
359
364
  const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
360
365
  try {
366
+ const proxyBody = { url, method };
367
+ if (body !== void 0 && method !== "GET") {
368
+ proxyBody.body = body;
369
+ }
361
370
  const response = await fetch(proxyUrl, {
362
371
  method: "POST",
363
372
  headers: {
364
373
  "Content-Type": "application/json",
365
374
  Authorization: `Bearer ${token}`
366
375
  },
367
- body: JSON.stringify({
368
- url,
369
- method
370
- }),
376
+ body: JSON.stringify(proxyBody),
371
377
  signal: controller.signal
372
378
  });
373
379
  const data = await response.json();
@@ -390,66 +396,73 @@ Authentication is handled automatically via OAuth proxy.`,
390
396
  var requestToolName = `google-sheets-oauth_${requestTool.name}`;
391
397
  var googleSheetsOnboarding = new ConnectorOnboarding({
392
398
  connectionSetupInstructions: {
393
- 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\u5206\u6790\u5BFE\u8C61\u306E\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306F\u30E6\u30FC\u30B6\u30FC\u304B\u3089\u53D7\u3051\u53D6\u3063\u305FURL\u3067\u6307\u5B9A\u3057\u307E\u3059\uFF08\u65B0\u3057\u3044\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306F\u4F5C\u6210\u3057\u307E\u305B\u3093\uFF09\u3002
399
+ 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
394
400
 
395
- 1. \`askUserQuestion\` \u3067\u5206\u6790\u5BFE\u8C61\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306EURL\u3092\u30D2\u30A2\u30EA\u30F3\u30B0\u3059\u308B:
401
+ 1. \`askUserQuestion\` \u3067\u64CD\u4F5C\u5BFE\u8C61\u306E\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8URL\u3092\u30D2\u30A2\u30EA\u30F3\u30B0\u3059\u308B:
396
402
  - \`type\`: \`"freeText"\`
397
- - \`question\`: \u300C\u5206\u6790\u3057\u305F\u3044Google Sheets\u306EURL\u3092\u8CBC\u308A\u4ED8\u3051\u3066\u304F\u3060\u3055\u3044\u300D
403
+ - \`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
398
404
  - \`placeholder\`: \`"https://docs.google.com/spreadsheets/d/.../edit"\`
399
405
  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
400
- 3. \u62BD\u51FA\u3057\u305FID\u3092 \`updateConnectionParameters\` \u3067\u4FDD\u5B58\u3059\u308B:
401
- - \`parameterSlug\`: \`"spreadsheet-id"\`
402
- - \`options\`: \`[{ value: <\u62BD\u51FA\u3057\u305FID>, label: <\u540C\u3058\u5024> }]\`\uFF081\u4EF6\u306E\u307F\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u81EA\u52D5\u9078\u629E\u3055\u308C\u308B\uFF09
403
- 4. \`${requestToolName}\` \u3067\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3059\u308B:
406
+ 3. \`${requestToolName}\` \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u6027\u3092\u78BA\u8A8D\u3059\u308B:
404
407
  - \`method\`: \`"GET"\`
405
- - \`path\`: \`"/{spreadsheetId}"\`\uFF08\`{spreadsheetId}\` \u306F\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u3002\u305D\u306E\u307E\u307E\u6E21\u305B\u3070\u4FDD\u5B58\u6E08\u307FID\u306B\u81EA\u52D5\u7F6E\u63DB\u3055\u308C\u307E\u3059\uFF09
406
- 5. **\u691C\u8A3C\u5931\u6557\u6642\u306E\u518D\u30D2\u30A2\u30EA\u30F3\u30B0**: \u30B9\u30C6\u30C3\u30D74\u304C \`success: false\` \u3092\u8FD4\u3057\u305F\u5834\u5408\uFF08404/403/\u898B\u3064\u304B\u3089\u306A\u3044\u7B49\u3001\u3069\u3093\u306A\u30A8\u30E9\u30FC\u3067\u3082\uFF09\u3001\u4EE5\u4E0B\u306E\u624B\u9806\u3067\u518D\u8A66\u884C\u3059\u308B:
407
- a. \u30E6\u30FC\u30B6\u30FC\u306B\u539F\u56E0\u306E\u53EF\u80FD\u6027\u3092\u4F1D\u3048\u308B\uFF08\u4F8B: URL\u304C\u9593\u9055\u3063\u3066\u3044\u308B\u3001OAuth\u9023\u643A\u3057\u305FGoogle\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u95B2\u89A7\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\uFF09
408
- b. \`askUserQuestion\` \u3067\u3082\u3046\u4E00\u5EA6URL\u3092\u805E\u304D\u76F4\u3059\uFF08\`type: "freeText"\`\u3001\`question: \u300C\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6URL\u3092\u8CBC\u308A\u4ED8\u3051\u3066\u3044\u305F\u3060\u304F\u304B\u3001\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u5171\u6709\u8A2D\u5B9A\u3092\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u300D\`\uFF09
409
- c. \u65B0\u3057\u304F\u53D7\u3051\u53D6\u3063\u305FURL\u304B\u3089ID\u3092\u62BD\u51FA\u3057 \`updateConnectionParameters\` \u3067\u4E0A\u66F8\u304D\u4FDD\u5B58\u3001\u518D\u5EA6 \`${requestToolName}\` \u3067\u691C\u8A3C
410
- d. \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\u3002\u540C\u3058ID\u304C\u518D\u5EA6\u5931\u6557\u3059\u308B\u5834\u5408\u306F\u5171\u6709\u8A2D\u5B9A\u306E\u554F\u984C\u306A\u306E\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u305D\u306E\u65E8\u3092\u4F1D\u3048\u3066\u5224\u65AD\u3092\u4EF0\u3050
408
+ - \`path\`: \`"/<\u62BD\u51FA\u3057\u305FspreadsheetId>"\`
409
+ 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:
410
+ 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
411
+ b. \`askUserQuestion\` \u3067\u3082\u3046\u4E00\u5EA6URL\u3092\u805E\u304D\u76F4\u3057\u3001\u518D\u5EA6 \`${requestToolName}\` \u3067\u691C\u8A3C
412
+ 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
411
413
 
412
414
  #### \u5236\u7D04
413
- - **\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u4E2D\u306B\u30BB\u30EB\u5024\u3092\u5927\u91CF\u306B\u53D6\u5F97\u3057\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u306E\u307F
415
+ - **\u63A5\u7D9A\u8A2D\u5B9A\u4E2D\u306F\u5927\u91CF\u306E\u30BB\u30EB\u5024\u3092\u53D6\u5F97\u3057\u306A\u3044\u3053\u3068**\u3002\u5B9F\u884C\u3057\u3066\u3088\u3044\u306E\u306F\u4E0A\u8A18\u624B\u9806\u3067\u6307\u5B9A\u3055\u308C\u305F\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u306E\u307F
416
+ - **\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u3092\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u4FDD\u5B58\u3057\u306A\u3044**\u3002\u30CF\u30F3\u30C9\u30E9\u5074\u306E\u30B3\u30FC\u30C9\uFF08\`server-logic\`\uFF09\u306B\u5BFE\u8C61\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u3092\u76F4\u63A5\u6E21\u3059\u8A2D\u8A08\u306B\u306A\u3063\u3066\u3044\u308B\u305F\u3081\u3001\`updateConnectionParameters\` \u306F\u547C\u3070\u306A\u3044\u3053\u3068
414
417
  - \u30C4\u30FC\u30EB\u9593\u306F1\u6587\u3060\u3051\u66F8\u3044\u3066\u5373\u6B21\u306E\u30C4\u30FC\u30EB\u547C\u3073\u51FA\u3057\u3002\u4E0D\u8981\u306A\u8AAC\u660E\u306F\u7701\u7565\u3057\u3001\u52B9\u7387\u7684\u306B\u9032\u3081\u308B`,
415
- en: `Follow these steps to set up the Google Sheets (OAuth) connection. The spreadsheet to analyze is specified by the URL provided by the user (no new spreadsheet is created).
418
+ en: `Follow these steps to set up the Google Sheets (OAuth) connection. This connector uses the read/write \`spreadsheets\` scope, so it can read and edit any spreadsheet the authenticated Google account has access to.
416
419
 
417
- 1. Call \`askUserQuestion\` to ask for the spreadsheet URL to analyze:
420
+ 1. Call \`askUserQuestion\` to ask for the spreadsheet URL the user wants to work with:
418
421
  - \`type\`: \`"freeText"\`
419
- - \`question\`: "Please paste the URL of the Google Sheet you want to analyze"
422
+ - \`question\`: "Please paste the URL of the Google Sheet you want to work with (both read and edit are supported)."
420
423
  - \`placeholder\`: \`"https://docs.google.com/spreadsheets/d/.../edit"\`
421
424
  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.
422
- 3. Save the extracted ID via \`updateConnectionParameters\`:
423
- - \`parameterSlug\`: \`"spreadsheet-id"\`
424
- - \`options\`: \`[{ value: <extracted ID>, label: <same value> }]\` (a single option is auto-selected)
425
- 4. Verify access by calling \`${requestToolName}\`:
425
+ 3. Verify accessibility by calling \`${requestToolName}\`:
426
426
  - \`method\`: \`"GET"\`
427
- - \`path\`: \`"/{spreadsheetId}"\` (the \`{spreadsheetId}\` placeholder is auto-replaced with the saved ID \u2014 pass it as-is)
428
- 5. **Retry on verification failure**: If step 4 returns \`success: false\` (404/403/not found or any other error):
429
- a. Tell the user the likely causes (wrong URL, OAuth-connected Google account lacks read access, private sheet shared with a different account, etc.)
430
- b. Call \`askUserQuestion\` to re-ask for the URL (\`type: "freeText"\`, \`question: "I could not access that sheet. Please paste the URL again, or verify the share settings of the spreadsheet."\`)
431
- c. Extract the ID from the new URL, overwrite it via \`updateConnectionParameters\`, and re-verify with \`${requestToolName}\`
432
- d. Repeat until verification succeeds (or the user aborts). If the same ID keeps failing, it is a sharing/permissions issue \u2014 inform the user and ask how to proceed
427
+ - \`path\`: \`"/<extracted spreadsheetId>"\`
428
+ 4. **Retry on verification failure**: If step 3 returns \`success: false\` (404/403/not found or any other error):
429
+ a. Tell the user the likely causes (wrong URL, OAuth-connected Google account lacks access, private sheet shared with a different account, etc.)
430
+ b. Call \`askUserQuestion\` again to re-ask for the URL and re-verify with \`${requestToolName}\`
431
+ c. Repeat until verification succeeds (or the user aborts)
433
432
 
434
433
  #### Constraints
435
- - **Do NOT read large amounts of cell data during setup**. Only the metadata request specified above is allowed
436
- - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
434
+ - **Do NOT fetch large amounts of cell data during setup**. Only the metadata request specified above is allowed.
435
+ - **Do NOT persist the spreadsheet ID as a connection parameter.** The handler-side code (\`server-logic\`) is designed to receive the target spreadsheet ID directly, so do NOT call \`updateConnectionParameters\`.
436
+ - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently.`
437
437
  },
438
438
  dataOverviewInstructions: {
439
- en: `1. Call ${requestToolName} with GET /{spreadsheetId} to fetch spreadsheet metadata (sheet names, grid properties)
440
- 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`,
441
- 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
442
- 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`
439
+ en: `1. Call ${requestToolName} with GET /<spreadsheetId> to fetch spreadsheet metadata (sheet names, grid properties)
440
+ 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`,
441
+ 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
442
+ 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`
443
443
  }
444
444
  });
445
445
 
446
+ // ../connectors/src/connectors/google-sheets/parameters.ts
447
+ var parameters = {
448
+ spreadsheetId: new ParameterDefinition({
449
+ slug: "spreadsheet-id",
450
+ name: "Google Sheets Spreadsheet ID",
451
+ description: "The spreadsheet ID from the Google Sheets URL (the segment between /d/ and /edit in https://docs.google.com/spreadsheets/d/{spreadsheetId}/edit). Collected during the setup flow.",
452
+ envVarBaseKey: "GOOGLE_SHEETS_SPREADSHEET_ID",
453
+ type: "text",
454
+ secret: false,
455
+ required: false
456
+ })
457
+ };
458
+
446
459
  // ../connectors/src/connectors/google-sheets/index.ts
447
460
  var tools = { request: requestTool };
448
461
  var googleSheetsConnector = new ConnectorPlugin({
449
462
  slug: "google-sheets",
450
463
  authType: AUTH_TYPES.OAUTH,
451
464
  name: "Google Sheets",
452
- description: "Connect to an existing Google Sheets spreadsheet for read-only data analysis using OAuth.",
465
+ description: "Connect to Google Sheets for read/write access via OAuth. Any spreadsheet the authenticated Google account can access is supported \u2014 the target spreadsheetId is passed per call.",
453
466
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1UPQuggyiZmbb26CuaSr2h/032770e8739b183fa00b7625f024e536/google-sheets.svg",
454
467
  parameters,
455
468
  releaseFlag: { dev1: true, dev2: false, prod: false },
@@ -458,25 +471,33 @@ var googleSheetsConnector = new ConnectorPlugin({
458
471
  allowlist: [
459
472
  {
460
473
  host: "sheets.googleapis.com",
461
- methods: ["GET"]
474
+ methods: ["GET", "POST", "PUT"]
462
475
  }
463
476
  ]
464
477
  },
465
478
  systemPrompt: {
466
479
  en: `### Tools (setup-time only)
467
480
 
468
- - \`google-sheets-oauth_request\`: Call the Google Sheets API during setup / data overview. Read-only (GET only). Use it to fetch spreadsheet metadata and sample cell values. The \`{spreadsheetId}\` placeholder in the path is automatically replaced with the spreadsheet configured at setup time. Authentication is configured automatically via OAuth.
481
+ - \`google-sheets-oauth_request\`: Call the Google Sheets API during setup / data overview. Supports GET, POST, and PUT. The caller must include the target spreadsheetId in the path explicitly (e.g., \`/1AbCxyz...\`, \`/1AbCxyz.../values/Sheet1!A1:D10\`). Authentication is configured automatically via OAuth.
469
482
 
470
- > **Important**: The \`google-sheets-oauth_request\` tool is only available at setup time. Inside server-logic handlers, use the SDK (\`connection(id).getValues\`, etc.) \u2014 the SDK's fetch is already wired through the OAuth proxy. **Do NOT** hand-roll HTTP calls to \`_sqcore/connections/*/request\` from a handler.
483
+ > **Important**: The \`google-sheets-oauth_request\` tool is only available at setup time. Inside server-logic handlers, use the SDK (\`connection(id).getValues(spreadsheetId, range)\`, etc.) \u2014 the SDK's fetch is already wired through the OAuth proxy. **Do NOT** hand-roll HTTP calls to \`_sqcore/connections/*/request\` from a handler.
471
484
 
472
- > **Connection scope**: Each connection is bound to a single spreadsheet selected at setup time via URL. This connector does NOT create new spreadsheets and does NOT write to spreadsheets. The OAuth scope is \`spreadsheets.readonly\`.
485
+ > **Connection scope**: The OAuth scope is \`spreadsheets\` (read/write). A connection is NOT bound to a single spreadsheet \u2014 the target spreadsheetId is passed per call. The spreadsheetId is NOT stored as a connection parameter or environment variable; pass it explicitly from the caller (e.g., as a query param or request input to the handler).
473
486
 
474
- ### Google Sheets API Reference (read-only)
487
+ ### Google Sheets API Reference
475
488
 
489
+ Reads:
476
490
  - GET \`/{spreadsheetId}\` \u2014 Get spreadsheet metadata (title, sheets, properties)
477
491
  - GET \`/{spreadsheetId}/values/{range}\` \u2014 Get cell values for a range
478
492
  - GET \`/{spreadsheetId}/values:batchGet?ranges={range1}&ranges={range2}\` \u2014 Get values for multiple ranges
479
493
 
494
+ Writes:
495
+ - PUT \`/{spreadsheetId}/values/{range}?valueInputOption=USER_ENTERED\` \u2014 Overwrite a range (body: \`{ range, majorDimension, values }\`)
496
+ - POST \`/{spreadsheetId}/values/{range}:append?valueInputOption=USER_ENTERED\` \u2014 Append rows after the existing data
497
+ - POST \`/{spreadsheetId}/values/{range}:clear\` \u2014 Clear values in a range
498
+ - POST \`/{spreadsheetId}/values:batchUpdate\` \u2014 Batch update / batch clear
499
+ - POST \`/{spreadsheetId}:batchUpdate\` \u2014 Structural edits (addSheet, deleteSheet, updateCells, formatting, \u2026)
500
+
480
501
  ### Range Notation (A1 notation)
481
502
  - \`Sheet1!A1:D10\` \u2014 Specific range on Sheet1
482
503
  - \`Sheet1!A:A\` \u2014 Entire column A on Sheet1
@@ -486,20 +507,24 @@ var googleSheetsConnector = new ConnectorPlugin({
486
507
 
487
508
  ### Tips
488
509
  - To explore a spreadsheet, first get metadata to see available sheet names
510
+ - Use \`valueInputOption=USER_ENTERED\` to parse formulas/dates like the UI; use \`RAW\` to store inputs literally
489
511
  - Use \`valueRenderOption=FORMATTED_VALUE\` query param to get display values
490
512
  - Use \`valueRenderOption=UNFORMATTED_VALUE\` for raw numeric values
491
513
  - Use \`majorDimension=COLUMNS\` to get data organized by columns instead of rows
492
514
 
493
515
  ### Business Logic
494
516
 
495
- 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 and do NOT read \`INTERNAL_SQUADBASE_*\` env vars \u2014 the SDK takes care of OAuth. The spreadsheet ID is bound to the connection at setup time; do NOT ask handler callers to pass it.
517
+ 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 and do NOT read \`INTERNAL_SQUADBASE_*\` env vars \u2014 the SDK takes care of OAuth. The target spreadsheetId is NOT stored on the connection \u2014 the handler caller must pass it (as part of the request input).
496
518
 
497
519
  SDK surface (client created via \`connection(connectionId)\`):
498
- - \`client.spreadsheetId\` \u2014 the spreadsheet ID configured for this connection.
499
- - \`client.request(path, init?)\` \u2014 low-level authenticated fetch (\`path\` is appended to \`https://sheets.googleapis.com/v4/spreadsheets\`; \`{spreadsheetId}\` is auto-replaced).
500
- - \`client.getSpreadsheet()\` \u2014 fetch spreadsheet metadata for the configured spreadsheet.
501
- - \`client.getValues(range)\` \u2014 read a range (A1 notation) from the configured spreadsheet.
502
- - \`client.batchGetValues(ranges)\` \u2014 read multiple ranges from the configured spreadsheet.
520
+ - \`client.request(path, init?)\` \u2014 low-level authenticated fetch (\`path\` is appended to \`https://sheets.googleapis.com/v4/spreadsheets\`; the caller must include the target spreadsheetId).
521
+ - \`client.getSpreadsheet(spreadsheetId)\` \u2014 fetch spreadsheet metadata.
522
+ - \`client.getValues(spreadsheetId, range)\` \u2014 read a range (A1 notation).
523
+ - \`client.batchGetValues(spreadsheetId, ranges)\` \u2014 read multiple ranges.
524
+ - \`client.updateValues(spreadsheetId, range, values, valueInputOption?)\` \u2014 overwrite a range (requires write scope).
525
+ - \`client.appendValues(spreadsheetId, range, values, valueInputOption?)\` \u2014 append rows (requires write scope).
526
+ - \`client.clearValues(spreadsheetId, range)\` \u2014 clear a range (requires write scope).
527
+ - \`client.batchUpdate(spreadsheetId, requests)\` \u2014 structural edits (requires write scope).
503
528
 
504
529
  If a handler test fails with \`Connection proxy is not configured\`, retry \u2014 the sandbox is still initializing. Do NOT abandon the SDK and construct OAuth proxy URLs manually.
505
530
 
@@ -509,32 +534,44 @@ If a handler test fails with \`Connection proxy is not configured\`, retry \u201
509
534
  import { connection } from "@squadbase/vite-server/connectors/google-sheets";
510
535
 
511
536
  const sheets = connection("<connectionId>");
537
+ const spreadsheetId = "<passed from request input>";
512
538
 
513
- // Get metadata for the configured spreadsheet
514
- const metadata = await sheets.getSpreadsheet();
515
- console.log(metadata.properties.title, metadata.sheets.map(s => s.properties.title));
539
+ // Read: metadata and values
540
+ const metadata = await sheets.getSpreadsheet(spreadsheetId);
541
+ const values = await sheets.getValues(spreadsheetId, "Sheet1!A1:D10");
516
542
 
517
- // Get cell values
518
- const values = await sheets.getValues("Sheet1!A1:D10");
519
- console.log(values.values); // 2D array
543
+ // Write: overwrite, append, clear
544
+ await sheets.updateValues(spreadsheetId, "Sheet1!A1:B2", [["name", "age"], ["Alice", 30]]);
545
+ await sheets.appendValues(spreadsheetId, "Sheet1!A:B", [["Bob", 25]]);
546
+ await sheets.clearValues(spreadsheetId, "Sheet1!A1:B10");
520
547
 
521
- // Batch-get multiple ranges
522
- const batch = await sheets.batchGetValues(["Sheet1!A:A", "Sheet2!B2:C100"]);
548
+ // Structural edits (add a sheet)
549
+ await sheets.batchUpdate(spreadsheetId, [
550
+ { addSheet: { properties: { title: "NewSheet" } } },
551
+ ]);
523
552
  \`\`\``,
524
553
  ja: `### \u30C4\u30FC\u30EB\uFF08\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306E\u307F\uFF09
525
554
 
526
- - \`google-sheets-oauth_request\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3084\u30C7\u30FC\u30BF\u6982\u8981\u628A\u63E1\u6642\u306B Google Sheets API \u3092\u547C\u3073\u51FA\u3059\u30C4\u30FC\u30EB\u3067\u3059\u3002\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF08GET \u306E\u307F\uFF09\u3067\u3059\u3002\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u53D6\u5F97\u3084\u30BB\u30EB\u5024\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E \`{spreadsheetId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B\u6307\u5B9A\u3055\u308C\u305F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u306B\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
555
+ - \`google-sheets-oauth_request\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3084\u30C7\u30FC\u30BF\u6982\u8981\u628A\u63E1\u6642\u306B Google Sheets API \u3092\u547C\u3073\u51FA\u3059\u30C4\u30FC\u30EB\u3067\u3059\u3002GET / POST / PUT \u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\u547C\u3073\u51FA\u3057\u5074\u304C\u30D1\u30B9\u306B\u5BFE\u8C61\u306E spreadsheetId \u3092\u660E\u793A\u7684\u306B\u542B\u3081\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u4F8B: \`/1AbCxyz...\`\u3001\`/1AbCxyz.../values/Sheet1!A1:D10\`\uFF09\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
527
556
 
528
- > **\u91CD\u8981**: \`google-sheets-oauth_request\` \u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306E\u307F\u5229\u7528\u53EF\u80FD\u3067\u3059\u3002\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u306E\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u5FC5\u305A SDK\uFF08\`connection(id).getValues\` \u306A\u3069\uFF09\u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002SDK \u306E fetch \u306F OAuth \u30D7\u30ED\u30AD\u30B7\u7D4C\u7531\u3067\u65E2\u306B\u914D\u7DDA\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u304B\u3089 \`_sqcore/connections/*/request\` \u3092\u624B\u66F8\u304D\u3067\u547C\u3073\u51FA\u3055\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
557
+ > **\u91CD\u8981**: \`google-sheets-oauth_request\` \u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306E\u307F\u5229\u7528\u53EF\u80FD\u3067\u3059\u3002\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u306E\u30CF\u30F3\u30C9\u30E9\u5185\u3067\u306F\u5FC5\u305A SDK\uFF08\`connection(id).getValues(spreadsheetId, range)\` \u306A\u3069\uFF09\u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044\u3002SDK \u306E fetch \u306F OAuth \u30D7\u30ED\u30AD\u30B7\u7D4C\u7531\u3067\u65E2\u306B\u914D\u7DDA\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u30CF\u30F3\u30C9\u30E9\u304B\u3089 \`_sqcore/connections/*/request\` \u3092\u624B\u66F8\u304D\u3067\u547C\u3073\u51FA\u3055\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
529
558
 
530
- > **\u63A5\u7D9A\u30B9\u30B3\u30FC\u30D7**: \u5404\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306BURL\u3067\u6307\u5B9A\u3055\u308C\u305F1\u3064\u306E\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306B\u7D10\u3065\u304D\u307E\u3059\u3002\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u4F5C\u6210\u3084\u66F8\u304D\u8FBC\u307F\u306F\u884C\u3044\u307E\u305B\u3093\u3002OAuth \u30B9\u30B3\u30FC\u30D7\u306F \`spreadsheets.readonly\` \u3067\u3059\u3002
559
+ > **\u63A5\u7D9A\u30B9\u30B3\u30FC\u30D7**: OAuth \u30B9\u30B3\u30FC\u30D7\u306F \`spreadsheets\`\uFF08\u8AAD\u307F\u66F8\u304D\u53EF\u80FD\uFF09\u3067\u3059\u3002\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306F\u5358\u4E00\u306E\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306B\u7D10\u3065\u304D\u307E\u305B\u3093 \u2014 \u5BFE\u8C61\u306E spreadsheetId \u306F\u547C\u3073\u51FA\u3057\u3054\u3068\u306B\u6E21\u3057\u307E\u3059\u3002spreadsheetId \u306F\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u30D1\u30E9\u30E1\u30FC\u30BF\u3084\u74B0\u5883\u5909\u6570\u3068\u3057\u3066\u4FDD\u5B58\u3055\u308C\u306A\u3044\u305F\u3081\u3001\u30CF\u30F3\u30C9\u30E9\u306E\u547C\u3073\u51FA\u3057\u5143\uFF08\u30EA\u30AF\u30A8\u30B9\u30C8\u5165\u529B\u306A\u3069\uFF09\u304B\u3089\u660E\u793A\u7684\u306B\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
531
560
 
532
- ### Google Sheets API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF09
561
+ ### Google Sheets API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
533
562
 
563
+ \u8AAD\u307F\u53D6\u308A:
534
564
  - GET \`/{spreadsheetId}\` \u2014 \u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\uFF08\u30BF\u30A4\u30C8\u30EB\u3001\u30B7\u30FC\u30C8\u3001\u30D7\u30ED\u30D1\u30C6\u30A3\uFF09
535
565
  - GET \`/{spreadsheetId}/values/{range}\` \u2014 \u7BC4\u56F2\u306E\u30BB\u30EB\u5024\u3092\u53D6\u5F97
536
566
  - GET \`/{spreadsheetId}/values:batchGet?ranges={range1}&ranges={range2}\` \u2014 \u8907\u6570\u7BC4\u56F2\u306E\u5024\u3092\u53D6\u5F97
537
567
 
568
+ \u66F8\u304D\u8FBC\u307F:
569
+ - PUT \`/{spreadsheetId}/values/{range}?valueInputOption=USER_ENTERED\` \u2014 \u7BC4\u56F2\u3092\u4E0A\u66F8\u304D\uFF08body: \`{ range, majorDimension, values }\`\uFF09
570
+ - POST \`/{spreadsheetId}/values/{range}:append?valueInputOption=USER_ENTERED\` \u2014 \u65E2\u5B58\u30C7\u30FC\u30BF\u306E\u5F8C\u308D\u306B\u884C\u3092\u8FFD\u8A18
571
+ - POST \`/{spreadsheetId}/values/{range}:clear\` \u2014 \u7BC4\u56F2\u306E\u5024\u3092\u30AF\u30EA\u30A2
572
+ - POST \`/{spreadsheetId}/values:batchUpdate\` \u2014 \u30D0\u30C3\u30C1\u66F4\u65B0 / \u30D0\u30C3\u30C1\u30AF\u30EA\u30A2
573
+ - POST \`/{spreadsheetId}:batchUpdate\` \u2014 \u69CB\u9020\u5909\u66F4\uFF08addSheet, deleteSheet, updateCells, \u66F8\u5F0F\u8A2D\u5B9A \u7B49\uFF09
574
+
538
575
  ### \u7BC4\u56F2\u306E\u8868\u8A18\u6CD5\uFF08A1\u8868\u8A18\u6CD5\uFF09
539
576
  - \`Sheet1!A1:D10\` \u2014 Sheet1\u4E0A\u306E\u7279\u5B9A\u7BC4\u56F2
540
577
  - \`Sheet1!A:A\` \u2014 Sheet1\u306EA\u5217\u5168\u4F53
@@ -544,20 +581,24 @@ const batch = await sheets.batchGetValues(["Sheet1!A:A", "Sheet2!B2:C100"]);
544
581
 
545
582
  ### \u30D2\u30F3\u30C8
546
583
  - \u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u3092\u63A2\u7D22\u3059\u308B\u306B\u306F\u3001\u307E\u305A\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u3066\u5229\u7528\u53EF\u80FD\u306A\u30B7\u30FC\u30C8\u540D\u3092\u78BA\u8A8D\u3057\u307E\u3059
584
+ - \u6570\u5F0F\u3084\u65E5\u4ED8\u3092 UI \u3068\u540C\u3058\u3088\u3046\u306B\u89E3\u91C8\u3055\u305B\u308B\u306B\u306F \`valueInputOption=USER_ENTERED\`\u3001\u305D\u306E\u307E\u307E\u6587\u5B57\u5217\u3068\u3057\u3066\u4FDD\u5B58\u3059\u308B\u306B\u306F \`RAW\` \u3092\u4F7F\u3044\u307E\u3059
547
585
  - \u8868\u793A\u5024\u3092\u53D6\u5F97\u3059\u308B\u306B\u306F \`valueRenderOption=FORMATTED_VALUE\` \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059
548
586
  - \u751F\u306E\u6570\u5024\u3092\u53D6\u5F97\u3059\u308B\u306B\u306F \`valueRenderOption=UNFORMATTED_VALUE\` \u3092\u4F7F\u7528\u3057\u307E\u3059
549
587
  - \u5217\u3054\u3068\u306B\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3059\u308B\u306B\u306F \`majorDimension=COLUMNS\` \u3092\u4F7F\u7528\u3057\u307E\u3059
550
588
 
551
589
  ### Business Logic
552
590
 
553
- \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\u30BF SDK \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\`INTERNAL_SQUADBASE_*\` \u306E\u74B0\u5883\u5909\u6570\u3092\u4F7F\u3063\u3066\u624B\u52D5\u3067 OAuth \u30D7\u30ED\u30AD\u30B7\u3092\u53E9\u304F\u3053\u3068\u3082\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044 \u2014 SDK \u304C OAuth \u3092\u51E6\u7406\u3057\u307E\u3059\u3002\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u306F\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306B\u7D10\u3065\u3051\u3089\u308C\u3066\u3044\u308B\u306E\u3067\u3001\u30CF\u30F3\u30C9\u30E9\u306E\u547C\u3073\u51FA\u3057\u5143\u306B\u6E21\u3055\u305B\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
591
+ \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\u30BF SDK \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\`INTERNAL_SQUADBASE_*\` \u306E\u74B0\u5883\u5909\u6570\u3092\u4F7F\u3063\u3066\u624B\u52D5\u3067 OAuth \u30D7\u30ED\u30AD\u30B7\u3092\u53E9\u304F\u3053\u3068\u3082\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044 \u2014 SDK \u304C OAuth \u3092\u51E6\u7406\u3057\u307E\u3059\u3002\u5BFE\u8C61 spreadsheetId \u306F\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306B\u4FDD\u5B58\u3055\u308C\u306A\u3044\u305F\u3081\u3001\u30CF\u30F3\u30C9\u30E9\u306E\u547C\u3073\u51FA\u3057\u5143\uFF08\u30EA\u30AF\u30A8\u30B9\u30C8\u5165\u529B\u306A\u3069\uFF09\u304B\u3089\u6E21\u3057\u3066\u304F\u3060\u3055\u3044\u3002
554
592
 
555
593
  SDK\uFF08\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\uFF09:
556
- - \`client.spreadsheetId\` \u2014 \u3053\u306E\u30B3\u30CD\u30AF\u30B7\u30E7\u30F3\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8ID\u3002
557
- - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304D fetch\uFF08\`path\` \u306F \`https://sheets.googleapis.com/v4/spreadsheets\` \u306B\u8FFD\u52A0\u3055\u308C\u3001\`{spreadsheetId}\` \u306F\u81EA\u52D5\u7F6E\u63DB\u3055\u308C\u307E\u3059\uFF09\u3002
558
- - \`client.getSpreadsheet()\` \u2014 \u8A2D\u5B9A\u6E08\u307F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3002
559
- - \`client.getValues(range)\` \u2014 \u8A2D\u5B9A\u6E08\u307F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u7BC4\u56F2\u306E\u5024\u3092\u53D6\u5F97\uFF08A1 \u8868\u8A18\uFF09\u3002
560
- - \`client.batchGetValues(ranges)\` \u2014 \u8A2D\u5B9A\u6E08\u307F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u8907\u6570\u7BC4\u56F2\u306E\u5024\u3092\u53D6\u5F97\u3002
594
+ - \`client.request(path, init?)\` \u2014 \u4F4E\u30EC\u30D9\u30EB\u306E\u8A8D\u8A3C\u4ED8\u304D fetch\uFF08\`path\` \u306F \`https://sheets.googleapis.com/v4/spreadsheets\` \u306B\u8FFD\u52A0\u3055\u308C\u3001\u547C\u3073\u51FA\u3057\u5074\u304C spreadsheetId \u3092\u542B\u3081\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF09\u3002
595
+ - \`client.getSpreadsheet(spreadsheetId)\` \u2014 \u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3002
596
+ - \`client.getValues(spreadsheetId, range)\` \u2014 \u7BC4\u56F2\u306E\u5024\u3092\u53D6\u5F97\uFF08A1 \u8868\u8A18\uFF09\u3002
597
+ - \`client.batchGetValues(spreadsheetId, ranges)\` \u2014 \u8907\u6570\u7BC4\u56F2\u306E\u5024\u3092\u53D6\u5F97\u3002
598
+ - \`client.updateValues(spreadsheetId, range, values, valueInputOption?)\` \u2014 \u7BC4\u56F2\u3092\u4E0A\u66F8\u304D\uFF08\u66F8\u304D\u8FBC\u307F\u30B9\u30B3\u30FC\u30D7\u304C\u5FC5\u8981\uFF09\u3002
599
+ - \`client.appendValues(spreadsheetId, range, values, valueInputOption?)\` \u2014 \u884C\u3092\u8FFD\u8A18\uFF08\u66F8\u304D\u8FBC\u307F\u30B9\u30B3\u30FC\u30D7\u304C\u5FC5\u8981\uFF09\u3002
600
+ - \`client.clearValues(spreadsheetId, range)\` \u2014 \u7BC4\u56F2\u306E\u5024\u3092\u30AF\u30EA\u30A2\uFF08\u66F8\u304D\u8FBC\u307F\u30B9\u30B3\u30FC\u30D7\u304C\u5FC5\u8981\uFF09\u3002
601
+ - \`client.batchUpdate(spreadsheetId, requests)\` \u2014 \u69CB\u9020\u5909\u66F4\uFF08\u66F8\u304D\u8FBC\u307F\u30B9\u30B3\u30FC\u30D7\u304C\u5FC5\u8981\uFF09\u3002
561
602
 
562
603
  \u30CF\u30F3\u30C9\u30E9\u306E\u30C6\u30B9\u30C8\u304C \`Connection proxy is not configured\` \u3067\u5931\u6557\u3059\u308B\u5834\u5408\u306F\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u901A\u5E38\u306F\u30B5\u30F3\u30C9\u30DC\u30C3\u30AF\u30B9\u306E\u521D\u671F\u5316\u4E2D\u306B\u8D77\u304D\u307E\u3059\u3002SDK \u3092\u8AE6\u3081\u3066 OAuth \u30D7\u30ED\u30AD\u30B7\u306E URL \u3092\u81EA\u5206\u3067\u7D44\u307F\u7ACB\u3066\u308B\u3053\u3068\u306F **\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044**\u3002
563
604
 
@@ -567,17 +608,21 @@ SDK\uFF08\`connection(connectionId)\` \u3067\u4F5C\u6210\u3057\u305F\u30AF\u30E9
567
608
  import { connection } from "@squadbase/vite-server/connectors/google-sheets";
568
609
 
569
610
  const sheets = connection("<connectionId>");
611
+ const spreadsheetId = "<\u30EA\u30AF\u30A8\u30B9\u30C8\u5165\u529B\u304B\u3089\u53D7\u3051\u53D6\u308B>";
570
612
 
571
- // \u8A2D\u5B9A\u6E08\u307F\u30B9\u30D7\u30EC\u30C3\u30C9\u30B7\u30FC\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
572
- const metadata = await sheets.getSpreadsheet();
573
- console.log(metadata.properties.title, metadata.sheets.map(s => s.properties.title));
613
+ // \u8AAD\u307F\u53D6\u308A: \u30E1\u30BF\u30C7\u30FC\u30BF\u3068\u5024
614
+ const metadata = await sheets.getSpreadsheet(spreadsheetId);
615
+ const values = await sheets.getValues(spreadsheetId, "Sheet1!A1:D10");
574
616
 
575
- // \u30BB\u30EB\u5024\u3092\u53D6\u5F97
576
- const values = await sheets.getValues("Sheet1!A1:D10");
577
- console.log(values.values); // 2D array
617
+ // \u66F8\u304D\u8FBC\u307F: \u4E0A\u66F8\u304D\u30FB\u8FFD\u8A18\u30FB\u30AF\u30EA\u30A2
618
+ await sheets.updateValues(spreadsheetId, "Sheet1!A1:B2", [["name", "age"], ["Alice", 30]]);
619
+ await sheets.appendValues(spreadsheetId, "Sheet1!A:B", [["Bob", 25]]);
620
+ await sheets.clearValues(spreadsheetId, "Sheet1!A1:B10");
578
621
 
579
- // \u8907\u6570\u7BC4\u56F2\u3092\u30D0\u30C3\u30C1\u53D6\u5F97
580
- const batch = await sheets.batchGetValues(["Sheet1!A:A", "Sheet2!B2:C100"]);
622
+ // \u69CB\u9020\u5909\u66F4\uFF08\u30B7\u30FC\u30C8\u3092\u8FFD\u52A0\uFF09
623
+ await sheets.batchUpdate(spreadsheetId, [
624
+ { addSheet: { properties: { title: "NewSheet" } } },
625
+ ]);
581
626
  \`\`\``
582
627
  },
583
628
  tools
@@ -413,7 +413,7 @@ var grafanaConnector = new ConnectorPlugin({
413
413
  description: "Connect to Grafana for monitoring dashboards, datasource queries, and alerting.",
414
414
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/3nGaPhV94lXQsHcCtv4mXz/0559d42f83066e8ba79e78410806750c/grafana-icon.webp",
415
415
  parameters,
416
- releaseFlag: { dev1: true, dev2: false, prod: false },
416
+ releaseFlag: { dev1: true, dev2: true, prod: true },
417
417
  onboarding: grafanaOnboarding,
418
418
  systemPrompt: {
419
419
  en: `### Tools
@@ -519,7 +519,7 @@ var influxdbConnector = new ConnectorPlugin({
519
519
  description: "Connect to InfluxDB (Cloud or OSS) to query time-series data with SQL, InfluxQL, or Flux and to write line protocol.",
520
520
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/J1JauVRNmahSVTVrpPfQK/18350d8d3f2dc3be25e8e36ee52914a0/influxdb.png",
521
521
  parameters,
522
- releaseFlag: { dev1: true, dev2: false, prod: false },
522
+ releaseFlag: { dev1: true, dev2: true, prod: true },
523
523
  onboarding: influxdbOnboarding,
524
524
  systemPrompt: {
525
525
  en: `### Variant Detection