@squadbase/vite-server 0.1.17-dev.a107052 → 0.1.17-dev.d4fff69
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 +4284 -820
- 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 +47 -10
- 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 +475 -95
- 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/hackernews.d.ts +5 -0
- package/dist/connectors/hackernews.js +890 -0
- 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 +37 -10
- 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 +39 -11
- package/dist/connectors/outlook-oauth.js +21 -21
- package/dist/connectors/powerbi-oauth.js +13 -13
- 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 +47 -10
- package/dist/connectors/stripe-api-key.js +66 -15
- package/dist/connectors/stripe-oauth.js +70 -19
- package/dist/connectors/supabase.js +31 -6
- package/dist/connectors/tableau.js +15 -15
- package/dist/connectors/tiktok-ads.js +37 -16
- package/dist/connectors/wix-store.js +8 -8
- package/dist/connectors/x.d.ts +5 -0
- package/dist/connectors/x.js +927 -0
- package/dist/connectors/zendesk-oauth.js +55 -12
- package/dist/connectors/zendesk.js +12 -12
- package/dist/index.js +4302 -818
- package/dist/main.js +4302 -818
- package/dist/vite-plugin.js +4282 -818
- package/package.json +9 -1
|
@@ -333,7 +333,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
333
333
|
/**
|
|
334
334
|
* Create tools for connections that belong to this connector.
|
|
335
335
|
* Filters connections by connectorKey internally.
|
|
336
|
-
* Returns tools keyed as
|
|
336
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
337
337
|
*/
|
|
338
338
|
createTools(connections, config, opts) {
|
|
339
339
|
const myConnections = connections.filter(
|
|
@@ -343,7 +343,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
343
343
|
for (const t of Object.values(this.tools)) {
|
|
344
344
|
const tool = t.createTool(myConnections, config);
|
|
345
345
|
const originalToModelOutput = tool.toModelOutput;
|
|
346
|
-
result[
|
|
346
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
347
347
|
...tool,
|
|
348
348
|
toModelOutput: async (options) => {
|
|
349
349
|
if (!originalToModelOutput) {
|
|
@@ -473,11 +473,11 @@ var AUTH_TYPES = {
|
|
|
473
473
|
// ../connectors/src/connectors/salesforce/setup.ts
|
|
474
474
|
var salesforceOnboarding = new ConnectorOnboarding({
|
|
475
475
|
dataOverviewInstructions: {
|
|
476
|
-
en: `1. Call
|
|
477
|
-
2. Call
|
|
476
|
+
en: `1. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/ to list available sObjects (standard + custom)
|
|
477
|
+
2. Call connector_salesforce_request with GET /services/data/v60.0/sobjects/Account/describe to inspect Account fields; repeat for Contact, Opportunity, Lead as needed
|
|
478
478
|
3. Run a sample SOQL query: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 to verify access and explore data`,
|
|
479
|
-
ja: `1.
|
|
480
|
-
2.
|
|
479
|
+
ja: `1. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5229\u7528\u53EF\u80FD\u306A sObject\uFF08\u6A19\u6E96 + \u30AB\u30B9\u30BF\u30E0\uFF09\u3092\u4E00\u89A7\u53D6\u5F97
|
|
480
|
+
2. connector_salesforce_request \u3067 GET /services/data/v60.0/sobjects/Account/describe \u3092\u547C\u3073\u51FA\u3057 Account \u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u78BA\u8A8D\u3002Contact / Opportunity / Lead \u306A\u3069\u5FC5\u8981\u306A sObject \u306B\u5BFE\u3057\u3066\u540C\u69D8\u306B\u5B9F\u884C
|
|
481
481
|
3. \u30B5\u30F3\u30D7\u30EB SOQL \u3092\u5B9F\u884C: GET /services/data/v60.0/query?q=SELECT+Id,Name,Industry+FROM+Account+LIMIT+5 \u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u5426\u3068\u30C7\u30FC\u30BF\u69CB\u9020\u3092\u78BA\u8A8D`
|
|
482
482
|
}
|
|
483
483
|
});
|
|
@@ -567,6 +567,20 @@ async function describeSObject(params, name) {
|
|
|
567
567
|
const data = await res.json();
|
|
568
568
|
return data.fields ?? [];
|
|
569
569
|
}
|
|
570
|
+
async function fetchSObjectCount(params, objectName) {
|
|
571
|
+
try {
|
|
572
|
+
const query = encodeURIComponent(`SELECT COUNT() FROM ${objectName}`);
|
|
573
|
+
const res = await apiFetch(
|
|
574
|
+
params,
|
|
575
|
+
`/services/data/${SALESFORCE_API_VERSION}/query?q=${query}`
|
|
576
|
+
);
|
|
577
|
+
if (!res.ok) return null;
|
|
578
|
+
const data = await res.json();
|
|
579
|
+
return typeof data.totalSize === "number" ? data.totalSize : null;
|
|
580
|
+
} catch {
|
|
581
|
+
return null;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
570
584
|
var salesforceSetupFlow = {
|
|
571
585
|
initialState: () => ({}),
|
|
572
586
|
steps: [
|
|
@@ -601,8 +615,27 @@ var salesforceSetupFlow = {
|
|
|
601
615
|
limit: SALESFORCE_SETUP_MAX_OBJECTS
|
|
602
616
|
});
|
|
603
617
|
const sections = ["## Salesforce", ""];
|
|
618
|
+
const countByObject = /* @__PURE__ */ new Map();
|
|
619
|
+
for (const objectName of targetObjects) {
|
|
620
|
+
countByObject.set(
|
|
621
|
+
objectName,
|
|
622
|
+
await fetchSObjectCount(rt.params, objectName)
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
sections.push("### Record counts", "");
|
|
626
|
+
sections.push("| sObject | Record count |");
|
|
627
|
+
sections.push("|---------|-------------|");
|
|
628
|
+
for (const objectName of targetObjects) {
|
|
629
|
+
const count = countByObject.get(objectName);
|
|
630
|
+
sections.push(
|
|
631
|
+
`| ${objectName} | ${count == null ? "-" : count.toLocaleString()} |`
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
sections.push("");
|
|
604
635
|
for (const objectName of targetObjects) {
|
|
605
|
-
|
|
636
|
+
const count = countByObject.get(objectName);
|
|
637
|
+
const countLabel = count == null ? "" : ` (${count.toLocaleString()} records)`;
|
|
638
|
+
sections.push(`### sObject: ${objectName}${countLabel}`, "");
|
|
606
639
|
const fields = await describeSObject(rt.params, objectName);
|
|
607
640
|
const limited = fields.slice(0, SALESFORCE_SETUP_MAX_FIELDS);
|
|
608
641
|
sections.push("| Field | Type | Label | Custom |");
|
|
@@ -772,7 +805,7 @@ var salesforceConnector = new ConnectorPlugin({
|
|
|
772
805
|
systemPrompt: {
|
|
773
806
|
en: `### Tools
|
|
774
807
|
|
|
775
|
-
- \`
|
|
808
|
+
- \`connector_salesforce_request\`: The only way to call the Salesforce REST API. Use it to run SOQL queries, describe sObjects, and read/create/update/delete standard (Account, Contact, Opportunity, Lead, Case) and custom objects. Authentication (OAuth 2.0 Client Credentials Flow against the External Client App / Connected App) is configured automatically \u2014 an access token is resolved on each request against the configured org instance URL. Prefer SOQL via \`GET /services/data/v60.0/query?q=...\` over paginating \`/sobjects/{Type}\` endpoints for filtered or joined reads.
|
|
776
809
|
|
|
777
810
|
### Business Logic
|
|
778
811
|
|
|
@@ -843,7 +876,7 @@ export default async function handler(c: Context) {
|
|
|
843
876
|
- Parent-to-child subquery: \`SELECT Id, Name, (SELECT Id, Email FROM Contacts) FROM Account\``,
|
|
844
877
|
ja: `### \u30C4\u30FC\u30EB
|
|
845
878
|
|
|
846
|
-
- \`
|
|
879
|
+
- \`connector_salesforce_request\`: Salesforce REST API \u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002SOQL \u30AF\u30A8\u30EA\u306E\u5B9F\u884C\u3001sObject \u306E describe\u3001\u6A19\u6E96\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\uFF08Account, Contact, Opportunity, Lead, Case\uFF09\u3084\u30AB\u30B9\u30BF\u30E0\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u8AAD\u307F\u66F8\u304D\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08External Client App / Connected App + OAuth 2.0 Client Credentials Flow\uFF09\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u3001\u8A2D\u5B9A\u3055\u308C\u305F\u7D44\u7E54\u306E instance URL \u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u304C\u89E3\u6C7A\u3055\u308C\u307E\u3059\u3002\u30D5\u30A3\u30EB\u30BF\u3084\u7D50\u5408\u306E\u3042\u308B\u8AAD\u307F\u53D6\u308A\u3067\u306F \`/sobjects/{Type}\` \u3092\u30DA\u30FC\u30B8\u30F3\u30B0\u3059\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`GET /services/data/v60.0/query?q=...\` \u306E SOQL \u3092\u512A\u5148\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
847
880
|
|
|
848
881
|
### Business Logic
|
|
849
882
|
|
|
@@ -297,7 +297,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
297
297
|
/**
|
|
298
298
|
* Create tools for connections that belong to this connector.
|
|
299
299
|
* Filters connections by connectorKey internally.
|
|
300
|
-
* Returns tools keyed as
|
|
300
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
301
301
|
*/
|
|
302
302
|
createTools(connections, config, opts) {
|
|
303
303
|
const myConnections = connections.filter(
|
|
@@ -307,7 +307,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
307
307
|
for (const t of Object.values(this.tools)) {
|
|
308
308
|
const tool = t.createTool(myConnections, config);
|
|
309
309
|
const originalToModelOutput = tool.toModelOutput;
|
|
310
|
-
result[
|
|
310
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
311
311
|
...tool,
|
|
312
312
|
toModelOutput: async (options) => {
|
|
313
313
|
if (!originalToModelOutput) {
|
|
@@ -1067,7 +1067,7 @@ var semrushConnector = new ConnectorPlugin({
|
|
|
1067
1067
|
systemPrompt: {
|
|
1068
1068
|
en: `### Tools
|
|
1069
1069
|
|
|
1070
|
-
- \`
|
|
1070
|
+
- \`connector_semrush-api-key_request\`: The only way to call the Semrush API. Use it for the Standard Analytics API (\`/?type=...\` reports), the Trends API (\`/analytics/v1/...\`), and the Projects API (\`/management/v1/...\`). Authentication is handled automatically \u2014 the API key is appended as the \`key\` query parameter; never include it yourself. The Standard Analytics API returns semicolon-separated CSV with the first row as the header (use \`responseFormat="text"\`); the Trends and Projects APIs return JSON (use \`responseFormat="json"\`). Errors from the Standard API are returned as a body that starts with \`ERROR\`, often with HTTP 200 \u2014 the tool surfaces these as \`success: false\` automatically.
|
|
1071
1071
|
|
|
1072
1072
|
### Business Logic
|
|
1073
1073
|
|
|
@@ -1080,7 +1080,7 @@ SDK methods (client created via \`connection(connectionId)\`):
|
|
|
1080
1080
|
- \`client.trends(path, query?)\` \u2014 call a Trends API endpoint (\`/analytics/v1/...\`) and return parsed JSON
|
|
1081
1081
|
- \`client.projects(path, init?)\` \u2014 call a Projects API endpoint (\`/management/v1/...\`) and return parsed JSON
|
|
1082
1082
|
|
|
1083
|
-
\u{1F6A8} **MANDATORY pre-flight before creating any server logic that calls \`report()\`.** Before authoring a TypeScript handler that invokes \`client.report(...)\` (Standard Analytics \u2014 \`domain_ranks\`, \`domain_organic\`, \`phrase_this\`, etc.), you MUST first call the \`
|
|
1083
|
+
\u{1F6A8} **MANDATORY pre-flight before creating any server logic that calls \`report()\`.** Before authoring a TypeScript handler that invokes \`client.report(...)\` (Standard Analytics \u2014 \`domain_ranks\`, \`domain_organic\`, \`phrase_this\`, etc.), you MUST first call the \`connector_semrush-api-key_request\` tool with \`path: "https://www.semrush.com/users/countapiunits.html"\`, no \`queryParams\`, \`responseFormat: "text"\` to confirm the unit balance is greater than 0. If the balance is 0, **stop, do not create the server logic**, and report the issue to the user (the account owner needs to top up API units in the Semrush console). \`testFetchServerLogic\` will execute the handler and consume units; creating handlers when the balance is 0 produces \`ERROR 132 :: API UNITS BALANCE IS ZERO\` failures across every server logic.
|
|
1084
1084
|
|
|
1085
1085
|
\u{1F6A8} **Always set a small \`display_limit\` explicitly \u2014 never rely on the default.** Semrush computes "required units = display_limit \xD7 per-row cost" up front, and rejects the request with \`ERROR 132 :: API UNITS BALANCE IS ZERO\` when the *estimated* cost exceeds the remaining balance, **even when the actual balance is non-zero** (e.g. balance \u2248 40,950 still fails for \`display_limit=10000\` on costly reports). Default to \`display_limit: "1000"\` (or smaller \u2014 \`"100"\` is plenty for most dashboards), and only increase it when the user explicitly asks for a larger sample AND \`checkUnits()\` confirms enough headroom. If you truly need all rows, paginate with \`display_offset\` in chunks of 1000 instead of bumping \`display_limit\`. Treat \`ERROR 132\` as "request too large for the current balance" first, and only as "balance is literally zero" after re-checking units.
|
|
1086
1086
|
|
|
@@ -1170,7 +1170,7 @@ To check remaining API units (free, does NOT consume units), call the request to
|
|
|
1170
1170
|
- Date strings in historical endpoints must be the 15th of the month (\`YYYYMM15\`)`,
|
|
1171
1171
|
ja: `### \u30C4\u30FC\u30EB
|
|
1172
1172
|
|
|
1173
|
-
- \`
|
|
1173
|
+
- \`connector_semrush-api-key_request\`: Semrush API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002Standard Analytics API\uFF08\`/?type=...\` \u5F62\u5F0F\u306E\u30EC\u30DD\u30FC\u30C8\uFF09\u3001Trends API\uFF08\`/analytics/v1/...\`\uFF09\u3001Projects API\uFF08\`/management/v1/...\`\uFF09\u3059\u3079\u3066\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\u306F\u81EA\u52D5\u7684\u306B\u884C\u308F\u308C\u3001API\u30AD\u30FC\u306F \`key\` \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u4ED8\u4E0E\u3055\u308C\u308B\u305F\u3081\u3001\u81EA\u5206\u3067\u542B\u3081\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002Standard Analytics API \u306F1\u884C\u76EE\u304C\u30D8\u30C3\u30C0\u30FC\u306E\u30BB\u30DF\u30B3\u30ED\u30F3\u533A\u5207\u308ACSV\u3092\u8FD4\u3059\u305F\u3081 \`responseFormat="text"\` \u3092\u4F7F\u7528\u3057\u3001Trends/Projects API \u306F JSON \u3092\u8FD4\u3059\u305F\u3081 \`responseFormat="json"\` \u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002Standard API \u306E\u30A8\u30E9\u30FC\u306F HTTP 200 \u3067\u3082\u672C\u6587\u304C \`ERROR\` \u3067\u59CB\u307E\u308B\u5F62\u5F0F\u3067\u8FD4\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u304C\u3001\u30C4\u30FC\u30EB\u306F\u81EA\u52D5\u7684\u306B \`success: false\` \u3068\u3057\u3066\u8FD4\u3057\u307E\u3059\u3002
|
|
1174
1174
|
|
|
1175
1175
|
### Business Logic
|
|
1176
1176
|
|
|
@@ -1183,7 +1183,7 @@ SDK\u30E1\u30BD\u30C3\u30C9 (\`connection(connectionId)\` \u3067\u4F5C\u6210\u30
|
|
|
1183
1183
|
- \`client.trends(path, query?)\` \u2014 Trends API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\`/analytics/v1/...\`\uFF09\u3092\u547C\u3073\u51FA\u3057 JSON \u3092\u8FD4\u3059
|
|
1184
1184
|
- \`client.projects(path, init?)\` \u2014 Projects API \u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\`/management/v1/...\`\uFF09\u3092\u547C\u3073\u51FA\u3057 JSON \u3092\u8FD4\u3059
|
|
1185
1185
|
|
|
1186
|
-
\u{1F6A8} **\`report()\` \u3092\u547C\u3076\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u3092\u4F5C\u6210\u3059\u308B\u524D\u306E\u5FC5\u9808\u30D7\u30EA\u30D5\u30E9\u30A4\u30C8\u3002** Standard Analytics\uFF08\`domain_ranks\`\u3001\`domain_organic\`\u3001\`phrase_this\` \u306A\u3069\uFF09\u306E \`client.report(...)\` \u3092\u542B\u3080 TypeScript \u30CF\u30F3\u30C9\u30E9\u3092\u4F5C\u6210\u3059\u308B\u524D\u306B\u3001\u5FC5\u305A \`
|
|
1186
|
+
\u{1F6A8} **\`report()\` \u3092\u547C\u3076\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u3092\u4F5C\u6210\u3059\u308B\u524D\u306E\u5FC5\u9808\u30D7\u30EA\u30D5\u30E9\u30A4\u30C8\u3002** Standard Analytics\uFF08\`domain_ranks\`\u3001\`domain_organic\`\u3001\`phrase_this\` \u306A\u3069\uFF09\u306E \`client.report(...)\` \u3092\u542B\u3080 TypeScript \u30CF\u30F3\u30C9\u30E9\u3092\u4F5C\u6210\u3059\u308B\u524D\u306B\u3001\u5FC5\u305A \`connector_semrush-api-key_request\` \u30C4\u30FC\u30EB\u3092 \`path: "https://www.semrush.com/users/countapiunits.html"\`\u3001\`queryParams\` \u7121\u3057\u3001\`responseFormat: "text"\` \u3067\u547C\u3073\u51FA\u3057\u3066\u30E6\u30CB\u30C3\u30C8\u6B8B\u91CF\u304C 0 \u3088\u308A\u5927\u304D\u3044\u3053\u3068\u3092\u78BA\u8A8D\u3059\u308B\u3053\u3068\u3002\u6B8B\u91CF\u304C 0 \u306E\u5834\u5408\u306F **\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u3092\u4F5C\u6210\u305B\u305A\u306B\u505C\u6B62\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u306B\u5831\u544A**\u3059\u308B\uFF08Semrush \u306E\u7BA1\u7406\u30B3\u30F3\u30BD\u30FC\u30EB\u304B\u3089 API \u30E6\u30CB\u30C3\u30C8\u3092\u88DC\u5145\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\uFF09\u3002\`testFetchServerLogic\` \u306F\u30CF\u30F3\u30C9\u30E9\u3092\u5B9F\u884C\u3057\u3066\u30E6\u30CB\u30C3\u30C8\u3092\u6D88\u8CBB\u3059\u308B\u305F\u3081\u3001\u6B8B\u91CF 0 \u306E\u307E\u307E\u4F5C\u6210\u3059\u308B\u3068\u5168\u30B5\u30FC\u30D0\u30FC\u30ED\u30B8\u30C3\u30AF\u304C \`ERROR 132 :: API UNITS BALANCE IS ZERO\` \u3067\u5931\u6557\u3059\u308B\u3002
|
|
1187
1187
|
|
|
1188
1188
|
\u{1F6A8} **\`display_limit\` \u306F\u5FC5\u305A\u660E\u793A\u7684\u306B\u5C0F\u3055\u3044\u5024\u3092\u6307\u5B9A\u3057\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u306B\u983C\u3089\u306A\u3044\u3053\u3068\u3002** Semrush \u306F\u4E8B\u524D\u306B\u300C\u5FC5\u8981\u30E6\u30CB\u30C3\u30C8 = display_limit \xD7 \u884C\u3042\u305F\u308A\u5358\u4FA1\u300D\u3092\u8A08\u7B97\u3057\u3001\u305D\u306E**\u898B\u7A4D\u984D**\u304C\u6B8B\u91CF\u3092\u8D85\u3048\u308B\u3068\u30EA\u30AF\u30A8\u30B9\u30C8\u3092 \`ERROR 132 :: API UNITS BALANCE IS ZERO\` \u3067\u62D2\u5426\u3059\u308B\u3002**\u5B9F\u6B8B\u91CF\u304C\u30BC\u30ED\u3067\u306A\u304F\u3066\u3082**\u8D77\u3053\u308B\uFF08\u4F8B\uFF1A\u6B8B\u91CF\u7D04 40,950 \u3067\u3082\u3001\u30B3\u30B9\u30C8\u306E\u9AD8\u3044\u30EC\u30DD\u30FC\u30C8\u3067 \`display_limit=10000\` \u3060\u3068\u5931\u6557\u3059\u308B\uFF09\u3002\u539F\u5247\u3068\u3057\u3066 \`display_limit: "1000"\`\uFF08\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u7528\u9014\u306A\u3089 \`"100"\` \u3067\u3082\u5341\u5206\uFF09\u3092\u6307\u5B9A\u3057\u3001\u30E6\u30FC\u30B6\u30FC\u304C\u660E\u793A\u7684\u306B\u5927\u304D\u306A\u30B5\u30F3\u30D7\u30EB\u3092\u8981\u6C42\u3057\u3001\u304B\u3064 \`checkUnits()\` \u3067\u6B8B\u91CF\u306B\u5341\u5206\u306A\u4F59\u88D5\u304C\u3042\u308B\u3053\u3068\u3092\u78BA\u8A8D\u3067\u304D\u305F\u5834\u5408\u306E\u307F\u5897\u3084\u3059\u3002\u5168\u884C\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F \`display_limit\` \u3092\u4E0A\u3052\u308B\u306E\u3067\u306F\u306A\u304F\u3001\`display_offset\` \u3067 1000 \u4EF6\u523B\u307F\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u5B9F\u88C5\u3059\u308B\u3053\u3068\u3002\`ERROR 132\` \u306F\u300C\u6B8B\u91CF\u304C\u6587\u5B57\u901A\u308A\u30BC\u30ED\u300D\u3088\u308A\u5148\u306B\u300C\u73FE\u5728\u306E\u6B8B\u91CF\u306B\u5BFE\u3057\u3066\u30EA\u30AF\u30A8\u30B9\u30C8\u304C\u5927\u304D\u3059\u304E\u308B\u300D\u3092\u7591\u3044\u3001\u30E6\u30CB\u30C3\u30C8\u3092\u518D\u78BA\u8A8D\u3057\u3066\u304B\u3089\u5224\u65AD\u3059\u308B\u3053\u3068\u3002
|
|
1189
1189
|
|
|
@@ -288,7 +288,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
288
288
|
/**
|
|
289
289
|
* Create tools for connections that belong to this connector.
|
|
290
290
|
* Filters connections by connectorKey internally.
|
|
291
|
-
* Returns tools keyed as
|
|
291
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
292
292
|
*/
|
|
293
293
|
createTools(connections, config, opts) {
|
|
294
294
|
const myConnections = connections.filter(
|
|
@@ -298,7 +298,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
298
298
|
for (const t of Object.values(this.tools)) {
|
|
299
299
|
const tool = t.createTool(myConnections, config);
|
|
300
300
|
const originalToModelOutput = tool.toModelOutput;
|
|
301
|
-
result[
|
|
301
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
302
302
|
...tool,
|
|
303
303
|
toModelOutput: async (options) => {
|
|
304
304
|
if (!originalToModelOutput) {
|
|
@@ -428,12 +428,12 @@ var AUTH_TYPES = {
|
|
|
428
428
|
// ../connectors/src/connectors/sentry/setup.ts
|
|
429
429
|
var sentryOnboarding = new ConnectorOnboarding({
|
|
430
430
|
dataOverviewInstructions: {
|
|
431
|
-
en: `1. Call
|
|
432
|
-
2. Call
|
|
433
|
-
3. For a specific issue, call
|
|
434
|
-
ja: `1.
|
|
435
|
-
2.
|
|
436
|
-
3. \u7279\u5B9A\u306E\u30A4\u30B7\u30E5\u30FC\u306B\u3064\u3044\u3066
|
|
431
|
+
en: `1. Call connector_sentry_request with GET /organizations/{organizationSlug}/projects/ to list all projects
|
|
432
|
+
2. Call connector_sentry_request with GET /organizations/{organizationSlug}/issues/?sort=date&query=is:unresolved to get recent unresolved issues
|
|
433
|
+
3. For a specific issue, call connector_sentry_request with GET /organizations/{organizationSlug}/issues/{issueId}/ to get details`,
|
|
434
|
+
ja: `1. connector_sentry_request \u3067 GET /organizations/{organizationSlug}/projects/ \u3092\u547C\u3073\u51FA\u3057\u3001\u5168\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4E00\u89A7\u8868\u793A
|
|
435
|
+
2. connector_sentry_request \u3067 GET /organizations/{organizationSlug}/issues/?sort=date&query=is:unresolved \u3092\u547C\u3073\u51FA\u3057\u3001\u6700\u8FD1\u306E\u672A\u89E3\u6C7A\u30A4\u30B7\u30E5\u30FC\u3092\u53D6\u5F97
|
|
436
|
+
3. \u7279\u5B9A\u306E\u30A4\u30B7\u30E5\u30FC\u306B\u3064\u3044\u3066 connector_sentry_request \u3067 GET /organizations/{organizationSlug}/issues/{issueId}/ \u3092\u547C\u3073\u51FA\u3057\u3001\u8A73\u7D30\u3092\u53D6\u5F97`
|
|
437
437
|
}
|
|
438
438
|
});
|
|
439
439
|
|
|
@@ -463,6 +463,19 @@ async function listOrganizations(params) {
|
|
|
463
463
|
const data = await res.json();
|
|
464
464
|
return data ?? [];
|
|
465
465
|
}
|
|
466
|
+
async function listRecentIssues(params, orgSlug, projectSlug) {
|
|
467
|
+
try {
|
|
468
|
+
const res = await apiFetch(
|
|
469
|
+
params,
|
|
470
|
+
`/projects/${orgSlug}/${projectSlug}/issues/?limit=5&query=is:unresolved`
|
|
471
|
+
);
|
|
472
|
+
if (!res.ok) return [];
|
|
473
|
+
const data = await res.json();
|
|
474
|
+
return data ?? [];
|
|
475
|
+
} catch {
|
|
476
|
+
return [];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
466
479
|
async function listProjects(params, orgSlug) {
|
|
467
480
|
const res = await apiFetch(params, `/organizations/${orgSlug}/projects/`);
|
|
468
481
|
if (!res.ok) {
|
|
@@ -544,6 +557,19 @@ var sentrySetupFlow = {
|
|
|
544
557
|
sections.push(`| First event | ${project.firstEvent ?? "-"} |`);
|
|
545
558
|
sections.push(`| Created | ${project.dateCreated ?? "-"} |`);
|
|
546
559
|
sections.push("");
|
|
560
|
+
const issues = await listRecentIssues(rt.params, orgSlug, project.slug);
|
|
561
|
+
if (issues.length > 0) {
|
|
562
|
+
sections.push("##### Recent unresolved issues", "");
|
|
563
|
+
sections.push("| ID | Title | Level | Events | Users | Last seen |");
|
|
564
|
+
sections.push("|----|-------|-------|--------|-------|-----------|");
|
|
565
|
+
for (const issue of issues) {
|
|
566
|
+
const title = (issue.title ?? "").replace(/\|/g, "\\|").slice(0, 60);
|
|
567
|
+
sections.push(
|
|
568
|
+
`| ${issue.shortId ?? "-"} | ${title || "-"} | ${issue.level ?? "-"} | ${issue.count ?? "-"} | ${issue.userCount ?? "-"} | ${issue.lastSeen ?? "-"} |`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
sections.push("");
|
|
572
|
+
}
|
|
547
573
|
}
|
|
548
574
|
return sections.join("\n");
|
|
549
575
|
}
|
|
@@ -646,7 +672,7 @@ var sentryConnector = new ConnectorPlugin({
|
|
|
646
672
|
systemPrompt: {
|
|
647
673
|
en: `### Tools
|
|
648
674
|
|
|
649
|
-
- \`
|
|
675
|
+
- \`connector_sentry_request\`: Send authenticated requests to the Sentry API. Supports GET, POST, PUT, and DELETE methods. Authentication is handled automatically via Bearer token. The {organizationSlug} placeholder in paths is automatically replaced with the configured organization slug.
|
|
650
676
|
|
|
651
677
|
### Sentry API Reference
|
|
652
678
|
|
|
@@ -729,7 +755,7 @@ await sentry.updateIssue("12345", { status: "resolved" });
|
|
|
729
755
|
\`\`\``,
|
|
730
756
|
ja: `### \u30C4\u30FC\u30EB
|
|
731
757
|
|
|
732
|
-
- \`
|
|
758
|
+
- \`connector_sentry_request\`: Sentry API\u3078\u306E\u8A8D\u8A3C\u6E08\u307F\u30EA\u30AF\u30A8\u30B9\u30C8\u3092\u9001\u4FE1\u3057\u307E\u3059\u3002GET, POST, PUT, DELETE\u30E1\u30BD\u30C3\u30C9\u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002Bearer token\u306B\u3088\u308B\u8A8D\u8A3C\u306F\u81EA\u52D5\u3067\u884C\u308F\u308C\u307E\u3059\u3002\u30D1\u30B9\u5185\u306E{organizationSlug}\u30D7\u30EC\u30FC\u30B9\u30DB\u30EB\u30C0\u30FC\u306F\u8A2D\u5B9A\u6E08\u307F\u306E\u7D44\u7E54\u30B9\u30E9\u30C3\u30B0\u3067\u81EA\u52D5\u7684\u306B\u7F6E\u63DB\u3055\u308C\u307E\u3059\u3002
|
|
733
759
|
|
|
734
760
|
### Sentry API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
735
761
|
|
|
@@ -112,7 +112,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
112
112
|
/**
|
|
113
113
|
* Create tools for connections that belong to this connector.
|
|
114
114
|
* Filters connections by connectorKey internally.
|
|
115
|
-
* Returns tools keyed as
|
|
115
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
116
116
|
*/
|
|
117
117
|
createTools(connections, config, opts) {
|
|
118
118
|
const myConnections = connections.filter(
|
|
@@ -122,7 +122,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
122
122
|
for (const t of Object.values(this.tools)) {
|
|
123
123
|
const tool = t.createTool(myConnections, config);
|
|
124
124
|
const originalToModelOutput = tool.toModelOutput;
|
|
125
|
-
result[
|
|
125
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
126
126
|
...tool,
|
|
127
127
|
toModelOutput: async (options) => {
|
|
128
128
|
if (!originalToModelOutput) {
|
|
@@ -384,11 +384,11 @@ var shopifyOauthOnboarding = new ConnectorOnboarding({
|
|
|
384
384
|
- Write only 1 sentence between tool calls, then immediately call the next tool. Skip unnecessary explanations and proceed efficiently`
|
|
385
385
|
},
|
|
386
386
|
dataOverviewInstructions: {
|
|
387
|
-
en: `1. Call
|
|
388
|
-
2. Call
|
|
387
|
+
en: `1. Call connector_shopify-oauth_request with GET /admin/api/2024-10/products.json?limit=5 to explore products structure
|
|
388
|
+
2. Call connector_shopify-oauth_request with GET /admin/api/2024-10/orders.json?limit=5 to explore orders structure
|
|
389
389
|
3. Explore other endpoints (customers, inventory, collections) as needed`,
|
|
390
|
-
ja: `1.
|
|
391
|
-
2.
|
|
390
|
+
ja: `1. connector_shopify-oauth_request \u3067 GET /admin/api/2024-10/products.json?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u5546\u54C1\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
391
|
+
2. connector_shopify-oauth_request \u3067 GET /admin/api/2024-10/orders.json?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u6CE8\u6587\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
392
392
|
3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\uFF09\u3092\u63A2\u7D22`
|
|
393
393
|
}
|
|
394
394
|
});
|
|
@@ -450,6 +450,9 @@ var shopifyOauthSetupFlow = {
|
|
|
450
450
|
(e) => ENTITY_VALUES.includes(e)
|
|
451
451
|
).slice(0, SHOPIFY_OAUTH_SETUP_MAX_ENTITIES);
|
|
452
452
|
const sections = ["## Shopify", ""];
|
|
453
|
+
sections.push("### Entity counts", "");
|
|
454
|
+
sections.push("| Entity | Count |");
|
|
455
|
+
sections.push("|--------|-------|");
|
|
453
456
|
for (const entity of selected) {
|
|
454
457
|
const path2 = COUNT_PATHS[entity];
|
|
455
458
|
let count = "available";
|
|
@@ -460,8 +463,38 @@ var shopifyOauthSetupFlow = {
|
|
|
460
463
|
if (typeof data.count === "number") count = String(data.count);
|
|
461
464
|
}
|
|
462
465
|
}
|
|
463
|
-
sections.push(
|
|
464
|
-
|
|
466
|
+
sections.push(`| ${ENTITY_LABELS[entity].en} | ${count} |`);
|
|
467
|
+
}
|
|
468
|
+
sections.push("");
|
|
469
|
+
if (selected.includes("orders")) {
|
|
470
|
+
try {
|
|
471
|
+
const ordersRes = await rt.config.proxyFetch(
|
|
472
|
+
`/admin/api/${SHOPIFY_API_VERSION}/orders.json?limit=5&status=any&order=created_at+desc`,
|
|
473
|
+
{ method: "GET" }
|
|
474
|
+
);
|
|
475
|
+
if (ordersRes.ok) {
|
|
476
|
+
const ordersData = await ordersRes.json();
|
|
477
|
+
const orders = ordersData.orders ?? [];
|
|
478
|
+
if (orders.length > 0) {
|
|
479
|
+
sections.push("### Recent orders (sample)", "");
|
|
480
|
+
sections.push(
|
|
481
|
+
"| Order | Total | Status | Created |"
|
|
482
|
+
);
|
|
483
|
+
sections.push(
|
|
484
|
+
"|-------|-------|--------|---------|"
|
|
485
|
+
);
|
|
486
|
+
for (const o of orders.slice(0, 5)) {
|
|
487
|
+
const name = (o.name ?? `#${o.order_number ?? "?"}`).replace(/\|/g, "\\|");
|
|
488
|
+
const total = o.total_price ? `${o.total_price} ${o.currency ?? ""}`.trim() : "-";
|
|
489
|
+
const status = o.financial_status ?? "-";
|
|
490
|
+
const created = o.created_at ? o.created_at.slice(0, 10) : "-";
|
|
491
|
+
sections.push(`| ${name} | ${total} | ${status} | ${created} |`);
|
|
492
|
+
}
|
|
493
|
+
sections.push("");
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
} catch {
|
|
497
|
+
}
|
|
465
498
|
}
|
|
466
499
|
return sections.join("\n");
|
|
467
500
|
}
|
|
@@ -491,7 +524,7 @@ var shopifyOauthConnector = new ConnectorPlugin({
|
|
|
491
524
|
systemPrompt: {
|
|
492
525
|
en: `### Tools
|
|
493
526
|
|
|
494
|
-
- \`
|
|
527
|
+
- \`connector_shopify-oauth_request\`: The only way to call the Shopify Admin REST API. Use it to query products, orders, customers, inventory, collections, and more. Authentication is configured automatically via OAuth proxy. Shopify uses cursor-based pagination via the \`page_info\` query parameter (obtained from the Link header in the response).
|
|
495
528
|
|
|
496
529
|
### Shopify Admin REST API Reference
|
|
497
530
|
|
|
@@ -538,7 +571,7 @@ const data = await res.json();
|
|
|
538
571
|
\`\`\``,
|
|
539
572
|
ja: `### \u30C4\u30FC\u30EB
|
|
540
573
|
|
|
541
|
-
- \`
|
|
574
|
+
- \`connector_shopify-oauth_request\`: Shopify Admin REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u5546\u54C1\u3001\u6CE8\u6587\u3001\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306A\u3069\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002OAuth\u30D7\u30ED\u30AD\u30B7\u7D4C\u7531\u3067\u8A8D\u8A3C\u306F\u81EA\u52D5\u8A2D\u5B9A\u3055\u308C\u307E\u3059\u3002Shopify\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E Link \u30D8\u30C3\u30C0\u30FC\u304B\u3089\u53D6\u5F97\u3059\u308B \`page_info\` \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
542
575
|
|
|
543
576
|
### Shopify Admin REST API \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
544
577
|
|
|
@@ -401,7 +401,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
401
401
|
/**
|
|
402
402
|
* Create tools for connections that belong to this connector.
|
|
403
403
|
* Filters connections by connectorKey internally.
|
|
404
|
-
* Returns tools keyed as
|
|
404
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
405
405
|
*/
|
|
406
406
|
createTools(connections, config, opts) {
|
|
407
407
|
const myConnections = connections.filter(
|
|
@@ -411,7 +411,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
411
411
|
for (const t of Object.values(this.tools)) {
|
|
412
412
|
const tool = t.createTool(myConnections, config);
|
|
413
413
|
const originalToModelOutput = tool.toModelOutput;
|
|
414
|
-
result[
|
|
414
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
415
415
|
...tool,
|
|
416
416
|
toModelOutput: async (options) => {
|
|
417
417
|
if (!originalToModelOutput) {
|
|
@@ -536,11 +536,11 @@ var AUTH_TYPES = {
|
|
|
536
536
|
// ../connectors/src/connectors/shopify/setup.ts
|
|
537
537
|
var shopifyOnboarding = new ConnectorOnboarding({
|
|
538
538
|
dataOverviewInstructions: {
|
|
539
|
-
en: `1. Call
|
|
540
|
-
2. Call
|
|
539
|
+
en: `1. Call connector_shopify_request with GET /admin/api/2024-10/products.json?limit=5 to explore products structure
|
|
540
|
+
2. Call connector_shopify_request with GET /admin/api/2024-10/orders.json?limit=5&status=any to explore orders structure
|
|
541
541
|
3. Explore other endpoints (customers, inventory, collections) as needed`,
|
|
542
|
-
ja: `1.
|
|
543
|
-
2.
|
|
542
|
+
ja: `1. connector_shopify_request \u3067 GET /admin/api/2024-10/products.json?limit=5 \u3092\u547C\u3073\u51FA\u3057\u3001\u5546\u54C1\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
543
|
+
2. connector_shopify_request \u3067 GET /admin/api/2024-10/orders.json?limit=5&status=any \u3092\u547C\u3073\u51FA\u3057\u3001\u6CE8\u6587\u306E\u69CB\u9020\u3092\u78BA\u8A8D
|
|
544
544
|
3. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u4ED6\u306E\u30A8\u30F3\u30C9\u30DD\u30A4\u30F3\u30C8\uFF08\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\uFF09\u3092\u63A2\u7D22`
|
|
545
545
|
}
|
|
546
546
|
});
|
|
@@ -792,7 +792,7 @@ var shopifyConnector = new ConnectorPlugin({
|
|
|
792
792
|
systemPrompt: {
|
|
793
793
|
en: `### Tools
|
|
794
794
|
|
|
795
|
-
- \`
|
|
795
|
+
- \`connector_shopify_request\`: The only way to call the Shopify Admin REST API. Use it to query products, orders, customers, inventory, collections, and more. Authentication (Custom App Client ID + Client Secret) is configured automatically \u2014 an access token is obtained on each request. Only provide the path starting with \`/admin/api/\`. Shopify uses cursor-based pagination via the \`page_info\` query parameter (obtained from the Link header in the response).
|
|
796
796
|
|
|
797
797
|
### Business Logic
|
|
798
798
|
|
|
@@ -864,7 +864,7 @@ export default async function handler(c: Context) {
|
|
|
864
864
|
- \`status\` \u2014 Filter by status (e.g., active, draft, archived for products; open, closed, cancelled, any for orders)`,
|
|
865
865
|
ja: `### \u30C4\u30FC\u30EB
|
|
866
866
|
|
|
867
|
-
- \`
|
|
867
|
+
- \`connector_shopify_request\`: Shopify Admin REST API\u3092\u547C\u3073\u51FA\u3059\u552F\u4E00\u306E\u624B\u6BB5\u3067\u3059\u3002\u5546\u54C1\u3001\u6CE8\u6587\u3001\u9867\u5BA2\u3001\u5728\u5EAB\u3001\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u306A\u3069\u306E\u30AF\u30A8\u30EA\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002\u8A8D\u8A3C\uFF08\u30AB\u30B9\u30BF\u30E0\u30A2\u30D7\u30EA\u306E Client ID + Client Secret\uFF09\u306F\u81EA\u52D5\u7684\u306B\u8A2D\u5B9A\u3055\u308C\u3001\u30EA\u30AF\u30A8\u30B9\u30C8\u3054\u3068\u306B\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u3092\u53D6\u5F97\u3057\u307E\u3059\u3002\`/admin/api/\` \u304B\u3089\u59CB\u307E\u308B\u30D1\u30B9\u306E\u307F\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002Shopify\u306F\u30EC\u30B9\u30DD\u30F3\u30B9\u306E Link \u30D8\u30C3\u30C0\u30FC\u304B\u3089\u53D6\u5F97\u3059\u308B \`page_info\` \u30AF\u30A8\u30EA\u30D1\u30E9\u30E1\u30FC\u30BF\u306B\u3088\u308B\u30AB\u30FC\u30BD\u30EB\u30D9\u30FC\u30B9\u306E\u30DA\u30FC\u30B8\u30CD\u30FC\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002
|
|
868
868
|
|
|
869
869
|
### Business Logic
|
|
870
870
|
|
|
@@ -308,7 +308,7 @@ async function runMssqlQuery(parsed, sql, options = {}) {
|
|
|
308
308
|
try {
|
|
309
309
|
const result = await pool.request().query(sql);
|
|
310
310
|
const recordset = result.recordset ?? [];
|
|
311
|
-
return { rows: recordset };
|
|
311
|
+
return { rows: recordset, rowsAffected: result.rowsAffected ?? [] };
|
|
312
312
|
} finally {
|
|
313
313
|
await pool.close();
|
|
314
314
|
}
|
|
@@ -512,7 +512,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
512
512
|
/**
|
|
513
513
|
* Create tools for connections that belong to this connector.
|
|
514
514
|
* Filters connections by connectorKey internally.
|
|
515
|
-
* Returns tools keyed as
|
|
515
|
+
* Returns tools keyed as `connector_${connectorKey}_${toolName}`.
|
|
516
516
|
*/
|
|
517
517
|
createTools(connections, config, opts) {
|
|
518
518
|
const myConnections = connections.filter(
|
|
@@ -522,7 +522,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
522
522
|
for (const t of Object.values(this.tools)) {
|
|
523
523
|
const tool = t.createTool(myConnections, config);
|
|
524
524
|
const originalToModelOutput = tool.toModelOutput;
|
|
525
|
-
result[
|
|
525
|
+
result[`connector_${this.connectorKey}_${t.name}`] = {
|
|
526
526
|
...tool,
|
|
527
527
|
toModelOutput: async (options) => {
|
|
528
528
|
if (!originalToModelOutput) {
|
|
@@ -649,6 +649,12 @@ var AUTH_TYPES = {
|
|
|
649
649
|
USER_PASSWORD: "user-password"
|
|
650
650
|
};
|
|
651
651
|
|
|
652
|
+
// ../connectors/src/lib/sql-dml.ts
|
|
653
|
+
function isDmlStatement(sql) {
|
|
654
|
+
const stripped = sql.replace(/^(\s*(--[^\n]*\n|\/\*[\s\S]*?\*\/))+/, "").trimStart();
|
|
655
|
+
return /^(insert|update|delete|merge)\b/i.test(stripped);
|
|
656
|
+
}
|
|
657
|
+
|
|
652
658
|
// ../connectors/src/lib/unwrap-sample-limit.ts
|
|
653
659
|
var STRICT_WRAPPER_RE = /^\s*SELECT\s+\*\s+FROM\s+\(([\s\S]+)\)\s+AS\s+\w+\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
654
660
|
var TRAILING_LIMIT_RE = /\s+LIMIT\s+(\d+)\s*;?\s*$/i;
|
|
@@ -671,11 +677,11 @@ init_mssql_runner();
|
|
|
671
677
|
// ../connectors/src/connectors/sqlserver/setup.ts
|
|
672
678
|
var sqlserverOnboarding = new ConnectorOnboarding({
|
|
673
679
|
dataOverviewInstructions: {
|
|
674
|
-
en: `1. Use
|
|
680
|
+
en: `1. Use connector_sqlserver_executeQuery to discover the database flavor and version: \`SELECT @@VERSION\`
|
|
675
681
|
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')\`
|
|
676
682
|
3. For key tables, fetch column info: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
|
|
677
683
|
4. Sample up to 3 tables. SQL Server uses \`TOP\` rather than \`LIMIT\`: \`SELECT TOP 5 * FROM <schema>.<table_name>\``,
|
|
678
|
-
ja: `1.
|
|
684
|
+
ja: `1. connector_sqlserver_executeQuery \u3067\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u53D6\u5F97: \`SELECT @@VERSION\`
|
|
679
685
|
2. \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97: \`SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA NOT IN ('sys', 'INFORMATION_SCHEMA')\`
|
|
680
686
|
3. \u4E3B\u8981\u30C6\u30FC\u30D6\u30EB\u306E\u30AB\u30E9\u30E0\u60C5\u5831\u3092\u53D6\u5F97: \`SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'xxx'\`
|
|
681
687
|
4. \u5FC5\u8981\u306B\u5FDC\u3058\u3066\u6700\u59273\u30C6\u30FC\u30D6\u30EB\u3092\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0\u3002SQL Server \u3067\u306F \`LIMIT\` \u3067\u306F\u306A\u304F \`TOP\` \u3092\u4F7F\u7528: \`SELECT TOP 5 * FROM <schema>.<table_name>\``
|
|
@@ -772,6 +778,28 @@ function buildFlow(options) {
|
|
|
772
778
|
fetchAll: () => fetchTableNames(rt.params, schema),
|
|
773
779
|
limit: SQLSERVER_SETUP_MAX_TABLES
|
|
774
780
|
});
|
|
781
|
+
let rowCounts = /* @__PURE__ */ new Map();
|
|
782
|
+
try {
|
|
783
|
+
const countRows = await runSqlServerSetupQuery(
|
|
784
|
+
rt.params,
|
|
785
|
+
`SELECT t.TABLE_NAME, SUM(p.rows) AS row_count
|
|
786
|
+
FROM INFORMATION_SCHEMA.TABLES t
|
|
787
|
+
JOIN sys.partitions p
|
|
788
|
+
ON OBJECT_ID(t.TABLE_SCHEMA + '.' + t.TABLE_NAME) = p.object_id
|
|
789
|
+
AND p.index_id IN (0, 1)
|
|
790
|
+
WHERE t.TABLE_SCHEMA = ${quoteLiteral(schema)}
|
|
791
|
+
AND t.TABLE_TYPE IN ('BASE TABLE', 'VIEW')
|
|
792
|
+
GROUP BY t.TABLE_NAME`,
|
|
793
|
+
forceEncrypt
|
|
794
|
+
);
|
|
795
|
+
rowCounts = new Map(
|
|
796
|
+
countRows.map((r) => [
|
|
797
|
+
String(r["TABLE_NAME"] ?? ""),
|
|
798
|
+
Number(r["row_count"] ?? 0)
|
|
799
|
+
])
|
|
800
|
+
);
|
|
801
|
+
} catch {
|
|
802
|
+
}
|
|
775
803
|
const sections = [
|
|
776
804
|
`## ${connectorName}`,
|
|
777
805
|
"",
|
|
@@ -788,7 +816,9 @@ function buildFlow(options) {
|
|
|
788
816
|
ORDER BY ORDINAL_POSITION`,
|
|
789
817
|
forceEncrypt
|
|
790
818
|
);
|
|
791
|
-
|
|
819
|
+
const rowCount = rowCounts.get(table);
|
|
820
|
+
const heading = typeof rowCount === "number" ? `#### Table: ${table} (~${rowCount.toLocaleString()} rows)` : `#### Table: ${table}`;
|
|
821
|
+
sections.push(heading, "");
|
|
792
822
|
sections.push("| Column | Type | Nullable | Default |");
|
|
793
823
|
sections.push("|--------|------|----------|---------|");
|
|
794
824
|
for (const c of cols) {
|
|
@@ -833,6 +863,9 @@ var outputSchema = z.discriminatedUnion("success", [
|
|
|
833
863
|
z.object({
|
|
834
864
|
success: z.literal(true),
|
|
835
865
|
rowCount: z.number(),
|
|
866
|
+
rowsAffected: z.number().optional().describe(
|
|
867
|
+
"Affected rows for INSERT/UPDATE/DELETE; undefined for SELECT"
|
|
868
|
+
),
|
|
836
869
|
truncated: z.boolean(),
|
|
837
870
|
rows: z.array(z.record(z.string(), z.unknown()))
|
|
838
871
|
}),
|
|
@@ -846,7 +879,8 @@ var executeQueryTool = new ConnectorTool({
|
|
|
846
879
|
description: `Execute a T-SQL query against Microsoft SQL Server. Returns up to ${MAX_ROWS} rows.
|
|
847
880
|
Use for: schema exploration via \`INFORMATION_SCHEMA\`, data sampling, and analytical queries.
|
|
848
881
|
SQL Server uses \`TOP n\` instead of \`LIMIT n\`. Identifiers can be wrapped in square brackets (\`[schema].[table]\`).
|
|
849
|
-
Avoid loading large amounts of data; always include \`TOP\` in queries
|
|
882
|
+
Avoid loading large amounts of data; always include \`TOP\` in queries.
|
|
883
|
+
For INSERT/UPDATE/DELETE, \`rowCount\` is 0 and \`rows\` is empty (rowCount counts returned rows, not affected rows) \u2014 this is normal, not a failure; check \`rowsAffected\` for the number of affected rows.`,
|
|
850
884
|
inputSchema,
|
|
851
885
|
outputSchema,
|
|
852
886
|
async execute({ connectionId, sql }, connections) {
|
|
@@ -873,13 +907,16 @@ Avoid loading large amounts of data; always include \`TOP\` in queries.`,
|
|
|
873
907
|
};
|
|
874
908
|
}
|
|
875
909
|
try {
|
|
876
|
-
const { rows } = await runMssqlQuery(parsed, sql, {
|
|
910
|
+
const { rows, rowsAffected } = await runMssqlQuery(parsed, sql, {
|
|
877
911
|
tunnelParams: connectionParamsToRecord(connection2)
|
|
878
912
|
});
|
|
879
913
|
const truncated = rows.length > MAX_ROWS;
|
|
880
914
|
return {
|
|
881
915
|
success: true,
|
|
882
916
|
rowCount: Math.min(rows.length, MAX_ROWS),
|
|
917
|
+
// tedious counts SELECT result rows in rowsAffected too, so only
|
|
918
|
+
// report it for DML. Multi-statement batches are summed.
|
|
919
|
+
rowsAffected: isDmlStatement(sql) ? rowsAffected.reduce((sum, n) => sum + n, 0) : void 0,
|
|
883
920
|
truncated,
|
|
884
921
|
rows: rows.slice(0, MAX_ROWS)
|
|
885
922
|
};
|
|
@@ -907,7 +944,7 @@ var sqlserverConnector = new ConnectorPlugin({
|
|
|
907
944
|
systemPrompt: {
|
|
908
945
|
en: `### Tools
|
|
909
946
|
|
|
910
|
-
- \`
|
|
947
|
+
- \`connector_sqlserver_executeQuery\`: Executes a T-SQL query against Microsoft SQL Server and returns rows. Use this for schema exploration via \`INFORMATION_SCHEMA\` and for sampling data. See the SQL Reference below for SQL Server-specific syntax.
|
|
911
948
|
|
|
912
949
|
### Business Logic
|
|
913
950
|
|
|
@@ -924,7 +961,7 @@ The business logic type for this connector is "sql".
|
|
|
924
961
|
- 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.`,
|
|
925
962
|
ja: `### \u30C4\u30FC\u30EB
|
|
926
963
|
|
|
927
|
-
- \`
|
|
964
|
+
- \`connector_sqlserver_executeQuery\`: Microsoft SQL Server \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\u3002SQL Server \u56FA\u6709\u306E\u69CB\u6587\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
928
965
|
|
|
929
966
|
### Business Logic
|
|
930
967
|
|