@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.
- package/dist/cli/index.js +3281 -731
- package/dist/connectors/airtable-oauth.js +48 -8
- package/dist/connectors/airtable.js +44 -8
- package/dist/connectors/amplitude.js +8 -8
- package/dist/connectors/anthropic.js +2 -2
- package/dist/connectors/asana.js +37 -10
- package/dist/connectors/attio.js +30 -13
- package/dist/connectors/aws-billing.js +8 -8
- package/dist/connectors/azure-sql.js +31 -7
- package/dist/connectors/backlog-api-key.js +40 -15
- package/dist/connectors/clickup.js +50 -10
- package/dist/connectors/cosmosdb.js +12 -12
- package/dist/connectors/customerio.js +8 -8
- package/dist/connectors/dbt.js +686 -25
- package/dist/connectors/freshdesk.js +82 -8
- package/dist/connectors/freshsales.js +8 -8
- package/dist/connectors/freshservice.js +8 -8
- package/dist/connectors/gamma.js +15 -15
- package/dist/connectors/gemini.js +2 -2
- package/dist/connectors/github.js +12 -12
- package/dist/connectors/gmail-oauth.js +10 -10
- package/dist/connectors/gmail.js +4 -4
- package/dist/connectors/google-ads.js +8 -8
- package/dist/connectors/google-analytics-oauth.js +152 -25
- package/dist/connectors/google-analytics.js +490 -96
- package/dist/connectors/google-audit-log.js +4 -4
- package/dist/connectors/google-calendar-oauth.js +61 -15
- package/dist/connectors/google-calendar.js +61 -11
- package/dist/connectors/google-docs.js +10 -10
- package/dist/connectors/google-drive.js +32 -10
- package/dist/connectors/google-search-console-oauth.js +126 -17
- package/dist/connectors/google-sheets.js +6 -6
- package/dist/connectors/google-slides.js +10 -10
- package/dist/connectors/grafana.js +45 -10
- package/dist/connectors/hubspot-oauth.js +41 -9
- package/dist/connectors/hubspot.js +25 -9
- package/dist/connectors/influxdb.js +8 -8
- package/dist/connectors/intercom-oauth.js +72 -12
- package/dist/connectors/intercom.js +12 -12
- package/dist/connectors/jdbc.js +6 -6
- package/dist/connectors/jira-api-key.js +68 -11
- package/dist/connectors/kintone-api-token.js +66 -18
- package/dist/connectors/kintone.js +54 -11
- package/dist/connectors/linear.js +54 -12
- package/dist/connectors/linkedin-ads.js +41 -14
- package/dist/connectors/mailchimp-oauth.js +6 -6
- package/dist/connectors/mailchimp.js +6 -6
- package/dist/connectors/meta-ads-oauth.js +33 -14
- package/dist/connectors/meta-ads.js +35 -14
- package/dist/connectors/mixpanel.js +8 -8
- package/dist/connectors/monday.js +9 -9
- package/dist/connectors/mongodb.js +8 -8
- package/dist/connectors/notion-oauth.js +60 -11
- package/dist/connectors/notion.js +60 -11
- package/dist/connectors/openai.js +2 -2
- package/dist/connectors/oracle.js +23 -7
- package/dist/connectors/outlook-oauth.js +20 -20
- package/dist/connectors/powerbi-oauth.js +12 -12
- package/dist/connectors/salesforce.js +42 -9
- package/dist/connectors/semrush.js +6 -6
- package/dist/connectors/sentry.js +36 -10
- package/dist/connectors/shopify-oauth.js +43 -10
- package/dist/connectors/shopify.js +8 -8
- package/dist/connectors/sqlserver.js +31 -7
- package/dist/connectors/stripe-api-key.js +66 -15
- package/dist/connectors/stripe-oauth.js +70 -19
- package/dist/connectors/supabase.js +22 -5
- package/dist/connectors/tableau.js +14 -14
- package/dist/connectors/tiktok-ads.js +37 -16
- package/dist/connectors/wix-store.js +8 -8
- package/dist/connectors/zendesk-oauth.js +55 -12
- package/dist/connectors/zendesk.js +12 -12
- package/dist/index.js +3299 -729
- package/dist/main.js +3299 -729
- package/dist/vite-plugin.js +3279 -729
- 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
|
|
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[
|
|
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
|
|
482
|
-
2. Call
|
|
483
|
-
ja: `1.
|
|
484
|
-
2.
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
|
461
|
-
2. Call
|
|
462
|
-
ja: `1.
|
|
463
|
-
2.
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
|
417
|
-
3. Call
|
|
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.
|
|
422
|
-
3.
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
157
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
158
158
|
...tool,
|
|
159
159
|
toModelOutput: async (options) => {
|
|
160
160
|
if (!originalToModelOutput) {
|
package/dist/connectors/asana.js
CHANGED
|
@@ -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
|
|
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[
|
|
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
|
|
468
|
-
2. Pick the first workspace and call
|
|
469
|
-
3. Pick one project and call
|
|
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.
|
|
472
|
-
2. \u6700\u521D\u306E\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u9078\u3073\
|
|
473
|
-
3. \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30921\u3064\u9078\u3073\
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
package/dist/connectors/attio.js
CHANGED
|
@@ -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
|
|
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[
|
|
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
|
|
594
|
-
2. For each object you plan to use, call
|
|
595
|
-
3. Call
|
|
596
|
-
4. Call
|
|
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.
|
|
600
|
-
2. \u4F7F\u3046\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3054\u3068\u306B
|
|
601
|
-
3.
|
|
602
|
-
4.
|
|
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
|
-
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
-
- \`
|
|
884
|
-
- \`
|
|
885
|
-
- \`
|
|
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
|
-
- \`
|
|
969
|
-
- \`
|
|
970
|
-
- \`
|
|
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
|
|
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[
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
- \`
|
|
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
|
-
- \`
|
|
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
|
|