@squadbase/vite-server 0.1.17-dev.a9ddcfa → 0.1.17-dev.e4768d1
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.
- package/dist/cli/index.js +8941 -3700
- package/dist/connectors/airtable-oauth.js +87 -23
- package/dist/connectors/airtable.js +130 -23
- package/dist/connectors/amplitude.js +47 -23
- package/dist/connectors/anthropic.js +41 -17
- package/dist/connectors/asana.js +76 -25
- package/dist/connectors/attio.js +69 -28
- package/dist/connectors/aws-billing.js +47 -23
- package/dist/connectors/azure-sql.js +322 -25
- package/dist/connectors/backlog-api-key.js +79 -30
- package/dist/connectors/clickup.js +89 -25
- package/dist/connectors/cosmosdb.js +51 -27
- package/dist/connectors/customerio.js +47 -23
- package/dist/connectors/dbt.js +725 -40
- package/dist/connectors/freshdesk.js +121 -23
- package/dist/connectors/freshsales.js +47 -23
- package/dist/connectors/freshservice.js +47 -23
- package/dist/connectors/gamma.js +54 -30
- package/dist/connectors/gemini.js +41 -17
- package/dist/connectors/github.js +51 -27
- package/dist/connectors/gmail-oauth.js +42 -23
- package/dist/connectors/gmail.js +43 -19
- package/dist/connectors/google-ads.js +47 -23
- package/dist/connectors/google-analytics-oauth.js +191 -40
- package/dist/connectors/google-analytics.js +529 -111
- package/dist/connectors/google-audit-log.js +43 -19
- package/dist/connectors/google-calendar-oauth.js +100 -30
- package/dist/connectors/google-calendar.js +100 -26
- package/dist/connectors/google-docs.js +42 -23
- package/dist/connectors/google-drive.js +64 -23
- package/dist/connectors/google-search-console-oauth.js +165 -32
- package/dist/connectors/google-sheets.js +142 -199
- package/dist/connectors/google-slides.js +42 -23
- package/dist/connectors/grafana.js +84 -25
- package/dist/connectors/hackernews.d.ts +5 -0
- package/dist/connectors/hackernews.js +909 -0
- package/dist/connectors/hubspot-oauth.js +73 -22
- package/dist/connectors/hubspot.js +64 -24
- package/dist/connectors/influxdb.js +47 -23
- package/dist/connectors/intercom-oauth.js +104 -25
- package/dist/connectors/intercom.js +51 -27
- package/dist/connectors/jdbc.js +76 -25
- package/dist/connectors/jira-api-key.js +107 -26
- package/dist/connectors/kintone-api-token.js +105 -33
- package/dist/connectors/kintone.js +182 -26
- package/dist/connectors/linear.js +93 -27
- package/dist/connectors/linkedin-ads.js +80 -29
- package/dist/connectors/mailchimp-oauth.js +45 -21
- package/dist/connectors/mailchimp.js +45 -21
- package/dist/connectors/meta-ads-oauth.js +72 -29
- package/dist/connectors/meta-ads.js +74 -29
- package/dist/connectors/mixpanel.js +47 -23
- package/dist/connectors/monday.js +48 -24
- package/dist/connectors/mongodb.js +47 -23
- package/dist/connectors/notion-oauth.js +92 -24
- package/dist/connectors/notion.js +144 -26
- package/dist/connectors/openai.js +41 -17
- package/dist/connectors/oracle.js +316 -26
- package/dist/connectors/outlook-oauth.js +53 -34
- package/dist/connectors/powerbi-oauth.js +45 -26
- package/dist/connectors/salesforce.js +150 -24
- package/dist/connectors/semrush.js +45 -21
- package/dist/connectors/sentry.js +75 -25
- package/dist/connectors/shopify-oauth.js +75 -23
- package/dist/connectors/shopify.js +47 -23
- package/dist/connectors/sqlserver.js +322 -25
- package/dist/connectors/stripe-api-key.js +105 -30
- package/dist/connectors/stripe-oauth.js +102 -32
- package/dist/connectors/supabase.js +315 -21
- package/dist/connectors/tableau.js +54 -30
- package/dist/connectors/tiktok-ads.js +76 -31
- package/dist/connectors/wix-store.js +47 -23
- package/dist/connectors/x.d.ts +5 -0
- package/dist/connectors/x.js +951 -0
- package/dist/connectors/zendesk-oauth.js +87 -25
- package/dist/connectors/zendesk.js +51 -27
- package/dist/index.js +9005 -3709
- package/dist/main.js +9005 -3709
- package/dist/vite-plugin.js +8939 -3698
- package/package.json +12 -4
|
@@ -121,6 +121,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
121
121
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
122
122
|
*/
|
|
123
123
|
setup;
|
|
124
|
+
/**
|
|
125
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
126
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
127
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
128
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
129
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
130
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
131
|
+
*/
|
|
132
|
+
introspect;
|
|
124
133
|
/**
|
|
125
134
|
* Opt-out of the default "verify before save" behavior on connection
|
|
126
135
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -135,6 +144,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
135
144
|
* the default verify-on-create behavior without opt-in.
|
|
136
145
|
*/
|
|
137
146
|
skipConnectionCheckOnCreate;
|
|
147
|
+
/**
|
|
148
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
149
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
150
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
151
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
152
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
153
|
+
*/
|
|
154
|
+
surveyProbes;
|
|
138
155
|
constructor(config) {
|
|
139
156
|
this.slug = config.slug;
|
|
140
157
|
this.authType = config.authType;
|
|
@@ -152,7 +169,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
152
169
|
this.query = config.query;
|
|
153
170
|
this.checkConnection = config.checkConnection;
|
|
154
171
|
this.setup = config.setup;
|
|
172
|
+
this.introspect = config.introspect;
|
|
155
173
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
174
|
+
this.surveyProbes = config.surveyProbes;
|
|
156
175
|
}
|
|
157
176
|
get connectorKey() {
|
|
158
177
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -160,7 +179,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
160
179
|
/**
|
|
161
180
|
* Create tools for connections that belong to this connector.
|
|
162
181
|
* Filters connections by connectorKey internally.
|
|
163
|
-
* Returns tools keyed as
|
|
182
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
164
183
|
*/
|
|
165
184
|
createTools(connections, config, opts) {
|
|
166
185
|
const myConnections = connections.filter(
|
|
@@ -170,7 +189,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
170
189
|
for (const t of Object.values(this.tools)) {
|
|
171
190
|
const tool = t.createTool(myConnections, config);
|
|
172
191
|
const originalToModelOutput = tool.toModelOutput;
|
|
173
|
-
result[
|
|
192
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
174
193
|
...tool,
|
|
175
194
|
toModelOutput: async (options) => {
|
|
176
195
|
if (!originalToModelOutput) {
|
|
@@ -190,25 +209,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
190
209
|
if (authType) return `${slug}-${authType}`;
|
|
191
210
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
192
211
|
// user-password
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
postgresql: "user-password",
|
|
213
|
+
mysql: "user-password",
|
|
214
|
+
clickhouse: "user-password",
|
|
215
|
+
kintone: "user-password",
|
|
197
216
|
"squadbase-db": "user-password",
|
|
198
217
|
// service-account
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
snowflake: "service-account",
|
|
219
|
+
bigquery: "service-account",
|
|
201
220
|
"google-analytics": "service-account",
|
|
202
221
|
"google-calendar": "service-account",
|
|
203
222
|
"aws-athena": "service-account",
|
|
204
|
-
|
|
223
|
+
redshift: "service-account",
|
|
205
224
|
// api-key
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
225
|
+
databricks: "api-key",
|
|
226
|
+
dbt: "api-key",
|
|
227
|
+
airtable: "api-key",
|
|
228
|
+
openai: "api-key",
|
|
229
|
+
gemini: "api-key",
|
|
230
|
+
anthropic: "api-key",
|
|
212
231
|
"wix-store": "api-key"
|
|
213
232
|
};
|
|
214
233
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -310,10 +329,10 @@ function normalizeRequestPath(path2, basePathSegment) {
|
|
|
310
329
|
// ../connectors/src/connectors/google-docs/setup.ts
|
|
311
330
|
var googleDocsOnboarding = new ConnectorOnboarding({
|
|
312
331
|
dataOverviewInstructions: {
|
|
313
|
-
en: `1. Create a new document with
|
|
314
|
-
2. Call
|
|
315
|
-
ja: `1.
|
|
316
|
-
2.
|
|
332
|
+
en: `1. Create a new document with connector_google-docs-oauth_request (POST with body { title: "..." }) or use an existing document ID.
|
|
333
|
+
2. Call connector_google-docs-oauth_request with GET /{documentId} to fetch the document's content and metadata.`,
|
|
334
|
+
ja: `1. connector_google-docs-oauth_request \u3092 POST\uFF08Body: { title: "..." }\uFF09\u3067\u547C\u3073\u51FA\u3057\u3066\u65B0\u3057\u3044\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u4F5C\u6210\u3059\u308B\u304B\u3001\u65E2\u5B58\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8ID\u3092\u5229\u7528\u3057\u307E\u3059\u3002
|
|
335
|
+
2. connector_google-docs-oauth_request \u3067 GET /{documentId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u5185\u5BB9\u3068\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002`
|
|
317
336
|
}
|
|
318
337
|
});
|
|
319
338
|
|
|
@@ -566,9 +585,9 @@ var googleDocsConnector = new ConnectorPlugin({
|
|
|
566
585
|
systemPrompt: {
|
|
567
586
|
en: `### Tools (setup-time only)
|
|
568
587
|
|
|
569
|
-
- \`
|
|
588
|
+
- \`connector_google-docs-oauth_request\`: Call the Google Docs API directly during setup / data overview. Supports read and write operations. Use it to get document content, create new documents, and modify document content via batchUpdate. Authentication is configured automatically via OAuth.
|
|
570
589
|
|
|
571
|
-
> **Important**: The \`
|
|
590
|
+
> **Important**: The \`connector_google-docs-oauth_request\` tool is only available at setup time. Inside server-logic handlers, use the SDK (\`connection(id).createDocument\`, 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.
|
|
572
591
|
|
|
573
592
|
### Google Docs API Reference
|
|
574
593
|
|
|
@@ -635,9 +654,9 @@ await docs.batchUpdate(documentId, [
|
|
|
635
654
|
\`\`\``,
|
|
636
655
|
ja: `### \u30C4\u30FC\u30EB\uFF08\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306E\u307F\uFF09
|
|
637
656
|
|
|
638
|
-
- \`
|
|
657
|
+
- \`connector_google-docs-oauth_request\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3084\u30C7\u30FC\u30BF\u6982\u8981\u628A\u63E1\u6642\u306B Google Docs API \u3092\u76F4\u63A5\u53E9\u304F\u30C4\u30FC\u30EB\u3067\u3059\u3002\u8AAD\u307F\u53D6\u308A\u3068\u66F8\u304D\u8FBC\u307F\u306E\u4E21\u65B9\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u5BB9\u306E\u53D6\u5F97\u3001\u65B0\u3057\u3044\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u4F5C\u6210\u3001batchUpdate \u306B\u3088\u308B\u5185\u5BB9\u5909\u66F4\u306A\u3069\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
639
658
|
|
|
640
|
-
> **\u91CD\u8981**: \`
|
|
659
|
+
> **\u91CD\u8981**: \`connector_google-docs-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).createDocument\` \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
|
|
641
660
|
|
|
642
661
|
### Google Docs API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
643
662
|
|
|
@@ -210,6 +210,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
210
210
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
211
211
|
*/
|
|
212
212
|
setup;
|
|
213
|
+
/**
|
|
214
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
215
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
216
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
217
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
218
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
219
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
220
|
+
*/
|
|
221
|
+
introspect;
|
|
213
222
|
/**
|
|
214
223
|
* Opt-out of the default "verify before save" behavior on connection
|
|
215
224
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -224,6 +233,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
224
233
|
* the default verify-on-create behavior without opt-in.
|
|
225
234
|
*/
|
|
226
235
|
skipConnectionCheckOnCreate;
|
|
236
|
+
/**
|
|
237
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
238
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
239
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
240
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
241
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
242
|
+
*/
|
|
243
|
+
surveyProbes;
|
|
227
244
|
constructor(config) {
|
|
228
245
|
this.slug = config.slug;
|
|
229
246
|
this.authType = config.authType;
|
|
@@ -241,7 +258,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
241
258
|
this.query = config.query;
|
|
242
259
|
this.checkConnection = config.checkConnection;
|
|
243
260
|
this.setup = config.setup;
|
|
261
|
+
this.introspect = config.introspect;
|
|
244
262
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
263
|
+
this.surveyProbes = config.surveyProbes;
|
|
245
264
|
}
|
|
246
265
|
get connectorKey() {
|
|
247
266
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -249,7 +268,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
249
268
|
/**
|
|
250
269
|
* Create tools for connections that belong to this connector.
|
|
251
270
|
* Filters connections by connectorKey internally.
|
|
252
|
-
* Returns tools keyed as
|
|
271
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
253
272
|
*/
|
|
254
273
|
createTools(connections, config, opts) {
|
|
255
274
|
const myConnections = connections.filter(
|
|
@@ -259,7 +278,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
259
278
|
for (const t of Object.values(this.tools)) {
|
|
260
279
|
const tool = t.createTool(myConnections, config);
|
|
261
280
|
const originalToModelOutput = tool.toModelOutput;
|
|
262
|
-
result[
|
|
281
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
263
282
|
...tool,
|
|
264
283
|
toModelOutput: async (options) => {
|
|
265
284
|
if (!originalToModelOutput) {
|
|
@@ -279,25 +298,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
279
298
|
if (authType) return `${slug}-${authType}`;
|
|
280
299
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
281
300
|
// user-password
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
301
|
+
postgresql: "user-password",
|
|
302
|
+
mysql: "user-password",
|
|
303
|
+
clickhouse: "user-password",
|
|
304
|
+
kintone: "user-password",
|
|
286
305
|
"squadbase-db": "user-password",
|
|
287
306
|
// service-account
|
|
288
|
-
|
|
289
|
-
|
|
307
|
+
snowflake: "service-account",
|
|
308
|
+
bigquery: "service-account",
|
|
290
309
|
"google-analytics": "service-account",
|
|
291
310
|
"google-calendar": "service-account",
|
|
292
311
|
"aws-athena": "service-account",
|
|
293
|
-
|
|
312
|
+
redshift: "service-account",
|
|
294
313
|
// api-key
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
314
|
+
databricks: "api-key",
|
|
315
|
+
dbt: "api-key",
|
|
316
|
+
airtable: "api-key",
|
|
317
|
+
openai: "api-key",
|
|
318
|
+
gemini: "api-key",
|
|
319
|
+
anthropic: "api-key",
|
|
301
320
|
"wix-store": "api-key"
|
|
302
321
|
};
|
|
303
322
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -399,10 +418,10 @@ function normalizeRequestPath(path2, basePathSegment) {
|
|
|
399
418
|
// ../connectors/src/connectors/google-drive/setup.ts
|
|
400
419
|
var googleDriveOnboarding = new ConnectorOnboarding({
|
|
401
420
|
dataOverviewInstructions: {
|
|
402
|
-
en: `1. Call
|
|
403
|
-
2. Call
|
|
404
|
-
ja: `1.
|
|
405
|
-
2.
|
|
421
|
+
en: `1. Call connector_google-drive-oauth_request with GET /files?pageSize=20&fields=files(id,name,mimeType,modifiedTime)&orderBy=modifiedTime desc to list recent files
|
|
422
|
+
2. Call connector_google-drive-oauth_request with GET /about?fields=user,storageQuota to get account info and storage usage`,
|
|
423
|
+
ja: `1. connector_google-drive-oauth_request \u3067 GET /files?pageSize=20&fields=files(id,name,mimeType,modifiedTime)&orderBy=modifiedTime desc \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u4E00\u89A7\u8868\u793A
|
|
424
|
+
2. connector_google-drive-oauth_request \u3067 GET /about?fields=user,storageQuota \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AB\u30A6\u30F3\u30C8\u60C5\u5831\u3068\u30B9\u30C8\u30EC\u30FC\u30B8\u4F7F\u7528\u91CF\u3092\u53D6\u5F97`
|
|
406
425
|
}
|
|
407
426
|
});
|
|
408
427
|
|
|
@@ -543,6 +562,28 @@ var googleDriveSetupFlow = {
|
|
|
543
562
|
);
|
|
544
563
|
}
|
|
545
564
|
sections.push("");
|
|
565
|
+
try {
|
|
566
|
+
const counts = /* @__PURE__ */ new Map();
|
|
567
|
+
for (const f of allFiles) {
|
|
568
|
+
const key = f.mimeType === FOLDER_MIME ? "folder" : f.mimeType ?? "(unknown)";
|
|
569
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
570
|
+
}
|
|
571
|
+
const top = Array.from(counts.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10);
|
|
572
|
+
if (top.length > 0) {
|
|
573
|
+
sections.push(
|
|
574
|
+
rt.language === "ja" ? "### \u30D5\u30A1\u30A4\u30EB\u7A2E\u5225\u306E\u5185\u8A33 (\u4E0A\u4F4D10\u4EF6)" : "### File type breakdown (top 10)",
|
|
575
|
+
""
|
|
576
|
+
);
|
|
577
|
+
sections.push("| Mime Type | Count |");
|
|
578
|
+
sections.push("|-----------|-------|");
|
|
579
|
+
for (const [mime, count] of top) {
|
|
580
|
+
const safe = mime.replace(/\|/g, "\\|");
|
|
581
|
+
sections.push(`| ${safe} | ${count} |`);
|
|
582
|
+
}
|
|
583
|
+
sections.push("");
|
|
584
|
+
}
|
|
585
|
+
} catch {
|
|
586
|
+
}
|
|
546
587
|
return sections.join("\n");
|
|
547
588
|
}
|
|
548
589
|
};
|
|
@@ -694,9 +735,9 @@ var googleDriveConnector = new ConnectorPlugin({
|
|
|
694
735
|
systemPrompt: {
|
|
695
736
|
en: `### Tools (setup-time only)
|
|
696
737
|
|
|
697
|
-
- \`
|
|
738
|
+
- \`connector_google-drive-oauth_request\`: Send authenticated requests to the Google Drive API v3 during setup / data overview. Supports GET, POST, and PATCH methods. Authentication is configured automatically via OAuth.
|
|
698
739
|
|
|
699
|
-
> **Important**: The \`
|
|
740
|
+
> **Important**: The \`connector_google-drive-oauth_request\` tool is only available at setup time. Inside server-logic handlers, use the SDK (\`connection(id).listFiles\`, 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.
|
|
700
741
|
|
|
701
742
|
### Google Drive API Reference
|
|
702
743
|
|
|
@@ -830,9 +871,9 @@ await drive.updateFile("fileId123", {}, "newFolderId", "oldFolderId");
|
|
|
830
871
|
\`\`\``,
|
|
831
872
|
ja: `### \u30C4\u30FC\u30EB\uFF08\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306E\u307F\uFF09
|
|
832
873
|
|
|
833
|
-
- \`
|
|
874
|
+
- \`connector_google-drive-oauth_request\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u3084\u30C7\u30FC\u30BF\u6982\u8981\u628A\u63E1\u6642\u306B Google Drive API v3 \u3078\u8A8D\u8A3C\u6E08\u307F\u30EA\u30AF\u30A8\u30B9\u30C8\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002GET, POST, PATCH \u30E1\u30BD\u30C3\u30C9\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
834
875
|
|
|
835
|
-
> **\u91CD\u8981**: \`
|
|
876
|
+
> **\u91CD\u8981**: \`connector_google-drive-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).listFiles\` \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
|
|
836
877
|
|
|
837
878
|
### Google Drive API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
838
879
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
-
var __esm = (fn, res) => function __init() {
|
|
3
|
-
|
|
2
|
+
var __esm = (fn, res, err) => function __init() {
|
|
3
|
+
if (err) throw err[0];
|
|
4
|
+
try {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
} catch (e) {
|
|
7
|
+
throw err = [e], e;
|
|
8
|
+
}
|
|
4
9
|
};
|
|
5
10
|
|
|
6
11
|
// ../connectors/src/parameter-definition.ts
|
|
@@ -217,6 +222,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
217
222
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
218
223
|
*/
|
|
219
224
|
setup;
|
|
225
|
+
/**
|
|
226
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
227
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
228
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
229
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
230
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
231
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
232
|
+
*/
|
|
233
|
+
introspect;
|
|
220
234
|
/**
|
|
221
235
|
* Opt-out of the default "verify before save" behavior on connection
|
|
222
236
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -231,6 +245,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
231
245
|
* the default verify-on-create behavior without opt-in.
|
|
232
246
|
*/
|
|
233
247
|
skipConnectionCheckOnCreate;
|
|
248
|
+
/**
|
|
249
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
250
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
251
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
252
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
253
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
254
|
+
*/
|
|
255
|
+
surveyProbes;
|
|
234
256
|
constructor(config) {
|
|
235
257
|
this.slug = config.slug;
|
|
236
258
|
this.authType = config.authType;
|
|
@@ -248,7 +270,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
248
270
|
this.query = config.query;
|
|
249
271
|
this.checkConnection = config.checkConnection;
|
|
250
272
|
this.setup = config.setup;
|
|
273
|
+
this.introspect = config.introspect;
|
|
251
274
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
275
|
+
this.surveyProbes = config.surveyProbes;
|
|
252
276
|
}
|
|
253
277
|
get connectorKey() {
|
|
254
278
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -256,7 +280,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
256
280
|
/**
|
|
257
281
|
* Create tools for connections that belong to this connector.
|
|
258
282
|
* Filters connections by connectorKey internally.
|
|
259
|
-
* Returns tools keyed as
|
|
283
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
260
284
|
*/
|
|
261
285
|
createTools(connections, config, opts) {
|
|
262
286
|
const myConnections = connections.filter(
|
|
@@ -266,7 +290,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
266
290
|
for (const t of Object.values(this.tools)) {
|
|
267
291
|
const tool = t.createTool(myConnections, config);
|
|
268
292
|
const originalToModelOutput = tool.toModelOutput;
|
|
269
|
-
result[
|
|
293
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
270
294
|
...tool,
|
|
271
295
|
toModelOutput: async (options) => {
|
|
272
296
|
if (!originalToModelOutput) {
|
|
@@ -286,25 +310,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
286
310
|
if (authType) return `${slug}-${authType}`;
|
|
287
311
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
288
312
|
// user-password
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
313
|
+
postgresql: "user-password",
|
|
314
|
+
mysql: "user-password",
|
|
315
|
+
clickhouse: "user-password",
|
|
316
|
+
kintone: "user-password",
|
|
293
317
|
"squadbase-db": "user-password",
|
|
294
318
|
// service-account
|
|
295
|
-
|
|
296
|
-
|
|
319
|
+
snowflake: "service-account",
|
|
320
|
+
bigquery: "service-account",
|
|
297
321
|
"google-analytics": "service-account",
|
|
298
322
|
"google-calendar": "service-account",
|
|
299
323
|
"aws-athena": "service-account",
|
|
300
|
-
|
|
324
|
+
redshift: "service-account",
|
|
301
325
|
// api-key
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
326
|
+
databricks: "api-key",
|
|
327
|
+
dbt: "api-key",
|
|
328
|
+
airtable: "api-key",
|
|
329
|
+
openai: "api-key",
|
|
330
|
+
gemini: "api-key",
|
|
331
|
+
anthropic: "api-key",
|
|
308
332
|
"wix-store": "api-key"
|
|
309
333
|
};
|
|
310
334
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -551,10 +575,10 @@ var googleSearchConsoleOauthOnboarding = new ConnectorOnboarding({
|
|
|
551
575
|
- Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
|
|
552
576
|
},
|
|
553
577
|
dataOverviewInstructions: {
|
|
554
|
-
en: `1. Call
|
|
555
|
-
2. Call
|
|
556
|
-
ja: `1.
|
|
557
|
-
2.
|
|
578
|
+
en: `1. Call connector_google-search-console-oauth_request with GET /sites/{siteUrl} to fetch metadata for the configured site
|
|
579
|
+
2. Call connector_google-search-console-oauth_request with POST /sites/{siteUrl}/searchAnalytics/query and a small body \u2014 startDate/endDate covering the last 7 days, dimensions ["date"], rowLimit 7 \u2014 to verify that performance data is available`,
|
|
580
|
+
ja: `1. connector_google-search-console-oauth_request \u3067 GET /sites/{siteUrl} \u3092\u547C\u3073\u51FA\u3057\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u30B5\u30A4\u30C8\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u53D6\u5F97
|
|
581
|
+
2. connector_google-search-console-oauth_request \u3067 POST /sites/{siteUrl}/searchAnalytics/query \u3092\u76F4\u8FD17\u65E5\u9593\u306E startDate/endDate\u3001dimensions ["date"]\u3001rowLimit 7 \u3067\u547C\u3073\u51FA\u3057\u3001\u30D1\u30D5\u30A9\u30FC\u30DE\u30F3\u30B9\u30C7\u30FC\u30BF\u306E\u53EF\u7528\u6027\u3092\u78BA\u8A8D`
|
|
558
582
|
}
|
|
559
583
|
});
|
|
560
584
|
|
|
@@ -577,6 +601,33 @@ function isVerified(site) {
|
|
|
577
601
|
const level = site.permissionLevel ?? "";
|
|
578
602
|
return level !== "" && level !== "siteUnverifiedUser";
|
|
579
603
|
}
|
|
604
|
+
function formatDate(daysAgo) {
|
|
605
|
+
const d = /* @__PURE__ */ new Date();
|
|
606
|
+
d.setDate(d.getDate() - daysAgo);
|
|
607
|
+
return d.toISOString().slice(0, 10);
|
|
608
|
+
}
|
|
609
|
+
async function querySearchAnalytics(proxyFetch, siteUrl, dimensions, rowLimit) {
|
|
610
|
+
try {
|
|
611
|
+
const res = await proxyFetch(
|
|
612
|
+
`${SITES_URL}/${encodeURIComponent(siteUrl)}/searchAnalytics/query`,
|
|
613
|
+
{
|
|
614
|
+
method: "POST",
|
|
615
|
+
headers: { "Content-Type": "application/json" },
|
|
616
|
+
body: JSON.stringify({
|
|
617
|
+
startDate: formatDate(28),
|
|
618
|
+
endDate: formatDate(1),
|
|
619
|
+
dimensions,
|
|
620
|
+
rowLimit
|
|
621
|
+
})
|
|
622
|
+
}
|
|
623
|
+
);
|
|
624
|
+
if (!res.ok) return [];
|
|
625
|
+
const data = await res.json();
|
|
626
|
+
return data.rows ?? [];
|
|
627
|
+
} catch {
|
|
628
|
+
return [];
|
|
629
|
+
}
|
|
630
|
+
}
|
|
580
631
|
var googleSearchConsoleOauthSetupFlow = {
|
|
581
632
|
initialState: () => ({}),
|
|
582
633
|
steps: [
|
|
@@ -615,7 +666,6 @@ var googleSearchConsoleOauthSetupFlow = {
|
|
|
615
666
|
}
|
|
616
667
|
const allSites = await listSites(rt.config.proxyFetch);
|
|
617
668
|
const verified = allSites.filter(isVerified);
|
|
618
|
-
const siteByUrl = new Map(verified.map((s) => [s.siteUrl ?? "", s]));
|
|
619
669
|
const targetSiteUrls = await resolveSetupSelection({
|
|
620
670
|
selected: state.sites,
|
|
621
671
|
allSentinel: ALL_SITES,
|
|
@@ -627,15 +677,98 @@ var googleSearchConsoleOauthSetupFlow = {
|
|
|
627
677
|
sections.push("_No sites selected._", "");
|
|
628
678
|
return sections.join("\n");
|
|
629
679
|
}
|
|
630
|
-
sections.push("| Site URL | Permission Level |");
|
|
631
|
-
sections.push("|----------|------------------|");
|
|
632
680
|
for (const siteUrl of targetSiteUrls) {
|
|
633
|
-
const site = siteByUrl.get(siteUrl);
|
|
634
|
-
const permission = site?.permissionLevel ?? "-";
|
|
635
681
|
const safeSiteUrl = siteUrl.replace(/\|/g, "\\|");
|
|
636
|
-
sections.push(
|
|
682
|
+
sections.push(`### Site: ${safeSiteUrl}`, "");
|
|
683
|
+
const topQueries = await querySearchAnalytics(
|
|
684
|
+
rt.config.proxyFetch,
|
|
685
|
+
siteUrl,
|
|
686
|
+
["query"],
|
|
687
|
+
10
|
|
688
|
+
);
|
|
689
|
+
if (topQueries.length > 0) {
|
|
690
|
+
sections.push("#### Top Search Queries (last 28 days)", "");
|
|
691
|
+
sections.push("| Query | Clicks | Impressions | CTR | Avg Position |");
|
|
692
|
+
sections.push("|-------|--------|-------------|-----|-------------|");
|
|
693
|
+
for (const row of topQueries) {
|
|
694
|
+
const q = (row.keys?.[0] ?? "").replace(/\|/g, "\\|");
|
|
695
|
+
const clicks = row.clicks ?? 0;
|
|
696
|
+
const impressions = row.impressions ?? 0;
|
|
697
|
+
const ctr = ((row.ctr ?? 0) * 100).toFixed(1);
|
|
698
|
+
const pos = (row.position ?? 0).toFixed(1);
|
|
699
|
+
sections.push(
|
|
700
|
+
`| ${q} | ${clicks} | ${impressions} | ${ctr}% | ${pos} |`
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
sections.push("");
|
|
704
|
+
}
|
|
705
|
+
const topPages = await querySearchAnalytics(
|
|
706
|
+
rt.config.proxyFetch,
|
|
707
|
+
siteUrl,
|
|
708
|
+
["page"],
|
|
709
|
+
10
|
|
710
|
+
);
|
|
711
|
+
if (topPages.length > 0) {
|
|
712
|
+
sections.push("#### Top Pages (last 28 days)", "");
|
|
713
|
+
sections.push("| Page | Clicks | Impressions | CTR | Avg Position |");
|
|
714
|
+
sections.push("|------|--------|-------------|-----|-------------|");
|
|
715
|
+
for (const row of topPages) {
|
|
716
|
+
const pg = (row.keys?.[0] ?? "").replace(/\|/g, "\\|");
|
|
717
|
+
const clicks = row.clicks ?? 0;
|
|
718
|
+
const impressions = row.impressions ?? 0;
|
|
719
|
+
const ctr = ((row.ctr ?? 0) * 100).toFixed(1);
|
|
720
|
+
const pos = (row.position ?? 0).toFixed(1);
|
|
721
|
+
sections.push(
|
|
722
|
+
`| ${pg} | ${clicks} | ${impressions} | ${ctr}% | ${pos} |`
|
|
723
|
+
);
|
|
724
|
+
}
|
|
725
|
+
sections.push("");
|
|
726
|
+
}
|
|
727
|
+
const deviceRows = await querySearchAnalytics(
|
|
728
|
+
rt.config.proxyFetch,
|
|
729
|
+
siteUrl,
|
|
730
|
+
["device"],
|
|
731
|
+
5
|
|
732
|
+
);
|
|
733
|
+
if (deviceRows.length > 0) {
|
|
734
|
+
sections.push("#### Device Breakdown (last 28 days)", "");
|
|
735
|
+
sections.push("| Device | Clicks | Impressions | CTR | Avg Position |");
|
|
736
|
+
sections.push("|--------|--------|-------------|-----|-------------|");
|
|
737
|
+
for (const row of deviceRows) {
|
|
738
|
+
const dev = row.keys?.[0] ?? "";
|
|
739
|
+
const clicks = row.clicks ?? 0;
|
|
740
|
+
const impressions = row.impressions ?? 0;
|
|
741
|
+
const ctr = ((row.ctr ?? 0) * 100).toFixed(1);
|
|
742
|
+
const pos = (row.position ?? 0).toFixed(1);
|
|
743
|
+
sections.push(
|
|
744
|
+
`| ${dev} | ${clicks} | ${impressions} | ${ctr}% | ${pos} |`
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
sections.push("");
|
|
748
|
+
}
|
|
749
|
+
const countryRows = await querySearchAnalytics(
|
|
750
|
+
rt.config.proxyFetch,
|
|
751
|
+
siteUrl,
|
|
752
|
+
["country"],
|
|
753
|
+
10
|
|
754
|
+
);
|
|
755
|
+
if (countryRows.length > 0) {
|
|
756
|
+
sections.push("#### Top Countries (last 28 days)", "");
|
|
757
|
+
sections.push("| Country | Clicks | Impressions | CTR | Avg Position |");
|
|
758
|
+
sections.push("|---------|--------|-------------|-----|-------------|");
|
|
759
|
+
for (const row of countryRows) {
|
|
760
|
+
const c = row.keys?.[0] ?? "";
|
|
761
|
+
const clicks = row.clicks ?? 0;
|
|
762
|
+
const impressions = row.impressions ?? 0;
|
|
763
|
+
const ctr = ((row.ctr ?? 0) * 100).toFixed(1);
|
|
764
|
+
const pos = (row.position ?? 0).toFixed(1);
|
|
765
|
+
sections.push(
|
|
766
|
+
`| ${c} | ${clicks} | ${impressions} | ${ctr}% | ${pos} |`
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
sections.push("");
|
|
770
|
+
}
|
|
637
771
|
}
|
|
638
|
-
sections.push("");
|
|
639
772
|
return sections.join("\n");
|
|
640
773
|
}
|
|
641
774
|
};
|
|
@@ -798,8 +931,8 @@ var googleSearchConsoleOauthConnector = new ConnectorPlugin({
|
|
|
798
931
|
systemPrompt: {
|
|
799
932
|
en: `### Tools
|
|
800
933
|
|
|
801
|
-
- \`
|
|
802
|
-
- \`
|
|
934
|
+
- \`connector_google-search-console-oauth_request\`: Send authenticated requests to the Google Search Console API (Webmasters v3). Use it for searchAnalytics queries, sitemap inspection, and site metadata. The {siteUrl} placeholder in paths is automatically replaced and URL-encoded. Authentication is configured automatically via OAuth.
|
|
935
|
+
- \`connector_google-search-console-oauth_listSites\`: List accessible Search Console sites. Use during setup to discover available properties.
|
|
803
936
|
|
|
804
937
|
### Search Console API Reference
|
|
805
938
|
|
|
@@ -884,8 +1017,8 @@ sitemaps.forEach(s => console.log(s.path, s.lastSubmitted));
|
|
|
884
1017
|
\`\`\``,
|
|
885
1018
|
ja: `### \u30C4\u30FC\u30EB
|
|
886
1019
|
|
|
887
|
-
- \`
|
|
888
|
-
- \`
|
|
1020
|
+
- \`connector_google-search-console-oauth_request\`: Google Search Console API (Webmasters v3) \u3078\u8A8D\u8A3C\u6E08\u307F\u30EA\u30AF\u30A8\u30B9\u30C8\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002searchAnalytics \u30AF\u30A8\u30EA\u3001\u30B5\u30A4\u30C8\u30DE\u30C3\u30D7\u78BA\u8A8D\u3001\u30B5\u30A4\u30C8\u30E1\u30BF\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{siteUrl}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u81EA\u52D5\u7684\u306BURL\u30A8\u30F3\u30B3\u30FC\u30C9\u3055\u308C\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
1021
|
+
- \`connector_google-search-console-oauth_listSites\`: \u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306ASearch Console\u30B5\u30A4\u30C8\u306E\u4E00\u89A7\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u6642\u306B\u5229\u7528\u53EF\u80FD\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u78BA\u8A8D\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
889
1022
|
|
|
890
1023
|
### Search Console API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
891
1024
|
|