@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.
Files changed (80) hide show
  1. package/dist/cli/index.js +8941 -3700
  2. package/dist/connectors/airtable-oauth.js +87 -23
  3. package/dist/connectors/airtable.js +130 -23
  4. package/dist/connectors/amplitude.js +47 -23
  5. package/dist/connectors/anthropic.js +41 -17
  6. package/dist/connectors/asana.js +76 -25
  7. package/dist/connectors/attio.js +69 -28
  8. package/dist/connectors/aws-billing.js +47 -23
  9. package/dist/connectors/azure-sql.js +322 -25
  10. package/dist/connectors/backlog-api-key.js +79 -30
  11. package/dist/connectors/clickup.js +89 -25
  12. package/dist/connectors/cosmosdb.js +51 -27
  13. package/dist/connectors/customerio.js +47 -23
  14. package/dist/connectors/dbt.js +725 -40
  15. package/dist/connectors/freshdesk.js +121 -23
  16. package/dist/connectors/freshsales.js +47 -23
  17. package/dist/connectors/freshservice.js +47 -23
  18. package/dist/connectors/gamma.js +54 -30
  19. package/dist/connectors/gemini.js +41 -17
  20. package/dist/connectors/github.js +51 -27
  21. package/dist/connectors/gmail-oauth.js +42 -23
  22. package/dist/connectors/gmail.js +43 -19
  23. package/dist/connectors/google-ads.js +47 -23
  24. package/dist/connectors/google-analytics-oauth.js +191 -40
  25. package/dist/connectors/google-analytics.js +529 -111
  26. package/dist/connectors/google-audit-log.js +43 -19
  27. package/dist/connectors/google-calendar-oauth.js +100 -30
  28. package/dist/connectors/google-calendar.js +100 -26
  29. package/dist/connectors/google-docs.js +42 -23
  30. package/dist/connectors/google-drive.js +64 -23
  31. package/dist/connectors/google-search-console-oauth.js +165 -32
  32. package/dist/connectors/google-sheets.js +142 -199
  33. package/dist/connectors/google-slides.js +42 -23
  34. package/dist/connectors/grafana.js +84 -25
  35. package/dist/connectors/hackernews.d.ts +5 -0
  36. package/dist/connectors/hackernews.js +909 -0
  37. package/dist/connectors/hubspot-oauth.js +73 -22
  38. package/dist/connectors/hubspot.js +64 -24
  39. package/dist/connectors/influxdb.js +47 -23
  40. package/dist/connectors/intercom-oauth.js +104 -25
  41. package/dist/connectors/intercom.js +51 -27
  42. package/dist/connectors/jdbc.js +76 -25
  43. package/dist/connectors/jira-api-key.js +107 -26
  44. package/dist/connectors/kintone-api-token.js +105 -33
  45. package/dist/connectors/kintone.js +182 -26
  46. package/dist/connectors/linear.js +93 -27
  47. package/dist/connectors/linkedin-ads.js +80 -29
  48. package/dist/connectors/mailchimp-oauth.js +45 -21
  49. package/dist/connectors/mailchimp.js +45 -21
  50. package/dist/connectors/meta-ads-oauth.js +72 -29
  51. package/dist/connectors/meta-ads.js +74 -29
  52. package/dist/connectors/mixpanel.js +47 -23
  53. package/dist/connectors/monday.js +48 -24
  54. package/dist/connectors/mongodb.js +47 -23
  55. package/dist/connectors/notion-oauth.js +92 -24
  56. package/dist/connectors/notion.js +144 -26
  57. package/dist/connectors/openai.js +41 -17
  58. package/dist/connectors/oracle.js +316 -26
  59. package/dist/connectors/outlook-oauth.js +53 -34
  60. package/dist/connectors/powerbi-oauth.js +45 -26
  61. package/dist/connectors/salesforce.js +150 -24
  62. package/dist/connectors/semrush.js +45 -21
  63. package/dist/connectors/sentry.js +75 -25
  64. package/dist/connectors/shopify-oauth.js +75 -23
  65. package/dist/connectors/shopify.js +47 -23
  66. package/dist/connectors/sqlserver.js +322 -25
  67. package/dist/connectors/stripe-api-key.js +105 -30
  68. package/dist/connectors/stripe-oauth.js +102 -32
  69. package/dist/connectors/supabase.js +315 -21
  70. package/dist/connectors/tableau.js +54 -30
  71. package/dist/connectors/tiktok-ads.js +76 -31
  72. package/dist/connectors/wix-store.js +47 -23
  73. package/dist/connectors/x.d.ts +5 -0
  74. package/dist/connectors/x.js +951 -0
  75. package/dist/connectors/zendesk-oauth.js +87 -25
  76. package/dist/connectors/zendesk.js +51 -27
  77. package/dist/index.js +9005 -3709
  78. package/dist/main.js +9005 -3709
  79. package/dist/vite-plugin.js +8939 -3698
  80. package/package.json +12 -4
