@squadbase/vite-server 0.1.17-dev.a9ddcfa → 0.1.17

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 (76) hide show
  1. package/dist/cli/index.js +3281 -731
  2. package/dist/connectors/airtable-oauth.js +48 -8
  3. package/dist/connectors/airtable.js +44 -8
  4. package/dist/connectors/amplitude.js +8 -8
  5. package/dist/connectors/anthropic.js +2 -2
  6. package/dist/connectors/asana.js +37 -10
  7. package/dist/connectors/attio.js +30 -13
  8. package/dist/connectors/aws-billing.js +8 -8
  9. package/dist/connectors/azure-sql.js +31 -7
  10. package/dist/connectors/backlog-api-key.js +40 -15
  11. package/dist/connectors/clickup.js +50 -10
  12. package/dist/connectors/cosmosdb.js +12 -12
  13. package/dist/connectors/customerio.js +8 -8
  14. package/dist/connectors/dbt.js +686 -25
  15. package/dist/connectors/freshdesk.js +82 -8
  16. package/dist/connectors/freshsales.js +8 -8
  17. package/dist/connectors/freshservice.js +8 -8
  18. package/dist/connectors/gamma.js +15 -15
  19. package/dist/connectors/gemini.js +2 -2
  20. package/dist/connectors/github.js +12 -12
  21. package/dist/connectors/gmail-oauth.js +10 -10
  22. package/dist/connectors/gmail.js +4 -4
  23. package/dist/connectors/google-ads.js +8 -8
  24. package/dist/connectors/google-analytics-oauth.js +152 -25
  25. package/dist/connectors/google-analytics.js +490 -96
  26. package/dist/connectors/google-audit-log.js +4 -4
  27. package/dist/connectors/google-calendar-oauth.js +61 -15
  28. package/dist/connectors/google-calendar.js +61 -11
  29. package/dist/connectors/google-docs.js +10 -10
  30. package/dist/connectors/google-drive.js +32 -10
  31. package/dist/connectors/google-search-console-oauth.js +126 -17
  32. package/dist/connectors/google-sheets.js +6 -6
  33. package/dist/connectors/google-slides.js +10 -10
  34. package/dist/connectors/grafana.js +45 -10
  35. package/dist/connectors/hubspot-oauth.js +41 -9
  36. package/dist/connectors/hubspot.js +25 -9
  37. package/dist/connectors/influxdb.js +8 -8
  38. package/dist/connectors/intercom-oauth.js +72 -12
  39. package/dist/connectors/intercom.js +12 -12
  40. package/dist/connectors/jdbc.js +6 -6
  41. package/dist/connectors/jira-api-key.js +68 -11
  42. package/dist/connectors/kintone-api-token.js +66 -18
  43. package/dist/connectors/kintone.js +54 -11
  44. package/dist/connectors/linear.js +54 -12
  45. package/dist/connectors/linkedin-ads.js +41 -14
  46. package/dist/connectors/mailchimp-oauth.js +6 -6
  47. package/dist/connectors/mailchimp.js +6 -6
  48. package/dist/connectors/meta-ads-oauth.js +33 -14
  49. package/dist/connectors/meta-ads.js +35 -14
  50. package/dist/connectors/mixpanel.js +8 -8
  51. package/dist/connectors/monday.js +9 -9
  52. package/dist/connectors/mongodb.js +8 -8
  53. package/dist/connectors/notion-oauth.js +60 -11
  54. package/dist/connectors/notion.js +60 -11
  55. package/dist/connectors/openai.js +2 -2
  56. package/dist/connectors/oracle.js +23 -7
  57. package/dist/connectors/outlook-oauth.js +20 -20
  58. package/dist/connectors/powerbi-oauth.js +12 -12
  59. package/dist/connectors/salesforce.js +42 -9
  60. package/dist/connectors/semrush.js +6 -6
  61. package/dist/connectors/sentry.js +36 -10
  62. package/dist/connectors/shopify-oauth.js +43 -10
  63. package/dist/connectors/shopify.js +8 -8
  64. package/dist/connectors/sqlserver.js +31 -7
  65. package/dist/connectors/stripe-api-key.js +66 -15
  66. package/dist/connectors/stripe-oauth.js +70 -19
  67. package/dist/connectors/supabase.js +22 -5
  68. package/dist/connectors/tableau.js +14 -14
  69. package/dist/connectors/tiktok-ads.js +37 -16
  70. package/dist/connectors/wix-store.js +8 -8
  71. package/dist/connectors/zendesk-oauth.js +55 -12
  72. package/dist/connectors/zendesk.js +12 -12
  73. package/dist/index.js +3299 -729
  74. package/dist/main.js +3299 -729
  75. package/dist/vite-plugin.js +3279 -729
  76. package/package.json +1 -1
@@ -187,7 +187,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
187
187
  /**
188
188
  * Create tools for connections that belong to this connector.
189
189
  * Filters connections by connectorKey internally.
190
- * Returns tools keyed as `${connectorKey}_${toolName}`.
190
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
191
191
  */
