@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
|
@@ -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
|
|
@@ -148,6 +153,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
148
153
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
149
154
|
*/
|
|
150
155
|
setup;
|
|
156
|
+
/**
|
|
157
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
158
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
159
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
160
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
161
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
162
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
163
|
+
*/
|
|
164
|
+
introspect;
|
|
151
165
|
/**
|
|
152
166
|
* Opt-out of the default "verify before save" behavior on connection
|
|
153
167
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -162,6 +176,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
162
176
|
* the default verify-on-create behavior without opt-in.
|
|
163
177
|
*/
|
|
164
178
|
skipConnectionCheckOnCreate;
|
|
179
|
+
/**
|
|
180
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
181
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
182
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
183
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
184
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
185
|
+
*/
|
|
186
|
+
surveyProbes;
|
|
165
187
|
constructor(config) {
|
|
166
188
|
this.slug = config.slug;
|
|
167
189
|
this.authType = config.authType;
|
|
@@ -179,7 +201,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
179
201
|
this.query = config.query;
|
|
180
202
|
this.checkConnection = config.checkConnection;
|
|
181
203
|
this.setup = config.setup;
|
|
204
|
+
this.introspect = config.introspect;
|
|
182
205
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
206
|
+
this.surveyProbes = config.surveyProbes;
|
|
183
207
|
}
|
|
184
208
|
get connectorKey() {
|
|
185
209
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -187,7 +211,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
187
211
|
/**
|
|
188
212
|
* Create tools for connections that belong to this connector.
|
|
189
213
|
* Filters connections by connectorKey internally.
|
|
190
|
-
* Returns tools keyed as
|
|
214
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
191
215
|
*/
|
|
192
216
|
createTools(connections, config, opts) {
|
|
193
217
|
const myConnections = connections.filter(
|
|
@@ -197,7 +221,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
197
221
|
for (const t of Object.values(this.tools)) {
|
|
198
222
|
const tool = t.createTool(myConnections, config);
|
|
199
223
|
const originalToModelOutput = tool.toModelOutput;
|
|
200
|
-
result[
|
|
224
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
201
225
|
...tool,
|
|
202
226
|
toModelOutput: async (options) => {
|
|
203
227
|
if (!originalToModelOutput) {
|
|
@@ -217,25 +241,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
217
241
|
if (authType) return `${slug}-${authType}`;
|
|
218
242
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
219
243
|
// user-password
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
244
|
+
postgresql: "user-password",
|
|
245
|
+
mysql: "user-password",
|
|
246
|
+
clickhouse: "user-password",
|
|
247
|
+
kintone: "user-password",
|
|
224
248
|
"squadbase-db": "user-password",
|
|
225
249
|
// service-account
|
|
226
|
-
|
|
227
|
-
|
|
250
|
+
snowflake: "service-account",
|
|
251
|
+
bigquery: "service-account",
|
|
228
252
|
"google-analytics": "service-account",
|
|
229
253
|
"google-calendar": "service-account",
|
|
230
254
|
"aws-athena": "service-account",
|
|
231
|
-
|
|
255
|
+
redshift: "service-account",
|
|
232
256
|
// api-key
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
257
|
+
databricks: "api-key",
|
|
258
|
+
dbt: "api-key",
|
|
259
|
+
airtable: "api-key",
|
|
260
|
+
openai: "api-key",
|
|
261
|
+
gemini: "api-key",
|
|
262
|
+
anthropic: "api-key",
|
|
239
263
|
"wix-store": "api-key"
|
|
240
264
|
};
|
|
241
265
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -478,10 +502,10 @@ var airtableOauthOnboarding = new ConnectorOnboarding({
|
|
|
478
502
|
- Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
|
|
479
503
|
},
|
|
480
504
|
dataOverviewInstructions: {
|
|
481
|
-
en: `1. Call
|
|
482
|
-
2. Call
|
|
483
|
-
ja: `1.
|
|
484
|
-
2.
|
|
505
|
+
en: `1. Call connector_airtable-oauth_request with GET /meta/bases/{baseId}/tables to list tables and their fields
|
|
506
|
+
2. Call connector_airtable-oauth_request with GET /{baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
|
|
507
|
+
ja: `1. connector_airtable-oauth_request \u3067 GET /meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
|
|
508
|
+
2. connector_airtable-oauth_request \u3067 GET /{baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
|
|
485
509
|
}
|
|
486
510
|
});
|
|
487
511
|
|
|
@@ -517,6 +541,26 @@ async function listTables(proxyFetch, baseId) {
|
|
|
517
541
|
const data = await res.json();
|
|
518
542
|
return data.tables ?? [];
|
|
519
543
|
}
|
|
544
|
+
async function listSampleRecords(proxyFetch, baseId, tableId) {
|
|
545
|
+
try {
|
|
546
|
+
const res = await apiFetch(
|
|
547
|
+
proxyFetch,
|
|
548
|
+
`/${baseId}/${encodeURIComponent(tableId)}?maxRecords=3`
|
|
549
|
+
);
|
|
550
|
+
if (!res.ok) return [];
|
|
551
|
+
const data = await res.json();
|
|
552
|
+
return data.records ?? [];
|
|
553
|
+
} catch {
|
|
554
|
+
return [];
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
function formatCell(val) {
|
|
558
|
+
if (val == null) return "";
|
|
559
|
+
if (typeof val === "string") return val.length > 40 ? `${val.slice(0, 40)}\u2026` : val;
|
|
560
|
+
if (Array.isArray(val)) return `[${val.length} items]`;
|
|
561
|
+
if (typeof val === "object") return JSON.stringify(val).slice(0, 40);
|
|
562
|
+
return String(val);
|
|
563
|
+
}
|
|
520
564
|
var airtableOauthSetupFlow = {
|
|
521
565
|
initialState: () => ({}),
|
|
522
566
|
steps: [
|
|
@@ -588,6 +632,26 @@ var airtableOauthSetupFlow = {
|
|
|
588
632
|
sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
|
|
589
633
|
}
|
|
590
634
|
sections.push("");
|
|
635
|
+
const records = await listSampleRecords(
|
|
636
|
+
rt.config.proxyFetch,
|
|
637
|
+
baseId,
|
|
638
|
+
table.id
|
|
639
|
+
);
|
|
640
|
+
if (records.length > 0) {
|
|
641
|
+
const sampleFields = (table.fields ?? []).slice(0, 5).map((f) => f.name);
|
|
642
|
+
if (sampleFields.length > 0) {
|
|
643
|
+
sections.push(`##### Sample records (${records.length})`, "");
|
|
644
|
+
sections.push(`| ${sampleFields.join(" | ")} |`);
|
|
645
|
+
sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
|
|
646
|
+
for (const record of records) {
|
|
647
|
+
const cells = sampleFields.map(
|
|
648
|
+
(name) => formatCell(record.fields?.[name]).replace(/\|/g, "\\|")
|
|
649
|
+
);
|
|
650
|
+
sections.push(`| ${cells.join(" | ")} |`);
|
|
651
|
+
}
|
|
652
|
+
sections.push("");
|
|
653
|
+
}
|
|
654
|
+
}
|
|
591
655
|
}
|
|
592
656
|
return sections.join("\n");
|
|
593
657
|
}
|
|
@@ -617,7 +681,7 @@ var airtableOauthConnector = new ConnectorPlugin({
|
|
|
617
681
|
systemPrompt: {
|
|
618
682
|
en: `### Tools
|
|
619
683
|
|
|
620
|
-
- \`
|
|
684
|
+
- \`connector_airtable-oauth_request\`: The only way to call the Airtable REST API. Use it to list tables, query/create/update/delete records. Authentication is configured automatically via OAuth. The {baseId} placeholder in paths is automatically replaced with the configured default base ID.
|
|
621
685
|
|
|
622
686
|
### Airtable API Reference
|
|
623
687
|
|
|
@@ -665,7 +729,7 @@ const recordsData = await records.json();
|
|
|
665
729
|
\`\`\``,
|
|
666
730
|
ja: `### \u30C4\u30FC\u30EB
|
|
667
731
|
|
|
668
|
-
- \`
|
|
732
|
+
- \`connector_airtable-oauth_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\u30FB\u4F5C\u6210\u30FB\u66F4\u65B0\u30FB\u524A\u9664\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{baseId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30D9\u30FC\u30B9ID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002
|
|
669
733
|
|
|
670
734
|
### Airtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
671
735
|
|
|
@@ -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
|
|
@@ -278,6 +283,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
278
283
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
279
284
|
*/
|
|
280
285
|
setup;
|
|
286
|
+
/**
|
|
287
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
288
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
289
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
290
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
291
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
292
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
293
|
+
*/
|
|
294
|
+
introspect;
|
|
281
295
|
/**
|
|
282
296
|
* Opt-out of the default "verify before save" behavior on connection
|
|
283
297
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -292,6 +306,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
292
306
|
* the default verify-on-create behavior without opt-in.
|
|
293
307
|
*/
|
|
294
308
|
skipConnectionCheckOnCreate;
|
|
309
|
+
/**
|
|
310
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
311
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
312
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
313
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
314
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
315
|
+
*/
|
|
316
|
+
surveyProbes;
|
|
295
317
|
constructor(config) {
|
|
296
318
|
this.slug = config.slug;
|
|
297
319
|
this.authType = config.authType;
|
|
@@ -309,7 +331,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
309
331
|
this.query = config.query;
|
|
310
332
|
this.checkConnection = config.checkConnection;
|
|
311
333
|
this.setup = config.setup;
|
|
334
|
+
this.introspect = config.introspect;
|
|
312
335
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
336
|
+
this.surveyProbes = config.surveyProbes;
|
|
313
337
|
}
|
|
314
338
|
get connectorKey() {
|
|
315
339
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -317,7 +341,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
317
341
|
/**
|
|
318
342
|
* Create tools for connections that belong to this connector.
|
|
319
343
|
* Filters connections by connectorKey internally.
|
|
320
|
-
* Returns tools keyed as
|
|
344
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
321
345
|
*/
|
|
322
346
|
createTools(connections, config, opts) {
|
|
323
347
|
const myConnections = connections.filter(
|
|
@@ -327,7 +351,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
327
351
|
for (const t of Object.values(this.tools)) {
|
|
328
352
|
const tool = t.createTool(myConnections, config);
|
|
329
353
|
const originalToModelOutput = tool.toModelOutput;
|
|
330
|
-
result[
|
|
354
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
331
355
|
...tool,
|
|
332
356
|
toModelOutput: async (options) => {
|
|
333
357
|
if (!originalToModelOutput) {
|
|
@@ -347,25 +371,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
347
371
|
if (authType) return `${slug}-${authType}`;
|
|
348
372
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
349
373
|
// user-password
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
374
|
+
postgresql: "user-password",
|
|
375
|
+
mysql: "user-password",
|
|
376
|
+
clickhouse: "user-password",
|
|
377
|
+
kintone: "user-password",
|
|
354
378
|
"squadbase-db": "user-password",
|
|
355
379
|
// service-account
|
|
356
|
-
|
|
357
|
-
|
|
380
|
+
snowflake: "service-account",
|
|
381
|
+
bigquery: "service-account",
|
|
358
382
|
"google-analytics": "service-account",
|
|
359
383
|
"google-calendar": "service-account",
|
|
360
384
|
"aws-athena": "service-account",
|
|
361
|
-
|
|
385
|
+
redshift: "service-account",
|
|
362
386
|
// api-key
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
387
|
+
databricks: "api-key",
|
|
388
|
+
dbt: "api-key",
|
|
389
|
+
airtable: "api-key",
|
|
390
|
+
openai: "api-key",
|
|
391
|
+
gemini: "api-key",
|
|
392
|
+
anthropic: "api-key",
|
|
369
393
|
"wix-store": "api-key"
|
|
370
394
|
};
|
|
371
395
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -457,10 +481,10 @@ var AUTH_TYPES = {
|
|
|
457
481
|
// ../connectors/src/connectors/airtable/setup.ts
|
|
458
482
|
var airtableOnboarding = new ConnectorOnboarding({
|
|
459
483
|
dataOverviewInstructions: {
|
|
460
|
-
en: `1. Call
|
|
461
|
-
2. Call
|
|
462
|
-
ja: `1.
|
|
463
|
-
2.
|
|
484
|
+
en: `1. Call connector_airtable_request with GET meta/bases/{baseId}/tables to list tables and their fields
|
|
485
|
+
2. Call connector_airtable_request with GET {baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
|
|
486
|
+
ja: `1. connector_airtable_request \u3067 GET meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
|
|
487
|
+
2. connector_airtable_request \u3067 GET {baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
|
|
464
488
|
}
|
|
465
489
|
});
|
|
466
490
|
|
|
@@ -498,6 +522,26 @@ async function listTables(params, baseId) {
|
|
|
498
522
|
const data = await res.json();
|
|
499
523
|
return data.tables ?? [];
|
|
500
524
|
}
|
|
525
|
+
async function listSampleRecords(params, baseId, tableId) {
|
|
526
|
+
try {
|
|
527
|
+
const res = await apiFetch(
|
|
528
|
+
params,
|
|
529
|
+
`/${baseId}/${encodeURIComponent(tableId)}?maxRecords=3`
|
|
530
|
+
);
|
|
531
|
+
if (!res.ok) return [];
|
|
532
|
+
const data = await res.json();
|
|
533
|
+
return data.records ?? [];
|
|
534
|
+
} catch {
|
|
535
|
+
return [];
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
function formatCell(val) {
|
|
539
|
+
if (val == null) return "";
|
|
540
|
+
if (typeof val === "string") return val.length > 40 ? `${val.slice(0, 40)}\u2026` : val;
|
|
541
|
+
if (Array.isArray(val)) return `[${val.length} items]`;
|
|
542
|
+
if (typeof val === "object") return JSON.stringify(val).slice(0, 40);
|
|
543
|
+
return String(val);
|
|
544
|
+
}
|
|
501
545
|
var airtableSetupFlow = {
|
|
502
546
|
initialState: () => ({}),
|
|
503
547
|
steps: [
|
|
@@ -569,11 +613,61 @@ var airtableSetupFlow = {
|
|
|
569
613
|
sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
|
|
570
614
|
}
|
|
571
615
|
sections.push("");
|
|
616
|
+
const records = await listSampleRecords(rt.params, baseId, table.id);
|
|
617
|
+
if (records.length > 0) {
|
|
618
|
+
const sampleFields = (table.fields ?? []).slice(0, 5).map((f) => f.name);
|
|
619
|
+
if (sampleFields.length > 0) {
|
|
620
|
+
sections.push(`##### Sample records (${records.length})`, "");
|
|
621
|
+
sections.push(`| ${sampleFields.join(" | ")} |`);
|
|
622
|
+
sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
|
|
623
|
+
for (const record of records) {
|
|
624
|
+
const cells = sampleFields.map(
|
|
625
|
+
(name) => formatCell(record.fields?.[name]).replace(/\|/g, "\\|")
|
|
626
|
+
);
|
|
627
|
+
sections.push(`| ${cells.join(" | ")} |`);
|
|
628
|
+
}
|
|
629
|
+
sections.push("");
|
|
630
|
+
}
|
|
631
|
+
}
|
|
572
632
|
}
|
|
573
633
|
return sections.join("\n");
|
|
574
634
|
}
|
|
575
635
|
};
|
|
576
636
|
|
|
637
|
+
// ../connectors/src/connectors/airtable/introspect.ts
|
|
638
|
+
async function introspectAirtable(ctx) {
|
|
639
|
+
const baseId = ctx.params[parameters.baseId.slug];
|
|
640
|
+
if (!baseId) return { tables: [] };
|
|
641
|
+
const res = await apiFetch(ctx.params, `/meta/bases/${baseId}/tables`);
|
|
642
|
+
if (!res.ok) {
|
|
643
|
+
throw new Error(`airtable: meta/tables failed (${res.status})`);
|
|
644
|
+
}
|
|
645
|
+
const data = await res.json();
|
|
646
|
+
const atTables = data.tables ?? [];
|
|
647
|
+
const tableNameById = new Map(atTables.map((t) => [t.id, t.name]));
|
|
648
|
+
const tables = atTables.map((t) => {
|
|
649
|
+
const columns = (t.fields ?? []).map((f) => {
|
|
650
|
+
const column = {
|
|
651
|
+
name: f.name,
|
|
652
|
+
dataType: f.type,
|
|
653
|
+
nullable: true
|
|
654
|
+
};
|
|
655
|
+
if (f.id === t.primaryFieldId) column.isPrimaryKey = true;
|
|
656
|
+
const linkedId = f.options?.linkedTableId;
|
|
657
|
+
if (f.type === "multipleRecordLinks" && linkedId) {
|
|
658
|
+
column.foreignKey = {
|
|
659
|
+
schema: baseId,
|
|
660
|
+
table: tableNameById.get(linkedId) ?? linkedId,
|
|
661
|
+
column: ""
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
return column;
|
|
665
|
+
});
|
|
666
|
+
return { schema: baseId, name: t.name, type: "table", columns };
|
|
667
|
+
});
|
|
668
|
+
return { tables };
|
|
669
|
+
}
|
|
670
|
+
|
|
577
671
|
// ../connectors/src/connectors/airtable/tools/request.ts
|
|
578
672
|
import { z } from "zod";
|
|
579
673
|
var BASE_URL3 = "https://api.airtable.com/v0/";
|
|
@@ -660,7 +754,7 @@ var airtableConnector = new ConnectorPlugin({
|
|
|
660
754
|
systemPrompt: {
|
|
661
755
|
en: `### Tools
|
|
662
756
|
|
|
663
|
-
- \`
|
|
757
|
+
- \`connector_airtable_request\`: The only way to call the Airtable REST API. Use it to list tables, read records, and create/update records. The \`{baseId}\` placeholder in the path is automatically replaced. See the Airtable API Reference below for available endpoints and query parameters.
|
|
664
758
|
|
|
665
759
|
### Business Logic
|
|
666
760
|
|
|
@@ -719,7 +813,7 @@ export default async function handler(c: Context) {
|
|
|
719
813
|
- If the response contains an \`offset\`, fetch the next page by appending \`?offset={offset}\` to the next request`,
|
|
720
814
|
ja: `### \u30C4\u30FC\u30EB
|
|
721
815
|
|
|
722
|
-
- \`
|
|
816
|
+
- \`connector_airtable_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u53D6\u308A\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E \`{baseId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u306F\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3068\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u4E0B\u90E8\u306E\u300CAirtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
723
817
|
|
|
724
818
|
### Business Logic
|
|
725
819
|
|
|
@@ -778,6 +872,19 @@ export default async function handler(c: Context) {
|
|
|
778
872
|
- \u30EC\u30B9\u30DD\u30F3\u30B9\u306B \`offset\` \u304C\u542B\u307E\u308C\u308B\u5834\u5408\u3001\u6B21\u306E\u30EA\u30AF\u30A8\u30B9\u30C8\u306B \`?offset={offset}\` \u3092\u8FFD\u52A0\u3057\u3066\u6B21\u306E\u30DA\u30FC\u30B8\u3092\u53D6\u5F97\u3057\u307E\u3059`
|
|
779
873
|
},
|
|
780
874
|
tools,
|
|
875
|
+
// 決定論的な立ち上げ survey(ルールベース prewarm)。テーブル一覧(フィールド定義込み)を 1 GET で取得。
|
|
876
|
+
// `{baseId}` は request ツールが自動置換する。read-only。
|
|
877
|
+
surveyProbes: (_connectionId, prior) => prior.length === 0 ? [
|
|
878
|
+
{
|
|
879
|
+
tool: "request",
|
|
880
|
+
input: {
|
|
881
|
+
method: "GET",
|
|
882
|
+
path: "meta/bases/{baseId}/tables",
|
|
883
|
+
toolUseIntent: "List Airtable tables"
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
] : [],
|
|
887
|
+
introspect: (ctx) => introspectAirtable(ctx),
|
|
781
888
|
setup: (params, ctx, config) => runSetupFlow(airtableSetupFlow, params, ctx, config),
|
|
782
889
|
async checkConnection(params, _config) {
|
|
783
890
|
const apiKey = params[parameters.apiKey.slug];
|
|
@@ -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
|
|
@@ -238,6 +243,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
238
243
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
239
244
|
*/
|
|
240
245
|
setup;
|
|
246
|
+
/**
|
|
247
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
248
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
249
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
250
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
251
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
252
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
253
|
+
*/
|
|
254
|
+
introspect;
|
|
241
255
|
/**
|
|
242
256
|
* Opt-out of the default "verify before save" behavior on connection
|
|
243
257
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -252,6 +266,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
252
266
|
* the default verify-on-create behavior without opt-in.
|
|
253
267
|
*/
|
|
254
268
|
skipConnectionCheckOnCreate;
|
|
269
|
+
/**
|
|
270
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
271
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
272
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
273
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
274
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
275
|
+
*/
|
|
276
|
+
surveyProbes;
|
|
255
277
|
constructor(config) {
|
|
256
278
|
this.slug = config.slug;
|
|
257
279
|
this.authType = config.authType;
|
|
@@ -269,7 +291,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
269
291
|
this.query = config.query;
|
|
270
292
|
this.checkConnection = config.checkConnection;
|
|
271
293
|
this.setup = config.setup;
|
|
294
|
+
this.introspect = config.introspect;
|
|
272
295
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
296
|
+
this.surveyProbes = config.surveyProbes;
|
|
273
297
|
}
|
|
274
298
|
get connectorKey() {
|
|
275
299
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -277,7 +301,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
277
301
|
/**
|
|
278
302
|
* Create tools for connections that belong to this connector.
|
|
279
303
|
* Filters connections by connectorKey internally.
|
|
280
|
-
* Returns tools keyed as
|
|
304
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
281
305
|
*/
|
|
282
306
|
createTools(connections, config, opts) {
|
|
283
307
|
const myConnections = connections.filter(
|
|
@@ -287,7 +311,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
287
311
|
for (const t of Object.values(this.tools)) {
|
|
288
312
|
const tool = t.createTool(myConnections, config);
|
|
289
313
|
const originalToModelOutput = tool.toModelOutput;
|
|
290
|
-
result[
|
|
314
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
291
315
|
...tool,
|
|
292
316
|
toModelOutput: async (options) => {
|
|
293
317
|
if (!originalToModelOutput) {
|
|
@@ -307,25 +331,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
307
331
|
if (authType) return `${slug}-${authType}`;
|
|
308
332
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
309
333
|
// user-password
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
334
|
+
postgresql: "user-password",
|
|
335
|
+
mysql: "user-password",
|
|
336
|
+
clickhouse: "user-password",
|
|
337
|
+
kintone: "user-password",
|
|
314
338
|
"squadbase-db": "user-password",
|
|
315
339
|
// service-account
|
|
316
|
-
|
|
317
|
-
|
|
340
|
+
snowflake: "service-account",
|
|
341
|
+
bigquery: "service-account",
|
|
318
342
|
"google-analytics": "service-account",
|
|
319
343
|
"google-calendar": "service-account",
|
|
320
344
|
"aws-athena": "service-account",
|
|
321
|
-
|
|
345
|
+
redshift: "service-account",
|
|
322
346
|
// api-key
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
347
|
+
databricks: "api-key",
|
|
348
|
+
dbt: "api-key",
|
|
349
|
+
airtable: "api-key",
|
|
350
|
+
openai: "api-key",
|
|
351
|
+
gemini: "api-key",
|
|
352
|
+
anthropic: "api-key",
|
|
329
353
|
"wix-store": "api-key"
|
|
330
354
|
};
|
|
331
355
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -413,13 +437,13 @@ var AUTH_TYPES = {
|
|
|
413
437
|
var amplitudeOnboarding = new ConnectorOnboarding({
|
|
414
438
|
dataOverviewInstructions: {
|
|
415
439
|
en: `1. Check the connection's region parameter: use https://analytics.eu.amplitude.com for EU, https://amplitude.com for US (default)
|
|
416
|
-
2. Call
|
|
417
|
-
3. Call
|
|
440
|
+
2. Call connector_amplitude_request with GET {baseUrl}/api/2/events/list to list available event types
|
|
441
|
+
3. Call connector_amplitude_request with GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH to export raw event data for a time range
|
|
418
442
|
4. Use GET {baseUrl}/api/2/usersearch?user=QUERY and GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID to explore user-level data
|
|
419
443
|
NOTE: The Dashboard REST API endpoints (events/segmentation, funnels, retention, etc.) require a paid Growth or Enterprise plan. If you get a 403 Forbidden error, fall back to the Export API (/api/2/export) to retrieve raw events and perform aggregation in code instead.`,
|
|
420
444
|
ja: `1. \u63A5\u7D9A\u306Eregion\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u78BA\u8A8D\uFF1AEU\u306E\u5834\u5408\u306F https://analytics.eu.amplitude.com\u3001US\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\uFF09\u306E\u5834\u5408\u306F https://amplitude.com \u3092\u4F7F\u7528
|
|
421
|
-
2.
|
|
422
|
-
3.
|
|
445
|
+
2. connector_amplitude_request \u3067 GET {baseUrl}/api/2/events/list \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3092\u53D6\u5F97
|
|
446
|
+
3. connector_amplitude_request \u3067 GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH \u3092\u547C\u3073\u51FA\u3057\u3001\u6307\u5B9A\u671F\u9593\u306E\u751F\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
|
|
423
447
|
4. GET {baseUrl}/api/2/usersearch?user=QUERY \u3084 GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID \u3067\u30E6\u30FC\u30B6\u30FC\u30EC\u30D9\u30EB\u306E\u30C7\u30FC\u30BF\u3092\u63A2\u7D22
|
|
424
448
|
\u6CE8\u610F: Dashboard REST API\uFF08events/segmentation\u3001funnels\u3001retention\u7B49\uFF09\u306F\u6709\u6599\u306EGrowth\u307E\u305F\u306FEnterprise\u30D7\u30E9\u30F3\u304C\u5FC5\u8981\u3067\u3059\u3002403 Forbidden\u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u306F\u3001Export API\uFF08/api/2/export\uFF09\u3067\u751F\u30A4\u30D9\u30F3\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B3\u30FC\u30C9\u4E0A\u3067\u96C6\u8A08\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
|
|
425
449
|
}
|
|
@@ -645,7 +669,7 @@ var amplitudeConnector = new ConnectorPlugin({
|
|
|
645
669
|
systemPrompt: {
|
|
646
670
|
en: `### Tools
|
|
647
671
|
|
|
648
|
-
- \`
|
|
672
|
+
- \`connector_amplitude_request\`: The only way to call the Amplitude REST API. Use it for event segmentation, listing event types, user search, user activity, and data export. Authentication (Basic auth with API Key + Secret Key) is configured automatically. Provide the full URL including query parameters \u2014 the base URL varies by endpoint.
|
|
649
673
|
|
|
650
674
|
### Business Logic
|
|
651
675
|
|
|
@@ -709,7 +733,7 @@ IMPORTANT: Always start with the endpoints available on all plans. If you need a
|
|
|
709
733
|
- \`g\` \u2014 Group by property`,
|
|
710
734
|
ja: `### \u30C4\u30FC\u30EB
|
|
711
735
|
|
|
712
|
-
- \`
|
|
736
|
+
- \`connector_amplitude_request\`: Amplitude REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u3001\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u691C\u7D22\u3001\u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u3001\u30C7\u30FC\u30BF\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API Key + Secret Key\u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u542B\u3080\u5B8C\u5168\u306AURL\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 \u30D9\u30FC\u30B9URL\u306F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002
|
|
713
737
|
|
|
714
738
|
### Business Logic
|
|
715
739
|
|