@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
|
|
@@ -185,6 +190,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
185
190
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
186
191
|
*/
|
|
187
192
|
setup;
|
|
193
|
+
/**
|
|
194
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
195
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
196
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
197
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
198
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
199
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
200
|
+
*/
|
|
201
|
+
introspect;
|
|
188
202
|
/**
|
|
189
203
|
* Opt-out of the default "verify before save" behavior on connection
|
|
190
204
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -199,6 +213,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
199
213
|
* the default verify-on-create behavior without opt-in.
|
|
200
214
|
*/
|
|
201
215
|
skipConnectionCheckOnCreate;
|
|
216
|
+
/**
|
|
217
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
218
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
219
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
220
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
221
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
222
|
+
*/
|
|
223
|
+
surveyProbes;
|
|
202
224
|
constructor(config) {
|
|
203
225
|
this.slug = config.slug;
|
|
204
226
|
this.authType = config.authType;
|
|
@@ -216,7 +238,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
216
238
|
this.query = config.query;
|
|
217
239
|
this.checkConnection = config.checkConnection;
|
|
218
240
|
this.setup = config.setup;
|
|
241
|
+
this.introspect = config.introspect;
|
|
219
242
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
243
|
+
this.surveyProbes = config.surveyProbes;
|
|
220
244
|
}
|
|
221
245
|
get connectorKey() {
|
|
222
246
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -224,7 +248,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
224
248
|
/**
|
|
225
249
|
* Create tools for connections that belong to this connector.
|
|
226
250
|
* Filters connections by connectorKey internally.
|
|
227
|
-
* Returns tools keyed as
|
|
251
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
228
252
|
*/
|
|
229
253
|
createTools(connections, config, opts) {
|
|
230
254
|
const myConnections = connections.filter(
|
|
@@ -234,7 +258,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
234
258
|
for (const t of Object.values(this.tools)) {
|
|
235
259
|
const tool = t.createTool(myConnections, config);
|
|
236
260
|
const originalToModelOutput = tool.toModelOutput;
|
|
237
|
-
result[
|
|
261
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
238
262
|
...tool,
|
|
239
263
|
toModelOutput: async (options) => {
|
|
240
264
|
if (!originalToModelOutput) {
|
|
@@ -254,25 +278,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
254
278
|
if (authType) return `${slug}-${authType}`;
|
|
255
279
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
256
280
|
// user-password
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
281
|
+
postgresql: "user-password",
|
|
282
|
+
mysql: "user-password",
|
|
283
|
+
clickhouse: "user-password",
|
|
284
|
+
kintone: "user-password",
|
|
261
285
|
"squadbase-db": "user-password",
|
|
262
286
|
// service-account
|
|
263
|
-
|
|
264
|
-
|
|
287
|
+
snowflake: "service-account",
|
|
288
|
+
bigquery: "service-account",
|
|
265
289
|
"google-analytics": "service-account",
|
|
266
290
|
"google-calendar": "service-account",
|
|
267
291
|
"aws-athena": "service-account",
|
|
268
|
-
|
|
292
|
+
redshift: "service-account",
|
|
269
293
|
// api-key
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
294
|
+
databricks: "api-key",
|
|
295
|
+
dbt: "api-key",
|
|
296
|
+
airtable: "api-key",
|
|
297
|
+
openai: "api-key",
|
|
298
|
+
gemini: "api-key",
|
|
299
|
+
anthropic: "api-key",
|
|
276
300
|
"wix-store": "api-key"
|
|
277
301
|
};
|
|
278
302
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -364,12 +388,12 @@ var AUTH_TYPES = {
|
|
|
364
388
|
// ../connectors/src/connectors/jira/setup.ts
|
|
365
389
|
var jiraOnboarding = new ConnectorOnboarding({
|
|
366
390
|
dataOverviewInstructions: {
|
|
367
|
-
en: `1. Call
|
|
368
|
-
2. For key projects, call
|
|
369
|
-
3. Call
|
|
370
|
-
ja: `1.
|
|
371
|
-
2. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066
|
|
372
|
-
3.
|
|
391
|
+
en: `1. Call connector_jira-api-key_request with GET project to list all accessible projects
|
|
392
|
+
2. For key projects, call connector_jira-api-key_request with POST search to search issues using JQL (e.g., body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] })
|
|
393
|
+
3. Call connector_jira-api-key_request with GET issue/{issueKey} to inspect a sample issue's full details`,
|
|
394
|
+
ja: `1. connector_jira-api-key_request \u3067 GET project \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
|
|
395
|
+
2. \u4E3B\u8981\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u3064\u3044\u3066 connector_jira-api-key_request \u3067 POST search \u3092\u4F7F\u7528\u3057\u3066JQL\u3067\u30A4\u30B7\u30E5\u30FC\u3092\u691C\u7D22\uFF08\u4F8B: body: { "jql": "project = PROJ order by created DESC", "maxResults": 5, "fields": ["summary", "status", "assignee", "priority", "created"] }\uFF09
|
|
396
|
+
3. connector_jira-api-key_request \u3067 GET issue/{issueKey} \u3092\u547C\u3073\u51FA\u3057\u3001\u30B5\u30F3\u30D7\u30EB\u30A4\u30B7\u30E5\u30FC\u306E\u8A73\u7D30\u3092\u78BA\u8A8D`
|
|
373
397
|
}
|
|
374
398
|
});
|
|
375
399
|
|
|
@@ -431,6 +455,43 @@ async function getProject(params, keyOrId) {
|
|
|
431
455
|
}
|
|
432
456
|
return await res.json();
|
|
433
457
|
}
|
|
458
|
+
async function fetchProjectIssueCount(params, projectKey) {
|
|
459
|
+
try {
|
|
460
|
+
const jql = encodeURIComponent(`project = ${projectKey}`);
|
|
461
|
+
const res = await apiFetch(
|
|
462
|
+
params,
|
|
463
|
+
`search?jql=${jql}&maxResults=0`
|
|
464
|
+
);
|
|
465
|
+
if (!res.ok) return null;
|
|
466
|
+
const data = await res.json();
|
|
467
|
+
return typeof data.total === "number" ? data.total : null;
|
|
468
|
+
} catch {
|
|
469
|
+
return null;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
async function fetchStatusBreakdown(params, projectKey) {
|
|
473
|
+
try {
|
|
474
|
+
const jql = encodeURIComponent(
|
|
475
|
+
`project = ${projectKey} ORDER BY created DESC`
|
|
476
|
+
);
|
|
477
|
+
const res = await apiFetch(
|
|
478
|
+
params,
|
|
479
|
+
`search?jql=${jql}&maxResults=100&fields=status`
|
|
480
|
+
);
|
|
481
|
+
if (!res.ok) return null;
|
|
482
|
+
const data = await res.json();
|
|
483
|
+
const issues = data.issues ?? [];
|
|
484
|
+
if (issues.length === 0) return null;
|
|
485
|
+
const breakdown = {};
|
|
486
|
+
for (const issue of issues) {
|
|
487
|
+
const category = issue.fields?.status?.statusCategory?.name ?? "Unknown";
|
|
488
|
+
breakdown[category] = (breakdown[category] ?? 0) + 1;
|
|
489
|
+
}
|
|
490
|
+
return breakdown;
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
434
495
|
var jiraSetupFlow = {
|
|
435
496
|
initialState: () => ({}),
|
|
436
497
|
steps: [
|
|
@@ -471,17 +532,37 @@ var jiraSetupFlow = {
|
|
|
471
532
|
const sections = ["## Jira", ""];
|
|
472
533
|
for (const key of targetKeys) {
|
|
473
534
|
const project = await getProject(rt.params, key);
|
|
474
|
-
|
|
535
|
+
const issueCount = await fetchProjectIssueCount(rt.params, key);
|
|
536
|
+
const countLabel = issueCount == null ? "" : ` - ${issueCount.toLocaleString()} issues`;
|
|
537
|
+
sections.push(
|
|
538
|
+
`### Project: ${project.name} (${project.key})${countLabel}`,
|
|
539
|
+
""
|
|
540
|
+
);
|
|
475
541
|
const lead = project.lead?.displayName ?? "-";
|
|
476
542
|
const typeKey = project.projectTypeKey ?? "-";
|
|
477
543
|
sections.push(`- Lead: ${lead}`);
|
|
478
544
|
sections.push(`- Project type: ${typeKey}`);
|
|
545
|
+
if (issueCount != null) {
|
|
546
|
+
sections.push(`- Total issues: ${issueCount.toLocaleString()}`);
|
|
547
|
+
}
|
|
479
548
|
const issueTypes = project.issueTypes ?? [];
|
|
480
549
|
sections.push(`- Issue types (${issueTypes.length}):`);
|
|
481
550
|
for (const it of issueTypes) {
|
|
482
551
|
const suffix = it.subtask ? " (sub-task)" : "";
|
|
483
552
|
sections.push(` - ${it.name}${suffix}`);
|
|
484
553
|
}
|
|
554
|
+
const breakdown = await fetchStatusBreakdown(rt.params, key);
|
|
555
|
+
if (breakdown && Object.keys(breakdown).length > 0) {
|
|
556
|
+
sections.push("");
|
|
557
|
+
sections.push("**Status category breakdown (from recent 100 issues):**", "");
|
|
558
|
+
sections.push("| Status category | Count |");
|
|
559
|
+
sections.push("|-----------------|-------|");
|
|
560
|
+
for (const [category, count] of Object.entries(breakdown).sort(
|
|
561
|
+
(a, b) => b[1] - a[1]
|
|
562
|
+
)) {
|
|
563
|
+
sections.push(`| ${category} | ${count} |`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
485
566
|
sections.push("");
|
|
486
567
|
}
|
|
487
568
|
return sections.join("\n");
|
|
@@ -580,7 +661,7 @@ var jiraConnector = new ConnectorPlugin({
|
|
|
580
661
|
systemPrompt: {
|
|
581
662
|
en: `### Tools
|
|
582
663
|
|
|
583
|
-
- \`
|
|
664
|
+
- \`connector_jira-api-key_request\`: The only way to call the Jira Cloud REST API (v3). Use it to list projects, search issues with JQL, get issue details, create/update issues, manage transitions, and add comments. Authentication (Basic Auth with email + API token) and instance URL are configured automatically.
|
|
584
665
|
|
|
585
666
|
### Business Logic
|
|
586
667
|
|
|
@@ -650,7 +731,7 @@ await jira.request("/rest/api/3/issue", {
|
|
|
650
731
|
- Text search: summary ~ "keyword"`,
|
|
651
732
|
ja: `### \u30C4\u30FC\u30EB
|
|
652
733
|
|
|
653
|
-
- \`
|
|
734
|
+
- \`connector_jira-api-key_request\`: Jira Cloud REST API\uFF08v3\uFF09\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u306E\u53D6\u5F97\u3001JQL\u306B\u3088\u308B\u30A4\u30B7\u30E5\u30FC\u691C\u7D22\u3001\u30A4\u30B7\u30E5\u30FC\u8A73\u7D30\u306E\u53D6\u5F97\u3001\u30A4\u30B7\u30E5\u30FC\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u3001\u30C8\u30E9\u30F3\u30B8\u30B7\u30E7\u30F3\u7BA1\u7406\u3001\u30B3\u30E1\u30F3\u30C8\u8FFD\u52A0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Basic Auth: \u30E1\u30FC\u30EB + API\u30C8\u30FC\u30AF\u30F3\uFF09\u3068\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9URL\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
|
|
654
735
|
|
|
655
736
|
### Business Logic
|
|
656
737
|
|
|
@@ -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
|
|
@@ -214,6 +219,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
214
219
|
* `runSetupFlow` from `setup-flow.ts`.
|
|
215
220
|
*/
|
|
216
221
|
setup;
|
|
222
|
+
/**
|
|
223
|
+
* 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
|
|
224
|
+
* メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
|
|
225
|
+
* {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
|
|
226
|
+
* 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
|
|
227
|
+
* `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
|
|
228
|
+
* coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
|
|
229
|
+
*/
|
|
230
|
+
introspect;
|
|
217
231
|
/**
|
|
218
232
|
* Opt-out of the default "verify before save" behavior on connection
|
|
219
233
|
* creation. The backend invokes `checkConnection` synchronously while
|
|
@@ -228,6 +242,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
228
242
|
* the default verify-on-create behavior without opt-in.
|
|
229
243
|
*/
|
|
230
244
|
skipConnectionCheckOnCreate;
|
|
245
|
+
/**
|
|
246
|
+
* 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
|
|
247
|
+
* read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
|
|
248
|
+
* recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
|
|
249
|
+
* driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
|
|
250
|
+
* 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
|
|
251
|
+
*/
|
|
252
|
+
surveyProbes;
|
|
231
253
|
constructor(config) {
|
|
232
254
|
this.slug = config.slug;
|
|
233
255
|
this.authType = config.authType;
|
|
@@ -245,7 +267,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
245
267
|
this.query = config.query;
|
|
246
268
|
this.checkConnection = config.checkConnection;
|
|
247
269
|
this.setup = config.setup;
|
|
270
|
+
this.introspect = config.introspect;
|
|
248
271
|
this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
|
|
272
|
+
this.surveyProbes = config.surveyProbes;
|
|
249
273
|
}
|
|
250
274
|
get connectorKey() {
|
|
251
275
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -253,7 +277,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
253
277
|
/**
|
|
254
278
|
* Create tools for connections that belong to this connector.
|
|
255
279
|
* Filters connections by connectorKey internally.
|
|
256
|
-
* Returns tools keyed as
|
|
280
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
257
281
|
*/
|
|
258
282
|
createTools(connections, config, opts) {
|
|
259
283
|
const myConnections = connections.filter(
|
|
@@ -263,7 +287,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
263
287
|
for (const t of Object.values(this.tools)) {
|
|
264
288
|
const tool = t.createTool(myConnections, config);
|
|
265
289
|
const originalToModelOutput = tool.toModelOutput;
|
|
266
|
-
result[
|
|
290
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
267
291
|
...tool,
|
|
268
292
|
toModelOutput: async (options) => {
|
|
269
293
|
if (!originalToModelOutput) {
|
|
@@ -283,25 +307,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
283
307
|
if (authType) return `${slug}-${authType}`;
|
|
284
308
|
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
285
309
|
// user-password
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
310
|
+
postgresql: "user-password",
|
|
311
|
+
mysql: "user-password",
|
|
312
|
+
clickhouse: "user-password",
|
|
313
|
+
kintone: "user-password",
|
|
290
314
|
"squadbase-db": "user-password",
|
|
291
315
|
// service-account
|
|
292
|
-
|
|
293
|
-
|
|
316
|
+
snowflake: "service-account",
|
|
317
|
+
bigquery: "service-account",
|
|
294
318
|
"google-analytics": "service-account",
|
|
295
319
|
"google-calendar": "service-account",
|
|
296
320
|
"aws-athena": "service-account",
|
|
297
|
-
|
|
321
|
+
redshift: "service-account",
|
|
298
322
|
// api-key
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
323
|
+
databricks: "api-key",
|
|
324
|
+
dbt: "api-key",
|
|
325
|
+
airtable: "api-key",
|
|
326
|
+
openai: "api-key",
|
|
327
|
+
gemini: "api-key",
|
|
328
|
+
anthropic: "api-key",
|
|
305
329
|
"wix-store": "api-key"
|
|
306
330
|
};
|
|
307
331
|
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
@@ -390,14 +414,14 @@ var kintoneApiTokenOnboarding = new ConnectorOnboarding({
|
|
|
390
414
|
dataOverviewInstructions: {
|
|
391
415
|
en: `Each connection is scoped to a single kintone app (configured via the "app-id" parameter). The request tool auto-injects the configured app id, so you do NOT need to specify "app=" in paths or "app" in bodies. apps.json is NOT available with API Token auth.
|
|
392
416
|
|
|
393
|
-
1. Call
|
|
394
|
-
2. Call
|
|
395
|
-
3. Call
|
|
417
|
+
1. Call connector_kintone-api-key_request with GET app.json to fetch the scoped app's metadata (name, description, creator)
|
|
418
|
+
2. Call connector_kintone-api-key_request with GET app/form/fields.json to get field definitions
|
|
419
|
+
3. Call connector_kintone-api-key_request with GET records.json with query=limit 5 to sample records`,
|
|
396
420
|
ja: `\u5404\u63A5\u7D9A\u306F1\u3064\u306Ekintone\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\uFF08"app-id" \u30D1\u30E9\u30E1\u30FC\u30BF\u3067\u8A2D\u5B9A\uFF09\u3002request \u30C4\u30FC\u30EB\u306F\u8A2D\u5B9A\u3055\u308C\u305F\u30A2\u30D7\u30EAID\u3092\u81EA\u52D5\u6CE8\u5165\u3059\u308B\u305F\u3081\u3001\u30D1\u30B9\u306B "app=" \u3084 body \u306B "app" \u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u306F\u3042\u308A\u307E\u305B\u3093\u3002API Token \u8A8D\u8A3C\u3067\u306F apps.json \u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002
|
|
397
421
|
|
|
398
|
-
1.
|
|
399
|
-
2.
|
|
400
|
-
3.
|
|
422
|
+
1. connector_kintone-api-key_request \u3067 GET app.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30B9\u30B3\u30FC\u30D7\u5BFE\u8C61\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\uFF08\u30A2\u30D7\u30EA\u540D\u3001\u8AAC\u660E\u3001\u4F5C\u6210\u8005\uFF09\u3092\u53D6\u5F97
|
|
423
|
+
2. connector_kintone-api-key_request \u3067 GET app/form/fields.json \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
|
|
424
|
+
3. connector_kintone-api-key_request \u3067 GET records.json \u3092 query=limit 5 \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
|
|
401
425
|
}
|
|
402
426
|
});
|
|
403
427
|
|
|
@@ -421,6 +445,7 @@ async function apiFetch(params, path2, init) {
|
|
|
421
445
|
}
|
|
422
446
|
|
|
423
447
|
// ../connectors/src/connectors/kintone-api-token/setup-flow.ts
|
|
448
|
+
var SAMPLE_RECORD_LIMIT = 5;
|
|
424
449
|
async function getAppMetadata(params, appId) {
|
|
425
450
|
const res = await apiFetch(
|
|
426
451
|
params,
|
|
@@ -447,15 +472,28 @@ async function getFormFields(params, appId) {
|
|
|
447
472
|
}
|
|
448
473
|
return await res.json();
|
|
449
474
|
}
|
|
475
|
+
async function getSampleRecords(params, appId) {
|
|
476
|
+
const res = await apiFetch(
|
|
477
|
+
params,
|
|
478
|
+
`records.json?app=${encodeURIComponent(appId)}&query=${encodeURIComponent(`limit ${SAMPLE_RECORD_LIMIT}`)}&totalCount=true`
|
|
479
|
+
);
|
|
480
|
+
if (!res.ok) return { records: [], totalCount: null };
|
|
481
|
+
return await res.json();
|
|
482
|
+
}
|
|
483
|
+
function formatRecordValue(val) {
|
|
484
|
+
if (val == null) return "";
|
|
485
|
+
if (typeof val === "string") return val.length > 50 ? `${val.slice(0, 50)}\u2026` : val;
|
|
486
|
+
if (Array.isArray(val)) return `[${val.length} items]`;
|
|
487
|
+
if (typeof val === "object") return JSON.stringify(val).slice(0, 50);
|
|
488
|
+
return String(val);
|
|
489
|
+
}
|
|
450
490
|
var kintoneApiTokenSetupFlow = {
|
|
451
491
|
initialState: () => ({}),
|
|
452
492
|
steps: [],
|
|
453
493
|
async finalize(_state, rt) {
|
|
454
|
-
const appId = rt.params[
|
|
494
|
+
const appId = rt.params["app-id"];
|
|
455
495
|
if (!appId) {
|
|
456
|
-
|
|
457
|
-
"kintone-api-token setup: missing app-id parameter on finalize"
|
|
458
|
-
);
|
|
496
|
+
return "## kintone\n\n_App ID \u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002_\n";
|
|
459
497
|
}
|
|
460
498
|
const sections = ["## kintone", ""];
|
|
461
499
|
const app = await getAppMetadata(rt.params, appId);
|
|
@@ -465,15 +503,39 @@ var kintoneApiTokenSetupFlow = {
|
|
|
465
503
|
sections.push(app.description, "");
|
|
466
504
|
}
|
|
467
505
|
const fields = await getFormFields(rt.params, appId);
|
|
506
|
+
const fieldEntries = Object.entries(fields.properties ?? {});
|
|
507
|
+
sections.push("#### Fields", "");
|
|
468
508
|
sections.push("| Field code | Label | Type | Required |");
|
|
469
509
|
sections.push("|------------|-------|------|----------|");
|
|
470
|
-
for (const [code, def] of
|
|
510
|
+
for (const [code, def] of fieldEntries) {
|
|
471
511
|
const escapedLabel = (def.label ?? "").replace(/\|/g, "\\|");
|
|
472
512
|
sections.push(
|
|
473
513
|
`| ${code} | ${escapedLabel || "-"} | ${def.type} | ${def.required ? "yes" : "no"} |`
|
|
474
514
|
);
|
|
475
515
|
}
|
|
476
516
|
sections.push("");
|
|
517
|
+
const sampleData = await getSampleRecords(rt.params, appId);
|
|
518
|
+
const totalCount = sampleData.totalCount ? Number(sampleData.totalCount) : null;
|
|
519
|
+
if (totalCount != null) {
|
|
520
|
+
sections.push(`#### Record count: ${totalCount.toLocaleString()}`, "");
|
|
521
|
+
}
|
|
522
|
+
const records = sampleData.records ?? [];
|
|
523
|
+
if (records.length > 0) {
|
|
524
|
+
const sampleFields = fieldEntries.slice(0, 8).map(([code]) => code);
|
|
525
|
+
if (sampleFields.length > 0) {
|
|
526
|
+
sections.push(`#### Sample records (${records.length})`, "");
|
|
527
|
+
sections.push(`| ${sampleFields.join(" | ")} |`);
|
|
528
|
+
sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
|
|
529
|
+
for (const record of records) {
|
|
530
|
+
const cells = sampleFields.map((code) => {
|
|
531
|
+
const cell = record[code];
|
|
532
|
+
return formatRecordValue(cell?.value).replace(/\|/g, "\\|");
|
|
533
|
+
});
|
|
534
|
+
sections.push(`| ${cells.join(" | ")} |`);
|
|
535
|
+
}
|
|
536
|
+
sections.push("");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
477
539
|
return sections.join("\n");
|
|
478
540
|
}
|
|
479
541
|
};
|
|
@@ -596,7 +658,7 @@ var kintoneApiTokenConnector = new ConnectorPlugin({
|
|
|
596
658
|
systemPrompt: {
|
|
597
659
|
en: `### Tools
|
|
598
660
|
|
|
599
|
-
- \`
|
|
661
|
+
- \`connector_kintone-api-key_request\`: The only way to call the kintone REST API. Use it to fetch app metadata/field definitions and read/write records. Authentication (API Token), base URL, and the connection's app id are configured automatically. Each connection is scoped to exactly one app (kintone API tokens are per-app).
|
|
600
662
|
|
|
601
663
|
### App scoping (important)
|
|
602
664
|
|
|
@@ -669,7 +731,7 @@ export default async function handler(c: Context) {
|
|
|
669
731
|
- String: \`like "partial match"\``,
|
|
670
732
|
ja: `### \u30C4\u30FC\u30EB
|
|
671
733
|
|
|
672
|
-
- \`
|
|
734
|
+
- \`connector_kintone-api-key_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u306E\u30E1\u30BF\u60C5\u5831\u30FB\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API\u30C8\u30FC\u30AF\u30F3\uFF09\u3001\u30D9\u30FC\u30B9URL\u3001\u304A\u3088\u3073\u63A5\u7D9A\u306E\u30A2\u30D7\u30EAID\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u5404\u63A5\u7D9A\u306F\u3061\u3087\u3046\u30691\u3064\u306E\u30A2\u30D7\u30EA\u306B\u30B9\u30B3\u30FC\u30D7\u3055\u308C\u3066\u3044\u307E\u3059\uFF08kintone API\u30C8\u30FC\u30AF\u30F3\u306F\u30A2\u30D7\u30EA\u5358\u4F4D\u306E\u305F\u3081\uFF09\u3002
|
|
673
735
|
|
|
674
736
|
### \u30A2\u30D7\u30EA\u30B9\u30B3\u30FC\u30D7\uFF08\u91CD\u8981\uFF09
|
|
675
737
|
|
|
@@ -747,14 +809,15 @@ export default async function handler(c: Context) {
|
|
|
747
809
|
const baseUrl = params[parameters.baseUrl.slug];
|
|
748
810
|
const apiToken = params[parameters.apiToken.slug];
|
|
749
811
|
const appId = params[parameters.appId.slug];
|
|
750
|
-
if (!baseUrl || !apiToken
|
|
812
|
+
if (!baseUrl || !apiToken) {
|
|
751
813
|
return {
|
|
752
814
|
success: false,
|
|
753
|
-
error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}
|
|
815
|
+
error: `Missing required parameters: ${parameters.baseUrl.slug}, ${parameters.apiToken.slug}`
|
|
754
816
|
};
|
|
755
817
|
}
|
|
756
818
|
try {
|
|
757
|
-
const
|
|
819
|
+
const path2 = appId ? `app.json?id=${encodeURIComponent(appId)}` : `app/form/fields.json?app=0`;
|
|
820
|
+
const url = `${baseUrl.replace(/\/+$/, "")}/k/v1/${path2}`;
|
|
758
821
|
const res = await fetch(url, {
|
|
759
822
|
method: "GET",
|
|
760
823
|
headers: {
|
|
@@ -762,6 +825,15 @@ export default async function handler(c: Context) {
|
|
|
762
825
|
Accept: "application/json"
|
|
763
826
|
}
|
|
764
827
|
});
|
|
828
|
+
if (!appId) {
|
|
829
|
+
if (res.status === 401 || res.status === 403) {
|
|
830
|
+
return {
|
|
831
|
+
success: false,
|
|
832
|
+
error: "kintone API failed: invalid API token"
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
return { success: true };
|
|
836
|
+
}
|
|
765
837
|
if (!res.ok) {
|
|
766
838
|
const data = await res.json().catch(() => null);
|
|
767
839
|
const message = data?.message ?? `HTTP ${res.status} ${res.statusText}`;
|