192
192
  createTools(connections, config, opts) {
193
193
  const myConnections = connections.filter(
@@ -197,7 +197,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
197
197
  for (const t of Object.values(this.tools)) {
198
198
  const tool = t.createTool(myConnections, config);
199
199
  const originalToModelOutput = tool.toModelOutput;
200
- result[`${this.connectorKey}_${t.name}`] = {
200
+ result[`connector_${this.connectorKey}_${t.name}`] = {
201
201
  ...tool,
202
202
  toModelOutput: async (options) => {
203
203
  if (!originalToModelOutput) {
@@ -478,10 +478,10 @@ var airtableOauthOnboarding = new ConnectorOnboarding({
478
478
  - Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
479
479
  },
480
480
  dataOverviewInstructions: {
481
- en: `1. Call airtable-oauth_request with GET /meta/bases/{baseId}/tables to list tables and their fields
482
- 2. Call airtable-oauth_request with GET /{baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
483
- ja: `1. airtable-oauth_request \u3067 GET /meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
484
- 2. airtable-oauth_request \u3067 GET /{baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
481
+ en: `1. Call connector_airtable-oauth_request with GET /meta/bases/{baseId}/tables to list tables and their fields
482
+ 2. Call connector_airtable-oauth_request with GET /{baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
483
+ ja: `1. connector_airtable-oauth_request \u3067 GET /meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
484
+ 2. connector_airtable-oauth_request \u3067 GET /{baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
485
485
  }
486
486
  });
487
487
 
@@ -517,6 +517,26 @@ async function listTables(proxyFetch, baseId) {
517
517
  const data = await res.json();
518
518
  return data.tables ?? [];
519
519
  }
520
+ async function listSampleRecords(proxyFetch, baseId, tableId) {
521
+ try {
522
+ const res = await apiFetch(
523
+ proxyFetch,
524
+ `/${baseId}/${encodeURIComponent(tableId)}?maxRecords=3`
525
+ );
526
+ if (!res.ok) return [];
527
+ const data = await res.json();
528
+ return data.records ?? [];
529
+ } catch {
530
+ return [];
531
+ }
532
+ }
533
+ function formatCell(val) {
534
+ if (val == null) return "";
535
+ if (typeof val === "string") return val.length > 40 ? `${val.slice(0, 40)}\u2026` : val;
536
+ if (Array.isArray(val)) return `[${val.length} items]`;
537
+ if (typeof val === "object") return JSON.stringify(val).slice(0, 40);
538
+ return String(val);
539
+ }
520
540
  var airtableOauthSetupFlow = {
521
541
  initialState: () => ({}),
522
542
  steps: [
@@ -588,6 +608,26 @@ var airtableOauthSetupFlow = {
588
608
  sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
589
609
  }
590
610
  sections.push("");
611
+ const records = await listSampleRecords(
612
+ rt.config.proxyFetch,
613
+ baseId,
614
+ table.id
615
+ );
616
+ if (records.length > 0) {
617
+ const sampleFields = (table.fields ?? []).slice(0, 5).map((f) => f.name);
618
+ if (sampleFields.length > 0) {
619
+ sections.push(`##### Sample records (${records.length})`, "");
620
+ sections.push(`| ${sampleFields.join(" | ")} |`);
621
+ sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
622
+ for (const record of records) {
623
+ const cells = sampleFields.map(
624
+ (name) => formatCell(record.fields?.[name]).replace(/\|/g, "\\|")
625
+ );
626
+ sections.push(`| ${cells.join(" | ")} |`);
627
+ }
628
+ sections.push("");
629
+ }
630
+ }
591
631
  }
592
632
  return sections.join("\n");
593
633
  }
@@ -617,7 +657,7 @@ var airtableOauthConnector = new ConnectorPlugin({
617
657
  systemPrompt: {
618
658
  en: `### Tools
619
659
 
620
- - \`airtable-oauth_request\`: The only way to call the Airtable REST API. Use it to list tables, query/create/update/delete records. Authentication is configured automatically via OAuth. The {baseId} placeholder in paths is automatically replaced with the configured default base ID.
660
+ - \`connector_airtable-oauth_request\`: The only way to call the Airtable REST API. Use it to list tables, query/create/update/delete records. Authentication is configured automatically via OAuth. The {baseId} placeholder in paths is automatically replaced with the configured default base ID.
621
661
 
622
662
  ### Airtable API Reference
623
663
 
@@ -665,7 +705,7 @@ const recordsData = await records.json();
665
705
  \`\`\``,
666
706
  ja: `### \u30C4\u30FC\u30EB
667
707
 
668
- - \`airtable-oauth_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\u30FB\u4F5C\u6210\u30FB\u66F4\u65B0\u30FB\u524A\u9664\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{baseId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30D9\u30FC\u30B9ID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002
708
+ - \`connector_airtable-oauth_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u691C\u7D22\u30FB\u4F5C\u6210\u30FB\u66F4\u65B0\u30FB\u524A\u9664\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{baseId}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u30D9\u30FC\u30B9ID\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002
669
709
 
670
710
  ### Airtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
671
711
 
@@ -317,7 +317,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
317
317
  /**
318
318
  * Create tools for connections that belong to this connector.
319
319
  * Filters connections by connectorKey internally.
320
- * Returns tools keyed as `${connectorKey}_${toolName}`.
320
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
321
321
  */
322
322
  createTools(connections, config, opts) {
323
323
  const myConnections = connections.filter(
@@ -327,7 +327,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
327
327
  for (const t of Object.values(this.tools)) {
328
328
  const tool = t.createTool(myConnections, config);
329
329
  const originalToModelOutput = tool.toModelOutput;
330
- result[`${this.connectorKey}_${t.name}`] = {
330
+ result[`connector_${this.connectorKey}_${t.name}`] = {
331
331
  ...tool,
332
332
  toModelOutput: async (options) => {
333
333
  if (!originalToModelOutput) {
@@ -457,10 +457,10 @@ var AUTH_TYPES = {
457
457
  // ../connectors/src/connectors/airtable/setup.ts
458
458
  var airtableOnboarding = new ConnectorOnboarding({
459
459
  dataOverviewInstructions: {
460
- en: `1. Call airtable_request with GET meta/bases/{baseId}/tables to list tables and their fields
461
- 2. Call airtable_request with GET {baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
462
- ja: `1. airtable_request \u3067 GET meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
463
- 2. airtable_request \u3067 GET {baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
460
+ en: `1. Call connector_airtable_request with GET meta/bases/{baseId}/tables to list tables and their fields
461
+ 2. Call connector_airtable_request with GET {baseId}/{tableIdOrName}?maxRecords=5 to sample records from key tables`,
462
+ ja: `1. connector_airtable_request \u3067 GET meta/bases/{baseId}/tables \u3092\u547C\u3073\u51FA\u3057\u3001\u30C6\u30FC\u30D6\u30EB\u3068\u30D5\u30A3\u30FC\u30EB\u30C9\u306E\u4E00\u89A7\u3092\u53D6\u5F97
463
+ 2. connector_airtable_request \u3067 GET {baseId}/{tableIdOrName}?maxRecords=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
464
464
  }
465
465
  });
466
466
 
@@ -498,6 +498,26 @@ async function listTables(params, baseId) {
498
498
  const data = await res.json();
499
499
  return data.tables ?? [];
500
500
  }
501
+ async function listSampleRecords(params, baseId, tableId) {
502
+ try {
503
+ const res = await apiFetch(
504
+ params,
505
+ `/${baseId}/${encodeURIComponent(tableId)}?maxRecords=3`
506
+ );
507
+ if (!res.ok) return [];
508
+ const data = await res.json();
509
+ return data.records ?? [];
510
+ } catch {
511
+ return [];
512
+ }
513
+ }
514
+ function formatCell(val) {
515
+ if (val == null) return "";
516
+ if (typeof val === "string") return val.length > 40 ? `${val.slice(0, 40)}\u2026` : val;
517
+ if (Array.isArray(val)) return `[${val.length} items]`;
518
+ if (typeof val === "object") return JSON.stringify(val).slice(0, 40);
519
+ return String(val);
520
+ }
501
521
  var airtableSetupFlow = {
502
522
  initialState: () => ({}),
503
523
  steps: [
@@ -569,6 +589,22 @@ var airtableSetupFlow = {
569
589
  sections.push(`| ${f.name} | ${f.type} | ${description || "-"} |`);
570
590
  }
571
591
  sections.push("");
592
+ const records = await listSampleRecords(rt.params, baseId, table.id);
593
+ if (records.length > 0) {
594
+ const sampleFields = (table.fields ?? []).slice(0, 5).map((f) => f.name);
595
+ if (sampleFields.length > 0) {
596
+ sections.push(`##### Sample records (${records.length})`, "");
597
+ sections.push(`| ${sampleFields.join(" | ")} |`);
598
+ sections.push(`| ${sampleFields.map(() => "---").join(" | ")} |`);
599
+ for (const record of records) {
600
+ const cells = sampleFields.map(
601
+ (name) => formatCell(record.fields?.[name]).replace(/\|/g, "\\|")
602
+ );
603
+ sections.push(`| ${cells.join(" | ")} |`);
604
+ }
605
+ sections.push("");
606
+ }
607
+ }
572
608
  }
573
609
  return sections.join("\n");
574
610
  }
@@ -660,7 +696,7 @@ var airtableConnector = new ConnectorPlugin({
660
696
  systemPrompt: {
661
697
  en: `### Tools
662
698
 
663
- - \`airtable_request\`: The only way to call the Airtable REST API. Use it to list tables, read records, and create/update records. The \`{baseId}\` placeholder in the path is automatically replaced. See the Airtable API Reference below for available endpoints and query parameters.
699
+ - \`connector_airtable_request\`: The only way to call the Airtable REST API. Use it to list tables, read records, and create/update records. The \`{baseId}\` placeholder in the path is automatically replaced. See the Airtable API Reference below for available endpoints and query parameters.
664
700
 
665
701
  ### Business Logic
666
702
 
@@ -719,7 +755,7 @@ export default async function handler(c: Context) {
719
755
  - If the response contains an \`offset\`, fetch the next page by appending \`?offset={offset}\` to the next request`,
720
756
  ja: `### \u30C4\u30FC\u30EB
721
757
 
722
- - \`airtable_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u53D6\u308A\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E \`{baseId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u306F\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3068\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u4E0B\u90E8\u306E\u300CAirtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
758
+ - \`connector_airtable_request\`: Airtable REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u306E\u53D6\u5F97\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u8AAD\u307F\u53D6\u308A\u3001\u30EC\u30B3\u30FC\u30C9\u306E\u4F5C\u6210\u30FB\u66F4\u65B0\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E \`{baseId}\` \u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u306F\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002\u5229\u7528\u53EF\u80FD\u306A\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u3068\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u4E0B\u90E8\u306E\u300CAirtable API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
723
759
 
724
760
  ### Business Logic
725
761
 
@@ -277,7 +277,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
277
277
  /**
278
278
  * Create tools for connections that belong to this connector.
279
279
  * Filters connections by connectorKey internally.
280
- * Returns tools keyed as `${connectorKey}_${toolName}`.
280
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
281
281
  */
282
282
  createTools(connections, config, opts) {
283
283
  const myConnections = connections.filter(
@@ -287,7 +287,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
287
287
  for (const t of Object.values(this.tools)) {
288
288
  const tool = t.createTool(myConnections, config);
289
289
  const originalToModelOutput = tool.toModelOutput;
290
- result[`${this.connectorKey}_${t.name}`] = {
290
+ result[`connector_${this.connectorKey}_${t.name}`] = {
291
291
  ...tool,
292
292
  toModelOutput: async (options) => {
293
293
  if (!originalToModelOutput) {
@@ -413,13 +413,13 @@ var AUTH_TYPES = {
413
413
  var amplitudeOnboarding = new ConnectorOnboarding({
414
414
  dataOverviewInstructions: {
415
415
  en: `1. Check the connection's region parameter: use https://analytics.eu.amplitude.com for EU, https://amplitude.com for US (default)
416
- 2. Call amplitude_request with GET {baseUrl}/api/2/events/list to list available event types
417
- 3. Call amplitude_request with GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH to export raw event data for a time range
416
+ 2. Call connector_amplitude_request with GET {baseUrl}/api/2/events/list to list available event types
417
+ 3. Call connector_amplitude_request with GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH to export raw event data for a time range
418
418
  4. Use GET {baseUrl}/api/2/usersearch?user=QUERY and GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID to explore user-level data
419
419
  NOTE: The Dashboard REST API endpoints (events/segmentation, funnels, retention, etc.) require a paid Growth or Enterprise plan. If you get a 403 Forbidden error, fall back to the Export API (/api/2/export) to retrieve raw events and perform aggregation in code instead.`,
420
420
  ja: `1. \u63A5\u7D9A\u306Eregion\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u78BA\u8A8D\uFF1AEU\u306E\u5834\u5408\u306F https://analytics.eu.amplitude.com\u3001US\uFF08\u30C7\u30D5\u30A9\u30EB\u30C8\uFF09\u306E\u5834\u5408\u306F https://amplitude.com \u3092\u4F7F\u7528
421
- 2. amplitude_request \u3067 GET {baseUrl}/api/2/events/list \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3092\u53D6\u5F97
422
- 3. amplitude_request \u3067 GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH \u3092\u547C\u3073\u51FA\u3057\u3001\u6307\u5B9A\u671F\u9593\u306E\u751F\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
421
+ 2. connector_amplitude_request \u3067 GET {baseUrl}/api/2/events/list \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3092\u53D6\u5F97
422
+ 3. connector_amplitude_request \u3067 GET {baseUrl}/api/2/export?start=YYYYMMDDTHH&end=YYYYMMDDTHH \u3092\u547C\u3073\u51FA\u3057\u3001\u6307\u5B9A\u671F\u9593\u306E\u751F\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
423
423
  4. GET {baseUrl}/api/2/usersearch?user=QUERY \u3084 GET {baseUrl}/api/2/useractivity?user=AMPLITUDE_ID \u3067\u30E6\u30FC\u30B6\u30FC\u30EC\u30D9\u30EB\u306E\u30C7\u30FC\u30BF\u3092\u63A2\u7D22
424
424
  \u6CE8\u610F: Dashboard REST API\uFF08events/segmentation\u3001funnels\u3001retention\u7B49\uFF09\u306F\u6709\u6599\u306EGrowth\u307E\u305F\u306FEnterprise\u30D7\u30E9\u30F3\u304C\u5FC5\u8981\u3067\u3059\u3002403 Forbidden\u30A8\u30E9\u30FC\u304C\u8FD4\u3055\u308C\u305F\u5834\u5408\u306F\u3001Export API\uFF08/api/2/export\uFF09\u3067\u751F\u30A4\u30D9\u30F3\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B3\u30FC\u30C9\u4E0A\u3067\u96C6\u8A08\u3092\u884C\u3063\u3066\u304F\u3060\u3055\u3044\u3002`
425
425
  }
@@ -645,7 +645,7 @@ var amplitudeConnector = new ConnectorPlugin({
645
645
  systemPrompt: {
646
646
  en: `### Tools
647
647
 
648
- - \`amplitude_request\`: The only way to call the Amplitude REST API. Use it for event segmentation, listing event types, user search, user activity, and data export. Authentication (Basic auth with API Key + Secret Key) is configured automatically. Provide the full URL including query parameters \u2014 the base URL varies by endpoint.
648
+ - \`connector_amplitude_request\`: The only way to call the Amplitude REST API. Use it for event segmentation, listing event types, user search, user activity, and data export. Authentication (Basic auth with API Key + Secret Key) is configured automatically. Provide the full URL including query parameters \u2014 the base URL varies by endpoint.
649
649
 
650
650
  ### Business Logic
651
651
 
@@ -709,7 +709,7 @@ IMPORTANT: Always start with the endpoints available on all plans. If you need a
709
709
  - \`g\` \u2014 Group by property`,
710
710
  ja: `### \u30C4\u30FC\u30EB
711
711
 
712
- - \`amplitude_request\`: Amplitude REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u3001\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u691C\u7D22\u3001\u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u3001\u30C7\u30FC\u30BF\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API Key + Secret Key\u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u542B\u3080\u5B8C\u5168\u306AURL\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 \u30D9\u30FC\u30B9URL\u306F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002
712
+ - \`connector_amplitude_request\`: Amplitude REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30A4\u30D9\u30F3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C6\u30FC\u30B7\u30E7\u30F3\u3001\u30A4\u30D9\u30F3\u30C8\u30BF\u30A4\u30D7\u4E00\u89A7\u3001\u30E6\u30FC\u30B6\u30FC\u691C\u7D22\u3001\u30E6\u30FC\u30B6\u30FC\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3\u3001\u30C7\u30FC\u30BF\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08API Key + Secret Key\u306B\u3088\u308BBasic\u8A8D\u8A3C\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u542B\u3080\u5B8C\u5168\u306AURL\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 \u30D9\u30FC\u30B9URL\u306F\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\u306B\u3088\u3063\u3066\u7570\u306A\u308A\u307E\u3059\u3002
713
713
 
714
714
  ### Business Logic
715
715
 
@@ -144,7 +144,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
144
144
  /**
145
145
  * Create tools for connections that belong to this connector.
146
146
  * Filters connections by connectorKey internally.
147
- * Returns tools keyed as `${connectorKey}_${toolName}`.
147
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
148
148
  */
149
149
  createTools(connections, config, opts) {
150
150
  const myConnections = connections.filter(
@@ -154,7 +154,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
154
154
  for (const t of Object.values(this.tools)) {
155
155
  const tool = t.createTool(myConnections, config);
156
156
  const originalToModelOutput = tool.toModelOutput;
157
- result[`${this.connectorKey}_${t.name}`] = {
157
+ result[`connector_${this.connectorKey}_${t.name}`] = {
158
158
  ...tool,
159
159
  toModelOutput: async (options) => {
160
160
  if (!originalToModelOutput) {
@@ -314,7 +314,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
314
314
  /**
315
315
  * Create tools for connections that belong to this connector.
316
316
  * Filters connections by connectorKey internally.
317
- * Returns tools keyed as `${connectorKey}_${toolName}`.
317
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
318
318
  */
319
319
  createTools(connections, config, opts) {
320
320
  const myConnections = connections.filter(
@@ -324,7 +324,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
324
324
  for (const t of Object.values(this.tools)) {
325
325
  const tool = t.createTool(myConnections, config);
326
326
  const originalToModelOutput = tool.toModelOutput;
327
- result[`${this.connectorKey}_${t.name}`] = {
327
+ result[`connector_${this.connectorKey}_${t.name}`] = {
328
328
  ...tool,
329
329
  toModelOutput: async (options) => {
330
330
  if (!originalToModelOutput) {
@@ -464,13 +464,13 @@ function normalizeRequestPath(path2, basePathSegment) {
464
464
  // ../connectors/src/connectors/asana/setup.ts
465
465
  var asanaOnboarding = new ConnectorOnboarding({
466
466
  dataOverviewInstructions: {
467
- en: `1. Call asana_request with GET /workspaces to list all available workspaces
468
- 2. Pick the first workspace and call asana_request with GET /projects?workspace=WORKSPACE_GID&opt_fields=name,archived,created_at to list projects
469
- 3. Pick one project and call asana_request with GET /tasks?project=PROJECT_GID&opt_fields=name,completed,assignee.name,due_on,created_at&limit=10 to sample tasks
467
+ en: `1. Call connector_asana_request with GET /workspaces to list all available workspaces
468
+ 2. Pick the first workspace and call connector_asana_request with GET /projects?workspace=WORKSPACE_GID&opt_fields=name,archived,created_at to list projects
469
+ 3. Pick one project and call connector_asana_request with GET /tasks?project=PROJECT_GID&opt_fields=name,completed,assignee.name,due_on,created_at&limit=10 to sample tasks
470
470
  4. Explore sections via GET /sections?project=PROJECT_GID if the project uses board or section-based workflows`,
471
- ja: `1. asana_request \u3067 GET /workspaces \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
472
- 2. \u6700\u521D\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u9078\u3073\u3001asana_request \u3067 GET /projects?workspace=WORKSPACE_GID&opt_fields=name,archived,created_at \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
473
- 3. \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30921\u3064\u9078\u3073\u3001asana_request \u3067 GET /tasks?project=PROJECT_GID&opt_fields=name,completed,assignee.name,due_on,created_at&limit=10 \u3092\u547C\u3073\u51FA\u3057\u3066\u30BF\u30B9\u30AF\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
471
+ ja: `1. connector_asana_request \u3067 GET /workspaces \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u4E00\u89A7\u3092\u53D6\u5F97
472
+ 2. \u6700\u521D\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u9078\u3073\u3001connector_asana_request \u3067 GET /projects?workspace=WORKSPACE_GID&opt_fields=name,archived,created_at \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97
473
+ 3. \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30921\u3064\u9078\u3073\u3001connector_asana_request \u3067 GET /tasks?project=PROJECT_GID&opt_fields=name,completed,assignee.name,due_on,created_at&limit=10 \u3092\u547C\u3073\u51FA\u3057\u3066\u30BF\u30B9\u30AF\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
474
474
  4. \u30DC\u30FC\u30C9\u3084\u30BB\u30AF\u30B7\u30E7\u30F3\u30D9\u30FC\u30B9\u306E\u30EF\u30FC\u30AF\u30D5\u30ED\u30FC\u306E\u5834\u5408\u306F GET /sections?project=PROJECT_GID \u3067\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u78BA\u8A8D`
475
475
  }
476
476
  });
@@ -501,6 +501,26 @@ async function listWorkspaces(params) {
501
501
  const data = await res.json();
502
502
  return data.data ?? [];
503
503
  }
504
+ async function getTaskBreakdown(params, projectGid) {
505
+ try {
506
+ const res = await apiFetch(
507
+ params,
508
+ `/projects/${encodeURIComponent(projectGid)}/tasks?limit=100&opt_fields=completed`
509
+ );
510
+ if (!res.ok) return null;
511
+ const data = await res.json();
512
+ const tasks = data.data ?? [];
513
+ const completed = tasks.filter((t) => t.completed).length;
514
+ const hasMore = !!data.next_page?.offset;
515
+ return {
516
+ total: tasks.length + (hasMore ? 100 : 0),
517
+ completed,
518
+ incomplete: tasks.length - completed
519
+ };
520
+ } catch {
521
+ return null;
522
+ }
523
+ }
504
524
  async function listProjects(params, workspaceGid) {
505
525
  const all = [];
506
526
  const fields = encodeURIComponent("name,team.name,current_status");
@@ -589,6 +609,13 @@ var asanaSetupFlow = {
589
609
  const status = project.current_status?.title ?? project.current_status?.text ?? "-";
590
610
  sections.push(`- Team: ${team}`);
591
611
  sections.push(`- Current status: ${status}`);
612
+ const tasks = await getTaskBreakdown(rt.params, gid);
613
+ if (tasks) {
614
+ const suffix = tasks.total >= 100 ? "+" : "";
615
+ sections.push(
616
+ `- Tasks: ${tasks.total}${suffix} (${tasks.completed} completed, ${tasks.incomplete} incomplete)`
617
+ );
618
+ }
592
619
  sections.push("");
593
620
  }
594
621
  return sections.join("\n");
@@ -710,7 +737,7 @@ var asanaConnector = new ConnectorPlugin({
710
737
  systemPrompt: {
711
738
  en: `### Tools
712
739
 
713
- - \`asana_request\`: The only way to call the Asana REST API. Use it to list workspaces, projects, tasks, users, sections, tags, and more. Authentication (Bearer token with Personal Access Token) is configured automatically. Provide the API path and optionally append query parameters like opt_fields for field selection.
740
+ - \`connector_asana_request\`: The only way to call the Asana REST API. Use it to list workspaces, projects, tasks, users, sections, tags, and more. Authentication (Bearer token with Personal Access Token) is configured automatically. Provide the API path and optionally append query parameters like opt_fields for field selection.
714
741
 
715
742
  ### Business Logic
716
743
 
@@ -797,7 +824,7 @@ export default async function handler(c: Context) {
797
824
  - Users: name, email, photo`,
798
825
  ja: `### \u30C4\u30FC\u30EB
799
826
 
800
- - \`asana_request\`: Asana REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30BF\u30B9\u30AF\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30BB\u30AF\u30B7\u30E7\u30F3\u3001\u30BF\u30B0\u306A\u3069\u306E\u4E00\u89A7\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Personal Access Token\u3092\u4F7F\u7528\u3057\u305FBearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002API\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3001\u5FC5\u8981\u306B\u5FDC\u3058\u3066opt_fields\u306A\u3069\u306E\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4ED8\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002
827
+ - \`connector_asana_request\`: Asana REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3001\u30BF\u30B9\u30AF\u3001\u30E6\u30FC\u30B6\u30FC\u3001\u30BB\u30AF\u30B7\u30E7\u30F3\u3001\u30BF\u30B0\u306A\u3069\u306E\u4E00\u89A7\u53D6\u5F97\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08Personal Access Token\u3092\u4F7F\u7528\u3057\u305FBearer\u30C8\u30FC\u30AF\u30F3\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002API\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3001\u5FC5\u8981\u306B\u5FDC\u3058\u3066opt_fields\u306A\u3069\u306E\u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u4ED8\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\u3002
801
828
 
802
829
  ### Business Logic
803
830
 
@@ -450,7 +450,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
450
450
  /**
451
451
  * Create tools for connections that belong to this connector.
452
452
  * Filters connections by connectorKey internally.
453
- * Returns tools keyed as `${connectorKey}_${toolName}`.
453
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
454
454
  */
455
455
  createTools(connections, config, opts) {
456
456
  const myConnections = connections.filter(
@@ -460,7 +460,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
460
460
  for (const t of Object.values(this.tools)) {
461
461
  const tool = t.createTool(myConnections, config);
462
462
  const originalToModelOutput = tool.toModelOutput;
463
- result[`${this.connectorKey}_${t.name}`] = {
463
+ result[`connector_${this.connectorKey}_${t.name}`] = {
464
464
  ...tool,
465
465
  toModelOutput: async (options) => {
466
466
  if (!originalToModelOutput) {
@@ -590,16 +590,16 @@ var AUTH_TYPES = {
590
590
  // ../connectors/src/connectors/attio/setup.ts
591
591
  var attioOnboarding = new ConnectorOnboarding({
592
592
  dataOverviewInstructions: {
593
- en: `1. Call attio_request with GET /objects to discover the object slugs actually configured in this workspace (typically people, companies, deals, plus any custom objects).
594
- 2. For each object you plan to use, call attio_request with GET /objects/{slug}/attributes to explore its attributes
595
- 3. Call attio_request with POST /objects/{slug}/records/query with { "limit": 5 } to sample records
596
- 4. Call attio_request with GET /workspace_members (top-level, snake_case) to list team members. The response shape is \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\`. You need this mapping in dashboard handlers to resolve \`owner\` and other actor-reference fields (which return \`referenced_actor_id\`, not a name). Sample one record that has an \`owner\` and confirm the shape \`{ referenced_actor_type, referenced_actor_id }\`, then use \`client.getWorkspaceMemberMap()\` in handlers to resolve IDs to names.
593
+ en: `1. Call connector_attio_request with GET /objects to discover the object slugs actually configured in this workspace (typically people, companies, deals, plus any custom objects).
594
+ 2. For each object you plan to use, call connector_attio_request with GET /objects/{slug}/attributes to explore its attributes
595
+ 3. Call connector_attio_request with POST /objects/{slug}/records/query with { "limit": 5 } to sample records
596
+ 4. Call connector_attio_request with GET /workspace_members (top-level, snake_case) to list team members. The response shape is \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\`. You need this mapping in dashboard handlers to resolve \`owner\` and other actor-reference fields (which return \`referenced_actor_id\`, not a name). Sample one record that has an \`owner\` and confirm the shape \`{ referenced_actor_type, referenced_actor_id }\`, then use \`client.getWorkspaceMemberMap()\` in handlers to resolve IDs to names.
597
597
  5. If an endpoint later returns 403 (tasks / threads / webhooks / meetings require specific scopes), call GET /self to inspect the token's active scopes.
598
598
  6. Explore lists via GET /lists as needed, and use /notes, /tasks, /threads, /comments, /webhooks, /meetings when the question requires them.`,
599
- ja: `1. attio_request \u3067 GET /objects \u3092\u547C\u3073\u51FA\u3057\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u901A\u5E38\u306F people / companies / deals\u3001\u52A0\u3048\u3066\u8A2D\u5B9A\u6E08\u307F\u306E\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09
600
- 2. \u4F7F\u3046\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3054\u3068\u306B attio_request \u3067 GET /objects/{slug}/attributes \u3092\u547C\u3073\u51FA\u3057\u3001\u5C5E\u6027\u3092\u78BA\u8A8D
601
- 3. attio_request \u3067 POST /objects/{slug}/records/query \u3092 { "limit": 5 } \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
602
- 4. attio_request \u3067 GET /workspace_members\uFF08\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u3001\u30B9\u30CD\u30FC\u30AF\u30B1\u30FC\u30B9\uFF09\u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3002\u30EC\u30B9\u30DD\u30F3\u30B9\u306F \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\` \u306E\u5F62\u5F0F\u3067\u3059\u3002\u3053\u306E\u30DE\u30C3\u30D4\u30F3\u30B0\u306F\u3001\`owner\` \u306A\u3069\u306E actor-reference \u30D5\u30A3\u30FC\u30EB\u30C9\uFF08\`referenced_actor_id\` \u3092\u8FD4\u3059\uFF09\u3092\u540D\u524D\u306B\u89E3\u6C7A\u3059\u308B\u305F\u3081\u306B\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u30CF\u30F3\u30C9\u30E9\u3067\u5FC5\u9808\u3067\u3059\u3002\`owner\` \u3092\u6301\u3064\u30EC\u30B3\u30FC\u30C9\u30921\u4EF6\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3057\u3001\`{ referenced_actor_type, referenced_actor_id }\` \u306E\u5F62\u3092\u78BA\u8A8D\u3057\u305F\u4E0A\u3067\u3001\u30CF\u30F3\u30C9\u30E9\u3067\u306F \`client.getWorkspaceMemberMap()\` \u3092\u4F7F\u3063\u3066 ID \u2192 \u540D\u524D \u306B\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044
599
+ ja: `1. connector_attio_request \u3067 GET /objects \u3092\u547C\u3073\u51FA\u3057\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u901A\u5E38\u306F people / companies / deals\u3001\u52A0\u3048\u3066\u8A2D\u5B9A\u6E08\u307F\u306E\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09
600
+ 2. \u4F7F\u3046\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3054\u3068\u306B connector_attio_request \u3067 GET /objects/{slug}/attributes \u3092\u547C\u3073\u51FA\u3057\u3001\u5C5E\u6027\u3092\u78BA\u8A8D
601
+ 3. connector_attio_request \u3067 POST /objects/{slug}/records/query \u3092 { "limit": 5 } \u3067\u547C\u3073\u51FA\u3057\u3001\u30EC\u30B3\u30FC\u30C9\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0
602
+ 4. connector_attio_request \u3067 GET /workspace_members\uFF08\u30C8\u30C3\u30D7\u30EC\u30D9\u30EB\u3001\u30B9\u30CD\u30FC\u30AF\u30B1\u30FC\u30B9\uFF09\u3092\u547C\u3073\u51FA\u3057\u3001\u30C1\u30FC\u30E0\u30E1\u30F3\u30D0\u30FC\u4E00\u89A7\u3092\u53D6\u5F97\u3002\u30EC\u30B9\u30DD\u30F3\u30B9\u306F \`{ data: [{ id: { workspace_member_id }, first_name, last_name, email_address, ... }] }\` \u306E\u5F62\u5F0F\u3067\u3059\u3002\u3053\u306E\u30DE\u30C3\u30D4\u30F3\u30B0\u306F\u3001\`owner\` \u306A\u3069\u306E actor-reference \u30D5\u30A3\u30FC\u30EB\u30C9\uFF08\`referenced_actor_id\` \u3092\u8FD4\u3059\uFF09\u3092\u540D\u524D\u306B\u89E3\u6C7A\u3059\u308B\u305F\u3081\u306B\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u30CF\u30F3\u30C9\u30E9\u3067\u5FC5\u9808\u3067\u3059\u3002\`owner\` \u3092\u6301\u3064\u30EC\u30B3\u30FC\u30C9\u30921\u4EF6\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3057\u3001\`{ referenced_actor_type, referenced_actor_id }\` \u306E\u5F62\u3092\u78BA\u8A8D\u3057\u305F\u4E0A\u3067\u3001\u30CF\u30F3\u30C9\u30E9\u3067\u306F \`client.getWorkspaceMemberMap()\` \u3092\u4F7F\u3063\u3066 ID \u2192 \u540D\u524D \u306B\u89E3\u6C7A\u3057\u3066\u304F\u3060\u3055\u3044
603
603
  5. \u5F8C\u6BB5\u3067 403 \u304C\u51FA\u305F\u5834\u5408\uFF08tasks / threads / webhooks / meetings \u306A\u3069\u306F\u500B\u5225\u306E scope \u304C\u5FC5\u8981\uFF09\u306F\u3001GET /self \u3092\u547C\u3073\u51FA\u3057\u3066API\u30C8\u30FC\u30AF\u30F3\u306E\u6709\u52B9 scope \u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044
604
604
  6. \u5FC5\u8981\u306B\u5FDC\u3058\u3066 GET /lists \u3067\u30EA\u30B9\u30C8\u3092\u63A2\u7D22\u3057\u3001/notes\u3001/tasks\u3001/threads\u3001/comments\u3001/webhooks\u3001/meetings \u3082\u6D3B\u7528\u3057\u3066\u304F\u3060\u3055\u3044`
605
605
  }
@@ -642,6 +642,21 @@ async function listAttributes(params, slug) {
642
642
  const data = await res.json();
643
643
  return data.data ?? [];
644
644
  }
645
+ async function probeRecordCount(params, slug) {
646
+ try {
647
+ const res = await apiFetch(params, `/objects/${slug}/records/query`, {
648
+ method: "POST",
649
+ headers: { "Content-Type": "application/json" },
650
+ body: JSON.stringify({ limit: 1 })
651
+ });
652
+ if (!res.ok) return null;
653
+ const data = await res.json();
654
+ const found = (data.data ?? []).length;
655
+ return found > 0 ? "1+" : "0";
656
+ } catch {
657
+ return null;
658
+ }
659
+ }
645
660
  var attioSetupFlow = {
646
661
  initialState: () => ({}),
647
662
  steps: [
@@ -677,7 +692,9 @@ var attioSetupFlow = {
677
692
  });
678
693
  const sections = ["## Attio", ""];
679
694
  for (const slug of targetObjects) {
680
- sections.push(`### Object: ${slug}`, "");
695
+ const recordIndicator = await probeRecordCount(rt.params, slug);
696
+ const heading = recordIndicator ? `### Object: ${slug} (records: ${recordIndicator})` : `### Object: ${slug}`;
697
+ sections.push(heading, "");
681
698
  const attrs = await listAttributes(rt.params, slug);
682
699
  const limited = attrs.slice(0, ATTIO_SETUP_MAX_ATTRIBUTES);
683
700
  sections.push("| Attribute | Type | Title |");
@@ -793,7 +810,7 @@ var attioConnector = new ConnectorPlugin({
793
810
  systemPrompt: {
794
811
  en: `### Tools
795
812
 
796
- - \`attio_request\`: The only way to call the Attio REST API. Use it for every Attio resource \u2014 records (people, companies, deals, and any custom objects configured in the workspace), their attributes, lists and entries, workspace members, notes, tasks, threads, comments, webhooks, and meetings. Authentication (Bearer token) is configured automatically. Querying records uses POST \`/objects/{object}/records/query\` with a JSON body. Use PATCH for partial updates (append multiselect) and PUT for full updates (overwrite multiselect). Always call GET \`/objects\` first to discover the actual object slugs in this workspace.
813
+ - \`connector_attio_request\`: The only way to call the Attio REST API. Use it for every Attio resource \u2014 records (people, companies, deals, and any custom objects configured in the workspace), their attributes, lists and entries, workspace members, notes, tasks, threads, comments, webhooks, and meetings. Authentication (Bearer token) is configured automatically. Querying records uses POST \`/objects/{object}/records/query\` with a JSON body. Use PATCH for partial updates (append multiselect) and PUT for full updates (overwrite multiselect). Always call GET \`/objects\` first to discover the actual object slugs in this workspace.
797
814
 
798
815
  ### Business Logic
799
816
 
@@ -940,7 +957,7 @@ export default async function handler(c: Context) {
940
957
  - \`offset\` \u2014 pagination offset`,
941
958
  ja: `### \u30C4\u30FC\u30EB
942
959
 
943
- - \`attio_request\`: Attio REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EC\u30B3\u30FC\u30C9\uFF08people\u3001companies\u3001deals\u3001\u304A\u3088\u3073\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u8A2D\u5B9A\u3055\u308C\u305F\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09\u3068\u305D\u306E\u5C5E\u6027\u3001\u30EA\u30B9\u30C8\u3068\u30A8\u30F3\u30C8\u30EA\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E1\u30F3\u30D0\u30FC\u3001\u30CE\u30FC\u30C8\u3001\u30BF\u30B9\u30AF\u3001\u30B9\u30EC\u30C3\u30C9\u3001\u30B3\u30E1\u30F3\u30C8\u3001Webhook\u3001\u30DF\u30FC\u30C6\u30A3\u30F3\u30B0\u306A\u3069\u3001\u3059\u3079\u3066\u306EAttio\u30EA\u30BD\u30FC\u30B9\u306E\u64CD\u4F5C\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\u3002\u30EC\u30B3\u30FC\u30C9\u306E\u30AF\u30A8\u30EA\u306B\u306F POST \`/objects/{object}/records/query\` \u3092\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306EJSON\u30DC\u30C7\u30A3\u3067\u4F7F\u7528\u3057\u307E\u3059\u3002\u90E8\u5206\u66F4\u65B0\uFF08multiselect\u306E\u8FFD\u52A0\uFF09\u306B\u306FPATCH\u3001\u5168\u7F6E\u63DB\uFF08multiselect\u306E\u4E0A\u66F8\u304D\uFF09\u306B\u306FPUT\u3092\u4F7F\u3044\u307E\u3059\u3002**\u5FC5\u305A** \u6700\u521D\u306B GET \`/objects\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
960
+ - \`connector_attio_request\`: Attio REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u30EC\u30B3\u30FC\u30C9\uFF08people\u3001companies\u3001deals\u3001\u304A\u3088\u3073\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u8A2D\u5B9A\u3055\u308C\u305F\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF09\u3068\u305D\u306E\u5C5E\u6027\u3001\u30EA\u30B9\u30C8\u3068\u30A8\u30F3\u30C8\u30EA\u3001\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u30E1\u30F3\u30D0\u30FC\u3001\u30CE\u30FC\u30C8\u3001\u30BF\u30B9\u30AF\u3001\u30B9\u30EC\u30C3\u30C9\u3001\u30B3\u30E1\u30F3\u30C8\u3001Webhook\u3001\u30DF\u30FC\u30C6\u30A3\u30F3\u30B0\u306A\u3069\u3001\u3059\u3079\u3066\u306EAttio\u30EA\u30BD\u30FC\u30B9\u306E\u64CD\u4F5C\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\u3002\u30EC\u30B3\u30FC\u30C9\u306E\u30AF\u30A8\u30EA\u306B\u306F POST \`/objects/{object}/records/query\` \u3092\u30D5\u30A3\u30EB\u30BF\u4ED8\u304D\u306EJSON\u30DC\u30C7\u30A3\u3067\u4F7F\u7528\u3057\u307E\u3059\u3002\u90E8\u5206\u66F4\u65B0\uFF08multiselect\u306E\u8FFD\u52A0\uFF09\u306B\u306FPATCH\u3001\u5168\u7F6E\u63DB\uFF08multiselect\u306E\u4E0A\u66F8\u304D\uFF09\u306B\u306FPUT\u3092\u4F7F\u3044\u307E\u3059\u3002**\u5FC5\u305A** \u6700\u521D\u306B GET \`/objects\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u3053\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u5B9F\u5728\u3059\u308B\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8slug\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
944
961
 
945
962
  ### Business Logic
946
963
 
@@ -216,7 +216,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
216
216
  /**
217
217
  * Create tools for connections that belong to this connector.
218
218
  * Filters connections by connectorKey internally.
219
- * Returns tools keyed as `${connectorKey}_${toolName}`.
219
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
220
220
  */
221
221
  createTools(connections, config, opts) {
222
222
  const myConnections = connections.filter(
@@ -226,7 +226,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
226
226
  for (const t of Object.values(this.tools)) {
227
227
  const tool = t.createTool(myConnections, config);
228
228
  const originalToModelOutput = tool.toModelOutput;
229
- result[`${this.connectorKey}_${t.name}`] = {
229
+ result[`connector_${this.connectorKey}_${t.name}`] = {
230
230
  ...tool,
231
231
  toModelOutput: async (options) => {
232
232
  if (!originalToModelOutput) {
@@ -880,9 +880,9 @@ var awsBillingConnector = new ConnectorPlugin({
880
880
  systemPrompt: {
881
881
  en: `### Tools
882
882
 
883
- - \`aws-billing-service-account_getCostAndUsage\`: Primary tool for querying historical AWS cost and usage. Use it for spend breakdowns by service/account/region/usage-type, month-over-month comparisons, and identifying cost drivers. Pass a TimePeriod (YYYY-MM-DD), Granularity (DAILY/MONTHLY/HOURLY), Metrics, and optionally GroupBy / Filter. See the Cost Explorer Reference below for valid keys.
884
- - \`aws-billing-service-account_getDimensionValues\`: Enumerate the valid values for a single Cost Explorer dimension (e.g., list all SERVICE names, LINKED_ACCOUNT IDs, REGIONS). Use this before constructing a Filter so the Filter Expression contains valid values.
885
- - \`aws-billing-service-account_getCostForecast\`: Forecast future cost or usage. Use this for "what will spend look like next month" questions. The TimePeriod must be in the future.
883
+ - \`connector_aws-billing-service-account_getCostAndUsage\`: Primary tool for querying historical AWS cost and usage. Use it for spend breakdowns by service/account/region/usage-type, month-over-month comparisons, and identifying cost drivers. Pass a TimePeriod (YYYY-MM-DD), Granularity (DAILY/MONTHLY/HOURLY), Metrics, and optionally GroupBy / Filter. See the Cost Explorer Reference below for valid keys.
884
+ - \`connector_aws-billing-service-account_getDimensionValues\`: Enumerate the valid values for a single Cost Explorer dimension (e.g., list all SERVICE names, LINKED_ACCOUNT IDs, REGIONS). Use this before constructing a Filter so the Filter Expression contains valid values.
885
+ - \`connector_aws-billing-service-account_getCostForecast\`: Forecast future cost or usage. Use this for "what will spend look like next month" questions. The TimePeriod must be in the future.
886
886
 
887
887
  ### Cost Explorer Reference
888
888
 
@@ -965,9 +965,9 @@ export default async function handler(c: Context) {
965
965
  \`\`\``,
966
966
  ja: `### \u30C4\u30FC\u30EB
967
967
 
968
- - \`aws-billing-service-account_getCostAndUsage\`: AWS\u306E\u904E\u53BB\u306E\u30B3\u30B9\u30C8\u30FB\u4F7F\u7528\u91CF\u3092\u53D6\u5F97\u3059\u308B\u30E1\u30A4\u30F3\u30C4\u30FC\u30EB\u3002\u30B5\u30FC\u30D3\u30B9\u5225\u30FB\u30A2\u30AB\u30A6\u30F3\u30C8\u5225\u30FB\u30EA\u30FC\u30B8\u30E7\u30F3\u5225\u30FB\u5229\u7528\u30BF\u30A4\u30D7\u5225\u306E\u652F\u51FA\u5185\u8A33\u3001\u524D\u6708\u6BD4\u8F03\u3001\u4E3B\u8981\u30B3\u30B9\u30C8\u8981\u56E0\u306E\u7279\u5B9A\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002TimePeriod (YYYY-MM-DD)\u3001Granularity (DAILY/MONTHLY/HOURLY)\u3001Metrics\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u3067 GroupBy / Filter \u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\u6709\u52B9\u306A\u30AD\u30FC\u306F\u4E0B\u8A18\u300CCost Explorer \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3002
969
- - \`aws-billing-service-account_getDimensionValues\`: \u5358\u4E00\u306ECost Explorer\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3\u306B\u3064\u3044\u3066\u6709\u52B9\u306A\u5024\u3092\u5217\u6319\u3057\u307E\u3059\uFF08\u4F8B: \u5168 SERVICE \u540D\u3001LINKED_ACCOUNT ID\u3001REGION \u306E\u53D6\u5F97\uFF09\u3002Filter \u3092\u69CB\u7BC9\u3059\u308B\u524D\u306B\u3053\u306E\u30C4\u30FC\u30EB\u3067\u6709\u52B9\u5024\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
970
- - \`aws-billing-service-account_getCostForecast\`: \u5C06\u6765\u306E\u30B3\u30B9\u30C8\u30FB\u4F7F\u7528\u91CF\u3092\u4E88\u6E2C\u3057\u307E\u3059\u3002\u300C\u6765\u6708\u306E\u652F\u51FA\u898B\u8FBC\u307F\u306F\uFF1F\u300D\u306E\u3088\u3046\u306A\u8CEA\u554F\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002TimePeriod \u306F\u672A\u6765\u306E\u65E5\u4ED8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
968
+ - \`connector_aws-billing-service-account_getCostAndUsage\`: AWS\u306E\u904E\u53BB\u306E\u30B3\u30B9\u30C8\u30FB\u4F7F\u7528\u91CF\u3092\u53D6\u5F97\u3059\u308B\u30E1\u30A4\u30F3\u30C4\u30FC\u30EB\u3002\u30B5\u30FC\u30D3\u30B9\u5225\u30FB\u30A2\u30AB\u30A6\u30F3\u30C8\u5225\u30FB\u30EA\u30FC\u30B8\u30E7\u30F3\u5225\u30FB\u5229\u7528\u30BF\u30A4\u30D7\u5225\u306E\u652F\u51FA\u5185\u8A33\u3001\u524D\u6708\u6BD4\u8F03\u3001\u4E3B\u8981\u30B3\u30B9\u30C8\u8981\u56E0\u306E\u7279\u5B9A\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002TimePeriod (YYYY-MM-DD)\u3001Granularity (DAILY/MONTHLY/HOURLY)\u3001Metrics\u3001\u30AA\u30D7\u30B7\u30E7\u30F3\u3067 GroupBy / Filter \u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\u6709\u52B9\u306A\u30AD\u30FC\u306F\u4E0B\u8A18\u300CCost Explorer \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3002
969
+ - \`connector_aws-billing-service-account_getDimensionValues\`: \u5358\u4E00\u306ECost Explorer\u30C7\u30A3\u30E1\u30F3\u30B7\u30E7\u30F3\u306B\u3064\u3044\u3066\u6709\u52B9\u306A\u5024\u3092\u5217\u6319\u3057\u307E\u3059\uFF08\u4F8B: \u5168 SERVICE \u540D\u3001LINKED_ACCOUNT ID\u3001REGION \u306E\u53D6\u5F97\uFF09\u3002Filter \u3092\u69CB\u7BC9\u3059\u308B\u524D\u306B\u3053\u306E\u30C4\u30FC\u30EB\u3067\u6709\u52B9\u5024\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002
970
+ - \`connector_aws-billing-service-account_getCostForecast\`: \u5C06\u6765\u306E\u30B3\u30B9\u30C8\u30FB\u4F7F\u7528\u91CF\u3092\u4E88\u6E2C\u3057\u307E\u3059\u3002\u300C\u6765\u6708\u306E\u652F\u51FA\u898B\u8FBC\u307F\u306F\uFF1F\u300D\u306E\u3088\u3046\u306A\u8CEA\u554F\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002TimePeriod \u306F\u672A\u6765\u306E\u65E5\u4ED8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
971
971
 
972
972
  ### Cost Explorer \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
973
973
 
@@ -513,7 +513,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
513
513
  /**
514
514
  * Create tools for connections that belong to this connector.
515
515
  * Filters connections by connectorKey internally.
516
- * Returns tools keyed as `${connectorKey}_${toolName}`.
516
+ * Returns tools keyed as `connector_${connectorKey}_${toolName}`.
517
517
  */
518
518
  createTools(connections, config, opts) {
519
519
  const myConnections = connections.filter(
@@ -523,7 +523,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
523
523
  for (const t of Object.values(this.tools)) {
524
524
  const tool = t.createTool(myConnections, config);
525
525
  const originalToModelOutput = tool.toModelOutput;
526
- result[`${this.connectorKey}_${t.name}`] = {
526
+ result[`connector_${this.connectorKey}_${t.name}`] = {
527
527
  ...tool,
528
528
  toModelOutput: async (options) => {
529
529
  if (!originalToModelOutput) {
@@ -756,6 +756,28 @@ function buildFlow(options) {
756
756
  fetchAll: () => fetchTableNames(rt.params, schema),
757
757
  limit: SQLSERVER_SETUP_MAX_TABLES
758
758
  });
759
+ let rowCounts = /* @__PURE__ */ new Map();
760
+ try {
761
+ const countRows = await runSqlServerSetupQuery(
762
+ rt.params,
763
+ `SELECT t.TABLE_NAME, SUM(p.rows) AS row_count
764
+ FROM INFORMATION_SCHEMA.TABLES t
765
+ JOIN sys.partitions p
766
+ ON OBJECT_ID(t.TABLE_SCHEMA + '.' + t.TABLE_NAME) = p.object_id
767
+ AND p.index_id IN (0, 1)
768
+ WHERE t.TABLE_SCHEMA = ${quoteLiteral(schema)}
769
+ AND t.TABLE_TYPE IN ('BASE TABLE', 'VIEW')
770
+ GROUP BY t.TABLE_NAME`,
771
+ forceEncrypt
772
+ );
773
+ rowCounts = new Map(
774
+ countRows.map((r) => [
775
+ String(r["TABLE_NAME"] ?? ""),
776
+ Number(r["row_count"] ?? 0)
777
+ ])
778
+ );
779
+ } catch {
780
+ }
759
781
  const sections = [
760
782
  `## ${connectorName}`,
761
783
  "",
@@ -772,7 +794,9 @@ function buildFlow(options) {
772
794
  ORDER BY ORDINAL_POSITION`,
773
795
  forceEncrypt
774
796
  );
775
- sections.push(`#### Table: ${table}`, "");
797
+ const rowCount = rowCounts.get(table);
798
+ const heading = typeof rowCount === "number" ? `#### Table: ${table} (~${rowCount.toLocaleString()} rows)` : `#### Table: ${table}`;
799
+ sections.push(heading, "");
776
800
  sections.push("| Column | Type | Nullable | Default |");
777
801
  sections.push("|--------|------|----------|---------|");
778
802
  for (const c of cols) {
@@ -805,11 +829,11 @@ init_utils();
805
829
  // ../connectors/src/connectors/azure-sql/setup.ts
806
830
  var azureSqlOnboarding = new ConnectorOnboarding({
807
831
  dataOverviewInstructions: {
808
- en: `1. Use azure-sql_executeQuery to confirm the database flavor: \`SELECT @@VERSION\` (Azure SQL returns "Microsoft SQL Azure \u2026")
832
+ en: `1. Use connector_azure-sql_executeQuery to confirm the database flavor: \`SELECT @@VERSION\` (Azure SQL returns "Microsoft SQL Azure \u2026")
809
833
  2. List user tables: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
810
834
  3. For key tables, fetch column info: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
811
835
  4. Sample up to 3 tables. Azure SQL is T-SQL, so use \`TOP\` rather than \`LIMIT\`: \`SELECT TOP 5 * FROM <schema>.<table_name>\``,
812
- ja: `1. azure-sql_executeQuery \u3067\u30D5\u30EC\u30FC\u30D0\u30FC\u3092\u78BA\u8A8D: \`SELECT @@VERSION\`\uFF08Azure SQL \u306F "Microsoft SQL Azure \u2026" \u3092\u8FD4\u3057\u307E\u3059\uFF09
836
+ ja: `1. connector_azure-sql_executeQuery \u3067\u30D5\u30EC\u30FC\u30D0\u30FC\u3092\u78BA\u8A8D: \`SELECT @@VERSION\`\uFF08Azure SQL \u306F "Microsoft SQL Azure \u2026" \u3092\u8FD4\u3057\u307E\u3059\uFF09
813
837
  2. \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
814
838
  3. \u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30AB\u30E9\u30E0\u60C5\u5831: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
815
839
  4. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u6700\u59273\u30C6\u30FC\u30D6\u30EB\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3002Azure SQL \u306F T-SQL \u306E\u305F\u3081 \`LIMIT\` \u3067\u306F\u306A\u304F \`TOP\` \u3092\u4F7F\u7528: \`SELECT TOP 5 * FROM <schema>.<table_name>\``
@@ -915,7 +939,7 @@ var azureSqlConnector = new ConnectorPlugin({
915
939
  systemPrompt: {
916
940
  en: `### Tools
917
941
 
918
- - \`azure-sql_executeQuery\`: Executes a T-SQL query against Azure SQL Database and returns rows. Use for schema exploration via \`INFORMATION_SCHEMA\` and data sampling. See the SQL Reference below for Azure SQL-specific notes.
942
+ - \`connector_azure-sql_executeQuery\`: Executes a T-SQL query against Azure SQL Database and returns rows. Use for schema exploration via \`INFORMATION_SCHEMA\` and data sampling. See the SQL Reference below for Azure SQL-specific notes.
919
943
 
920
944
  ### Business Logic
921
945
 
@@ -932,7 +956,7 @@ The business logic type for this connector is "sql".
932
956
  - Row-limit compatibility: the platform's server-logic schema inference may wrap your query as \`SELECT * FROM (<inner>) AS _sq LIMIT N\`. T-SQL does not understand \`LIMIT\`, so the connector detects this exact wrapper at \`query()\` time, executes \`<inner>\` directly, and slices the first N rows in JS. You do not need to handle this \u2014 but do not author your own \`LIMIT\` clauses; use \`TOP\` / \`OFFSET ... FETCH NEXT\` in queries you write.`,
933
957
  ja: `### \u30C4\u30FC\u30EB
934
958
 
935
- - \`azure-sql_executeQuery\`: Azure SQL Database \u306B\u5BFE\u3057\u3066 T-SQL \u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`INFORMATION_SCHEMA\` \u3092\u4F7F\u3063\u305F\u30B9\u30AD\u30FC\u30DE\u63A2\u7D22\u3084\u30C7\u30FC\u30BF\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u306B\u4F7F\u3044\u307E\u3059\u3002Azure SQL \u56FA\u6709\u306E\u6CE8\u610F\u70B9\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
959
+ - \`connector_azure-sql_executeQuery\`: Azure SQL Database \u306B\u5BFE\u3057\u3066 T-SQL \u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`INFORMATION_SCHEMA\` \u3092\u4F7F\u3063\u305F\u30B9\u30AD\u30FC\u30DE\u63A2\u7D22\u3084\u30C7\u30FC\u30BF\u306E\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u306B\u4F7F\u3044\u307E\u3059\u3002Azure SQL \u56FA\u6709\u306E\u6CE8\u610F\u70B9\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
936
960
 
937
961
  ### Business Logic
938
962