@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
@@ -193,6 +193,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
193
193
  * `runSetupFlow` from `setup-flow.ts`.
194
194
  */
195
195
  setup;
196
+ /**
197
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
198
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
199
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
200
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
201
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
202
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
203
+ */
204
+ introspect;
196
205
  /**
197
206
  * Opt-out of the default "verify before save" behavior on connection
198
207
  * creation. The backend invokes `checkConnection` synchronously while
@@ -207,6 +216,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
207
216
  * the default verify-on-create behavior without opt-in.
208
217
  */
209
218
  skipConnectionCheckOnCreate;
219
+ /**
220
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
221
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
222
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
223
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
224
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
225
+ */
226
+ surveyProbes;
210
227
  constructor(config) {
211
228
  this.slug = config.slug;
212
229
  this.authType = config.authType;
@@ -224,7 +241,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
224
241
  this.query = config.query;
225
242
  this.checkConnection = config.checkConnection;
226
243
  this.setup = config.setup;
244
+ this.introspect = config.introspect;
227
245
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
246
+ this.surveyProbes = config.surveyProbes;
228
247
  }
229
248
  get connectorKey() {
230
249
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -232,7 +251,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
232
251
  /**
233
252
  * Create tools for connections that belong to this connector.
234
253
  * Filters connections by connectorKey internally.
235
- * Returns tools keyed as `${connectorKey}_${toolName}`.
254
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
236
255
  */
237
256
  createTools(connections, config, opts) {
238
257
  const myConnections = connections.filter(
@@ -242,7 +261,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
242
261
  for (const t of Object.values(this.tools)) {
243
262
  const tool = t.createTool(myConnections, config);
244
263
  const originalToModelOutput = tool.toModelOutput;
245
- result[`${this.connectorKey}_${t.name}`] = {
264
+ result[`connector_${this.connectorKey}_${t.name}`] = {
246
265
  ...tool,
247
266
  toModelOutput: async (options) => {
248
267
  if (!originalToModelOutput) {
@@ -262,25 +281,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
262
281
  if (authType) return `${slug}-${authType}`;
263
282
  const LEGACY_NULL_AUTH_TYPE_MAP = {
264
283
  // user-password
265
- "postgresql": "user-password",
266
- "mysql": "user-password",
267
- "clickhouse": "user-password",
268
- "kintone": "user-password",
284
+ postgresql: "user-password",
285
+ mysql: "user-password",
286
+ clickhouse: "user-password",
287
+ kintone: "user-password",
269
288
  "squadbase-db": "user-password",
270
289
  // service-account
271
- "snowflake": "service-account",
272
- "bigquery": "service-account",
290
+ snowflake: "service-account",
291
+ bigquery: "service-account",
273
292
  "google-analytics": "service-account",
274
293
  "google-calendar": "service-account",
275
294
  "aws-athena": "service-account",
276
- "redshift": "service-account",
295
+ redshift: "service-account",
277
296
  // api-key
278
- "databricks": "api-key",
279
- "dbt": "api-key",
280
- "airtable": "api-key",
281
- "openai": "api-key",
282
- "gemini": "api-key",
283
- "anthropic": "api-key",
297
+ databricks: "api-key",
298
+ dbt: "api-key",
299
+ airtable: "api-key",
300
+ openai: "api-key",
301
+ gemini: "api-key",
302
+ anthropic: "api-key",
284
303
  "wix-store": "api-key"
285
304
  };
286
305
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -533,27 +552,27 @@ var outlookOnboarding = new ConnectorOnboarding({
533
552
  },
534
553
  dataOverviewInstructions: {
535
554
  en: `Mail
536
- 1. Call outlook-oauth_request with GET /me/mailFolders to list mail folders
537
- 2. Call outlook-oauth_request with GET /me/messages?$top=5&$select=id,subject,from,receivedDateTime,conversationId to sample recent messages
538
- 3. Call outlook-oauth_request with GET /me/messages/{id} for an interesting message to inspect the full payload
539
- 4. Call outlook-oauth_request with GET /me/mailFolders/{folderId}/messages?$top=5 to drill into a specific folder
540
- 5. For threading, call outlook-oauth_request with GET /me/messages?$filter=conversationId%20eq%20'<id>'&$orderby=receivedDateTime%20asc to pull every message in a conversation
555
+ 1. Call connector_outlook-oauth_request with GET /me/mailFolders to list mail folders
556
+ 2. Call connector_outlook-oauth_request with GET /me/messages?$top=5&$select=id,subject,from,receivedDateTime,conversationId to sample recent messages
557
+ 3. Call connector_outlook-oauth_request with GET /me/messages/{id} for an interesting message to inspect the full payload
558
+ 4. Call connector_outlook-oauth_request with GET /me/mailFolders/{folderId}/messages?$top=5 to drill into a specific folder
559
+ 5. For threading, call connector_outlook-oauth_request with GET /me/messages?$filter=conversationId%20eq%20'<id>'&$orderby=receivedDateTime%20asc to pull every message in a conversation
541
560
 
542
561
  Calendar
543
- 6. Call outlook-oauth_request with GET /me/calendars to list calendars (default + shared)
544
- 7. Call outlook-oauth_request with GET /me/calendarView?startDateTime=<startISO>&endDateTime=<endISO>&$top=5&$select=id,subject,start,end,attendees to sample upcoming occurrences (expands recurring events)
545
- 8. Call outlook-oauth_request with GET /me/events/{eventId} for an interesting event to inspect attendees, body, and location`,
562
+ 6. Call connector_outlook-oauth_request with GET /me/calendars to list calendars (default + shared)
563
+ 7. Call connector_outlook-oauth_request with GET /me/calendarView?startDateTime=<startISO>&endDateTime=<endISO>&$top=5&$select=id,subject,start,end,attendees to sample upcoming occurrences (expands recurring events)
564
+ 8. Call connector_outlook-oauth_request with GET /me/events/{eventId} for an interesting event to inspect attendees, body, and location`,
546
565
  ja: `\u30E1\u30FC\u30EB
547
- 1. outlook-oauth_request \u3067 GET /me/mailFolders \u3092\u547C\u3073\u51FA\u3057\u3001\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0\u4E00\u89A7\u3092\u53D6\u5F97
548
- 2. outlook-oauth_request \u3067 GET /me/messages?$top=5&$select=id,subject,from,receivedDateTime,conversationId \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
549
- 3. \u8208\u5473\u306E\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 outlook-oauth_request \u3067 GET /me/messages/{id} \u3092\u547C\u3073\u51FA\u3057\u3001\u30DA\u30A4\u30ED\u30FC\u30C9\u5168\u4F53\u3092\u78BA\u8A8D
550
- 4. outlook-oauth_request \u3067 GET /me/mailFolders/{folderId}/messages?$top=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u7279\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4E2D\u8EAB\u3092\u78BA\u8A8D
551
- 5. \u30B9\u30EC\u30C3\u30C9\u3092\u8FFD\u3046\u5834\u5408\u306F outlook-oauth_request \u3067 GET /me/messages?$filter=conversationId%20eq%20'<id>'&$orderby=receivedDateTime%20asc \u3092\u547C\u3073\u51FA\u3057\u3001\u4F1A\u8A71\u306B\u542B\u307E\u308C\u308B\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
566
+ 1. connector_outlook-oauth_request \u3067 GET /me/mailFolders \u3092\u547C\u3073\u51FA\u3057\u3001\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0\u4E00\u89A7\u3092\u53D6\u5F97
567
+ 2. connector_outlook-oauth_request \u3067 GET /me/messages?$top=5&$select=id,subject,from,receivedDateTime,conversationId \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u65B0\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
568
+ 3. \u8208\u5473\u306E\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3064\u3044\u3066 connector_outlook-oauth_request \u3067 GET /me/messages/{id} \u3092\u547C\u3073\u51FA\u3057\u3001\u30DA\u30A4\u30ED\u30FC\u30C9\u5168\u4F53\u3092\u78BA\u8A8D
569
+ 4. connector_outlook-oauth_request \u3067 GET /me/mailFolders/{folderId}/messages?$top=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u7279\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4E2D\u8EAB\u3092\u78BA\u8A8D
570
+ 5. \u30B9\u30EC\u30C3\u30C9\u3092\u8FFD\u3046\u5834\u5408\u306F connector_outlook-oauth_request \u3067 GET /me/messages?$filter=conversationId%20eq%20'<id>'&$orderby=receivedDateTime%20asc \u3092\u547C\u3073\u51FA\u3057\u3001\u4F1A\u8A71\u306B\u542B\u307E\u308C\u308B\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97
552
571
 
553
572
  \u30AB\u30EC\u30F3\u30C0\u30FC
554
- 6. outlook-oauth_request \u3067 GET /me/calendars \u3092\u547C\u3073\u51FA\u3057\u3001\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7 (\u30C7\u30D5\u30A9\u30EB\u30C8 + \u5171\u6709) \u3092\u53D6\u5F97
555
- 7. outlook-oauth_request \u3067 GET /me/calendarView?startDateTime=<startISO>&endDateTime=<endISO>&$top=5&$select=id,subject,start,end,attendees \u3092\u547C\u3073\u51FA\u3057\u3001\u76F4\u8FD1\u306E occurrence \u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0 (\u7E70\u308A\u8FD4\u3057\u30A4\u30D9\u30F3\u30C8\u3092\u5C55\u958B)
556
- 8. \u8208\u5473\u306E\u3042\u308B\u30A4\u30D9\u30F3\u30C8\u306B\u3064\u3044\u3066 outlook-oauth_request \u3067 GET /me/events/{eventId} \u3092\u547C\u3073\u51FA\u3057\u3001\u53C2\u52A0\u8005\u30FB\u672C\u6587\u30FB\u5834\u6240\u3092\u78BA\u8A8D`
573
+ 6. connector_outlook-oauth_request \u3067 GET /me/calendars \u3092\u547C\u3073\u51FA\u3057\u3001\u30AB\u30EC\u30F3\u30C0\u30FC\u4E00\u89A7 (\u30C7\u30D5\u30A9\u30EB\u30C8 + \u5171\u6709) \u3092\u53D6\u5F97
574
+ 7. connector_outlook-oauth_request \u3067 GET /me/calendarView?startDateTime=<startISO>&endDateTime=<endISO>&$top=5&$select=id,subject,start,end,attendees \u3092\u547C\u3073\u51FA\u3057\u3001\u76F4\u8FD1\u306E occurrence \u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0 (\u7E70\u308A\u8FD4\u3057\u30A4\u30D9\u30F3\u30C8\u3092\u5C55\u958B)
575
+ 8. \u8208\u5473\u306E\u3042\u308B\u30A4\u30D9\u30F3\u30C8\u306B\u3064\u3044\u3066 connector_outlook-oauth_request \u3067 GET /me/events/{eventId} \u3092\u547C\u3073\u51FA\u3057\u3001\u53C2\u52A0\u8005\u30FB\u672C\u6587\u30FB\u5834\u6240\u3092\u78BA\u8A8D`
557
576
  }
558
577
  });
559
578
 
@@ -653,7 +672,7 @@ var outlookOauthConnector = new ConnectorPlugin({
653
672
  description: "Connect to Microsoft Outlook (Mail + Calendar) via Microsoft Graph using OAuth. Read-only access to the user's mailbox, mail folders, messages, attachments, calendars, and events.",
654
673
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/1J1FrRTYJjOh3CcSIqsz3I/6a467b4d926075ff99dc60820e0ae4b1/Microsoft_Outlook_Icon__2025%C3%A2__present_.svg",
655
674
  parameters,
656
- releaseFlag: { dev1: true, dev2: false, prod: false },
675
+ releaseFlag: { dev1: true, dev2: true, prod: true },
657
676
  categories: ["productivity"],
658
677
  onboarding: outlookOnboarding,
659
678
  proxyPolicy: {
@@ -667,7 +686,7 @@ var outlookOauthConnector = new ConnectorPlugin({
667
686
  systemPrompt: {
668
687
  en: `### Tools
669
688
 
670
- - \`outlook-oauth_request\`: The only way to call Microsoft Graph for Outlook (read-only). Use it to fetch the user profile (\`/me\`), list mail folders (\`/me/mailFolders\`), read messages (\`/me/messages\`, \`/me/messages/{id}\`), fetch attachments (\`/me/messages/{id}/attachments\`), list calendars (\`/me/calendars\`), and read events (\`/me/events\`, \`/me/calendarView\`). Authentication is configured automatically via OAuth.
689
+ - \`connector_outlook-oauth_request\`: The only way to call Microsoft Graph for Outlook (read-only). Use it to fetch the user profile (\`/me\`), list mail folders (\`/me/mailFolders\`), read messages (\`/me/messages\`, \`/me/messages/{id}\`), fetch attachments (\`/me/messages/{id}/attachments\`), list calendars (\`/me/calendars\`), and read events (\`/me/events\`, \`/me/calendarView\`). Authentication is configured automatically via OAuth.
671
690
 
672
691
  ### Microsoft Graph Reference (Outlook Mail)
673
692
 
@@ -800,7 +819,7 @@ events.value.forEach(e => console.log(e.start.dateTime, e.subject));
800
819
  \`\`\``,
801
820
  ja: `### \u30C4\u30FC\u30EB
802
821
 
803
- - \`outlook-oauth_request\`: Outlook \u5411\u3051\u306E Microsoft Graph \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF09\u3002\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB (\`/me\`)\u3001\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0 (\`/me/mailFolders\`)\u3001\u30E1\u30C3\u30BB\u30FC\u30B8 (\`/me/messages\`)\u3001\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB (\`/me/messages/{id}/attachments\`)\u3001\u30AB\u30EC\u30F3\u30C0\u30FC (\`/me/calendars\`)\u3001\u30A4\u30D9\u30F3\u30C8 (\`/me/events\`, \`/me/calendarView\`) \u306E\u53D6\u5F97\u306B\u4F7F\u3044\u307E\u3059\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
822
+ - \`connector_outlook-oauth_request\`: Outlook \u5411\u3051\u306E Microsoft Graph \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528\uFF09\u3002\u30E6\u30FC\u30B6\u30FC\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB (\`/me\`)\u3001\u30E1\u30FC\u30EB\u30D5\u30A9\u30EB\u30C0 (\`/me/mailFolders\`)\u3001\u30E1\u30C3\u30BB\u30FC\u30B8 (\`/me/messages\`)\u3001\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB (\`/me/messages/{id}/attachments\`)\u3001\u30AB\u30EC\u30F3\u30C0\u30FC (\`/me/calendars\`)\u3001\u30A4\u30D9\u30F3\u30C8 (\`/me/events\`, \`/me/calendarView\`) \u306E\u53D6\u5F97\u306B\u4F7F\u3044\u307E\u3059\u3002OAuth \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
804
823
 
805
824
  ### Microsoft Graph \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9 (Outlook \u30E1\u30FC\u30EB)
806
825
 
@@ -151,6 +151,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
151
151
  * `runSetupFlow` from `setup-flow.ts`.
152
152
  */
153
153
  setup;
154
+ /**
155
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
156
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
157
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
158
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
159
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
160
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
161
+ */
162
+ introspect;
154
163
  /**
155
164
  * Opt-out of the default "verify before save" behavior on connection
156
165
  * creation. The backend invokes `checkConnection` synchronously while
@@ -165,6 +174,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
165
174
  * the default verify-on-create behavior without opt-in.
166
175
  */
167
176
  skipConnectionCheckOnCreate;
177
+ /**
178
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
179
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
180
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
181
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
182
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
183
+ */
184
+ surveyProbes;
168
185
  constructor(config) {
169
186
  this.slug = config.slug;
170
187
  this.authType = config.authType;
@@ -182,7 +199,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
182
199
  this.query = config.query;
183
200
  this.checkConnection = config.checkConnection;
184
201
  this.setup = config.setup;
202
+ this.introspect = config.introspect;
185
203
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
204
+ this.surveyProbes = config.surveyProbes;
186
205
  }
187
206
  get connectorKey() {
188
207
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -190,7 +209,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
190
209
  /**
191
210
  * Create tools for connections that belong to this connector.
192
211
  * Filters connections by connectorKey internally.
193
- * Returns tools keyed as `${connectorKey}_${toolName}`.
212
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
194
213
  */
195
214
  createTools(connections, config, opts) {
196
215
  const myConnections = connections.filter(
@@ -200,7 +219,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
200
219
  for (const t of Object.values(this.tools)) {
201
220
  const tool = t.createTool(myConnections, config);
202
221
  const originalToModelOutput = tool.toModelOutput;
203
- result[`${this.connectorKey}_${t.name}`] = {
222
+ result[`connector_${this.connectorKey}_${t.name}`] = {
204
223
  ...tool,
205
224
  toModelOutput: async (options) => {
206
225
  if (!originalToModelOutput) {
@@ -220,25 +239,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
220
239
  if (authType) return `${slug}-${authType}`;
221
240
  const LEGACY_NULL_AUTH_TYPE_MAP = {
222
241
  // user-password
223
- "postgresql": "user-password",
224
- "mysql": "user-password",
225
- "clickhouse": "user-password",
226
- "kintone": "user-password",
242
+ postgresql: "user-password",
243
+ mysql: "user-password",
244
+ clickhouse: "user-password",
245
+ kintone: "user-password",
227
246
  "squadbase-db": "user-password",
228
247
  // service-account
229
- "snowflake": "service-account",
230
- "bigquery": "service-account",
248
+ snowflake: "service-account",
249
+ bigquery: "service-account",
231
250
  "google-analytics": "service-account",
232
251
  "google-calendar": "service-account",
233
252
  "aws-athena": "service-account",
234
- "redshift": "service-account",
253
+ redshift: "service-account",
235
254
  // api-key
236
- "databricks": "api-key",
237
- "dbt": "api-key",
238
- "airtable": "api-key",
239
- "openai": "api-key",
240
- "gemini": "api-key",
241
- "anthropic": "api-key",
255
+ databricks: "api-key",
256
+ dbt: "api-key",
257
+ airtable: "api-key",
258
+ openai: "api-key",
259
+ gemini: "api-key",
260
+ anthropic: "api-key",
242
261
  "wix-store": "api-key"
243
262
  };
244
263
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -491,14 +510,14 @@ var powerbiOauthOnboarding = new ConnectorOnboarding({
491
510
  - Write only 1 sentence between tool calls, then immediately call the next tool`
492
511
  },
493
512
  dataOverviewInstructions: {
494
- en: `1. Call powerbi-oauth_request with GET /groups to list accessible workspaces
495
- 2. For a target workspace, call powerbi-oauth_request with GET /groups/{groupId}/datasets to list datasets
496
- 3. Call powerbi-oauth_request with GET /groups/{groupId}/reports to list reports
497
- 4. For each interesting dataset call powerbi-oauth_request with GET /groups/{groupId}/datasets/{datasetId}/tables to inspect tables`,
498
- ja: `1. powerbi-oauth_request \u3067 GET /groups \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
499
- 2. \u5BFE\u8C61\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5BFE\u3057\u3066 powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
500
- 3. powerbi-oauth_request \u3067 GET /groups/{groupId}/reports \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
501
- 4. \u8208\u5473\u306E\u3042\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u3064\u3044\u3066 powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets/{datasetId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u69CB\u9020\u3092\u78BA\u8A8D`
513
+ en: `1. Call connector_powerbi-oauth_request with GET /groups to list accessible workspaces
514
+ 2. For a target workspace, call connector_powerbi-oauth_request with GET /groups/{groupId}/datasets to list datasets
515
+ 3. Call connector_powerbi-oauth_request with GET /groups/{groupId}/reports to list reports
516
+ 4. For each interesting dataset call connector_powerbi-oauth_request with GET /groups/{groupId}/datasets/{datasetId}/tables to inspect tables`,
517
+ ja: `1. connector_powerbi-oauth_request \u3067 GET /groups \u3092\u547C\u3073\u51FA\u3057\u3001\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
518
+ 2. \u5BFE\u8C61\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5BFE\u3057\u3066 connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets \u3092\u547C\u3073\u51FA\u3057\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
519
+ 3. connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/reports \u3092\u547C\u3073\u51FA\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
520
+ 4. \u8208\u5473\u306E\u3042\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u3064\u3044\u3066 connector_powerbi-oauth_request \u3067 GET /groups/{groupId}/datasets/{datasetId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u69CB\u9020\u3092\u78BA\u8A8D`
502
521
  }
503
522
  });
504
523
 
@@ -892,7 +911,7 @@ var powerbiOauthConnector = new ConnectorPlugin({
892
911
  description: "Connect to Microsoft Power BI using OAuth (Microsoft Entra ID). Use it to enumerate workspaces, datasets, and reports the signed-in user has access to, and to run DAX queries.",
893
912
  iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2vXQCKGpMJ9kGSaqkZl9IS/cc5669c267fc5d11e7b1f8c01723e461/power-bi-icon.png",
894
913
  parameters,
895
- releaseFlag: { dev1: true, dev2: false, prod: false },
914
+ releaseFlag: { dev1: true, dev2: true, prod: true },
896
915
  categories: ["bi"],
897
916
  onboarding: powerbiOauthOnboarding,
898
917
  proxyPolicy: {
@@ -906,7 +925,7 @@ var powerbiOauthConnector = new ConnectorPlugin({
906
925
  systemPrompt: {
907
926
  en: `### Tools
908
927
 
909
- - \`powerbi-oauth_request\`: The only way to call the Power BI REST API v1.0. Use it to list workspaces (\`/groups\`), datasets, reports, and to run DAX via the \`executeQueries\` endpoint. Authentication is configured automatically via OAuth (Microsoft Entra ID).
928
+ - \`connector_powerbi-oauth_request\`: The only way to call the Power BI REST API v1.0. Use it to list workspaces (\`/groups\`), datasets, reports, and to run DAX via the \`executeQueries\` endpoint. Authentication is configured automatically via OAuth (Microsoft Entra ID).
910
929
 
911
930
  ### Business Logic
912
931
 
@@ -962,7 +981,7 @@ export default async function handler(c: Context) {
962
981
  - Each \`executeQueries\` call accepts one query in the \`queries\` array (per current Power BI API limits)`,
963
982
  ja: `### \u30C4\u30FC\u30EB
964
983
 
965
- - \`powerbi-oauth_request\`: Power BI REST API v1.0 \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9 (\`/groups\`)\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u4E00\u89A7\u53D6\u5F97\u3084\u3001\`executeQueries\` \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u308B DAX \u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth (Microsoft Entra ID) \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
984
+ - \`connector_powerbi-oauth_request\`: Power BI REST API v1.0 \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9 (\`/groups\`)\u3001\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3001\u30EC\u30DD\u30FC\u30C8\u306E\u4E00\u89A7\u53D6\u5F97\u3084\u3001\`executeQueries\` \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u308B DAX \u306E\u5B9F\u884C\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth (Microsoft Entra ID) \u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002
966
985
 
967
986
  ### Business Logic
968
987
 
@@ -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
@@ -294,6 +299,15 @@ var ConnectorPlugin = class _ConnectorPlugin {
294
299
  * `runSetupFlow` from `setup-flow.ts`.
295
300
  */
296
301
  setup;
302
+ /**
303
+ * 統一 introspection。SQL DB の `information_schema` / `SHOW` / `DESCRIBE` や SaaS の
304
+ * メタデータ API といった取得経路の差を吸収し、tables / columns / PK / FK を共通型
305
+ * {@link IntrospectedSchema} へ正規化して返す。取得経路は {@link IntrospectContext} で
306
+ * 抽象化され、SQL DB は `ctx.query`、SaaS は `ctx.proxyFetch` + `ctx.params` を使う。
307
+ * `ctx.profile === true` のときは L2 プロファイル(行数・NULL 率等)も best-effort で埋める。
308
+ * coding-agent の `DataContextIndex` がデータ地図を構築する際に使う。
309
+ */
310
+ introspect;
297
311
  /**
298
312
  * Opt-out of the default "verify before save" behavior on connection
299
313
  * creation. The backend invokes `checkConnection` synchronously while
@@ -308,6 +322,14 @@ var ConnectorPlugin = class _ConnectorPlugin {
308
322
  * the default verify-on-create behavior without opt-in.
309
323
  */
310
324
  skipConnectionCheckOnCreate;
325
+ /**
326
+ * 決定論的な「立ち上げ survey」レシピ(ルールベース prewarm 基盤)。実装した connector は、LLM を使わずに
327
+ * read-only で自分を survey する probe 列(テーブル/列メタデータ → 小サンプル)を宣言する。coding-agent の
328
+ * recon driver がこれを読み、connector ツールの `execute` を直接呼んで結果を seed にする。未実装の connector は
329
+ * driver 側で safely skip される(その connection は listConnections のみ seed)。標準 `information_schema` を
330
+ * 持つ SQL connector は `makeStandardSqlSurveyProbes` を使える。**probe は必ず read-only**。
331
+ */
332
+ surveyProbes;
311
333
  constructor(config) {
312
334
  this.slug = config.slug;
313
335
  this.authType = config.authType;
@@ -325,7 +347,9 @@ var ConnectorPlugin = class _ConnectorPlugin {
325
347
  this.query = config.query;
326
348
  this.checkConnection = config.checkConnection;
327
349
  this.setup = config.setup;
350
+ this.introspect = config.introspect;
328
351
  this.skipConnectionCheckOnCreate = config.skipConnectionCheckOnCreate;
352
+ this.surveyProbes = config.surveyProbes;
329
353
  }
330
354
  get connectorKey() {
331
355
  return _ConnectorPlugin.deriveKey(this.slug, this.authType);
@@ -333,7 +357,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
333
357
  /**
334
358
  * Create tools for connections that belong to this connector.
335
359
  * Filters connections by connectorKey internally.
336
- * Returns tools keyed as `${connectorKey}_${toolName}`.
360
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
337
361
  */
338
362
  createTools(connections, config, opts) {
339
363
  const myConnections = connections.filter(
@@ -343,7 +367,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
343
367
  for (const t of Object.values(this.tools)) {
344
368
  const tool = t.createTool(myConnections, config);
345
369
  const originalToModelOutput = tool.toModelOutput;
346
- result[`${this.connectorKey}_${t.name}`] = {
370
+ result[`connector_${this.connectorKey}_${t.name}`] = {
347
371
  ...tool,
348
372
  toModelOutput: async (options) => {
349
373
  if (!originalToModelOutput) {
@@ -363,25 +387,25 @@ var ConnectorPlugin = class _ConnectorPlugin {
363
387
  if (authType) return `${slug}-${authType}`;
364
388
  const LEGACY_NULL_AUTH_TYPE_MAP = {
365
389
  // user-password
366
- "postgresql": "user-password",
367
- "mysql": "user-password",
368
- "clickhouse": "user-password",
369
- "kintone": "user-password",
390
+ postgresql: "user-password",
391
+ mysql: "user-password",
392
+ clickhouse: "user-password",
393
+ kintone: "user-password",
370
394
  "squadbase-db": "user-password",
371
395
  // service-account
372
- "snowflake": "service-account",
373
- "bigquery": "service-account",
396
+ snowflake: "service-account",
397
+ bigquery: "service-account",
374
398
  "google-analytics": "service-account",
375
399
  "google-calendar": "service-account",
376
400
  "aws-athena": "service-account",
377
- "redshift": "service-account",
401
+ redshift: "service-account",
378
402
  // api-key
379
- "databricks": "api-key",
380
- "dbt": "api-key",
381
- "airtable": "api-key",
382
- "openai": "api-key",
383
- "gemini": "api-key",
384
- "anthropic": "api-key",
403
+ databricks: "api-key",
404
+ dbt: "api-key",
405
+ airtable: "api-key",
406
+ openai: "api-key",
407
+ gemini: "api-key",
408
+ anthropic: "api-key",
385
409
  "wix-store": "api-key"
386
410
  };
387
411
  const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
@@ -460,6 +484,24 @@ async function resolveSetupSelection(params) {
460
484
  return resolved.slice(0, limit);
461
485
  }
462
486
 
487
+ // ../connectors/src/introspect-concurrency.ts
488
+ async function mapWithConcurrency(items, limit, fn) {
489
+ const results = new Array(items.length);
490
+ let next = 0;
491
+ const workers = Array.from(
492
+ { length: Math.min(Math.max(limit, 1), items.length) },
493
+ async () => {
494
+ for (; ; ) {
495
+ const i = next++;
496
+ if (i >= items.length) return;
497
+ results[i] = await fn(items[i]);
498
+ }
499
+ }
500
+ );
501
+ await Promise.all(workers);
502
+ return results;
503
+ }
504
+
463
505
  // ../connectors/src/auth-types.ts
464
506
  var AUTH_TYPES = {
465
507
  OAUTH: "oauth",
@@ -473,11 +515,11 @@ var AUTH_TYPES = {
473
515
  // ../connectors/src/connectors/salesforce/setup.ts
474
516
  var salesforceOnboarding = new ConnectorOnboarding({
475
517
  dataOverviewInstructions: {
476
- en: `1. Call salesforce_request with GET /services/data/v60.0/sobjects/ to list available sObjects (standard + custom)
477
- 2. Call salesforce_request with GET /services/data/v60.0/sobjects/Account/describe to inspect Account fields; repeat for Contact, Opportunity, Lead as needed
518
+ en: `1. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/ to list available sObjects (standard + custom)
519
+ 2. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/Account/describe to inspect Account fields; repeat for Contact, Opportunity, Lead as needed
478
520
  3. Run a sample SOQL query: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 to verify access and explore data`,
479
- ja: `1. salesforce_request \u3067 GET /services/data/v60.0/sobjects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A sObject\uFF08\u6A19\u6E96 + \u30AB\u30B9\u30BF\u30E0\uFF09\u3092\u4E00\u89A7\u53D6\u5F97
480
- 2. salesforce_request \u3067 GET /services/data/v60.0/sobjects/Account/describe \u3092\u547C\u3073\u51FA\u3057 Account \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3002Contact / Opportunity / Lead \u306A\u3069\u5FC5\u8981\u306A sObject \u306B\u5BFE\u3057\u3066\u540C\u69D8\u306B\u5B9F\u884C
521
+ ja: `1. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A sObject\uFF08\u6A19\u6E96 + \u30AB\u30B9\u30BF\u30E0\uFF09\u3092\u4E00\u89A7\u53D6\u5F97
522
+ 2. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/Account/describe \u3092\u547C\u3073\u51FA\u3057 Account \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3002Contact / Opportunity / Lead \u306A\u3069\u5FC5\u8981\u306A sObject \u306B\u5BFE\u3057\u3066\u540C\u69D8\u306B\u5B9F\u884C
481
523
  3. \u30B5\u30F3\u30D7\u30EB SOQL \u3092\u5B9F\u884C: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u5426\u3068\u30C7\u30FC\u30BF\u69CB\u9020\u3092\u78BA\u8A8D`
482
524
  }
483
525
  });
@@ -567,6 +609,20 @@ async function describeSObject(params, name) {
567
609
  const data = await res.json();
568
610
  return data.fields ?? [];
569
611
  }
612
+ async function fetchSObjectCount(params, objectName) {
613
+ try {
614
+ const query = encodeURIComponent(`SELECT COUNT() FROM ${objectName}`);
615
+ const res = await apiFetch(
616
+ params,
617
+ `/services/data/${SALESFORCE_API_VERSION}/query?q=${query}`
618
+ );
619
+ if (!res.ok) return null;
620
+ const data = await res.json();
621
+ return typeof data.totalSize === "number" ? data.totalSize : null;
622
+ } catch {
623
+ return null;
624
+ }
625
+ }
570
626
  var salesforceSetupFlow = {
571
627
  initialState: () => ({}),
572
628
  steps: [
@@ -601,8 +657,27 @@ var salesforceSetupFlow = {
601
657
  limit: SALESFORCE_SETUP_MAX_OBJECTS
602
658
  });
603
659
  const sections = ["## Salesforce", ""];
660
+ const countByObject = /* @__PURE__ */ new Map();
661
+ for (const objectName of targetObjects) {
662
+ countByObject.set(
663
+ objectName,
664
+ await fetchSObjectCount(rt.params, objectName)
665
+ );
666
+ }
667
+ sections.push("### Record counts", "");
668
+ sections.push("| sObject | Record count |");
669
+ sections.push("|---------|-------------|");
670
+ for (const objectName of targetObjects) {
671
+ const count = countByObject.get(objectName);
672
+ sections.push(
673
+ `| ${objectName} | ${count == null ? "-" : count.toLocaleString()} |`
674
+ );
675
+ }
676
+ sections.push("");
604
677
  for (const objectName of targetObjects) {
605
- sections.push(`### sObject: ${objectName}`, "");
678
+ const count = countByObject.get(objectName);
679
+ const countLabel = count == null ? "" : ` (${count.toLocaleString()} records)`;
680
+ sections.push(`### sObject: ${objectName}${countLabel}`, "");
606
681
  const fields = await describeSObject(rt.params, objectName);
607
682
  const limited = fields.slice(0, SALESFORCE_SETUP_MAX_FIELDS);
608
683
  sections.push("| Field | Type | Label | Custom |");
@@ -627,6 +702,56 @@ var salesforceSetupFlow = {
627
702
  }
628
703
  };
629
704
 
705
+ // ../connectors/src/connectors/salesforce/introspect.ts
706
+ var MAX_SOBJECTS = 100;
707
+ var CONCURRENCY = 5;
708
+ async function introspectSalesforce(ctx) {
709
+ const { accessToken, instanceUrl } = await getAccessToken(ctx.params);
710
+ const base = `${instanceUrl}/services/data/${SALESFORCE_API_VERSION}`;
711
+ const headers = {
712
+ Authorization: `Bearer ${accessToken}`,
713
+ Accept: "application/json"
714
+ };
715
+ const listRes = await fetch(`${base}/sobjects`, { headers });
716
+ if (!listRes.ok) {
717
+ throw new Error(`salesforce: sobjects failed (${listRes.status})`);
718
+ }
719
+ const listData = await listRes.json();
720
+ const sobjects = (listData.sobjects ?? []).filter((s) => s.queryable && !s.deprecatedAndHidden).slice(0, MAX_SOBJECTS);
721
+ const tables = (await mapWithConcurrency(sobjects, CONCURRENCY, async (so) => {
722
+ try {
723
+ const res = await fetch(
724
+ `${base}/sobjects/${encodeURIComponent(so.name)}/describe`,
725
+ { headers }
726
+ );
727
+ if (!res.ok) return [];
728
+ const data = await res.json();
729
+ const columns = (data.fields ?? []).map((f) => {
730
+ const column = {
731
+ name: f.name,
732
+ dataType: f.type ?? "unknown",
733
+ nullable: f.nillable !== false
734
+ };
735
+ if (f.type === "id") column.isPrimaryKey = true;
736
+ if (f.type === "reference" && f.referenceTo?.length) {
737
+ column.foreignKey = { table: f.referenceTo[0], column: "Id" };
738
+ }
739
+ return column;
740
+ });
741
+ const table = {
742
+ schema: "",
743
+ name: so.name,
744
+ type: "table",
745
+ columns
746
+ };
747
+ return [table];
748
+ } catch {
749
+ return [];
750
+ }
751
+ })).flat();
752
+ return { tables };
753
+ }
754
+
630
755
  // ../connectors/src/connectors/salesforce/tools/request.ts
631
756
  import { z } from "zod";
632
757
  var REQUEST_TIMEOUT_MS = 6e4;
@@ -772,7 +897,7 @@ var salesforceConnector = new ConnectorPlugin({
772
897
  systemPrompt: {
773
898
  en: `### Tools
774
899
 
775
- - \`salesforce_request\`: The only way to call the Salesforce REST API. Use it to run SOQL queries, describe sObjects, and read/create/update/delete standard (Account, Contact, Opportunity, Lead, Case) and custom objects. Authentication (OAuth 2.0 Client Credentials Flow against the External Client App / Connected App) is configured automatically \u2014 an access token is resolved on each request against the configured org instance URL. Prefer SOQL via \`GET /services/data/v60.0/query?q=...\` over paginating \`/sobjects/{Type}\` endpoints for filtered or joined reads.
900
+ - \`connector_salesforce_request\`: The only way to call the Salesforce REST API. Use it to run SOQL queries, describe sObjects, and read/create/update/delete standard (Account, Contact, Opportunity, Lead, Case) and custom objects. Authentication (OAuth 2.0 Client Credentials Flow against the External Client App / Connected App) is configured automatically \u2014 an access token is resolved on each request against the configured org instance URL. Prefer SOQL via \`GET /services/data/v60.0/query?q=...\` over paginating \`/sobjects/{Type}\` endpoints for filtered or joined reads.
776
901
 
777
902
  ### Business Logic
778
903
 
@@ -843,7 +968,7 @@ export default async function handler(c: Context) {
843
968
  - Parent-to-child subquery: \`SELECT Id, Name, (SELECT Id, Email FROM Contacts) FROM Account\``,
844
969
  ja: `### \u30C4\u30FC\u30EB
845
970
 
846
- - \`salesforce_request\`: Salesforce REST API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SOQL \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001sObject \u306E describe\u3001\u6A19\u6E96\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08Account, Contact, Opportunity, Lead, Case\uFF09\u3084\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08External Client App / Connected App + OAuth 2.0 Client Credentials Flow\uFF09\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u7D44\u7E54\u306E instance URL \u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30D5\u30A3\u30EB\u30BF\u3084\u7D50\u5408\u306E\u3042\u308B\u8AAD\u307F\u53D6\u308A\u3067\u306F \`/sobjects/{Type}\` \u3092\u30DA\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`GET /services/data/v60.0/query?q=...\` \u306E SOQL \u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044\u3002
971
+ - \`connector_salesforce_request\`: Salesforce REST API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SOQL \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001sObject \u306E describe\u3001\u6A19\u6E96\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08Account, Contact, Opportunity, Lead, Case\uFF09\u3084\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08External Client App / Connected App + OAuth 2.0 Client Credentials Flow\uFF09\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u7D44\u7E54\u306E instance URL \u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30D5\u30A3\u30EB\u30BF\u3084\u7D50\u5408\u306E\u3042\u308B\u8AAD\u307F\u53D6\u308A\u3067\u306F \`/sobjects/{Type}\` \u3092\u30DA\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`GET /services/data/v60.0/query?q=...\` \u306E SOQL \u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044\u3002
847
972
 
848
973
  ### Business Logic
849
974
 
@@ -914,6 +1039,7 @@ export default async function handler(c: Context) {
914
1039
  - \u89AA\u2192\u5B50\u30B5\u30D6\u30AF\u30A8\u30EA: \`SELECT Id, Name, (SELECT Id, Email FROM Contacts) FROM Account\``
915
1040
  },
916
1041
  tools,
1042
+ introspect: (ctx) => introspectSalesforce(ctx),
917
1043
  setup: (params, ctx, config) => runSetupFlow(salesforceSetupFlow, params, ctx, config),
918
1044
  async checkConnection(params, _config) {
919
1045
  const instanceUrlParam = params[parameters.instanceUrl.slug];