@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
@@ -75,6 +75,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
75
75
  * `runSetupFlow` from `setup-flow.ts`.
76
76
  */
77
77
  setup;
78
+ /**
79
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
80
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
81
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
82
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
83
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
84
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
85
+ */
86
+ introspect;
78
87
  /**
79
88
  * Opt-out of the default "verify before save" behavior on connection
80
89
  * creation. The backend invokes `checkConnection` synchronously while
@@ -89,6 +98,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
89
98
  * the default verify-on-create behavior without opt-in.
90
99
  */
91
100
  skipConnectionCheckOnCreate;
101
+ /**
102
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
103
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
104
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
105
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
106
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
107
+ */
108
+ surveyProbes;
92
109
  constructor(config) {
93
110
  this.slug = config.slug;
94
111
  this.authType = config.authType;
@@ -106,7 +123,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
106
123
  this.query = config.query;
107
124
  this.checkConnection = config.checkConnection;
108
125
  this.setup = config.setup;
126
+ this.introspect = config.introspect;
109
127
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
128
+ this.surveyProbes = config.surveyProbes;
110
129
  }
111
130
  get connectorKey() {
112
131
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -114,7 +133,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
114
133
  /**
115
134
  * Create tools for connections that belong to this connector.
116
135
  * Filters connections by connectorKey internally.
117
- * Returns tools keyed as `${connectorKey}_${toolName}`.
136
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
118
137
  */
119
138
  createTools(connections, config, opts) {
120
139
  const myConnections = connections.filter(
@@ -124,7 +143,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
124
143
  for (const t of Object.values(this.tools)) {
125
144
  const tool = t.createTool(myConnections, config);
126
145
  const originalToModelOutput = tool.toModelOutput;
127
- result[`${this.connectorKey}_${t.name}`] = {
146
+ result[`connector_${this.connectorKey}_${t.name}`] = {
128
147
  ...tool,
129
148
  toModelOutput: async (options) => {
130
149
  if (!originalToModelOutput) {
@@ -144,25 +163,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
144
163
  if (authType) return `${slug}-${authType}`;
145
164
  const LEGACY_NULL_AUTH_TYPE_MAP = {
146
165
  // user-password
147
- "postgresql": "user-password",
148
- "mysql": "user-password",
149
- "clickhouse": "user-password",
150
- "kintone": "user-password",
166
+ postgresql: "user-password",
167
+ mysql: "user-password",
168
+ clickhouse: "user-password",
169
+ kintone: "user-password",
151
170
  "squadbase-db": "user-password",
152
171
  // service-account
153
- "snowflake": "service-account",
154
- "bigquery": "service-account",
172
+ snowflake: "service-account",
173
+ bigquery: "service-account",
155
174
  "google-analytics": "service-account",
156
175
  "google-calendar": "service-account",
157
176
  "aws-athena": "service-account",
158
- "redshift": "service-account",
177
+ redshift: "service-account",
159
178
  // api-key
160
- "databricks": "api-key",
161
- "dbt": "api-key",
162
- "airtable": "api-key",
163
- "openai": "api-key",
164
- "gemini": "api-key",
165
- "anthropic": "api-key",
179
+ databricks: "api-key",
180
+ dbt: "api-key",
181
+ airtable: "api-key",
182
+ openai: "api-key",
183
+ gemini: "api-key",
184
+ anthropic: "api-key",
166
185
  "wix-store": "api-key"
167
186
  };
168
187
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -392,11 +411,11 @@ var hubspotOnboarding = new ConnectorOnboarding({
392
411
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
393
412
  },
394
413
  dataOverviewInstructions: {
395
- en: `1. Call hubspot-oauth_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
396
- 2. Call hubspot-oauth_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
414
+ en: `1. Call connector_hubspot-oauth_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
415
+ 2. Call connector_hubspot-oauth_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
397
416
  3. Explore other object types (companies, etc.) as needed to understand available data`,
398
- ja: `1. hubspot-oauth_request \u3067 GET /crm/v3/objects/contacts?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30B3\u30F3\u30BF\u30AF\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
399
- 2. hubspot-oauth_request \u3067 GET /crm/v3/objects/deals?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u53D6\u5F15\u306E\u69CB\u9020\u3092\u78BA\u8A8D
417
+ ja: `1. connector_hubspot-oauth_request \u3067 GET /crm/v3/objects/contacts?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30B3\u30F3\u30BF\u30AF\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
418
+ 2. connector_hubspot-oauth_request \u3067 GET /crm/v3/objects/deals?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u53D6\u5F15\u306E\u69CB\u9020\u3092\u78BA\u8A8D
400
419
  3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30BF\u30A4\u30D7\uFF08\u4F01\u696D\u306A\u3069\uFF09\u3092\u63A2\u7D22\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C7\u30FC\u30BF\u3092\u628A\u63E1`
401
420
  }
402
421
  });
@@ -434,6 +453,19 @@ async function listProperties(proxyFetch, objectType) {
434
453
  const data = await res.json();
435
454
  return data.results ?? [];
436
455
  }
456
+ async function fetchObjectCount(proxyFetch, objectType) {
457
+ try {
458
+ const res = await apiFetch(
459
+ proxyFetch,
460
+ `/crm/v3/objects/${objectType}?limit=1`
461
+ );
462
+ if (!res.ok) return null;
463
+ const data = await res.json();
464
+ return typeof data.total === "number" ? data.total : null;
465
+ } catch {
466
+ return null;
467
+ }
468
+ }
437
469
  var hubspotOauthSetupFlow = {
438
470
  initialState: () => ({}),
439
471
  steps: [
@@ -464,8 +496,27 @@ var hubspotOauthSetupFlow = {
464
496
  limit: HUBSPOT_SETUP_MAX_OBJECT_TYPES
465
497
  });
466
498
  const sections = ["## HubSpot", ""];
499
+ const countByType = /* @__PURE__ */ new Map();
500
+ for (const objectType of targetObjectTypes) {
501
+ countByType.set(
502
+ objectType,
503
+ await fetchObjectCount(rt.config.proxyFetch, objectType)
504
+ );
505
+ }
506
+ sections.push("### Record counts", "");
507
+ sections.push("| Object type | Record count |");
508
+ sections.push("|-------------|-------------|");
509
+ for (const objectType of targetObjectTypes) {
510
+ const count = countByType.get(objectType);
511
+ sections.push(
512
+ `| ${objectType} | ${count == null ? "-" : count.toLocaleString()} |`
513
+ );
514
+ }
515
+ sections.push("");
467
516
  for (const objectType of targetObjectTypes) {
468
- sections.push(`### Object: ${objectType}`, "");
517
+ const count = countByType.get(objectType);
518
+ const countLabel = count == null ? "" : ` (${count.toLocaleString()} records)`;
519
+ sections.push(`### Object: ${objectType}${countLabel}`, "");
469
520
  const props = await listProperties(rt.config.proxyFetch, objectType);
470
521
  const limited = props.slice(0, HUBSPOT_SETUP_MAX_PROPERTIES);
471
522
  sections.push("| Property | Type | Label |");
@@ -515,7 +566,7 @@ var hubspotOauthConnector = new ConnectorPlugin({
515
566
  systemPrompt: {
516
567
  en: `### Tools
517
568
 
518
- - \`hubspot-oauth_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, and other CRM objects. Authentication is configured automatically via OAuth. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response.
569
+ - \`connector_hubspot-oauth_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, and other CRM objects. Authentication is configured automatically via OAuth. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response.
519
570
 
520
571
  ### HubSpot API Reference
521
572
 
@@ -560,7 +611,7 @@ const data = await res.json();
560
611
  \`\`\``,
561
612
  ja: `### \u30C4\u30FC\u30EB
562
613
 
563
- - \`hubspot-oauth_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
614
+ - \`connector_hubspot-oauth_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
564
615
 
565
616
  ### HubSpot API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
566
617
 
@@ -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
@@ -218,6 +223,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
218
223
  * `runSetupFlow` from `setup-flow.ts`.
219
224
  */
220
225
  setup;
226
+ /**
227
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
228
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
229
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
230
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
231
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
232
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
233
+ */
234
+ introspect;
221
235
  /**
222
236
  * Opt-out of the default "verify before save" behavior on connection
223
237
  * creation. The backend invokes `checkConnection` synchronously while
@@ -232,6 +246,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
232
246
  * the default verify-on-create behavior without opt-in.
233
247
  */
234
248
  skipConnectionCheckOnCreate;
249
+ /**
250
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
251
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
252
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
253
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
254
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
255
+ */
256
+ surveyProbes;
235
257
  constructor(config) {
236
258
  this.slug = config.slug;
237
259
  this.authType = config.authType;
@@ -249,7 +271,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
249
271
  this.query = config.query;
250
272
  this.checkConnection = config.checkConnection;
251
273
  this.setup = config.setup;
274
+ this.introspect = config.introspect;
252
275
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
276
+ this.surveyProbes = config.surveyProbes;
253
277
  }
254
278
  get connectorKey() {
255
279
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -257,7 +281,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
257
281
  /**
258
282
  * Create tools for connections that belong to this connector.
259
283
  * Filters connections by connectorKey internally.
260
- * Returns tools keyed as `${connectorKey}_${toolName}`.
284
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
261
285
  */
262
286
  createTools(connections, config, opts) {
263
287
  const myConnections = connections.filter(
@@ -267,7 +291,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
267
291
  for (const t of Object.values(this.tools)) {
268
292
  const tool = t.createTool(myConnections, config);
269
293
  const originalToModelOutput = tool.toModelOutput;
270
- result[`${this.connectorKey}_${t.name}`] = {
294
+ result[`connector_${this.connectorKey}_${t.name}`] = {
271
295
  ...tool,
272
296
  toModelOutput: async (options) => {
273
297
  if (!originalToModelOutput) {
@@ -287,25 +311,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
287
311
  if (authType) return `${slug}-${authType}`;
288
312
  const LEGACY_NULL_AUTH_TYPE_MAP = {
289
313
  // user-password
290
- "postgresql": "user-password",
291
- "mysql": "user-password",
292
- "clickhouse": "user-password",
293
- "kintone": "user-password",
314
+ postgresql: "user-password",
315
+ mysql: "user-password",
316
+ clickhouse: "user-password",
317
+ kintone: "user-password",
294
318
  "squadbase-db": "user-password",
295
319
  // service-account
296
- "snowflake": "service-account",
297
- "bigquery": "service-account",
320
+ snowflake: "service-account",
321
+ bigquery: "service-account",
298
322
  "google-analytics": "service-account",
299
323
  "google-calendar": "service-account",
300
324
  "aws-athena": "service-account",
301
- "redshift": "service-account",
325
+ redshift: "service-account",
302
326
  // api-key
303
- "databricks": "api-key",
304
- "dbt": "api-key",
305
- "airtable": "api-key",
306
- "openai": "api-key",
307
- "gemini": "api-key",
308
- "anthropic": "api-key",
327
+ databricks: "api-key",
328
+ dbt: "api-key",
329
+ airtable: "api-key",
330
+ openai: "api-key",
331
+ gemini: "api-key",
332
+ anthropic: "api-key",
309
333
  "wix-store": "api-key"
310
334
  };
311
335
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -397,11 +421,11 @@ var AUTH_TYPES = {
397
421
  // ../connectors/src/connectors/hubspot/setup.ts
398
422
  var hubspotOnboarding = new ConnectorOnboarding({
399
423
  dataOverviewInstructions: {
400
- en: `1. Call hubspot_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
401
- 2. Call hubspot_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
424
+ en: `1. Call connector_hubspot_request with GET /crm/v3/objects/contacts?limit=5 to explore contacts structure
425
+ 2. Call connector_hubspot_request with GET /crm/v3/objects/deals?limit=5 to explore deals structure
402
426
  3. Explore other object types (companies, tickets, etc.) as needed to understand available data`,
403
- ja: `1. hubspot_request \u3067 GET /crm/v3/objects/contacts?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30B3\u30F3\u30BF\u30AF\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
404
- 2. hubspot_request \u3067 GET /crm/v3/objects/deals?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u53D6\u5F15\u306E\u69CB\u9020\u3092\u78BA\u8A8D
427
+ ja: `1. connector_hubspot_request \u3067 GET /crm/v3/objects/contacts?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u30B3\u30F3\u30BF\u30AF\u30C8\u306E\u69CB\u9020\u3092\u78BA\u8A8D
428
+ 2. connector_hubspot_request \u3067 GET /crm/v3/objects/deals?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u53D6\u5F15\u306E\u69CB\u9020\u3092\u78BA\u8A8D
405
429
  3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u30BF\u30A4\u30D7\uFF08\u4F01\u696D\u3001\u30C1\u30B1\u30C3\u30C8\u306A\u3069\uFF09\u3092\u63A2\u7D22\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30C7\u30FC\u30BF\u3092\u628A\u63E1`
406
430
  }
407
431
  });
@@ -435,6 +459,20 @@ var HUBSPOT_OBJECT_TYPES = [
435
459
  { value: "meetings", label: "Meetings" },
436
460
  { value: "tasks", label: "Tasks" }
437
461
  ];
462
+ async function countObjects(params, objectType) {
463
+ try {
464
+ const res = await apiFetch(params, `/crm/v3/objects/${objectType}/search`, {
465
+ method: "POST",
466
+ headers: { "Content-Type": "application/json" },
467
+ body: JSON.stringify({ limit: 1 })
468
+ });
469
+ if (!res.ok) return null;
470
+ const data = await res.json();
471
+ return typeof data.total === "number" ? data.total : null;
472
+ } catch {
473
+ return null;
474
+ }
475
+ }
438
476
  async function listProperties(params, objectType) {
439
477
  const res = await apiFetch(params, `/crm/v3/properties/${objectType}`);
440
478
  if (!res.ok) {
@@ -479,7 +517,9 @@ var hubspotSetupFlow = {
479
517
  });
480
518
  const sections = ["## HubSpot", ""];
481
519
  for (const objectType of targetObjectTypes) {
482
- sections.push(`### Object: ${objectType}`, "");
520
+ const count = await countObjects(rt.params, objectType);
521
+ const heading = count != null ? `### Object: ${objectType} (${count.toLocaleString()} records)` : `### Object: ${objectType}`;
522
+ sections.push(heading, "");
483
523
  const props = await listProperties(rt.params, objectType);
484
524
  const limited = props.slice(0, HUBSPOT_SETUP_MAX_PROPERTIES);
485
525
  sections.push("| Property | Type | Label |");
@@ -595,7 +635,7 @@ var hubspotConnector = new ConnectorPlugin({
595
635
  systemPrompt: {
596
636
  en: `### Tools
597
637
 
598
- - \`hubspot_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, tickets, and other CRM objects. Authentication (Bearer token) is configured automatically. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response. Use the search endpoint for complex queries with filters.
638
+ - \`connector_hubspot_request\`: The only way to call the HubSpot API. Use it to query contacts, deals, companies, tickets, and other CRM objects. Authentication (Bearer token) is configured automatically. HubSpot uses cursor-based pagination with the \`after\` parameter from \`paging.next.after\` in the response. Use the search endpoint for complex queries with filters.
599
639
 
600
640
  ### Business Logic
601
641
 
@@ -661,7 +701,7 @@ export default async function handler(c: Context) {
661
701
  - \`after\` \u2014 Pagination offset`,
662
702
  ja: `### \u30C4\u30FC\u30EB
663
703
 
664
- - \`hubspot_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u30C1\u30B1\u30C3\u30C8\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Bearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u8907\u96D1\u306A\u30AF\u30A8\u30EA\u306B\u306F\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306Esearch\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
704
+ - \`connector_hubspot_request\`: HubSpot API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30B3\u30F3\u30BF\u30AF\u30C8\u3001\u53D6\u5F15\u3001\u4F1A\u793E\u3001\u30C1\u30B1\u30C3\u30C8\u3001\u305D\u306E\u4ED6\u306ECRM\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Bearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002HubSpot\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E \`paging.next.after\` \u304B\u3089\u306E \`after\` \u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002\u8907\u96D1\u306A\u30AF\u30A8\u30EA\u306B\u306F\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306Esearch\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
665
705
 
666
706
  ### Business Logic
667
707
 
@@ -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
@@ -277,6 +282,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
277
282
  * `runSetupFlow` from `setup-flow.ts`.
278
283
  */
279
284
  setup;
285
+ /**
286
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
287
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
288
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
289
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
290
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
291
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
292
+ */
293
+ introspect;
280
294
  /**
281
295
  * Opt-out of the default "verify before save" behavior on connection
282
296
  * creation. The backend invokes `checkConnection` synchronously while
@@ -291,6 +305,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
291
305
  * the default verify-on-create behavior without opt-in.
292
306
  */
293
307
  skipConnectionCheckOnCreate;
308
+ /**
309
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
310
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
311
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
312
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
313
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
314
+ */
315
+ surveyProbes;
294
316
  constructor(config) {
295
317
  this.slug = config.slug;
296
318
  this.authType = config.authType;
@@ -308,7 +330,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
308
330
  this.query = config.query;
309
331
  this.checkConnection = config.checkConnection;
310
332
  this.setup = config.setup;
333
+ this.introspect = config.introspect;
311
334
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
335
+ this.surveyProbes = config.surveyProbes;
312
336
  }
313
337
  get connectorKey() {
314
338
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -316,7 +340,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
316
340
  /**
317
341
  * Create tools for connections that belong to this connector.
318
342
  * Filters connections by connectorKey internally.
319
- * Returns tools keyed as `${connectorKey}_${toolName}`.
343
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
320
344
  */
321
345
  createTools(connections, config, opts) {
322
346
  const myConnections = connections.filter(
@@ -326,7 +350,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
326
350
  for (const t of Object.values(this.tools)) {
327
351
  const tool = t.createTool(myConnections, config);
328
352
  const originalToModelOutput = tool.toModelOutput;
329
- result[`${this.connectorKey}_${t.name}`] = {
353
+ result[`connector_${this.connectorKey}_${t.name}`] = {
330
354
  ...tool,
331
355
  toModelOutput: async (options) => {
332
356
  if (!originalToModelOutput) {
@@ -346,25 +370,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
346
370
  if (authType) return `${slug}-${authType}`;
347
371
  const LEGACY_NULL_AUTH_TYPE_MAP = {
348
372
  // user-password
349
- "postgresql": "user-password",
350
- "mysql": "user-password",
351
- "clickhouse": "user-password",
352
- "kintone": "user-password",
373
+ postgresql: "user-password",
374
+ mysql: "user-password",
375
+ clickhouse: "user-password",
376
+ kintone: "user-password",
353
377
  "squadbase-db": "user-password",
354
378
  // service-account
355
- "snowflake": "service-account",
356
- "bigquery": "service-account",
379
+ snowflake: "service-account",
380
+ bigquery: "service-account",
357
381
  "google-analytics": "service-account",
358
382
  "google-calendar": "service-account",
359
383
  "aws-athena": "service-account",
360
- "redshift": "service-account",
384
+ redshift: "service-account",
361
385
  // api-key
362
- "databricks": "api-key",
363
- "dbt": "api-key",
364
- "airtable": "api-key",
365
- "openai": "api-key",
366
- "gemini": "api-key",
367
- "anthropic": "api-key",
386
+ databricks: "api-key",
387
+ dbt: "api-key",
388
+ airtable: "api-key",
389
+ openai: "api-key",
390
+ gemini: "api-key",
391
+ anthropic: "api-key",
368
392
  "wix-store": "api-key"
369
393
  };
370
394
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -486,7 +510,7 @@ var influxdbOnboarding = new ConnectorOnboarding({
486
510
  dataOverviewInstructions: {
487
511
  en: `The instance may be either InfluxDB 3 (supports SQL) or InfluxDB 2 (Flux only; includes InfluxDB Cloud on '*.cloud2.influxdata.com'). Detect the variant first, then pick the matching endpoints.
488
512
 
489
- 1. Probe for InfluxDB 3: call influxdb_request with POST /api/v3/query_sql, body { "db": "<database>", "q": "SELECT 1" }
513
+ 1. Probe for InfluxDB 3: call connector_influxdb_request with POST /api/v3/query_sql, body { "db": "<database>", "q": "SELECT 1" }
490
514
  - 200 with JSON rows \u2192 InfluxDB 3. Continue with SQL.
491
515
  - 405 Method Not Allowed, or an HTML body like "<html>...405 Not Allowed..." \u2192 InfluxDB 2. Fall back to Flux (step 3).
492
516
  2. InfluxDB 3 data overview:
@@ -498,7 +522,7 @@ var influxdbOnboarding = new ConnectorOnboarding({
498
522
  - If the Organization parameter was not provided but v3 probing failed, ask the user to set it using updateConnectionParameters before continuing.`,
499
523
  ja: `\u63A5\u7D9A\u5148\u306F InfluxDB 3\uFF08SQL \u5BFE\u5FDC\uFF09\u3068 InfluxDB 2\uFF08Flux \u306E\u307F\u3002\`*.cloud2.influxdata.com\` \u306E InfluxDB Cloud \u3092\u542B\u3080\uFF09\u306E\u3069\u3061\u3089\u306E\u53EF\u80FD\u6027\u3082\u3042\u308A\u307E\u3059\u3002\u307E\u305A\u30D0\u30EA\u30A2\u30F3\u30C8\u3092\u5224\u5225\u3057\u3001\u305D\u308C\u306B\u5408\u3046\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002
500
524
 
501
- 1. InfluxDB 3 \u306E\u5224\u5225: influxdb_request \u3067 POST /api/v3/query_sql\u3001body { "db": "<database>", "q": "SELECT 1" } \u3092\u5B9F\u884C
525
+ 1. InfluxDB 3 \u306E\u5224\u5225: connector_influxdb_request \u3067 POST /api/v3/query_sql\u3001body { "db": "<database>", "q": "SELECT 1" } \u3092\u5B9F\u884C
502
526
  - 200 + JSON \u884C\u304C\u8FD4\u308B \u2192 InfluxDB 3\u3002\u305D\u306E\u307E\u307E SQL \u3067\u7D9A\u884C\u3002
503
527
  - 405 Method Not Allowed\u3001\u307E\u305F\u306F "<html>...405 Not Allowed..." \u306E\u3088\u3046\u306A HTML \u672C\u6587\u304C\u8FD4\u308B \u2192 InfluxDB 2\u3002Flux \u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\uFF08\u624B\u9806 3\uFF09\u3002
504
528
  2. InfluxDB 3 \u306E\u5834\u5408\u306E\u30C7\u30FC\u30BF\u6982\u8981:
@@ -875,13 +899,13 @@ var influxdbConnector = new ConnectorPlugin({
875
899
 
876
900
  The configured instance may be **InfluxDB 3** (supports SQL via \`/api/v3/query_sql\`) or **InfluxDB 2** (Flux only; includes InfluxDB Cloud on \`*.cloud2.influxdata.com\`). Always probe first, then use the matching endpoints:
877
901
 
878
- 1. Call \`influxdb_request\` POST \`/api/v3/query_sql\` with body \`{ "db": "<database>", "q": "SELECT 1" }\`
902
+ 1. Call \`connector_influxdb_request\` POST \`/api/v3/query_sql\` with body \`{ "db": "<database>", "q": "SELECT 1" }\`
879
903
  2. 200 + JSON rows \u2192 InfluxDB 3. Use SQL endpoints.
880
904
  3. 405 Method Not Allowed or HTML body (e.g. \`<html>...405 Not Allowed...</html>\`) \u2192 InfluxDB 2. Use Flux via \`/api/v2/query?org={org}\`. Require the \`org\` parameter; if missing, ask the user via \`updateConnectionParameters\`.
881
905
 
882
906
  ### Tools
883
907
 
884
- - \`influxdb_request\`: The only way to call the InfluxDB HTTP API. Use it to run SQL / InfluxQL / Flux queries, write line protocol, and inspect buckets / databases. Authentication (\`Authorization: Token {token}\`) and the instance URL are configured automatically. On InfluxDB 3 prefer SQL (\`POST /api/v3/query_sql\`) \u2014 it returns JSON rows that are directly usable. On InfluxDB 2 use Flux (\`POST /api/v2/query?org={org}\`) \u2014 the response is annotated CSV. Writes use \`POST /api/v3/write_lp?db={db}\` (v3) or \`POST /api/v2/write?org={org}&bucket={bucket}\` (v2) with a line-protocol body and \`contentType\` set to \`text/plain; charset=utf-8\`.
908
+ - \`connector_influxdb_request\`: The only way to call the InfluxDB HTTP API. Use it to run SQL / InfluxQL / Flux queries, write line protocol, and inspect buckets / databases. Authentication (\`Authorization: Token {token}\`) and the instance URL are configured automatically. On InfluxDB 3 prefer SQL (\`POST /api/v3/query_sql\`) \u2014 it returns JSON rows that are directly usable. On InfluxDB 2 use Flux (\`POST /api/v2/query?org={org}\`) \u2014 the response is annotated CSV. Writes use \`POST /api/v3/write_lp?db={db}\` (v3) or \`POST /api/v2/write?org={org}&bucket={bucket}\` (v2) with a line-protocol body and \`contentType\` set to \`text/plain; charset=utf-8\`.
885
909
 
886
910
  ### Business Logic
887
911
 
@@ -946,13 +970,13 @@ export default async function handler(c: Context) {
946
970
 
947
971
  \u63A5\u7D9A\u5148\u306F **InfluxDB 3**\uFF08\`/api/v3/query_sql\` \u306E SQL \u5BFE\u5FDC\uFF09\u3068 **InfluxDB 2**\uFF08Flux \u306E\u307F\u3002\`*.cloud2.influxdata.com\` \u306E InfluxDB Cloud \u3092\u542B\u3080\uFF09\u306E\u3069\u3061\u3089\u306E\u53EF\u80FD\u6027\u3082\u3042\u308A\u307E\u3059\u3002\u5FC5\u305A\u6700\u521D\u306B\u30D7\u30ED\u30FC\u30D6\u3057\u3066\u304B\u3089\u3001\u5BFE\u5FDC\u3059\u308B\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044:
948
972
 
949
- 1. \`influxdb_request\` \u3067 POST \`/api/v3/query_sql\`\u3001body \`{ "db": "<database>", "q": "SELECT 1" }\` \u3092\u547C\u3073\u51FA\u3059
973
+ 1. \`connector_influxdb_request\` \u3067 POST \`/api/v3/query_sql\`\u3001body \`{ "db": "<database>", "q": "SELECT 1" }\` \u3092\u547C\u3073\u51FA\u3059
950
974
  2. 200 + JSON \u884C \u2192 InfluxDB 3\u3002SQL \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3092\u4F7F\u7528\u3002
951
975
  3. 405 Method Not Allowed\u3001\u307E\u305F\u306F HTML \u672C\u6587\uFF08\u4F8B: \`<html>...405 Not Allowed...</html>\`\uFF09\u2192 InfluxDB 2\u3002\`/api/v2/query?org={org}\` \u304B\u3089 Flux \u3092\u4F7F\u7528\u3002\`org\` \u30D1\u30E9\u30E1\u30FC\u30BF\u5FC5\u9808\u3002\u672A\u8A2D\u5B9A\u306A\u3089 \`updateConnectionParameters\` \u3067\u30E6\u30FC\u30B6\u30FC\u306B\u8A2D\u5B9A\u3092\u4F9D\u983C\u3059\u308B\u3002
952
976
 
953
977
  ### \u30C4\u30FC\u30EB
954
978
 
955
- - \`influxdb_request\`: InfluxDB HTTP API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SQL / InfluxQL / Flux \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001line protocol \u66F8\u304D\u8FBC\u307F\u3001bucket / database \u306E\u78BA\u8A8D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08\`Authorization: Token {token}\`\uFF09\u3068 instance URL \u306F\u81EA\u52D5\u3067\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002InfluxDB 3 \u3067\u306F SQL (\`POST /api/v3/query_sql\`) \u304C JSON \u884C\u3092\u8FD4\u3059\u305F\u3081\u6700\u3082\u6271\u3044\u3084\u3059\u3044\u3067\u3059\u3002InfluxDB 2 \u3067\u306F Flux (\`POST /api/v2/query?org={org}\`) \u3092\u4F7F\u7528\u3057\u3001\u30EC\u30B9\u30DD\u30F3\u30B9\u306F\u6CE8\u91C8\u4ED8\u304D CSV \u3067\u3059\u3002\u66F8\u304D\u8FBC\u307F\u306F \`POST /api/v3/write_lp?db={db}\` (v3) \u307E\u305F\u306F \`POST /api/v2/write?org={org}&bucket={bucket}\` (v2) \u306B line protocol \u3092\u9001\u308A\u307E\u3059\uFF08\`contentType\` \u306F \`text/plain; charset=utf-8\`\uFF09\u3002
979
+ - \`connector_influxdb_request\`: InfluxDB HTTP API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SQL / InfluxQL / Flux \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001line protocol \u66F8\u304D\u8FBC\u307F\u3001bucket / database \u306E\u78BA\u8A8D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08\`Authorization: Token {token}\`\uFF09\u3068 instance URL \u306F\u81EA\u52D5\u3067\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002InfluxDB 3 \u3067\u306F SQL (\`POST /api/v3/query_sql\`) \u304C JSON \u884C\u3092\u8FD4\u3059\u305F\u3081\u6700\u3082\u6271\u3044\u3084\u3059\u3044\u3067\u3059\u3002InfluxDB 2 \u3067\u306F Flux (\`POST /api/v2/query?org={org}\`) \u3092\u4F7F\u7528\u3057\u3001\u30EC\u30B9\u30DD\u30F3\u30B9\u306F\u6CE8\u91C8\u4ED8\u304D CSV \u3067\u3059\u3002\u66F8\u304D\u8FBC\u307F\u306F \`POST /api/v3/write_lp?db={db}\` (v3) \u307E\u305F\u306F \`POST /api/v2/write?org={org}&bucket={bucket}\` (v2) \u306B line protocol \u3092\u9001\u308A\u307E\u3059\uFF08\`contentType\` \u306F \`text/plain; charset=utf-8\`\uFF09\u3002
956
980
 
957
981
  ### Business Logic
958
982