@squadbase/vite-server 0.1.8 → 0.1.9-dev.3841401
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 +73422 -59588
- package/dist/connectors/airtable-oauth.js +3 -0
- package/dist/connectors/airtable.js +3 -0
- package/dist/connectors/amplitude.js +3 -0
- package/dist/connectors/anthropic.js +3 -0
- package/dist/connectors/asana.js +18 -2
- package/dist/connectors/attio.js +3 -0
- package/dist/connectors/aws-billing.d.ts +5 -0
- package/dist/connectors/aws-billing.js +29843 -0
- package/dist/connectors/azure-sql.d.ts +5 -0
- package/dist/connectors/azure-sql.js +668 -0
- package/dist/connectors/backlog-api-key.js +3 -0
- package/dist/connectors/clickup.d.ts +5 -0
- package/dist/connectors/clickup.js +850 -0
- package/dist/connectors/customerio.js +3 -0
- package/dist/connectors/dbt.js +3 -0
- package/dist/connectors/freshdesk.d.ts +5 -0
- package/dist/connectors/freshdesk.js +842 -0
- package/dist/connectors/freshsales.d.ts +5 -0
- package/dist/connectors/freshsales.js +867 -0
- package/dist/connectors/freshservice.d.ts +5 -0
- package/dist/connectors/freshservice.js +813 -0
- package/dist/connectors/gamma.js +3 -0
- package/dist/connectors/gemini.js +3 -0
- package/dist/connectors/github.d.ts +5 -0
- package/dist/connectors/github.js +963 -0
- package/dist/connectors/gmail-oauth.js +18 -2
- package/dist/connectors/gmail.js +34 -16
- package/dist/connectors/google-ads.js +3 -0
- package/dist/connectors/google-analytics-oauth.js +3 -0
- package/dist/connectors/google-analytics.js +3 -0
- package/dist/connectors/google-audit-log.d.ts +5 -0
- package/dist/connectors/google-audit-log.js +813 -0
- package/dist/connectors/google-calendar-oauth.js +21 -2
- package/dist/connectors/google-calendar.js +140 -73
- package/dist/connectors/google-docs.js +21 -2
- package/dist/connectors/google-drive.js +18 -2
- package/dist/connectors/google-search-console-oauth.d.ts +5 -0
- package/dist/connectors/google-search-console-oauth.js +954 -0
- package/dist/connectors/google-sheets.js +21 -2
- package/dist/connectors/google-slides.js +21 -2
- package/dist/connectors/grafana.js +3 -0
- package/dist/connectors/hubspot-oauth.js +3 -0
- package/dist/connectors/hubspot.js +3 -0
- package/dist/connectors/influxdb.js +3 -0
- package/dist/connectors/intercom-oauth.js +3 -0
- package/dist/connectors/intercom.js +3 -0
- package/dist/connectors/jdbc.d.ts +5 -0
- package/dist/connectors/jdbc.js +21509 -0
- package/dist/connectors/jira-api-key.js +3 -0
- package/dist/connectors/kintone-api-token.js +3 -0
- package/dist/connectors/kintone.js +3 -0
- package/dist/connectors/linear.js +3 -0
- package/dist/connectors/linkedin-ads.js +3 -0
- package/dist/connectors/mailchimp-oauth.js +3 -0
- package/dist/connectors/mailchimp.js +3 -0
- package/dist/connectors/meta-ads-oauth.js +3 -0
- package/dist/connectors/meta-ads.js +3 -0
- package/dist/connectors/mixpanel.js +3 -0
- package/dist/connectors/monday.d.ts +5 -0
- package/dist/connectors/monday.js +853 -0
- package/dist/connectors/notion-oauth.js +3 -0
- package/dist/connectors/notion.js +3 -0
- package/dist/connectors/openai.js +3 -0
- package/dist/connectors/oracle.d.ts +5 -0
- package/dist/connectors/oracle.js +676 -0
- package/dist/connectors/salesforce.js +3 -0
- package/dist/connectors/semrush.d.ts +5 -0
- package/dist/connectors/semrush.js +812 -0
- package/dist/connectors/sentry.js +3 -0
- package/dist/connectors/shopify-oauth.js +3 -0
- package/dist/connectors/shopify.js +3 -0
- package/dist/connectors/sqlserver.d.ts +5 -0
- package/dist/connectors/sqlserver.js +667 -0
- package/dist/connectors/stripe-api-key.js +3 -0
- package/dist/connectors/stripe-oauth.js +3 -0
- package/dist/connectors/supabase.d.ts +5 -0
- package/dist/connectors/supabase.js +582 -0
- package/dist/connectors/tiktok-ads.js +18 -2
- package/dist/connectors/wix-store.js +3 -0
- package/dist/connectors/zendesk-oauth.js +3 -0
- package/dist/connectors/zendesk.js +3 -0
- package/dist/index.js +70184 -56350
- package/dist/main.js +70178 -56344
- package/dist/vite-plugin.js +71935 -58101
- package/package.json +64 -2
|
@@ -61,6 +61,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
61
61
|
releaseFlag;
|
|
62
62
|
proxyPolicy;
|
|
63
63
|
experimentalAttributes;
|
|
64
|
+
categories;
|
|
64
65
|
onboarding;
|
|
65
66
|
systemPrompt;
|
|
66
67
|
tools;
|
|
@@ -76,6 +77,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
76
77
|
this.releaseFlag = config.releaseFlag;
|
|
77
78
|
this.proxyPolicy = config.proxyPolicy;
|
|
78
79
|
this.experimentalAttributes = config.experimentalAttributes;
|
|
80
|
+
this.categories = config.categories ?? [];
|
|
79
81
|
this.onboarding = config.onboarding;
|
|
80
82
|
this.systemPrompt = config.systemPrompt;
|
|
81
83
|
this.tools = config.tools;
|
|
@@ -318,6 +320,7 @@ var stripeOauthConnector = new ConnectorPlugin({
|
|
|
318
320
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/2QNK0u2doqp41uL0POS4Ks/7a92367e2388ec77c7f4ada143606f9a/stripe.jpeg",
|
|
319
321
|
parameters,
|
|
320
322
|
releaseFlag: { dev1: true, dev2: false, prod: false },
|
|
323
|
+
categories: ["finance"],
|
|
321
324
|
onboarding: stripeOnboarding,
|
|
322
325
|
proxyPolicy: {
|
|
323
326
|
allowlist: [
|
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// ../connectors/src/parameter-definition.ts
|
|
2
|
+
var ParameterDefinition = class {
|
|
3
|
+
slug;
|
|
4
|
+
name;
|
|
5
|
+
description;
|
|
6
|
+
envVarBaseKey;
|
|
7
|
+
type;
|
|
8
|
+
secret;
|
|
9
|
+
required;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.slug = config.slug;
|
|
12
|
+
this.name = config.name;
|
|
13
|
+
this.description = config.description;
|
|
14
|
+
this.envVarBaseKey = config.envVarBaseKey;
|
|
15
|
+
this.type = config.type;
|
|
16
|
+
this.secret = config.secret;
|
|
17
|
+
this.required = config.required;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the parameter value from a ConnectorConnectionObject.
|
|
21
|
+
*/
|
|
22
|
+
getValue(connection2) {
|
|
23
|
+
const param = connection2.parameters.find(
|
|
24
|
+
(p) => p.parameterSlug === this.slug
|
|
25
|
+
);
|
|
26
|
+
if (!param || param.value == null) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Parameter "${this.slug}" not found or has no value in connection "${connection2.id}"`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return param.value;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Try to get the parameter value. Returns undefined if not found (for optional params).
|
|
35
|
+
*/
|
|
36
|
+
tryGetValue(connection2) {
|
|
37
|
+
const param = connection2.parameters.find(
|
|
38
|
+
(p) => p.parameterSlug === this.slug
|
|
39
|
+
);
|
|
40
|
+
if (!param || param.value == null) return void 0;
|
|
41
|
+
return param.value;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ../connectors/src/connectors/supabase/parameters.ts
|
|
46
|
+
var parameters = {
|
|
47
|
+
connectionUrl: new ParameterDefinition({
|
|
48
|
+
slug: "connection-url",
|
|
49
|
+
name: "Supabase Connection URL",
|
|
50
|
+
description: "The Supabase Postgres connection string. Copy it from the Supabase dashboard (Project Settings \u2192 Database \u2192 Connection string). Use the Transaction pooler (port 6543) URL for serverless workloads, e.g. `postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres`.",
|
|
51
|
+
envVarBaseKey: "SUPABASE_DB_URL",
|
|
52
|
+
type: "text",
|
|
53
|
+
secret: true,
|
|
54
|
+
required: true
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// ../connectors/src/connectors/supabase/sdk/index.ts
|
|
59
|
+
function createClient(params) {
|
|
60
|
+
const connectionUrl = params[parameters.connectionUrl.slug];
|
|
61
|
+
if (!connectionUrl) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`supabase: missing required parameter: ${parameters.connectionUrl.slug}`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
async function runQuery(sql, queryParams) {
|
|
67
|
+
try {
|
|
68
|
+
const { Pool } = await import("pg");
|
|
69
|
+
const pool = new Pool({
|
|
70
|
+
connectionString: connectionUrl,
|
|
71
|
+
ssl: { rejectUnauthorized: false },
|
|
72
|
+
connectionTimeoutMillis: 1e4,
|
|
73
|
+
statement_timeout: 6e4
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
const result = await pool.query(sql, queryParams);
|
|
77
|
+
return result.rows;
|
|
78
|
+
} finally {
|
|
79
|
+
await pool.end();
|
|
80
|
+
}
|
|
81
|
+
} catch (err) {
|
|
82
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
83
|
+
throw new Error(msg.replaceAll(connectionUrl, "***"));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
query: runQuery
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ../connectors/src/connector-onboarding.ts
|
|
92
|
+
var ConnectorOnboarding = class {
|
|
93
|
+
/** Phase 1: Connection setup instructions (optional — some connectors don't need this) */
|
|
94
|
+
connectionSetupInstructions;
|
|
95
|
+
/** Phase 2: Data overview instructions */
|
|
96
|
+
dataOverviewInstructions;
|
|
97
|
+
constructor(config) {
|
|
98
|
+
this.connectionSetupInstructions = config.connectionSetupInstructions;
|
|
99
|
+
this.dataOverviewInstructions = config.dataOverviewInstructions;
|
|
100
|
+
}
|
|
101
|
+
getConnectionSetupPrompt(language) {
|
|
102
|
+
return this.connectionSetupInstructions?.[language] ?? null;
|
|
103
|
+
}
|
|
104
|
+
getDataOverviewInstructions(language) {
|
|
105
|
+
return this.dataOverviewInstructions[language];
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// ../connectors/src/connector-tool.ts
|
|
110
|
+
var ConnectorTool = class {
|
|
111
|
+
name;
|
|
112
|
+
description;
|
|
113
|
+
inputSchema;
|
|
114
|
+
outputSchema;
|
|
115
|
+
_execute;
|
|
116
|
+
constructor(config) {
|
|
117
|
+
this.name = config.name;
|
|
118
|
+
this.description = config.description;
|
|
119
|
+
this.inputSchema = config.inputSchema;
|
|
120
|
+
this.outputSchema = config.outputSchema;
|
|
121
|
+
this._execute = config.execute;
|
|
122
|
+
}
|
|
123
|
+
createTool(connections, config) {
|
|
124
|
+
return {
|
|
125
|
+
description: this.description,
|
|
126
|
+
inputSchema: this.inputSchema,
|
|
127
|
+
outputSchema: this.outputSchema,
|
|
128
|
+
execute: (input) => this._execute(input, connections, config)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// ../connectors/src/connector-plugin.ts
|
|
134
|
+
var ConnectorPlugin = class _ConnectorPlugin {
|
|
135
|
+
slug;
|
|
136
|
+
authType;
|
|
137
|
+
name;
|
|
138
|
+
description;
|
|
139
|
+
iconUrl;
|
|
140
|
+
parameters;
|
|
141
|
+
releaseFlag;
|
|
142
|
+
proxyPolicy;
|
|
143
|
+
experimentalAttributes;
|
|
144
|
+
categories;
|
|
145
|
+
onboarding;
|
|
146
|
+
systemPrompt;
|
|
147
|
+
tools;
|
|
148
|
+
query;
|
|
149
|
+
checkConnection;
|
|
150
|
+
constructor(config) {
|
|
151
|
+
this.slug = config.slug;
|
|
152
|
+
this.authType = config.authType;
|
|
153
|
+
this.name = config.name;
|
|
154
|
+
this.description = config.description;
|
|
155
|
+
this.iconUrl = config.iconUrl;
|
|
156
|
+
this.parameters = config.parameters;
|
|
157
|
+
this.releaseFlag = config.releaseFlag;
|
|
158
|
+
this.proxyPolicy = config.proxyPolicy;
|
|
159
|
+
this.experimentalAttributes = config.experimentalAttributes;
|
|
160
|
+
this.categories = config.categories ?? [];
|
|
161
|
+
this.onboarding = config.onboarding;
|
|
162
|
+
this.systemPrompt = config.systemPrompt;
|
|
163
|
+
this.tools = config.tools;
|
|
164
|
+
this.query = config.query;
|
|
165
|
+
this.checkConnection = config.checkConnection;
|
|
166
|
+
}
|
|
167
|
+
get connectorKey() {
|
|
168
|
+
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Create tools for connections that belong to this connector.
|
|
172
|
+
* Filters connections by connectorKey internally.
|
|
173
|
+
* Returns tools keyed as `${connectorKey}_${toolName}`.
|
|
174
|
+
*/
|
|
175
|
+
createTools(connections, config, opts) {
|
|
176
|
+
const myConnections = connections.filter(
|
|
177
|
+
(c) => _ConnectorPlugin.deriveKey(c.connector.slug, c.connector.authType) === this.connectorKey
|
|
178
|
+
);
|
|
179
|
+
const result = {};
|
|
180
|
+
for (const t of Object.values(this.tools)) {
|
|
181
|
+
const tool = t.createTool(myConnections, config);
|
|
182
|
+
const originalToModelOutput = tool.toModelOutput;
|
|
183
|
+
result[`${this.connectorKey}_${t.name}`] = {
|
|
184
|
+
...tool,
|
|
185
|
+
toModelOutput: async (options) => {
|
|
186
|
+
if (!originalToModelOutput) {
|
|
187
|
+
return opts.truncateOutput(options.output);
|
|
188
|
+
}
|
|
189
|
+
const modelOutput = await originalToModelOutput(options);
|
|
190
|
+
if (modelOutput.type === "text" || modelOutput.type === "json") {
|
|
191
|
+
return opts.truncateOutput(modelOutput.value);
|
|
192
|
+
}
|
|
193
|
+
return modelOutput;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
static deriveKey(slug, authType) {
|
|
200
|
+
if (authType) return `${slug}-${authType}`;
|
|
201
|
+
const LEGACY_NULL_AUTH_TYPE_MAP = {
|
|
202
|
+
// user-password
|
|
203
|
+
"postgresql": "user-password",
|
|
204
|
+
"mysql": "user-password",
|
|
205
|
+
"clickhouse": "user-password",
|
|
206
|
+
"kintone": "user-password",
|
|
207
|
+
"squadbase-db": "user-password",
|
|
208
|
+
// service-account
|
|
209
|
+
"snowflake": "service-account",
|
|
210
|
+
"bigquery": "service-account",
|
|
211
|
+
"google-analytics": "service-account",
|
|
212
|
+
"google-calendar": "service-account",
|
|
213
|
+
"aws-athena": "service-account",
|
|
214
|
+
"redshift": "service-account",
|
|
215
|
+
// api-key
|
|
216
|
+
"databricks": "api-key",
|
|
217
|
+
"dbt": "api-key",
|
|
218
|
+
"airtable": "api-key",
|
|
219
|
+
"openai": "api-key",
|
|
220
|
+
"gemini": "api-key",
|
|
221
|
+
"anthropic": "api-key",
|
|
222
|
+
"wix-store": "api-key"
|
|
223
|
+
};
|
|
224
|
+
const fallbackAuthType = LEGACY_NULL_AUTH_TYPE_MAP[slug];
|
|
225
|
+
if (fallbackAuthType) return `${slug}-${fallbackAuthType}`;
|
|
226
|
+
return slug;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// ../connectors/src/auth-types.ts
|
|
231
|
+
var AUTH_TYPES = {
|
|
232
|
+
OAUTH: "oauth",
|
|
233
|
+
API_KEY: "api-key",
|
|
234
|
+
JWT: "jwt",
|
|
235
|
+
SERVICE_ACCOUNT: "service-account",
|
|
236
|
+
PAT: "pat",
|
|
237
|
+
USER_PASSWORD: "user-password"
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// ../connectors/src/lib/query-utils.ts
|
|
241
|
+
function buildPositionalParams(sql, namedParams) {
|
|
242
|
+
if (!namedParams) return { text: sql, values: [] };
|
|
243
|
+
const values = [];
|
|
244
|
+
const nameToIndex = /* @__PURE__ */ new Map();
|
|
245
|
+
const text = sql.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
|
|
246
|
+
if (!nameToIndex.has(name)) {
|
|
247
|
+
values.push(namedParams[name] ?? null);
|
|
248
|
+
nameToIndex.set(name, values.length);
|
|
249
|
+
}
|
|
250
|
+
return `$${nameToIndex.get(name)}`;
|
|
251
|
+
});
|
|
252
|
+
return { text, values };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ../connectors/src/connectors/supabase/setup.ts
|
|
256
|
+
var supabaseOnboarding = new ConnectorOnboarding({
|
|
257
|
+
dataOverviewInstructions: {
|
|
258
|
+
en: `1. Use executeQuery to list tables in the \`public\` schema: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
|
|
259
|
+
2. Most Supabase projects also expose Auth/Storage tables in dedicated schemas (\`auth\`, \`storage\`). Inspect them with \`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema IN ('auth', 'storage')\` only when the user explicitly needs them
|
|
260
|
+
3. For key tables, fetch column info: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
|
|
261
|
+
4. Sample up to 3 tables with \`SELECT * FROM <table_name> LIMIT 5\` if column info alone is insufficient`,
|
|
262
|
+
ja: `1. executeQuery \u3067 \`public\` \u30B9\u30AD\u30FC\u30DE\u306E\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
|
|
263
|
+
2. Supabase\u306F Auth / Storage \u7528\u306E\u30C6\u30FC\u30D6\u30EB\u3092 \`auth\` / \`storage\` \u30B9\u30AD\u30FC\u30DE\u306B\u6301\u3061\u307E\u3059\u3002\u30E6\u30FC\u30B6\u30FC\u304C\u660E\u793A\u7684\u306B\u5FC5\u8981\u3068\u3057\u3066\u3044\u308B\u5834\u5408\u306E\u307F \`SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema IN ('auth', 'storage')\` \u3067\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044
|
|
264
|
+
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 = 'public' AND table_name = 'xxx'\`
|
|
265
|
+
4. \u30AB\u30E9\u30E0\u60C5\u5831\u3060\u3051\u3067\u306F\u4E0D\u5341\u5206\u306A\u5834\u5408\u3001\u6700\u59273\u30C6\u30FC\u30D6\u30EB\u3092 \`SELECT * FROM <table_name> LIMIT 5\` \u3067\u30B5\u30F3\u30D7\u30EA\u30F3\u30B0`
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// ../connectors/src/connectors/supabase/tools/execute-query.ts
|
|
270
|
+
import { z } from "zod";
|
|
271
|
+
var MAX_ROWS = 500;
|
|
272
|
+
var CONNECT_TIMEOUT_MS = 1e4;
|
|
273
|
+
var STATEMENT_TIMEOUT_MS = 6e4;
|
|
274
|
+
var inputSchema = z.object({
|
|
275
|
+
toolUseIntent: z.string().optional().describe(
|
|
276
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
277
|
+
),
|
|
278
|
+
connectionId: z.string().describe("ID of the Supabase connection to use"),
|
|
279
|
+
sql: z.string().describe(
|
|
280
|
+
"PostgreSQL SQL query targeting the Supabase project. Use the `public` schema unless the user explicitly references Supabase Auth (`auth.*`) or Storage (`storage.*`). Always include LIMIT."
|
|
281
|
+
)
|
|
282
|
+
});
|
|
283
|
+
var outputSchema = z.discriminatedUnion("success", [
|
|
284
|
+
z.object({
|
|
285
|
+
success: z.literal(true),
|
|
286
|
+
rowCount: z.number(),
|
|
287
|
+
truncated: z.boolean(),
|
|
288
|
+
rows: z.array(z.record(z.string(), z.unknown()))
|
|
289
|
+
}),
|
|
290
|
+
z.object({
|
|
291
|
+
success: z.literal(false),
|
|
292
|
+
error: z.string()
|
|
293
|
+
})
|
|
294
|
+
]);
|
|
295
|
+
var executeQueryTool = new ConnectorTool({
|
|
296
|
+
name: "executeQuery",
|
|
297
|
+
description: `Execute SQL against a Supabase Postgres database. Returns up to ${MAX_ROWS} rows.
|
|
298
|
+
Use for: schema exploration (information_schema), data sampling, and analytical queries against Supabase tables.
|
|
299
|
+
User tables live in the \`public\` schema by default; Supabase-managed metadata lives in \`auth\` and \`storage\`.
|
|
300
|
+
Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
301
|
+
inputSchema,
|
|
302
|
+
outputSchema,
|
|
303
|
+
async execute({ connectionId, sql }, connections) {
|
|
304
|
+
const connection2 = connections.find((c) => c.id === connectionId);
|
|
305
|
+
if (!connection2) {
|
|
306
|
+
return {
|
|
307
|
+
success: false,
|
|
308
|
+
error: `Connection ${connectionId} not found`
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
console.log(
|
|
312
|
+
`[connector-query] supabase/${connection2.name}: ${sql}`
|
|
313
|
+
);
|
|
314
|
+
let connectionUrl;
|
|
315
|
+
try {
|
|
316
|
+
const { Pool } = await import("pg");
|
|
317
|
+
connectionUrl = parameters.connectionUrl.getValue(connection2);
|
|
318
|
+
const pool = new Pool({
|
|
319
|
+
connectionString: connectionUrl,
|
|
320
|
+
ssl: { rejectUnauthorized: false },
|
|
321
|
+
connectionTimeoutMillis: CONNECT_TIMEOUT_MS,
|
|
322
|
+
statement_timeout: STATEMENT_TIMEOUT_MS
|
|
323
|
+
});
|
|
324
|
+
try {
|
|
325
|
+
const result = await pool.query(sql);
|
|
326
|
+
const rows = result.rows;
|
|
327
|
+
const truncated = rows.length > MAX_ROWS;
|
|
328
|
+
return {
|
|
329
|
+
success: true,
|
|
330
|
+
rowCount: Math.min(rows.length, MAX_ROWS),
|
|
331
|
+
truncated,
|
|
332
|
+
rows: rows.slice(0, MAX_ROWS)
|
|
333
|
+
};
|
|
334
|
+
} finally {
|
|
335
|
+
await pool.end();
|
|
336
|
+
}
|
|
337
|
+
} catch (err) {
|
|
338
|
+
let msg = err instanceof Error ? err.message : String(err);
|
|
339
|
+
if (connectionUrl) {
|
|
340
|
+
msg = msg.replaceAll(connectionUrl, "***");
|
|
341
|
+
}
|
|
342
|
+
return { success: false, error: msg };
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// ../connectors/src/connectors/supabase/index.ts
|
|
348
|
+
var tools = { executeQuery: executeQueryTool };
|
|
349
|
+
var supabaseConnector = new ConnectorPlugin({
|
|
350
|
+
slug: "supabase",
|
|
351
|
+
authType: AUTH_TYPES.USER_PASSWORD,
|
|
352
|
+
name: "Supabase",
|
|
353
|
+
description: "Connect to a Supabase project's Postgres database to query application tables and Supabase-managed schemas (auth, storage).",
|
|
354
|
+
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/14k0U6F9PVovVjYjWyNzKb/2c4ff53adbe9334a63fee0a13d9f050a/supabase-icon.webp",
|
|
355
|
+
parameters,
|
|
356
|
+
releaseFlag: { dev1: true, dev2: true, prod: true },
|
|
357
|
+
categories: ["database"],
|
|
358
|
+
onboarding: supabaseOnboarding,
|
|
359
|
+
systemPrompt: {
|
|
360
|
+
en: `### Tools
|
|
361
|
+
|
|
362
|
+
- \`supabase_executeQuery\`: Executes a PostgreSQL query against the Supabase project's database and returns rows. Use this for schema exploration via \`information_schema.tables\`/\`columns\` and for sampling data. See the SQL Reference below for syntax notes and Supabase-specific schemas.
|
|
363
|
+
|
|
364
|
+
### Business Logic
|
|
365
|
+
|
|
366
|
+
The business logic type for this connector is "sql".
|
|
367
|
+
|
|
368
|
+
### SQL Reference
|
|
369
|
+
- Schema layout:
|
|
370
|
+
- User tables live in the \`public\` schema by default.
|
|
371
|
+
- Supabase Auth tables live in the \`auth\` schema (e.g. \`auth.users\`).
|
|
372
|
+
- Supabase Storage tables live in the \`storage\` schema (e.g. \`storage.objects\`, \`storage.buckets\`).
|
|
373
|
+
- Schema exploration:
|
|
374
|
+
- List user tables: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
|
|
375
|
+
- List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
|
|
376
|
+
- Always include LIMIT in queries`,
|
|
377
|
+
ja: `### \u30C4\u30FC\u30EB
|
|
378
|
+
|
|
379
|
+
- \`supabase_executeQuery\`: Supabase\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E Postgres \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u5BFE\u3057\u3066\u30AF\u30A8\u30EA\u3092\u5B9F\u884C\u3057\u3001\u884C\u30C7\u30FC\u30BF\u3092\u8FD4\u3057\u307E\u3059\u3002\`information_schema.tables\`/\`columns\` \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\u3002\u69CB\u6587\u306E\u6CE8\u610F\u70B9\u3068 Supabase \u56FA\u6709\u306E\u30B9\u30AD\u30FC\u30DE\u306F\u4E0B\u90E8\u306E\u300CSQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u300D\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
380
|
+
|
|
381
|
+
### Business Logic
|
|
382
|
+
|
|
383
|
+
\u3053\u306E\u30B3\u30CD\u30AF\u30BF\u306E\u30D3\u30B8\u30CD\u30B9\u30ED\u30B8\u30C3\u30AF\u30BF\u30A4\u30D7\u306F "sql" \u3067\u3059\u3002
|
|
384
|
+
|
|
385
|
+
### SQL \u30EA\u30D5\u30A1\u30EC\u30F3\u30B9
|
|
386
|
+
- \u30B9\u30AD\u30FC\u30DE\u69CB\u6210:
|
|
387
|
+
- \u30E6\u30FC\u30B6\u30FC\u306E\u30C6\u30FC\u30D6\u30EB\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067 \`public\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\u3002
|
|
388
|
+
- Supabase Auth \u306E\u30C6\u30FC\u30D6\u30EB\u306F \`auth\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\uFF08\u4F8B: \`auth.users\`\uFF09\u3002
|
|
389
|
+
- Supabase Storage \u306E\u30C6\u30FC\u30D6\u30EB\u306F \`storage\` \u30B9\u30AD\u30FC\u30DE\u306B\u5B58\u5728\u3057\u307E\u3059\uFF08\u4F8B: \`storage.objects\`, \`storage.buckets\`\uFF09\u3002
|
|
390
|
+
- \u30B9\u30AD\u30FC\u30DE\u63A2\u7D22:
|
|
391
|
+
- \u30E6\u30FC\u30B6\u30FC\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7: \`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'\`
|
|
392
|
+
- \u30AB\u30E9\u30E0\u4E00\u89A7: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
|
|
393
|
+
- \u30AF\u30A8\u30EA\u306B\u306F\u5FC5\u305A LIMIT \u3092\u542B\u3081\u3066\u304F\u3060\u3055\u3044`
|
|
394
|
+
},
|
|
395
|
+
tools,
|
|
396
|
+
async checkConnection(params, _config) {
|
|
397
|
+
const { Pool } = await import("pg");
|
|
398
|
+
const connectionUrl = params[parameters.connectionUrl.slug];
|
|
399
|
+
const pool = new Pool({
|
|
400
|
+
connectionString: connectionUrl,
|
|
401
|
+
ssl: { rejectUnauthorized: false },
|
|
402
|
+
connectionTimeoutMillis: 1e4
|
|
403
|
+
});
|
|
404
|
+
try {
|
|
405
|
+
await pool.query("SELECT 1");
|
|
406
|
+
return { success: true };
|
|
407
|
+
} catch (error) {
|
|
408
|
+
return {
|
|
409
|
+
success: false,
|
|
410
|
+
error: error instanceof Error ? error.message : String(error)
|
|
411
|
+
};
|
|
412
|
+
} finally {
|
|
413
|
+
await pool.end();
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
async query(params, sql, namedParams) {
|
|
417
|
+
const { Pool } = await import("pg");
|
|
418
|
+
const cleanSql = sql.replace(/;\s*$/, "");
|
|
419
|
+
const { text, values } = buildPositionalParams(cleanSql, namedParams);
|
|
420
|
+
const connectionUrl = params[parameters.connectionUrl.slug];
|
|
421
|
+
const pool = new Pool({
|
|
422
|
+
connectionString: connectionUrl,
|
|
423
|
+
ssl: { rejectUnauthorized: false },
|
|
424
|
+
connectionTimeoutMillis: 1e4,
|
|
425
|
+
statement_timeout: 6e4
|
|
426
|
+
});
|
|
427
|
+
try {
|
|
428
|
+
const result = await pool.query(text, values);
|
|
429
|
+
return { rows: result.rows };
|
|
430
|
+
} finally {
|
|
431
|
+
await pool.end();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// src/connectors/create-connector-sdk.ts
|
|
437
|
+
import { readFileSync } from "fs";
|
|
438
|
+
import path from "path";
|
|
439
|
+
|
|
440
|
+
// src/connector-client/env.ts
|
|
441
|
+
function resolveEnvVar(entry, key, connectionId) {
|
|
442
|
+
const envVarName = entry.envVars[key];
|
|
443
|
+
if (!envVarName) {
|
|
444
|
+
throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
|
|
445
|
+
}
|
|
446
|
+
const value = process.env[envVarName];
|
|
447
|
+
if (!value) {
|
|
448
|
+
throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
|
|
449
|
+
}
|
|
450
|
+
return value;
|
|
451
|
+
}
|
|
452
|
+
function resolveEnvVarOptional(entry, key) {
|
|
453
|
+
const envVarName = entry.envVars[key];
|
|
454
|
+
if (!envVarName) return void 0;
|
|
455
|
+
return process.env[envVarName] || void 0;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/connector-client/proxy-fetch.ts
|
|
459
|
+
import { getContext } from "hono/context-storage";
|
|
460
|
+
import { getCookie } from "hono/cookie";
|
|
461
|
+
var APP_SESSION_COOKIE_NAME = "__Host-squadbase-session";
|
|
462
|
+
function normalizeHeaders(input) {
|
|
463
|
+
const out = {};
|
|
464
|
+
if (!input) return out;
|
|
465
|
+
new Headers(input).forEach((value, key) => {
|
|
466
|
+
out[key] = value;
|
|
467
|
+
});
|
|
468
|
+
return out;
|
|
469
|
+
}
|
|
470
|
+
function createSandboxProxyFetch(connectionId) {
|
|
471
|
+
return async (input, init) => {
|
|
472
|
+
const token = process.env.INTERNAL_SQUADBASE_OAUTH_MACHINE_CREDENTIAL;
|
|
473
|
+
const sandboxId = process.env.INTERNAL_SQUADBASE_SANDBOX_ID;
|
|
474
|
+
if (!token || !sandboxId) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
"Connection proxy is not configured. Please check your deployment settings."
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
480
|
+
const originalMethod = init?.method ?? "GET";
|
|
481
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
482
|
+
const baseDomain = process.env["SQUADBASE_PREVIEW_BASE_DOMAIN"] ?? "preview.app.squadbase.dev";
|
|
483
|
+
const proxyUrl = `https://${sandboxId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
484
|
+
return fetch(proxyUrl, {
|
|
485
|
+
method: "POST",
|
|
486
|
+
headers: {
|
|
487
|
+
"Content-Type": "application/json",
|
|
488
|
+
Authorization: `Bearer ${token}`
|
|
489
|
+
},
|
|
490
|
+
body: JSON.stringify({
|
|
491
|
+
url: originalUrl,
|
|
492
|
+
method: originalMethod,
|
|
493
|
+
headers: normalizeHeaders(init?.headers),
|
|
494
|
+
body: originalBody
|
|
495
|
+
})
|
|
496
|
+
});
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function createDeployedAppProxyFetch(connectionId) {
|
|
500
|
+
const projectId = process.env["SQUADBASE_PROJECT_ID"];
|
|
501
|
+
if (!projectId) {
|
|
502
|
+
throw new Error(
|
|
503
|
+
"Connection proxy is not configured. Please check your deployment settings."
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
const baseDomain = process.env["SQUADBASE_APP_BASE_DOMAIN"] ?? "squadbase.app";
|
|
507
|
+
const proxyUrl = `https://${projectId}.${baseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
508
|
+
return async (input, init) => {
|
|
509
|
+
const originalUrl = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
510
|
+
const originalMethod = init?.method ?? "GET";
|
|
511
|
+
const originalBody = init?.body ? JSON.parse(init.body) : void 0;
|
|
512
|
+
const c = getContext();
|
|
513
|
+
const appSession = getCookie(c, APP_SESSION_COOKIE_NAME);
|
|
514
|
+
if (!appSession) {
|
|
515
|
+
throw new Error(
|
|
516
|
+
"No authentication method available for connection proxy."
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
return fetch(proxyUrl, {
|
|
520
|
+
method: "POST",
|
|
521
|
+
headers: {
|
|
522
|
+
"Content-Type": "application/json",
|
|
523
|
+
Authorization: `Bearer ${appSession}`
|
|
524
|
+
},
|
|
525
|
+
body: JSON.stringify({
|
|
526
|
+
url: originalUrl,
|
|
527
|
+
method: originalMethod,
|
|
528
|
+
headers: normalizeHeaders(init?.headers),
|
|
529
|
+
body: originalBody
|
|
530
|
+
})
|
|
531
|
+
});
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
function createProxyFetch(connectionId) {
|
|
535
|
+
if (process.env.INTERNAL_SQUADBASE_SANDBOX_ID) {
|
|
536
|
+
return createSandboxProxyFetch(connectionId);
|
|
537
|
+
}
|
|
538
|
+
return createDeployedAppProxyFetch(connectionId);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/connectors/create-connector-sdk.ts
|
|
542
|
+
function loadConnectionsSync() {
|
|
543
|
+
const filePath = process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
|
|
544
|
+
try {
|
|
545
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
546
|
+
return JSON.parse(raw);
|
|
547
|
+
} catch {
|
|
548
|
+
return {};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
function createConnectorSdk(plugin, createClient2) {
|
|
552
|
+
return (connectionId) => {
|
|
553
|
+
const connections = loadConnectionsSync();
|
|
554
|
+
const entry = connections[connectionId];
|
|
555
|
+
if (!entry) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
`Connection "${connectionId}" not found in .squadbase/connections.json`
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
if (entry.connector.slug !== plugin.slug) {
|
|
561
|
+
throw new Error(
|
|
562
|
+
`Connection "${connectionId}" is not a ${plugin.slug} connection (got "${entry.connector.slug}")`
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
const params = {};
|
|
566
|
+
for (const param of Object.values(plugin.parameters)) {
|
|
567
|
+
if (param.required) {
|
|
568
|
+
params[param.slug] = resolveEnvVar(entry, param.slug, connectionId);
|
|
569
|
+
} else {
|
|
570
|
+
const val = resolveEnvVarOptional(entry, param.slug);
|
|
571
|
+
if (val !== void 0) params[param.slug] = val;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return createClient2(params, createProxyFetch(connectionId));
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// src/connectors/entries/supabase.ts
|
|
579
|
+
var connection = createConnectorSdk(supabaseConnector, createClient);
|
|
580
|
+
export {
|
|
581
|
+
connection
|
|
582
|
+
};
|
|
@@ -105,6 +105,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
105
105
|
releaseFlag;
|
|
106
106
|
proxyPolicy;
|
|
107
107
|
experimentalAttributes;
|
|
108
|
+
categories;
|
|
108
109
|
onboarding;
|
|
109
110
|
systemPrompt;
|
|
110
111
|
tools;
|
|
@@ -120,6 +121,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
120
121
|
this.releaseFlag = config.releaseFlag;
|
|
121
122
|
this.proxyPolicy = config.proxyPolicy;
|
|
122
123
|
this.experimentalAttributes = config.experimentalAttributes;
|
|
124
|
+
this.categories = config.categories ?? [];
|
|
123
125
|
this.onboarding = config.onboarding;
|
|
124
126
|
this.systemPrompt = config.systemPrompt;
|
|
125
127
|
this.tools = config.tools;
|
|
@@ -199,6 +201,16 @@ var AUTH_TYPES = {
|
|
|
199
201
|
USER_PASSWORD: "user-password"
|
|
200
202
|
};
|
|
201
203
|
|
|
204
|
+
// ../connectors/src/lib/normalize-path.ts
|
|
205
|
+
function normalizeRequestPath(path2, basePathSegment) {
|
|
206
|
+
let p = path2.trim();
|
|
207
|
+
if (!p.startsWith("/")) p = "/" + p;
|
|
208
|
+
if (p === basePathSegment || p.startsWith(basePathSegment + "/")) {
|
|
209
|
+
p = p.slice(basePathSegment.length) || "/";
|
|
210
|
+
}
|
|
211
|
+
return p;
|
|
212
|
+
}
|
|
213
|
+
|
|
202
214
|
// ../connectors/src/connectors/tiktok-ads/tools/list-advertisers.ts
|
|
203
215
|
import { z } from "zod";
|
|
204
216
|
var BASE_URL2 = "https://business-api.tiktok.com/open_api/v1.3/";
|
|
@@ -373,7 +385,9 @@ var parameters = {
|
|
|
373
385
|
|
|
374
386
|
// ../connectors/src/connectors/tiktok-ads/tools/request.ts
|
|
375
387
|
import { z as z2 } from "zod";
|
|
376
|
-
var
|
|
388
|
+
var BASE_HOST = "https://business-api.tiktok.com";
|
|
389
|
+
var BASE_PATH_SEGMENT = "/open_api/v1.3";
|
|
390
|
+
var BASE_URL3 = `${BASE_HOST}${BASE_PATH_SEGMENT}`;
|
|
377
391
|
var REQUEST_TIMEOUT_MS2 = 6e4;
|
|
378
392
|
var cachedToken2 = null;
|
|
379
393
|
async function getProxyToken2(config) {
|
|
@@ -449,7 +463,8 @@ The advertiser_id is automatically injected if configured.`,
|
|
|
449
463
|
);
|
|
450
464
|
try {
|
|
451
465
|
const advertiserId = parameters.advertiserId.tryGetValue(connection2) ?? "";
|
|
452
|
-
|
|
466
|
+
const normalizedPath = normalizeRequestPath(path2, BASE_PATH_SEGMENT);
|
|
467
|
+
let url = `${BASE_URL3}${normalizedPath}`;
|
|
453
468
|
if (method === "GET") {
|
|
454
469
|
const params = new URLSearchParams(queryParams ?? {});
|
|
455
470
|
if (advertiserId && !params.has("advertiser_id")) {
|
|
@@ -519,6 +534,7 @@ var tiktokAdsConnector = new ConnectorPlugin({
|
|
|
519
534
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/01jHuwvmhe4ts0wj23Hxpm/afac9fa50ac5b353927900a122e898ab/tiktok.webp",
|
|
520
535
|
parameters,
|
|
521
536
|
releaseFlag: { dev1: true, dev2: false, prod: false },
|
|
537
|
+
categories: ["marketing"],
|
|
522
538
|
onboarding: tiktokAdsOnboarding,
|
|
523
539
|
proxyPolicy: {
|
|
524
540
|
allowlist: [
|
|
@@ -252,6 +252,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
252
252
|
releaseFlag;
|
|
253
253
|
proxyPolicy;
|
|
254
254
|
experimentalAttributes;
|
|
255
|
+
categories;
|
|
255
256
|
onboarding;
|
|
256
257
|
systemPrompt;
|
|
257
258
|
tools;
|
|
@@ -267,6 +268,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
267
268
|
this.releaseFlag = config.releaseFlag;
|
|
268
269
|
this.proxyPolicy = config.proxyPolicy;
|
|
269
270
|
this.experimentalAttributes = config.experimentalAttributes;
|
|
271
|
+
this.categories = config.categories ?? [];
|
|
270
272
|
this.onboarding = config.onboarding;
|
|
271
273
|
this.systemPrompt = config.systemPrompt;
|
|
272
274
|
this.tools = config.tools;
|
|
@@ -438,6 +440,7 @@ var wixStoreConnector = new ConnectorPlugin({
|
|
|
438
440
|
iconUrl: "https://images.ctfassets.net/9ncizv60xc5y/YyFxclQFzROIYpFam6vRK/e7e75d3feac49a1cc5e433c147216d23/Wix_logo_black.svg",
|
|
439
441
|
parameters,
|
|
440
442
|
releaseFlag: { dev1: true, dev2: true, prod: true },
|
|
443
|
+
categories: ["ecommerce"],
|
|
441
444
|
onboarding: wixStoreOnboarding,
|
|
442
445
|
systemPrompt: {
|
|
443
446
|
en: `### Tools
|