@@ -1,6 +1,11 @@
1
1
  var __getOwnPropNames = Object.getOwnPropertyNames;
2
- var __esm = (fn, res) => function __init() {
3
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
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
@@ -223,6 +228,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
223
228
  * `runSetupFlow` from `setup-flow.ts`.
224
229
  */
225
230
  setup;
231
+ /**
232
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
233
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
234
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
235
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
236
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
237
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
238
+ */
239
+ introspect;
226
240
  /**
227
241
  * Opt-out of the default "verify before save" behavior on connection
228
242
  * creation. The backend invokes `checkConnection` synchronously while
@@ -237,6 +251,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
237
251
  * the default verify-on-create behavior without opt-in.
238
252
  */
239
253
  skipConnectionCheckOnCreate;
254
+ /**
255
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
256
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
257
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
258
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
259
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
260
+ */
261
+ surveyProbes;
240
262
  constructor(config) {
241
263
  this.slug = config.slug;
242
264
  this.authType = config.authType;
@@ -254,7 +276,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
254
276
  this.query = config.query;
255
277
  this.checkConnection = config.checkConnection;
256
278
  this.setup = config.setup;
279
+ this.introspect = config.introspect;
257
280
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
281
+ this.surveyProbes = config.surveyProbes;
258
282
  }
259
283
  get connectorKey() {
260
284
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -262,7 +286,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
262
286
  /**
263
287
  * Create tools for connections that belong to this connector.
264
288
  * Filters connections by connectorKey internally.
265
- * Returns tools keyed as `${connectorKey}_${toolName}`.
289
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
266
290
  */
267
291
  createTools(connections, config, opts) {
268
292
  const myConnections = connections.filter(
@@ -272,7 +296,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
272
296
  for (const t of Object.values(this.tools)) {
273
297
  const tool = t.createTool(myConnections, config);
274
298
  const originalToModelOutput = tool.toModelOutput;
275
- result[`${this.connectorKey}_${t.name}`] = {
299
+ result[`connector_${this.connectorKey}_${t.name}`] = {
276
300
  ...tool,
277
301
  toModelOutput: async (options) => {
278
302
  if (!originalToModelOutput) {
@@ -292,25 +316,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
292
316
  if (authType) return `${slug}-${authType}`;
293
317
  const LEGACY_NULL_AUTH_TYPE_MAP = {
294
318
  // user-password
295
- "postgresql": "user-password",
296
- "mysql": "user-password",
297
- "clickhouse": "user-password",
298
- "kintone": "user-password",
319
+ postgresql: "user-password",
320
+ mysql: "user-password",
321
+ clickhouse: "user-password",
322
+ kintone: "user-password",
299
323
  "squadbase-db": "user-password",
300
324
  // service-account
301
- "snowflake": "service-account",
302
- "bigquery": "service-account",
325
+ snowflake: "service-account",
326
+ bigquery: "service-account",
303
327
  "google-analytics": "service-account",
304
328
  "google-calendar": "service-account",
305
329
  "aws-athena": "service-account",
306
- "redshift": "service-account",
330
+ redshift: "service-account",
307
331
  // api-key
308
- "databricks": "api-key",
309
- "dbt": "api-key",
310
- "airtable": "api-key",
311
- "openai": "api-key",
312
- "gemini": "api-key",
313
- "anthropic": "api-key",
332
+ databricks: "api-key",
333
+ dbt: "api-key",
334
+ airtable: "api-key",
335
+ openai: "api-key",
336
+ gemini: "api-key",
337
+ anthropic: "api-key",
314
338
  "wix-store": "api-key"
315
339
  };
316
340
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -389,6 +413,24 @@ async function resolveSetupSelection(params) {
389
413
  return resolved.slice(0, limit);
390
414
  }
391
415
 
416
+ // ../connectors/src/introspect-concurrency.ts
417
+ async function mapWithConcurrency(items, limit, fn) {
418
+ const results = new Array(items.length);
419
+ let next = 0;
420
+ const workers = Array.from(
421
+ { length: Math.min(Math.max(limit, 1), items.length) },
422
+ async () => {
423
+ for (; ; ) {
424
+ const i = next++;
425
+ if (i >= items.length) return;
426
+ results[i] = await fn(items[i]);
427
+ }
428
+ }
429
+ );
430
+ await Promise.all(workers);
431
+ return results;
432
+ }
433
+
392
434
  // ../connectors/src/auth-types.ts
393
435
  var AUTH_TYPES = {
394
436
  OAUTH: "oauth",
@@ -402,12 +444,12 @@ var AUTH_TYPES = {
402
444
  // ../connectors/src/connectors/kintone/setup.ts
403
445
  var kintoneOnboarding = new ConnectorOnboarding({
404
446
  dataOverviewInstructions: {
405
- en: `1. Call kintone_request with GET apps.json to list available apps
406
- 2. For key apps, call kintone_request with GET app/form/fields.json?app={appId} to get field definitions
407
- 3. Call kintone_request with GET records.json?app={appId}&query=limit 5 to sample records`,
408
- ja: `1. kintone_request \u3067 GET apps.json \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u4E00\u89A7\u3092\u53D6\u5F97
409
- 2. \u4E3B\u8981\u30A2\u30D7\u30EA\u306B\u3064\u3044\u3066 kintone_request \u3067 GET app/form/fields.json?app={appId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
410
- 3. kintone_request \u3067 GET records.json?app={appId}&query=limit 5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
447
+ en: `1. Call connector_kintone_request with GET apps.json to list available apps
448
+ 2. For key apps, call connector_kintone_request with GET app/form/fields.json?app={appId} to get field definitions
449
+ 3. Call connector_kintone_request with GET records.json?app={appId}&query=limit 5 to sample records`,
450
+ ja: `1. connector_kintone_request \u3067 GET apps.json \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A2\u30D7\u30EA\u4E00\u89A7\u3092\u53D6\u5F97
451
+ 2. \u4E3B\u8981\u30A2\u30D7\u30EA\u306B\u3064\u3044\u3066 connector_kintone_request \u3067 GET app/form/fields.json?app={appId} \u3092\u547C\u3073\u51FA\u3057\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u5B9A\u7FA9\u3092\u53D6\u5F97
452
+ 3. connector_kintone_request \u3067 GET records.json?app={appId}&query=limit 5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
411
453
  }
412
454
  });
413
455
 
@@ -435,6 +477,7 @@ async function apiFetch(params, path2, init) {
435
477
  // ../connectors/src/connectors/kintone/setup-flow.ts
436
478
  var ALL_APPS = "__ALL_APPS__";
437
479
  var KINTONE_SETUP_MAX_APPS = 20;
480
+ var SAMPLE_RECORD_LIMIT = 5;
438
481
  async function listApps(params) {
439
482
  const results = [];
440
483
  let offset = 0;
@@ -468,6 +511,25 @@ async function getFormFields(params, appId) {
468
511
  }
469
512
  return await res.json();
470
513
  }
514
+ async function getSampleRecords(params, appId) {
515
+ try {
516
+ const res = await apiFetch(
517
+ params,
518
+ `records.json?app=${encodeURIComponent(appId)}&query=${encodeURIComponent(`limit ${SAMPLE_RECORD_LIMIT}`)}&totalCount=true`
519
+ );
520
+ if (!res.ok) return { records: [], totalCount: null };
521
+ return await res.json();
522
+ } catch {
523
+ return { records: [], totalCount: null };
524
+ }
525
+ }
526
+ function formatRecordValue(val) {
527
+ if (val == null) return "";
528
+ if (typeof val === "string") return val.length > 50 ? `${val.slice(0, 50)}\u2026` : val;
529
+ if (Array.isArray(val)) return `[${val.length} items]`;
530
+ if (typeof val === "object") return JSON.stringify(val).slice(0, 50);
531
+ return String(val);
532
+ }
471
533
  var kintoneSetupFlow = {
472
534
  initialState: () => ({}),
473
535
  steps: [
@@ -513,20 +575,82 @@ var kintoneSetupFlow = {
513
575
  sections.push(app.description, "");
514
576
  }
515
577
  const fields = await getFormFields(rt.params, appId);
578
+ const fieldEntries = Object.entries(fields.properties ?? {});
516
579
  sections.push("| Field code | Label | Type | Required |");
517
580
  sections.push("|------------|-------|------|----------|");
518
- for (const [code, def] of Object.entries(fields.properties ?? {})) {
581
+ for (const [code, def] of fieldEntries) {
519
582
  const escapedLabel = (def.label ?? "").replace(/\|/g, "\\|");
520
583
  sections.push(
521
584
  `| ${code} | ${escapedLabel || "-"} | ${def.type} | ${def.required ? "yes" : "no"} |`
522
585
  );
523
586
  }
524
587
  sections.push("");
588
+ const sampleData = await getSampleRecords(rt.params, appId);
589
+ const totalCount = sampleData.totalCount ? Number(sampleData.totalCount) : null;
590
+ if (totalCount != null) {
591
+ sections.push(`#### Record count: ${totalCount.toLocaleString()}`, "");
592
+ }
593
+ const records = sampleData.records ?? [];
594
+ if (records.length > 0) {
595
+ const sampleFields = fieldEntries.slice(0, 8).map(([code]) => code);
596
+ if (sampleFields.length > 0) {
597
+ sections.push(`#### Sample records (${records.length})`, "");
598
+ sections.push(`| ${sampleFields.join(" | ")} |`);
599
+ sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
600
+ for (const record of records) {
601
+ const cells = sampleFields.map((code) => {
602
+ const cell = record[code];
603
+ return formatRecordValue(cell?.value).replace(/\|/g, "\\|");
604
+ });
605
+ sections.push(`| ${cells.join(" | ")} |`);
606
+ }
607
+ sections.push("");
608
+ }
609
+ }
525
610
  }
526
611
  return sections.join("\n");
527
612
  }
528
613
  };
529
614
 
615
+ // ../connectors/src/connectors/kintone/introspect.ts
616
+ var MAX_APPS = 100;
617
+ var CONCURRENCY = 5;
618
+ async function introspectKintone(ctx) {
619
+ const appsRes = await apiFetch(ctx.params, "apps.json");
620
+ if (!appsRes.ok) {
621
+ throw new Error(`kintone: apps.json failed (${appsRes.status})`);
622
+ }
623
+ const appsData = await appsRes.json();
624
+ const apps = (appsData.apps ?? []).slice(0, MAX_APPS);
625
+ const tables = (await mapWithConcurrency(apps, CONCURRENCY, async (app) => {
626
+ try {
627
+ const res = await apiFetch(
628
+ ctx.params,
629
+ `app/form/fields.json?app=${encodeURIComponent(app.appId)}`
630
+ );
631
+ if (!res.ok) return [];
632
+ const data = await res.json();
633
+ const columns = Object.values(
634
+ data.properties ?? {}
635
+ ).filter((f) => f.code || f.label).map((f) => ({
636
+ name: f.code || f.label || "",
637
+ dataType: f.type ?? "UNKNOWN",
638
+ nullable: f.required !== true
639
+ }));
640
+ const table = {
641
+ schema: String(app.appId),
642
+ name: app.name,
643
+ type: "table",
644
+ columns
645
+ };
646
+ return [table];
647
+ } catch {
648
+ return [];
649
+ }
650
+ })).flat();
651
+ return { tables };
652
+ }
653
+
530
654
  // ../connectors/src/connectors/kintone/tools/request.ts
531
655
  import { z } from "zod";
532
656
  var REQUEST_TIMEOUT_MS = 6e4;
@@ -614,7 +738,7 @@ var kintoneConnector = new ConnectorPlugin({
614
738
  systemPrompt: {
615
739
  en: `### Tools
616
740
 
617
- - \`kintone_request\`: The only way to call the kintone REST API. Use it to list apps, fetch field definitions, and read/write records. The base URL (e.g., \`https://example.cybozu.com\`) is automatically resolved. See the kintone REST API Reference below for endpoints and the kintone query syntax.
741
+ - \`connector_kintone_request\`: The only way to call the kintone REST API. Use it to list apps, fetch field definitions, and read/write records. The base URL (e.g., \`https://example.cybozu.com\`) is automatically resolved. See the kintone REST API Reference below for endpoints and the kintone query syntax.
618
742
 
619
743
  ### Business Logic
620
744
 
@@ -681,7 +805,7 @@ export default async function handler(c: Context) {
681
805
  - String: \`like "partial match"\``,
682
806
  ja: `### \u30C4\u30FC\u30EB
683
807
 
684
- - \`kintone_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\u3001\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\u30D9\u30FC\u30B9URL\uFF08\u4F8B: \`https://example.cybozu.com\`\uFF09\u306F\u81EA\u52D5\u7684\u306B\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304A\u3088\u3073kintone\u30AF\u30A8\u30EA\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300Ckintone REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
808
+ - \`connector_kintone_request\`: kintone REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A2\u30D7\u30EA\u4E00\u89A7\u306E\u53D6\u5F97\u3001\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\u30D9\u30FC\u30B9URL\uFF08\u4F8B: \`https://example.cybozu.com\`\uFF09\u306F\u81EA\u52D5\u7684\u306B\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u304A\u3088\u3073kintone\u30AF\u30A8\u30EA\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300Ckintone REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
685
809
 
686
810
  ### Business Logic
687
811
 
@@ -748,6 +872,38 @@ export default async function handler(c: Context) {
748
872
  - \u6587\u5B57\u5217: \`like "\u90E8\u5206\u4E00\u81F4"\``
749
873
  },
750
874
  tools,
875
+ // 決定論的な立ち上げ survey(ルールベース prewarm)。round1: `apps.json` でアプリ一覧 → round2: 先頭アプリの
876
+ // フィールド定義を read-only GET(kintone の「テーブル」= アプリ)。
877
+ surveyProbes: (_connectionId, prior) => {
878
+ if (prior.length === 0) {
879
+ return [
880
+ {
881
+ tool: "request",
882
+ input: {
883
+ method: "GET",
884
+ path: "apps.json",
885
+ toolUseIntent: "List kintone apps"
886
+ }
887
+ }
888
+ ];
889
+ }
890
+ if (prior.length === 1) {
891
+ const out = prior[0]?.output;
892
+ const apps = out?.success !== false ? out?.data?.apps ?? [] : [];
893
+ return apps.map((a) => a.appId).filter(
894
+ (id) => typeof id === "string" || typeof id === "number"
895
+ ).slice(0, 3).map((appId) => ({
896
+ tool: "request",
897
+ input: {
898
+ method: "GET",
899
+ path: `app/form/fields.json?app=${appId}`,
900
+ toolUseIntent: `Fields for app ${appId}`
901
+ }
902
+ }));
903
+ }
904
+ return [];
905
+ },
906
+ introspect: (ctx) => introspectKintone(ctx),
751
907
  setup: (params, ctx, config) => runSetupFlow(kintoneSetupFlow, params, ctx, config),
752
908
  async checkConnection(params, _config) {
753
909
  const baseUrl = params[parameters.baseUrl.slug];
@@ -1,6 +1,11 @@
1
1
  var __getOwnPropNames = Object.getOwnPropertyNames;
2
- var __esm = (fn, res) => function __init() {
3
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
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
@@ -229,6 +234,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
229
234
  * `runSetupFlow` from `setup-flow.ts`.
230
235
  */
231
236
  setup;
237
+ /**
238
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
239
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
240
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
241
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
242
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
243
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
244
+ */
245
+ introspect;
232
246
  /**
233
247
  * Opt-out of the default "verify before save" behavior on connection
234
248
  * creation. The backend invokes `checkConnection` synchronously while
@@ -243,6 +257,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
243
257
  * the default verify-on-create behavior without opt-in.
244
258
  */
245
259
  skipConnectionCheckOnCreate;
260
+ /**
261
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
262
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
263
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
264
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
265
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
266
+ */
267
+ surveyProbes;
246
268
  constructor(config) {
247
269
  this.slug = config.slug;
248
270
  this.authType = config.authType;
@@ -260,7 +282,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
260
282
  this.query = config.query;
261
283
  this.checkConnection = config.checkConnection;
262
284
  this.setup = config.setup;
285
+ this.introspect = config.introspect;
263
286
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
287
+ this.surveyProbes = config.surveyProbes;
264
288
  }
265
289
  get connectorKey() {
266
290
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -268,7 +292,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
268
292
  /**
269
293
  * Create tools for connections that belong to this connector.
270
294
  * Filters connections by connectorKey internally.
271
- * Returns tools keyed as `${connectorKey}_${toolName}`.
295
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
272
296
  */
273
297
  createTools(connections, config, opts) {
274
298
  const myConnections = connections.filter(
@@ -278,7 +302,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
278
302
  for (const t of Object.values(this.tools)) {
279
303
  const tool = t.createTool(myConnections, config);
280
304
  const originalToModelOutput = tool.toModelOutput;
281
- result[`${this.connectorKey}_${t.name}`] = {
305
+ result[`connector_${this.connectorKey}_${t.name}`] = {
282
306
  ...tool,
283
307
  toModelOutput: async (options) => {
284
308
  if (!originalToModelOutput) {
@@ -298,25 +322,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
298
322
  if (authType) return `${slug}-${authType}`;
299
323
  const LEGACY_NULL_AUTH_TYPE_MAP = {
300
324
  // user-password
301
- "postgresql": "user-password",
302
- "mysql": "user-password",
303
- "clickhouse": "user-password",
304
- "kintone": "user-password",
325
+ postgresql: "user-password",
326
+ mysql: "user-password",
327
+ clickhouse: "user-password",
328
+ kintone: "user-password",
305
329
  "squadbase-db": "user-password",
306
330
  // service-account
307
- "snowflake": "service-account",
308
- "bigquery": "service-account",
331
+ snowflake: "service-account",
332
+ bigquery: "service-account",
309
333
  "google-analytics": "service-account",
310
334
  "google-calendar": "service-account",
311
335
  "aws-athena": "service-account",
312
- "redshift": "service-account",
336
+ redshift: "service-account",
313
337
  // api-key
314
- "databricks": "api-key",
315
- "dbt": "api-key",
316
- "airtable": "api-key",
317
- "openai": "api-key",
318
- "gemini": "api-key",
319
- "anthropic": "api-key",
338
+ databricks: "api-key",
339
+ dbt: "api-key",
340
+ airtable: "api-key",
341
+ openai: "api-key",
342
+ gemini: "api-key",
343
+ anthropic: "api-key",
320
344
  "wix-store": "api-key"
321
345
  };
322
346
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -408,15 +432,15 @@ var AUTH_TYPES = {
408
432
  // ../connectors/src/connectors/linear/setup.ts
409
433
  var linearOnboarding = new ConnectorOnboarding({
410
434
  dataOverviewInstructions: {
411
- en: `1. Call linear_request with query \`{ teams { nodes { id name } } }\` to list all teams
412
- 2. Call linear_request with query \`{ workflowStates { nodes { id name type } } }\` to list workflow states
413
- 3. Call linear_request with query \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` to sample recent issues
414
- 4. Call linear_request with query \`{ projects(first: 5) { nodes { id name state } } }\` to list projects
435
+ en: `1. Call connector_linear_request with query \`{ teams { nodes { id name } } }\` to list all teams
436
+ 2. Call connector_linear_request with query \`{ workflowStates { nodes { id name type } } }\` to list workflow states
437
+ 3. Call connector_linear_request with query \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` to sample recent issues
438
+ 4. Call connector_linear_request with query \`{ projects(first: 5) { nodes { id name state } } }\` to list projects
415
439
  5. Explore other resources (cycles, labels, users) as needed`,
416
- ja: `1. linear_request \u3067\u30AF\u30A8\u30EA \`{ teams { nodes { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u4E00\u89A7\u3092\u53D6\u5F97
417
- 2. linear_request \u3067\u30AF\u30A8\u30EA \`{ workflowStates { nodes { id name type } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u4E00\u89A7\u3092\u53D6\u5F97
418
- 3. linear_request \u3067\u30AF\u30A8\u30EA \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306EIssue\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
419
- 4. linear_request \u3067\u30AF\u30A8\u30EA \`{ projects(first: 5) { nodes { id name state } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
440
+ ja: `1. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ teams { nodes { id name } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u4E00\u89A7\u3092\u53D6\u5F97
441
+ 2. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ workflowStates { nodes { id name type } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u4E00\u89A7\u3092\u53D6\u5F97
442
+ 3. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ issues(first: 5, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306EIssue\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
443
+ 4. connector_linear_request \u3067\u30AF\u30A8\u30EA \`{ projects(first: 5) { nodes { id name state } } }\` \u3092\u547C\u3073\u51FA\u3057\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
420
444
  5. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9\uFF08cycles\u3001labels\u3001users\uFF09\u3092\u63A2\u7D22`
421
445
  }
422
446
  });
@@ -473,6 +497,35 @@ async function getTeamDetail(params, teamId) {
473
497
  );
474
498
  return data.team ?? null;
475
499
  }
500
+ async function getIssueBreakdown(params, teamId) {
501
+ try {
502
+ const data = await gqlFetch(
503
+ params,
504
+ `query($id: String!) {
505
+ team(id: $id) {
506
+ issues(first: 250) { nodes { state { name type } } }
507
+ }
508
+ }`,
509
+ { id: teamId }
510
+ );
511
+ const nodes = data.team?.issues?.nodes ?? [];
512
+ const counts = /* @__PURE__ */ new Map();
513
+ for (const n of nodes) {
514
+ const key = `${n.state?.name ?? "Unknown"}|${n.state?.type ?? "unknown"}`;
515
+ const existing = counts.get(key);
516
+ if (existing) existing.count++;
517
+ else
518
+ counts.set(key, {
519
+ stateName: n.state?.name ?? "Unknown",
520
+ stateType: n.state?.type ?? "unknown",
521
+ count: 1
522
+ });
523
+ }
524
+ return { total: nodes.length, byState: Array.from(counts.values()) };
525
+ } catch {
526
+ return null;
527
+ }
528
+ }
476
529
  var linearSetupFlow = {
477
530
  initialState: () => ({}),
478
531
  steps: [
@@ -529,6 +582,19 @@ var linearSetupFlow = {
529
582
  sections.push(` - ${s.name} (${s.type})`);
530
583
  }
531
584
  sections.push("");
585
+ const breakdown = await getIssueBreakdown(rt.params, teamId);
586
+ if (breakdown && breakdown.byState.length > 0) {
587
+ sections.push(
588
+ `#### Issues (${breakdown.total}${breakdown.total === 250 ? "+" : ""})`,
589
+ ""
590
+ );
591
+ sections.push("| State | Type | Count |");
592
+ sections.push("|-------|------|-------|");
593
+ for (const b of breakdown.byState) {
594
+ sections.push(`| ${b.stateName} | ${b.stateType} | ${b.count} |`);
595
+ }
596
+ sections.push("");
597
+ }
532
598
  }
533
599
  return sections.join("\n");
534
600
  }
@@ -639,7 +705,7 @@ var linearConnector = new ConnectorPlugin({
639
705
  systemPrompt: {
640
706
  en: `### Tools
641
707
 
642
- - \`linear_request\`: The only way to call the Linear GraphQL API. Use it to query and mutate all Linear resources: issues, projects, teams, cycles, users, labels, workflow states, and comments. Authentication is configured automatically. Linear's API is GraphQL-only \u2014 send a query string and optional variables. Pagination uses Relay-style cursors with \`first\`/\`after\` and \`last\`/\`before\` arguments. Archived resources are hidden by default; pass \`includeArchived: true\` to include them.
708
+ - \`connector_linear_request\`: The only way to call the Linear GraphQL API. Use it to query and mutate all Linear resources: issues, projects, teams, cycles, users, labels, workflow states, and comments. Authentication is configured automatically. Linear's API is GraphQL-only \u2014 send a query string and optional variables. Pagination uses Relay-style cursors with \`first\`/\`after\` and \`last\`/\`before\` arguments. Archived resources are hidden by default; pass \`includeArchived: true\` to include them.
643
709
 
644
710
  ### Business Logic
645
711
 
@@ -700,7 +766,7 @@ export default async function handler(c: Context) {
700
766
  - \`mutation { commentCreate(input: { issueId: "...", body: "..." }) { success comment { id body } } }\` \u2014 add comment`,
701
767
  ja: `### \u30C4\u30FC\u30EB
702
768
 
703
- - \`linear_request\`: Linear GraphQL API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002Issue\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30C1\u30FC\u30E0\u3001\u30B5\u30A4\u30AF\u30EB\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30E9\u30D9\u30EB\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u3001\u30B3\u30E1\u30F3\u30C8\u306A\u3069\u3059\u3079\u3066\u306ELinear\u30EA\u30BD\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3068\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Linear\u306EAPI\u306FGraphQL\u306E\u307F\u3067\u3059\u3002\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u3068\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5909\u6570\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306FRelay\u5F62\u5F0F\u306E\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u3067\u3001\`first\`/\`after\`\u304A\u3088\u3073\`last\`/\`before\`\u5F15\u6570\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u30A2\u30FC\u30AB\u30A4\u30D6\u3055\u308C\u305F\u30EA\u30BD\u30FC\u30B9\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u975E\u8868\u793A\u3067\u3059\u3002\`includeArchived: true\`\u3092\u6E21\u3059\u3068\u542B\u3081\u3089\u308C\u307E\u3059\u3002
769
+ - \`connector_linear_request\`: Linear GraphQL API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002Issue\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30C1\u30FC\u30E0\u3001\u30B5\u30A4\u30AF\u30EB\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30E9\u30D9\u30EB\u3001\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u72B6\u614B\u3001\u30B3\u30E1\u30F3\u30C8\u306A\u3069\u3059\u3079\u3066\u306ELinear\u30EA\u30BD\u30FC\u30B9\u306E\u30AF\u30A8\u30EA\u3068\u30DF\u30E5\u30FC\u30C6\u30FC\u30B7\u30E7\u30F3\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Linear\u306EAPI\u306FGraphQL\u306E\u307F\u3067\u3059\u3002\u30AF\u30A8\u30EA\u6587\u5B57\u5217\u3068\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5909\u6570\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u306FRelay\u5F62\u5F0F\u306E\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u3067\u3001\`first\`/\`after\`\u304A\u3088\u3073\`last\`/\`before\`\u5F15\u6570\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u30A2\u30FC\u30AB\u30A4\u30D6\u3055\u308C\u305F\u30EA\u30BD\u30FC\u30B9\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u975E\u8868\u793A\u3067\u3059\u3002\`includeArchived: true\`\u3092\u6E21\u3059\u3068\u542B\u3081\u3089\u308C\u307E\u3059\u3002
704
770
 
705
771
  ### Business Logic
706
772