@squadbase/connectors 0.0.3 → 0.0.5
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/index.d.ts +13 -1
- package/dist/index.js +575 -285
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ interface ProxyPolicyRule {
|
|
|
52
52
|
interface ProxyPolicy {
|
|
53
53
|
allowlist: ProxyPolicyRule[];
|
|
54
54
|
}
|
|
55
|
+
type ConnectionCheckResult = {
|
|
56
|
+
success: true;
|
|
57
|
+
} | {
|
|
58
|
+
success: false;
|
|
59
|
+
error: string;
|
|
60
|
+
};
|
|
55
61
|
interface ConnectorToolsConfig {
|
|
56
62
|
oauthProxy: {
|
|
57
63
|
appApiKey: string;
|
|
@@ -97,6 +103,9 @@ declare class ConnectorPlugin<P extends Record<string, ParameterDefinition> = Re
|
|
|
97
103
|
}) => Promise<{
|
|
98
104
|
rows: Record<string, unknown>[];
|
|
99
105
|
}>;
|
|
106
|
+
readonly checkConnection?: (params: Record<string, string>, config: {
|
|
107
|
+
proxyFetch: typeof fetch;
|
|
108
|
+
}) => Promise<ConnectionCheckResult>;
|
|
100
109
|
constructor(config: {
|
|
101
110
|
slug: string;
|
|
102
111
|
authType: string | null;
|
|
@@ -115,6 +124,9 @@ declare class ConnectorPlugin<P extends Record<string, ParameterDefinition> = Re
|
|
|
115
124
|
}) => Promise<{
|
|
116
125
|
rows: Record<string, unknown>[];
|
|
117
126
|
}>;
|
|
127
|
+
checkConnection?: (params: Record<string, string>, config: {
|
|
128
|
+
proxyFetch: typeof fetch;
|
|
129
|
+
}) => Promise<ConnectionCheckResult>;
|
|
118
130
|
});
|
|
119
131
|
get connectorKey(): string;
|
|
120
132
|
/**
|
|
@@ -790,4 +802,4 @@ declare const squadbaseDbConnector: ConnectorPlugin<{
|
|
|
790
802
|
}>;
|
|
791
803
|
}>;
|
|
792
804
|
|
|
793
|
-
export { AUTH_TYPES, ConnectorPlugin, ConnectorSetup, ConnectorTool, type ConnectorToolsConfig, ParameterDefinition, type ProxyPolicy, type ProxyPolicyRule, type ReleaseFlag, type SetupLanguage, airtableConnector, awsAthenaConnector, bigqueryConnector, bigqueryOauthConnector, connectors, databricksConnector, dbtConnector, googleAnalyticsConnector, kintoneConnector, mysqlConnector, postgresqlConnector, redshiftConnector, snowflakeConnector, snowflakePatConnector, squadbaseDbConnector, wixStoreConnector };
|
|
805
|
+
export { AUTH_TYPES, type ConnectionCheckResult, ConnectorPlugin, ConnectorSetup, ConnectorTool, type ConnectorToolsConfig, ParameterDefinition, type ProxyPolicy, type ProxyPolicyRule, type ReleaseFlag, type SetupLanguage, airtableConnector, awsAthenaConnector, bigqueryConnector, bigqueryOauthConnector, connectors, databricksConnector, dbtConnector, googleAnalyticsConnector, kintoneConnector, mysqlConnector, postgresqlConnector, redshiftConnector, snowflakeConnector, snowflakePatConnector, squadbaseDbConnector, wixStoreConnector };
|
package/dist/index.js
CHANGED
|
@@ -92,6 +92,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
92
92
|
systemPrompt;
|
|
93
93
|
tools;
|
|
94
94
|
query;
|
|
95
|
+
checkConnection;
|
|
95
96
|
constructor(config) {
|
|
96
97
|
this.slug = config.slug;
|
|
97
98
|
this.authType = config.authType;
|
|
@@ -106,6 +107,7 @@ var ConnectorPlugin = class _ConnectorPlugin {
|
|
|
106
107
|
this.systemPrompt = config.systemPrompt;
|
|
107
108
|
this.tools = config.tools;
|
|
108
109
|
this.query = config.query;
|
|
110
|
+
this.checkConnection = config.checkConnection;
|
|
109
111
|
}
|
|
110
112
|
get connectorKey() {
|
|
111
113
|
return _ConnectorPlugin.deriveKey(this.slug, this.authType);
|
|
@@ -439,6 +441,45 @@ var snowflakeConnector = new ConnectorPlugin({
|
|
|
439
441
|
- List columns: \`DESCRIBE TABLE db_name.schema_name.table_name\`
|
|
440
442
|
- INFORMATION_SCHEMA is also available: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``,
|
|
441
443
|
tools,
|
|
444
|
+
async checkConnection(params, _config) {
|
|
445
|
+
try {
|
|
446
|
+
const snowflake = (await import("snowflake-sdk")).default;
|
|
447
|
+
snowflake.configure({ logLevel: "ERROR" });
|
|
448
|
+
const privateKey = Buffer.from(
|
|
449
|
+
params[parameters.privateKeyBase64.slug],
|
|
450
|
+
"base64"
|
|
451
|
+
).toString("utf-8");
|
|
452
|
+
const conn = snowflake.createConnection({
|
|
453
|
+
account: params[parameters.account.slug],
|
|
454
|
+
username: params[parameters.user.slug],
|
|
455
|
+
role: params[parameters.role.slug],
|
|
456
|
+
warehouse: params[parameters.warehouse.slug],
|
|
457
|
+
authenticator: "SNOWFLAKE_JWT",
|
|
458
|
+
privateKey
|
|
459
|
+
});
|
|
460
|
+
await new Promise((resolve, reject) => {
|
|
461
|
+
conn.connect((err) => {
|
|
462
|
+
if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
|
|
463
|
+
else resolve();
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
await new Promise((resolve, reject) => {
|
|
467
|
+
conn.execute({
|
|
468
|
+
sqlText: "SELECT 1",
|
|
469
|
+
complete: (err) => {
|
|
470
|
+
if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
|
|
471
|
+
else resolve();
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
conn.destroy((err) => {
|
|
476
|
+
if (err) console.warn(`[connector-client] Snowflake destroy error: ${err.message}`);
|
|
477
|
+
});
|
|
478
|
+
return { success: true };
|
|
479
|
+
} catch (e) {
|
|
480
|
+
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
481
|
+
}
|
|
482
|
+
},
|
|
442
483
|
async query(params, sql, namedParams) {
|
|
443
484
|
const resolvedSql = replaceLiteralParams(sql, namedParams);
|
|
444
485
|
const snowflake = (await import("snowflake-sdk")).default;
|
|
@@ -653,6 +694,45 @@ var snowflakePatConnector = new ConnectorPlugin({
|
|
|
653
694
|
- List columns: \`DESCRIBE TABLE db_name.schema_name.table_name\`
|
|
654
695
|
- INFORMATION_SCHEMA is also available: \`SELECT * FROM db_name.INFORMATION_SCHEMA.TABLES\``,
|
|
655
696
|
tools: tools2,
|
|
697
|
+
async checkConnection(params, _config) {
|
|
698
|
+
try {
|
|
699
|
+
const snowflake = (await import("snowflake-sdk")).default;
|
|
700
|
+
snowflake.configure({ logLevel: "ERROR" });
|
|
701
|
+
const conn = snowflake.createConnection({
|
|
702
|
+
account: params[parameters2.account.slug],
|
|
703
|
+
username: params[parameters2.user.slug],
|
|
704
|
+
role: params[parameters2.role.slug],
|
|
705
|
+
warehouse: params[parameters2.warehouse.slug],
|
|
706
|
+
password: params[parameters2.pat.slug]
|
|
707
|
+
});
|
|
708
|
+
await new Promise((resolve, reject) => {
|
|
709
|
+
conn.connect((err) => {
|
|
710
|
+
if (err)
|
|
711
|
+
reject(new Error(`Snowflake connect failed: ${err.message}`));
|
|
712
|
+
else resolve();
|
|
713
|
+
});
|
|
714
|
+
});
|
|
715
|
+
await new Promise((resolve, reject) => {
|
|
716
|
+
conn.execute({
|
|
717
|
+
sqlText: "SELECT 1",
|
|
718
|
+
complete: (err) => {
|
|
719
|
+
if (err)
|
|
720
|
+
reject(new Error(`Snowflake query failed: ${err.message}`));
|
|
721
|
+
else resolve();
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
conn.destroy((err) => {
|
|
726
|
+
if (err)
|
|
727
|
+
console.warn(
|
|
728
|
+
`[connector-client] Snowflake destroy error: ${err.message}`
|
|
729
|
+
);
|
|
730
|
+
});
|
|
731
|
+
return { success: true };
|
|
732
|
+
} catch (e) {
|
|
733
|
+
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
734
|
+
}
|
|
735
|
+
},
|
|
656
736
|
async query(params, sql, namedParams) {
|
|
657
737
|
const resolvedSql = replaceLiteralParams(sql, namedParams);
|
|
658
738
|
const snowflake = (await import("snowflake-sdk")).default;
|
|
@@ -797,6 +877,22 @@ var postgresqlConnector = new ConnectorPlugin({
|
|
|
797
877
|
- List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
|
|
798
878
|
- Always include LIMIT in queries`,
|
|
799
879
|
tools: tools3,
|
|
880
|
+
async checkConnection(params, _config) {
|
|
881
|
+
const { Pool } = await import("pg");
|
|
882
|
+
const pool = new Pool({
|
|
883
|
+
connectionString: params[parameters3.connectionUrl.slug],
|
|
884
|
+
ssl: { rejectUnauthorized: false },
|
|
885
|
+
connectionTimeoutMillis: 1e4
|
|
886
|
+
});
|
|
887
|
+
try {
|
|
888
|
+
await pool.query("SELECT 1");
|
|
889
|
+
return { success: true };
|
|
890
|
+
} catch (error) {
|
|
891
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
892
|
+
} finally {
|
|
893
|
+
await pool.end();
|
|
894
|
+
}
|
|
895
|
+
},
|
|
800
896
|
async query(params, sql, namedParams) {
|
|
801
897
|
const { Pool } = await import("pg");
|
|
802
898
|
const { text, values } = buildPositionalParams(sql, namedParams);
|
|
@@ -921,6 +1017,21 @@ var mysqlConnector = new ConnectorPlugin({
|
|
|
921
1017
|
- List columns: \`SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'xxx'\`
|
|
922
1018
|
- Always include LIMIT in queries`,
|
|
923
1019
|
tools: tools4,
|
|
1020
|
+
async checkConnection(params, _config) {
|
|
1021
|
+
const mysql = await import("mysql2/promise");
|
|
1022
|
+
const pool = mysql.createPool({
|
|
1023
|
+
uri: params[parameters4.connectionUrl.slug],
|
|
1024
|
+
connectTimeout: 1e4
|
|
1025
|
+
});
|
|
1026
|
+
try {
|
|
1027
|
+
await pool.query("SELECT 1");
|
|
1028
|
+
return { success: true };
|
|
1029
|
+
} catch (e) {
|
|
1030
|
+
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
1031
|
+
} finally {
|
|
1032
|
+
await pool.end();
|
|
1033
|
+
}
|
|
1034
|
+
},
|
|
924
1035
|
async query(params, sql, namedParams) {
|
|
925
1036
|
const mysql = await import("mysql2/promise");
|
|
926
1037
|
const { text, values } = buildQuestionmarkParams(sql, namedParams);
|
|
@@ -942,7 +1053,94 @@ var mysqlConnector = new ConnectorPlugin({
|
|
|
942
1053
|
}
|
|
943
1054
|
});
|
|
944
1055
|
|
|
1056
|
+
// src/connectors/bigquery/tools/list-projects.ts
|
|
1057
|
+
import { z as z5 } from "zod";
|
|
1058
|
+
|
|
1059
|
+
// src/connectors/bigquery/parameters.ts
|
|
1060
|
+
var parameters5 = {
|
|
1061
|
+
serviceAccountKeyJsonBase64: new ParameterDefinition({
|
|
1062
|
+
slug: "service-account-key-json-base64",
|
|
1063
|
+
name: "Google Cloud Service Account JSON",
|
|
1064
|
+
description: "The service account JSON key used to authenticate with Google Cloud Platform. Ensure that the service account has the necessary permissions to access the required resources.",
|
|
1065
|
+
envVarBaseKey: "BIGQUERY_SERVICE_ACCOUNT_JSON_BASE64",
|
|
1066
|
+
type: "base64EncodedJson",
|
|
1067
|
+
secret: true,
|
|
1068
|
+
required: true
|
|
1069
|
+
}),
|
|
1070
|
+
projectId: new ParameterDefinition({
|
|
1071
|
+
slug: "project-id",
|
|
1072
|
+
name: "Google Cloud Project ID",
|
|
1073
|
+
description: "The ID of the Google Cloud project where resources will be managed.",
|
|
1074
|
+
envVarBaseKey: "BIGQUERY_PROJECT_ID",
|
|
1075
|
+
type: "text",
|
|
1076
|
+
secret: false,
|
|
1077
|
+
required: false
|
|
1078
|
+
})
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
// src/connectors/bigquery/tools/list-projects.ts
|
|
1082
|
+
var inputSchema5 = z5.object({
|
|
1083
|
+
toolUseIntent: z5.string().optional().describe(
|
|
1084
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
1085
|
+
),
|
|
1086
|
+
connectionId: z5.string().describe("ID of the BigQuery connection to use")
|
|
1087
|
+
});
|
|
1088
|
+
var outputSchema5 = z5.discriminatedUnion("success", [
|
|
1089
|
+
z5.object({
|
|
1090
|
+
success: z5.literal(true),
|
|
1091
|
+
projects: z5.array(
|
|
1092
|
+
z5.object({
|
|
1093
|
+
projectId: z5.string(),
|
|
1094
|
+
friendlyName: z5.string()
|
|
1095
|
+
})
|
|
1096
|
+
)
|
|
1097
|
+
}),
|
|
1098
|
+
z5.object({
|
|
1099
|
+
success: z5.literal(false),
|
|
1100
|
+
error: z5.string()
|
|
1101
|
+
})
|
|
1102
|
+
]);
|
|
1103
|
+
var listProjectsTool = new ConnectorTool({
|
|
1104
|
+
name: "listProjects",
|
|
1105
|
+
description: `List GCP projects accessible with the service account credentials. Returns project IDs and friendly names.`,
|
|
1106
|
+
inputSchema: inputSchema5,
|
|
1107
|
+
outputSchema: outputSchema5,
|
|
1108
|
+
async execute({ connectionId }, connections) {
|
|
1109
|
+
const connection = connections.find((c) => c.id === connectionId);
|
|
1110
|
+
if (!connection) {
|
|
1111
|
+
return {
|
|
1112
|
+
success: false,
|
|
1113
|
+
error: `Connection ${connectionId} not found`
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
try {
|
|
1117
|
+
const serviceAccountJsonBase64 = parameters5.serviceAccountKeyJsonBase64.getValue(connection);
|
|
1118
|
+
const credentials = JSON.parse(
|
|
1119
|
+
Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8")
|
|
1120
|
+
);
|
|
1121
|
+
const { GoogleAuth } = await import("google-auth-library");
|
|
1122
|
+
const auth = new GoogleAuth({
|
|
1123
|
+
credentials,
|
|
1124
|
+
scopes: ["https://www.googleapis.com/auth/bigquery"]
|
|
1125
|
+
});
|
|
1126
|
+
const client = await auth.getClient();
|
|
1127
|
+
const res = await client.request({
|
|
1128
|
+
url: "https://bigquery.googleapis.com/bigquery/v2/projects"
|
|
1129
|
+
});
|
|
1130
|
+
const projects = (res.data.projects ?? []).map((p) => ({
|
|
1131
|
+
projectId: p.projectReference?.projectId ?? "",
|
|
1132
|
+
friendlyName: p.friendlyName ?? p.projectReference?.projectId ?? ""
|
|
1133
|
+
})).filter((p) => p.projectId !== "");
|
|
1134
|
+
return { success: true, projects };
|
|
1135
|
+
} catch (err) {
|
|
1136
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1137
|
+
return { success: false, error: msg };
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
|
|
945
1142
|
// src/connectors/bigquery/setup.ts
|
|
1143
|
+
var listProjectsToolName = `bigquery_${listProjectsTool.name}`;
|
|
946
1144
|
var bigquerySetup = new ConnectorSetup({
|
|
947
1145
|
ja: `## BigQuery \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u624B\u9806
|
|
948
1146
|
|
|
@@ -950,32 +1148,27 @@ var bigquerySetup = new ConnectorSetup({
|
|
|
950
1148
|
|
|
951
1149
|
### \u624B\u9806
|
|
952
1150
|
|
|
953
|
-
#### \u30B9\u30C6\u30C3\
|
|
954
|
-
1. \`
|
|
955
|
-
2. \
|
|
956
|
-
- **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: false\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u629E\u3055\u305B\u308B\u3002\u9078\u629E\u80A2\u306E label \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u306B\u3059\u308B
|
|
957
|
-
- **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
|
|
958
|
-
3. \`updateConnectionParameters\` \u3067\u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
|
|
1151
|
+
#### \u30B9\u30C6\u30C3\u30D71: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u9078\u629E
|
|
1152
|
+
1. \`${listProjectsToolName}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001\u30B5\u30FC\u30D3\u30B9\u30A2\u30AB\u30A6\u30F3\u30C8\u304C\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGCP\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
|
|
1153
|
+
2. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
|
|
959
1154
|
- \`parameterSlug\`: \`"project-id"\`
|
|
960
|
-
- \`
|
|
961
|
-
|
|
962
|
-
4. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D71\u306B\u9032\u3080
|
|
1155
|
+
- \`options\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
|
|
1156
|
+
3. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
|
|
963
1157
|
|
|
964
|
-
#### \u30B9\u30C6\u30C3\
|
|
1158
|
+
#### \u30B9\u30C6\u30C3\u30D72: \u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u9078\u629E
|
|
965
1159
|
1. \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` \u3092\u5B9F\u884C\u3057\u3066\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
|
|
966
1160
|
2. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
|
|
967
1161
|
- **\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: true\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3092\u9078\u629E\u3055\u305B\u308B
|
|
968
1162
|
- **\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
|
|
969
1163
|
|
|
970
|
-
#### \u30B9\u30C6\u30C3\
|
|
1164
|
+
#### \u30B9\u30C6\u30C3\u30D73: \u30C6\u30FC\u30D6\u30EB\u9078\u629E
|
|
971
1165
|
3. \u9078\u629E\u3055\u308C\u305F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u5BFE\u3057\u3066 \`SELECT table_name FROM \\\`{project}.{dataset}.INFORMATION_SCHEMA.TABLES\\\`\` \u3092\u5B9F\u884C\u3057\u3066\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B\uFF08\u8907\u6570\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306E\u5834\u5408\u306F UNION ALL \u3067\u4E00\u62EC\u53D6\u5F97\uFF09
|
|
972
1166
|
4. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
|
|
973
1167
|
- **\u30C6\u30FC\u30D6\u30EB\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: true\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u629E\u3055\u305B\u308B\u3002description \u306B\u306F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u540D\u3092\u8A18\u8F09\u3059\u308B
|
|
974
1168
|
- **\u30C6\u30FC\u30D6\u30EB\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528
|
|
975
1169
|
|
|
976
|
-
#### \u30B9\u30C6\u30C3\
|
|
1170
|
+
#### \u30B9\u30C6\u30C3\u30D74: \u4FDD\u5B58
|
|
977
1171
|
5. \`updateConnectionContext\` \u3067\u4EE5\u4E0B\u3092\u4FDD\u5B58\u3059\u308B:
|
|
978
|
-
- \`project\`: BigQuery\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
|
|
979
1172
|
- \`dataset\`: \u9078\u629E\u3055\u308C\u305F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u540D\uFF08\u8907\u6570\u306E\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09
|
|
980
1173
|
- \`tables\`: \u9078\u629E\u3055\u308C\u305F\u30C6\u30FC\u30D6\u30EB\u540D\uFF08\u8907\u6570\u306E\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09
|
|
981
1174
|
- \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
|
|
@@ -993,32 +1186,27 @@ Follow these steps to set up the BigQuery connection.
|
|
|
993
1186
|
|
|
994
1187
|
### Steps
|
|
995
1188
|
|
|
996
|
-
#### Step
|
|
997
|
-
1. Call \`
|
|
998
|
-
2.
|
|
999
|
-
- **2 or more projects**: Present them to the user via \`askUserQuestion\` (multiSelect: false) and let them select a project. Format option labels as \`Project Name (id: project-id)\`
|
|
1000
|
-
- **Exactly 1 project**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected project X" in one sentence
|
|
1001
|
-
3. Call \`updateConnectionParameters\` to save the selected project:
|
|
1189
|
+
#### Step 1: Project Selection
|
|
1190
|
+
1. Call \`${listProjectsToolName}\` to get the list of GCP projects accessible with the service account credentials
|
|
1191
|
+
2. Call \`updateConnectionParameters\` to save the project:
|
|
1002
1192
|
- \`parameterSlug\`: \`"project-id"\`
|
|
1003
|
-
- \`
|
|
1004
|
-
|
|
1005
|
-
4. After receiving the continuation message, proceed to Step 1
|
|
1193
|
+
- \`options\`: The project list. Each option's \`label\` should be \`Project Name (id: project-id)\`, \`value\` should be the project ID
|
|
1194
|
+
3. After receiving the continuation message, proceed to Step 2
|
|
1006
1195
|
|
|
1007
|
-
#### Step
|
|
1196
|
+
#### Step 2: Dataset Selection
|
|
1008
1197
|
1. Run \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` to get the list of datasets
|
|
1009
1198
|
2. Branch based on results:
|
|
1010
1199
|
- **2 or more datasets**: Present them to the user via \`askUserQuestion\` (multiSelect: true) and let them select which datasets to use
|
|
1011
1200
|
- **Exactly 1 dataset**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected dataset X" in one sentence
|
|
1012
1201
|
|
|
1013
|
-
#### Step
|
|
1202
|
+
#### Step 3: Table Selection
|
|
1014
1203
|
3. For the selected dataset(s), run \`SELECT table_name FROM \\\`{project}.{dataset}.INFORMATION_SCHEMA.TABLES\\\`\` to get the table list (use UNION ALL for multiple datasets)
|
|
1015
1204
|
4. Branch based on results:
|
|
1016
1205
|
- **2 or more tables**: Present them to the user via \`askUserQuestion\` (multiSelect: true) and let them select which tables to use. Include the dataset name in the description
|
|
1017
1206
|
- **Exactly 1 table**: Do NOT call askUserQuestion. Auto-select it
|
|
1018
1207
|
|
|
1019
|
-
#### Step
|
|
1208
|
+
#### Step 4: Save
|
|
1020
1209
|
5. Call \`updateConnectionContext\` to save:
|
|
1021
|
-
- \`project\`: BigQuery project ID
|
|
1022
1210
|
- \`dataset\`: Selected dataset name(s) (comma-separated if multiple)
|
|
1023
1211
|
- \`tables\`: Selected table name(s) (comma-separated if multiple)
|
|
1024
1212
|
- \`note\`: Brief description of the setup
|
|
@@ -1032,50 +1220,28 @@ Follow these steps to set up the BigQuery connection.
|
|
|
1032
1220
|
- Skip unnecessary explanations and proceed efficiently`
|
|
1033
1221
|
});
|
|
1034
1222
|
|
|
1035
|
-
// src/connectors/bigquery/parameters.ts
|
|
1036
|
-
var parameters5 = {
|
|
1037
|
-
serviceAccountKeyJsonBase64: new ParameterDefinition({
|
|
1038
|
-
slug: "service-account-key-json-base64",
|
|
1039
|
-
name: "Google Cloud Service Account JSON",
|
|
1040
|
-
description: "The service account JSON key used to authenticate with Google Cloud Platform. Ensure that the service account has the necessary permissions to access the required resources.",
|
|
1041
|
-
envVarBaseKey: "BIGQUERY_SERVICE_ACCOUNT_JSON_BASE64",
|
|
1042
|
-
type: "base64EncodedJson",
|
|
1043
|
-
secret: true,
|
|
1044
|
-
required: true
|
|
1045
|
-
}),
|
|
1046
|
-
projectId: new ParameterDefinition({
|
|
1047
|
-
slug: "project-id",
|
|
1048
|
-
name: "Google Cloud Project ID",
|
|
1049
|
-
description: "The ID of the Google Cloud project where resources will be managed.",
|
|
1050
|
-
envVarBaseKey: "BIGQUERY_PROJECT_ID",
|
|
1051
|
-
type: "text",
|
|
1052
|
-
secret: false,
|
|
1053
|
-
required: false
|
|
1054
|
-
})
|
|
1055
|
-
};
|
|
1056
|
-
|
|
1057
1223
|
// src/connectors/bigquery/tools/execute-query.ts
|
|
1058
|
-
import { z as
|
|
1224
|
+
import { z as z6 } from "zod";
|
|
1059
1225
|
var MAX_ROWS5 = 500;
|
|
1060
|
-
var
|
|
1061
|
-
toolUseIntent:
|
|
1226
|
+
var inputSchema6 = z6.object({
|
|
1227
|
+
toolUseIntent: z6.string().optional().describe(
|
|
1062
1228
|
"Brief description of what you intend to accomplish with this tool call"
|
|
1063
1229
|
),
|
|
1064
|
-
connectionId:
|
|
1065
|
-
sql:
|
|
1230
|
+
connectionId: z6.string().describe("ID of the BigQuery connection to use"),
|
|
1231
|
+
sql: z6.string().describe(
|
|
1066
1232
|
"BigQuery SQL (GoogleSQL) query. Use backtick-quoted fully qualified names `project.dataset.table` for table references."
|
|
1067
1233
|
)
|
|
1068
1234
|
});
|
|
1069
|
-
var
|
|
1070
|
-
|
|
1071
|
-
success:
|
|
1072
|
-
rowCount:
|
|
1073
|
-
truncated:
|
|
1074
|
-
rows:
|
|
1235
|
+
var outputSchema6 = z6.discriminatedUnion("success", [
|
|
1236
|
+
z6.object({
|
|
1237
|
+
success: z6.literal(true),
|
|
1238
|
+
rowCount: z6.number(),
|
|
1239
|
+
truncated: z6.boolean(),
|
|
1240
|
+
rows: z6.array(z6.record(z6.string(), z6.unknown()))
|
|
1075
1241
|
}),
|
|
1076
|
-
|
|
1077
|
-
success:
|
|
1078
|
-
error:
|
|
1242
|
+
z6.object({
|
|
1243
|
+
success: z6.literal(false),
|
|
1244
|
+
error: z6.string()
|
|
1079
1245
|
})
|
|
1080
1246
|
]);
|
|
1081
1247
|
var executeQueryTool5 = new ConnectorTool({
|
|
@@ -1083,8 +1249,8 @@ var executeQueryTool5 = new ConnectorTool({
|
|
|
1083
1249
|
description: `Execute SQL against BigQuery. Returns up to ${MAX_ROWS5} rows.
|
|
1084
1250
|
Use for: schema exploration (INFORMATION_SCHEMA), data sampling, analytical queries.
|
|
1085
1251
|
Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
1086
|
-
inputSchema:
|
|
1087
|
-
outputSchema:
|
|
1252
|
+
inputSchema: inputSchema6,
|
|
1253
|
+
outputSchema: outputSchema6,
|
|
1088
1254
|
async execute({ connectionId, sql }, connections) {
|
|
1089
1255
|
const connection = connections.find((c) => c.id === connectionId);
|
|
1090
1256
|
if (!connection) {
|
|
@@ -1121,68 +1287,6 @@ Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
|
1121
1287
|
}
|
|
1122
1288
|
});
|
|
1123
1289
|
|
|
1124
|
-
// src/connectors/bigquery/tools/list-projects.ts
|
|
1125
|
-
import { z as z6 } from "zod";
|
|
1126
|
-
var inputSchema6 = z6.object({
|
|
1127
|
-
toolUseIntent: z6.string().optional().describe(
|
|
1128
|
-
"Brief description of what you intend to accomplish with this tool call"
|
|
1129
|
-
),
|
|
1130
|
-
connectionId: z6.string().describe("ID of the BigQuery connection to use")
|
|
1131
|
-
});
|
|
1132
|
-
var outputSchema6 = z6.discriminatedUnion("success", [
|
|
1133
|
-
z6.object({
|
|
1134
|
-
success: z6.literal(true),
|
|
1135
|
-
projects: z6.array(
|
|
1136
|
-
z6.object({
|
|
1137
|
-
projectId: z6.string(),
|
|
1138
|
-
friendlyName: z6.string()
|
|
1139
|
-
})
|
|
1140
|
-
)
|
|
1141
|
-
}),
|
|
1142
|
-
z6.object({
|
|
1143
|
-
success: z6.literal(false),
|
|
1144
|
-
error: z6.string()
|
|
1145
|
-
})
|
|
1146
|
-
]);
|
|
1147
|
-
var listProjectsTool = new ConnectorTool({
|
|
1148
|
-
name: "listProjects",
|
|
1149
|
-
description: `List GCP projects accessible with the service account credentials. Returns project IDs and friendly names.`,
|
|
1150
|
-
inputSchema: inputSchema6,
|
|
1151
|
-
outputSchema: outputSchema6,
|
|
1152
|
-
async execute({ connectionId }, connections) {
|
|
1153
|
-
const connection = connections.find((c) => c.id === connectionId);
|
|
1154
|
-
if (!connection) {
|
|
1155
|
-
return {
|
|
1156
|
-
success: false,
|
|
1157
|
-
error: `Connection ${connectionId} not found`
|
|
1158
|
-
};
|
|
1159
|
-
}
|
|
1160
|
-
try {
|
|
1161
|
-
const serviceAccountJsonBase64 = parameters5.serviceAccountKeyJsonBase64.getValue(connection);
|
|
1162
|
-
const credentials = JSON.parse(
|
|
1163
|
-
Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8")
|
|
1164
|
-
);
|
|
1165
|
-
const { GoogleAuth } = await import("google-auth-library");
|
|
1166
|
-
const auth = new GoogleAuth({
|
|
1167
|
-
credentials,
|
|
1168
|
-
scopes: ["https://www.googleapis.com/auth/bigquery"]
|
|
1169
|
-
});
|
|
1170
|
-
const client = await auth.getClient();
|
|
1171
|
-
const res = await client.request({
|
|
1172
|
-
url: "https://bigquery.googleapis.com/bigquery/v2/projects"
|
|
1173
|
-
});
|
|
1174
|
-
const projects = (res.data.projects ?? []).map((p) => ({
|
|
1175
|
-
projectId: p.projectReference?.projectId ?? "",
|
|
1176
|
-
friendlyName: p.friendlyName ?? p.projectReference?.projectId ?? ""
|
|
1177
|
-
})).filter((p) => p.projectId !== "");
|
|
1178
|
-
return { success: true, projects };
|
|
1179
|
-
} catch (err) {
|
|
1180
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1181
|
-
return { success: false, error: msg };
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
});
|
|
1185
|
-
|
|
1186
1290
|
// src/connectors/bigquery/index.ts
|
|
1187
1291
|
var tools5 = { executeQuery: executeQueryTool5, listProjects: listProjectsTool };
|
|
1188
1292
|
var bigqueryConnector = new ConnectorPlugin({
|
|
@@ -1202,6 +1306,23 @@ var bigqueryConnector = new ConnectorPlugin({
|
|
|
1202
1306
|
- List columns: \`SELECT column_name, data_type FROM \\\`project_id.dataset\\\`.INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'xxx'\`
|
|
1203
1307
|
- Always specify project_id explicitly in queries`,
|
|
1204
1308
|
tools: tools5,
|
|
1309
|
+
async checkConnection(params, _config) {
|
|
1310
|
+
const { BigQuery } = await import("@google-cloud/bigquery");
|
|
1311
|
+
const credentials = JSON.parse(
|
|
1312
|
+
Buffer.from(params[parameters5.serviceAccountKeyJsonBase64.slug], "base64").toString("utf-8")
|
|
1313
|
+
);
|
|
1314
|
+
const bq = new BigQuery({
|
|
1315
|
+
projectId: params[parameters5.projectId.slug],
|
|
1316
|
+
credentials
|
|
1317
|
+
});
|
|
1318
|
+
try {
|
|
1319
|
+
const [job] = await bq.createQueryJob({ query: "SELECT 1" });
|
|
1320
|
+
await job.getQueryResults();
|
|
1321
|
+
return { success: true };
|
|
1322
|
+
} catch (error) {
|
|
1323
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
1324
|
+
}
|
|
1325
|
+
},
|
|
1205
1326
|
async query(params, sql, namedParams) {
|
|
1206
1327
|
const { BigQuery } = await import("@google-cloud/bigquery");
|
|
1207
1328
|
const resolvedSql = replaceLiteralParams(sql, namedParams);
|
|
@@ -1218,7 +1339,115 @@ var bigqueryConnector = new ConnectorPlugin({
|
|
|
1218
1339
|
}
|
|
1219
1340
|
});
|
|
1220
1341
|
|
|
1342
|
+
// src/connectors/bigquery-oauth/tools/list-projects.ts
|
|
1343
|
+
import { z as z7 } from "zod";
|
|
1344
|
+
var REQUEST_TIMEOUT_MS = 6e4;
|
|
1345
|
+
var cachedToken = null;
|
|
1346
|
+
async function getProxyToken(config) {
|
|
1347
|
+
if (cachedToken && cachedToken.expiresAt > Date.now() + 6e4) {
|
|
1348
|
+
return cachedToken.token;
|
|
1349
|
+
}
|
|
1350
|
+
const url = `${config.appApiBaseUrl}/v0/database/${config.projectId}/environment/${config.environmentId}/oauth-request-proxy-token`;
|
|
1351
|
+
const res = await fetch(url, {
|
|
1352
|
+
method: "POST",
|
|
1353
|
+
headers: {
|
|
1354
|
+
"Content-Type": "application/json",
|
|
1355
|
+
"x-api-key": config.appApiKey,
|
|
1356
|
+
"project-id": config.projectId
|
|
1357
|
+
},
|
|
1358
|
+
body: JSON.stringify({
|
|
1359
|
+
sandboxId: config.sandboxId,
|
|
1360
|
+
issuedBy: "coding-agent"
|
|
1361
|
+
})
|
|
1362
|
+
});
|
|
1363
|
+
if (!res.ok) {
|
|
1364
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
1365
|
+
throw new Error(`Failed to get proxy token: HTTP ${res.status} ${errorText}`);
|
|
1366
|
+
}
|
|
1367
|
+
const data = await res.json();
|
|
1368
|
+
cachedToken = {
|
|
1369
|
+
token: data.token,
|
|
1370
|
+
expiresAt: new Date(data.expiresAt).getTime()
|
|
1371
|
+
};
|
|
1372
|
+
return data.token;
|
|
1373
|
+
}
|
|
1374
|
+
var inputSchema7 = z7.object({
|
|
1375
|
+
toolUseIntent: z7.string().optional().describe(
|
|
1376
|
+
"Brief description of what you intend to accomplish with this tool call"
|
|
1377
|
+
),
|
|
1378
|
+
connectionId: z7.string().describe("ID of the BigQuery OAuth connection to use")
|
|
1379
|
+
});
|
|
1380
|
+
var outputSchema7 = z7.discriminatedUnion("success", [
|
|
1381
|
+
z7.object({
|
|
1382
|
+
success: z7.literal(true),
|
|
1383
|
+
projects: z7.array(
|
|
1384
|
+
z7.object({
|
|
1385
|
+
projectId: z7.string(),
|
|
1386
|
+
friendlyName: z7.string()
|
|
1387
|
+
})
|
|
1388
|
+
)
|
|
1389
|
+
}),
|
|
1390
|
+
z7.object({
|
|
1391
|
+
success: z7.literal(false),
|
|
1392
|
+
error: z7.string()
|
|
1393
|
+
})
|
|
1394
|
+
]);
|
|
1395
|
+
var listProjectsTool2 = new ConnectorTool({
|
|
1396
|
+
name: "listProjects",
|
|
1397
|
+
description: `List GCP projects accessible with the current OAuth credentials. Returns project IDs and friendly names.`,
|
|
1398
|
+
inputSchema: inputSchema7,
|
|
1399
|
+
outputSchema: outputSchema7,
|
|
1400
|
+
async execute({ connectionId }, connections, config) {
|
|
1401
|
+
const connection = connections.find((c) => c.id === connectionId);
|
|
1402
|
+
if (!connection) {
|
|
1403
|
+
return {
|
|
1404
|
+
success: false,
|
|
1405
|
+
error: `Connection ${connectionId} not found`
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
console.log(
|
|
1409
|
+
`[connector-query] bigquery-oauth/${connection.name}: listProjects`
|
|
1410
|
+
);
|
|
1411
|
+
try {
|
|
1412
|
+
const token = await getProxyToken(config.oauthProxy);
|
|
1413
|
+
const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1414
|
+
const controller = new AbortController();
|
|
1415
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
1416
|
+
try {
|
|
1417
|
+
const response = await fetch(proxyUrl, {
|
|
1418
|
+
method: "POST",
|
|
1419
|
+
headers: {
|
|
1420
|
+
"Content-Type": "application/json",
|
|
1421
|
+
Authorization: `Bearer ${token}`
|
|
1422
|
+
},
|
|
1423
|
+
body: JSON.stringify({
|
|
1424
|
+
url: "https://bigquery.googleapis.com/bigquery/v2/projects",
|
|
1425
|
+
method: "GET"
|
|
1426
|
+
}),
|
|
1427
|
+
signal: controller.signal
|
|
1428
|
+
});
|
|
1429
|
+
const data = await response.json();
|
|
1430
|
+
if (!response.ok) {
|
|
1431
|
+
const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
|
|
1432
|
+
return { success: false, error: errorMessage };
|
|
1433
|
+
}
|
|
1434
|
+
const projects = (data.projects ?? []).map((p) => ({
|
|
1435
|
+
projectId: p.projectReference?.projectId ?? "",
|
|
1436
|
+
friendlyName: p.friendlyName ?? p.projectReference?.projectId ?? ""
|
|
1437
|
+
})).filter((p) => p.projectId !== "");
|
|
1438
|
+
return { success: true, projects };
|
|
1439
|
+
} finally {
|
|
1440
|
+
clearTimeout(timeout);
|
|
1441
|
+
}
|
|
1442
|
+
} catch (err) {
|
|
1443
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1444
|
+
return { success: false, error: msg };
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
|
|
1221
1449
|
// src/connectors/bigquery-oauth/setup.ts
|
|
1450
|
+
var listProjectsToolName2 = `bigquery-oauth_${listProjectsTool2.name}`;
|
|
1222
1451
|
var bigquerySetup2 = new ConnectorSetup({
|
|
1223
1452
|
ja: `## BigQuery \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u624B\u9806
|
|
1224
1453
|
|
|
@@ -1226,32 +1455,27 @@ var bigquerySetup2 = new ConnectorSetup({
|
|
|
1226
1455
|
|
|
1227
1456
|
### \u624B\u9806
|
|
1228
1457
|
|
|
1229
|
-
#### \u30B9\u30C6\u30C3\
|
|
1230
|
-
1. \`
|
|
1231
|
-
2. \
|
|
1232
|
-
- **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: false\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u9078\u629E\u3055\u305B\u308B\u3002\u9078\u629E\u80A2\u306E label \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u306B\u3059\u308B
|
|
1233
|
-
- **\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
|
|
1234
|
-
3. \`updateConnectionParameters\` \u3067\u9078\u629E\u3055\u308C\u305F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
|
|
1458
|
+
#### \u30B9\u30C6\u30C3\u30D71: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u9078\u629E
|
|
1459
|
+
1. \`${listProjectsToolName2}\` \u3092\u547C\u3073\u51FA\u3057\u3066\u3001OAuth\u3067\u30A2\u30AF\u30BB\u30B9\u53EF\u80FD\u306AGCP\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
|
|
1460
|
+
2. \`updateConnectionParameters\` \u3092\u547C\u3073\u51FA\u3057\u3066\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3092\u4FDD\u5B58\u3059\u308B:
|
|
1235
1461
|
- \`parameterSlug\`: \`"project-id"\`
|
|
1236
|
-
- \`
|
|
1237
|
-
|
|
1238
|
-
4. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D71\u306B\u9032\u3080
|
|
1462
|
+
- \`options\`: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u4E00\u89A7\u3002\u5404 option \u306E \`label\` \u306F \`\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u540D (id: \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID)\` \u306E\u5F62\u5F0F\u3001\`value\` \u306F\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
|
|
1463
|
+
3. \u7D9A\u884C\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D7\u3051\u53D6\u3063\u305F\u3089\u3001\u30B9\u30C6\u30C3\u30D72\u306B\u9032\u3080
|
|
1239
1464
|
|
|
1240
|
-
#### \u30B9\u30C6\u30C3\
|
|
1465
|
+
#### \u30B9\u30C6\u30C3\u30D72: \u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u9078\u629E
|
|
1241
1466
|
1. \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` \u3092\u5B9F\u884C\u3057\u3066\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B
|
|
1242
1467
|
2. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
|
|
1243
1468
|
- **\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: true\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u3092\u9078\u629E\u3055\u305B\u308B
|
|
1244
1469
|
- **\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528\u3002\u300C\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8 X \u3092\u81EA\u52D5\u9078\u629E\u3057\u307E\u3057\u305F\u300D\u30681\u6587\u3060\u3051\u66F8\u304F
|
|
1245
1470
|
|
|
1246
|
-
#### \u30B9\u30C6\u30C3\
|
|
1471
|
+
#### \u30B9\u30C6\u30C3\u30D73: \u30C6\u30FC\u30D6\u30EB\u9078\u629E
|
|
1247
1472
|
3. \u9078\u629E\u3055\u308C\u305F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306B\u5BFE\u3057\u3066 \`SELECT table_name FROM \\\`{project}.{dataset}.INFORMATION_SCHEMA.TABLES\\\`\` \u3092\u5B9F\u884C\u3057\u3066\u30C6\u30FC\u30D6\u30EB\u4E00\u89A7\u3092\u53D6\u5F97\u3059\u308B\uFF08\u8907\u6570\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u306E\u5834\u5408\u306F UNION ALL \u3067\u4E00\u62EC\u53D6\u5F97\uFF09
|
|
1248
1473
|
4. \u7D50\u679C\u306B\u5FDC\u3058\u3066\u5206\u5C90:
|
|
1249
1474
|
- **\u30C6\u30FC\u30D6\u30EB\u304C2\u3064\u4EE5\u4E0A**: \`askUserQuestion\`\uFF08multiSelect: true\uFF09\u3067\u30E6\u30FC\u30B6\u30FC\u306B\u63D0\u793A\u3057\u3001\u4F7F\u7528\u3059\u308B\u30C6\u30FC\u30D6\u30EB\u3092\u9078\u629E\u3055\u305B\u308B\u3002description \u306B\u306F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u540D\u3092\u8A18\u8F09\u3059\u308B
|
|
1250
1475
|
- **\u30C6\u30FC\u30D6\u30EB\u304C1\u3064\u3060\u3051**: askUserQuestion \u306F\u4F7F\u308F\u305A\u81EA\u52D5\u63A1\u7528
|
|
1251
1476
|
|
|
1252
|
-
#### \u30B9\u30C6\u30C3\
|
|
1477
|
+
#### \u30B9\u30C6\u30C3\u30D74: \u4FDD\u5B58
|
|
1253
1478
|
5. \`updateConnectionContext\` \u3067\u4EE5\u4E0B\u3092\u4FDD\u5B58\u3059\u308B:
|
|
1254
|
-
- \`project\`: BigQuery\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID
|
|
1255
1479
|
- \`dataset\`: \u9078\u629E\u3055\u308C\u305F\u30C7\u30FC\u30BF\u30BB\u30C3\u30C8\u540D\uFF08\u8907\u6570\u306E\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09
|
|
1256
1480
|
- \`tables\`: \u9078\u629E\u3055\u308C\u305F\u30C6\u30FC\u30D6\u30EB\u540D\uFF08\u8907\u6570\u306E\u5834\u5408\u306F\u30AB\u30F3\u30DE\u533A\u5207\u308A\uFF09
|
|
1257
1481
|
- \`note\`: \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7\u5185\u5BB9\u306E\u7C21\u5358\u306A\u8AAC\u660E
|
|
@@ -1269,32 +1493,27 @@ Follow these steps to set up the BigQuery connection.
|
|
|
1269
1493
|
|
|
1270
1494
|
### Steps
|
|
1271
1495
|
|
|
1272
|
-
#### Step
|
|
1273
|
-
1. Call \`
|
|
1274
|
-
2.
|
|
1275
|
-
- **2 or more projects**: Present them to the user via \`askUserQuestion\` (multiSelect: false) and let them select a project. Format option labels as \`Project Name (id: project-id)\`
|
|
1276
|
-
- **Exactly 1 project**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected project X" in one sentence
|
|
1277
|
-
3. Call \`updateConnectionParameters\` to save the selected project:
|
|
1496
|
+
#### Step 1: Project Selection
|
|
1497
|
+
1. Call \`${listProjectsToolName2}\` to get the list of GCP projects accessible with the OAuth credentials
|
|
1498
|
+
2. Call \`updateConnectionParameters\` to save the project:
|
|
1278
1499
|
- \`parameterSlug\`: \`"project-id"\`
|
|
1279
|
-
- \`
|
|
1280
|
-
|
|
1281
|
-
4. After receiving the continuation message, proceed to Step 1
|
|
1500
|
+
- \`options\`: The project list. Each option's \`label\` should be \`Project Name (id: project-id)\`, \`value\` should be the project ID
|
|
1501
|
+
3. After receiving the continuation message, proceed to Step 2
|
|
1282
1502
|
|
|
1283
|
-
#### Step
|
|
1503
|
+
#### Step 2: Dataset Selection
|
|
1284
1504
|
1. Run \`SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA\` to get the list of datasets
|
|
1285
1505
|
2. Branch based on results:
|
|
1286
1506
|
- **2 or more datasets**: Present them to the user via \`askUserQuestion\` (multiSelect: true) and let them select which datasets to use
|
|
1287
1507
|
- **Exactly 1 dataset**: Do NOT call askUserQuestion. Auto-select it. Just write "Auto-selected dataset X" in one sentence
|
|
1288
1508
|
|
|
1289
|
-
#### Step
|
|
1509
|
+
#### Step 3: Table Selection
|
|
1290
1510
|
3. For the selected dataset(s), run \`SELECT table_name FROM \\\`{project}.{dataset}.INFORMATION_SCHEMA.TABLES\\\`\` to get the table list (use UNION ALL for multiple datasets)
|
|
1291
1511
|
4. Branch based on results:
|
|
1292
1512
|
- **2 or more tables**: Present them to the user via \`askUserQuestion\` (multiSelect: true) and let them select which tables to use. Include the dataset name in the description
|
|
1293
1513
|
- **Exactly 1 table**: Do NOT call askUserQuestion. Auto-select it
|
|
1294
1514
|
|
|
1295
|
-
#### Step
|
|
1515
|
+
#### Step 4: Save
|
|
1296
1516
|
5. Call \`updateConnectionContext\` to save:
|
|
1297
|
-
- \`project\`: BigQuery project ID
|
|
1298
1517
|
- \`dataset\`: Selected dataset name(s) (comma-separated if multiple)
|
|
1299
1518
|
- \`tables\`: Selected table name(s) (comma-separated if multiple)
|
|
1300
1519
|
- \`note\`: Brief description of the setup
|
|
@@ -1321,14 +1540,14 @@ var parameters6 = {
|
|
|
1321
1540
|
})
|
|
1322
1541
|
};
|
|
1323
1542
|
|
|
1324
|
-
// src/connectors/bigquery-oauth/tools/execute-query.ts
|
|
1325
|
-
import { z as
|
|
1326
|
-
var MAX_ROWS6 = 500;
|
|
1327
|
-
var
|
|
1328
|
-
var
|
|
1329
|
-
async function
|
|
1330
|
-
if (
|
|
1331
|
-
return
|
|
1543
|
+
// src/connectors/bigquery-oauth/tools/execute-query.ts
|
|
1544
|
+
import { z as z8 } from "zod";
|
|
1545
|
+
var MAX_ROWS6 = 500;
|
|
1546
|
+
var REQUEST_TIMEOUT_MS2 = 6e4;
|
|
1547
|
+
var cachedToken2 = null;
|
|
1548
|
+
async function getProxyToken2(config) {
|
|
1549
|
+
if (cachedToken2 && cachedToken2.expiresAt > Date.now() + 6e4) {
|
|
1550
|
+
return cachedToken2.token;
|
|
1332
1551
|
}
|
|
1333
1552
|
const url = `${config.appApiBaseUrl}/v0/database/${config.projectId}/environment/${config.environmentId}/oauth-request-proxy-token`;
|
|
1334
1553
|
const res = await fetch(url, {
|
|
@@ -1348,31 +1567,31 @@ async function getProxyToken(config) {
|
|
|
1348
1567
|
throw new Error(`Failed to get proxy token: HTTP ${res.status} ${errorText}`);
|
|
1349
1568
|
}
|
|
1350
1569
|
const data = await res.json();
|
|
1351
|
-
|
|
1570
|
+
cachedToken2 = {
|
|
1352
1571
|
token: data.token,
|
|
1353
1572
|
expiresAt: new Date(data.expiresAt).getTime()
|
|
1354
1573
|
};
|
|
1355
1574
|
return data.token;
|
|
1356
1575
|
}
|
|
1357
|
-
var
|
|
1358
|
-
toolUseIntent:
|
|
1576
|
+
var inputSchema8 = z8.object({
|
|
1577
|
+
toolUseIntent: z8.string().optional().describe(
|
|
1359
1578
|
"Brief description of what you intend to accomplish with this tool call"
|
|
1360
1579
|
),
|
|
1361
|
-
connectionId:
|
|
1362
|
-
sql:
|
|
1580
|
+
connectionId: z8.string().describe("ID of the BigQuery OAuth connection to use"),
|
|
1581
|
+
sql: z8.string().describe(
|
|
1363
1582
|
"BigQuery SQL (GoogleSQL) query. Use backtick-quoted fully qualified names `project.dataset.table` for table references."
|
|
1364
1583
|
)
|
|
1365
1584
|
});
|
|
1366
|
-
var
|
|
1367
|
-
|
|
1368
|
-
success:
|
|
1369
|
-
rowCount:
|
|
1370
|
-
truncated:
|
|
1371
|
-
rows:
|
|
1585
|
+
var outputSchema8 = z8.discriminatedUnion("success", [
|
|
1586
|
+
z8.object({
|
|
1587
|
+
success: z8.literal(true),
|
|
1588
|
+
rowCount: z8.number(),
|
|
1589
|
+
truncated: z8.boolean(),
|
|
1590
|
+
rows: z8.array(z8.record(z8.string(), z8.unknown()))
|
|
1372
1591
|
}),
|
|
1373
|
-
|
|
1374
|
-
success:
|
|
1375
|
-
error:
|
|
1592
|
+
z8.object({
|
|
1593
|
+
success: z8.literal(false),
|
|
1594
|
+
error: z8.string()
|
|
1376
1595
|
})
|
|
1377
1596
|
]);
|
|
1378
1597
|
function parseQueryResponse(data) {
|
|
@@ -1393,8 +1612,8 @@ var executeQueryTool6 = new ConnectorTool({
|
|
|
1393
1612
|
description: `Execute SQL against BigQuery via OAuth. Returns up to ${MAX_ROWS6} rows.
|
|
1394
1613
|
Use for: schema exploration (INFORMATION_SCHEMA), data sampling, analytical queries.
|
|
1395
1614
|
Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
1396
|
-
inputSchema:
|
|
1397
|
-
outputSchema:
|
|
1615
|
+
inputSchema: inputSchema8,
|
|
1616
|
+
outputSchema: outputSchema8,
|
|
1398
1617
|
async execute({ connectionId, sql }, connections, config) {
|
|
1399
1618
|
const connection = connections.find((c) => c.id === connectionId);
|
|
1400
1619
|
if (!connection) {
|
|
@@ -1408,11 +1627,11 @@ Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
|
1408
1627
|
`[connector-query] bigquery-oauth/${connection.name}: ${sql}`
|
|
1409
1628
|
);
|
|
1410
1629
|
try {
|
|
1411
|
-
const token = await
|
|
1630
|
+
const token = await getProxyToken2(config.oauthProxy);
|
|
1412
1631
|
const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1413
1632
|
const queryUrl = `https://bigquery.googleapis.com/bigquery/v2/projects/${gcpProjectId}/queries`;
|
|
1414
1633
|
const controller = new AbortController();
|
|
1415
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
1634
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
|
|
1416
1635
|
try {
|
|
1417
1636
|
const response = await fetch(proxyUrl, {
|
|
1418
1637
|
method: "POST",
|
|
@@ -1450,113 +1669,6 @@ Avoid loading large amounts of data; always include LIMIT in queries.`,
|
|
|
1450
1669
|
}
|
|
1451
1670
|
});
|
|
1452
1671
|
|
|
1453
|
-
// src/connectors/bigquery-oauth/tools/list-projects.ts
|
|
1454
|
-
import { z as z8 } from "zod";
|
|
1455
|
-
var REQUEST_TIMEOUT_MS2 = 6e4;
|
|
1456
|
-
var cachedToken2 = null;
|
|
1457
|
-
async function getProxyToken2(config) {
|
|
1458
|
-
if (cachedToken2 && cachedToken2.expiresAt > Date.now() + 6e4) {
|
|
1459
|
-
return cachedToken2.token;
|
|
1460
|
-
}
|
|
1461
|
-
const url = `${config.appApiBaseUrl}/v0/database/${config.projectId}/environment/${config.environmentId}/oauth-request-proxy-token`;
|
|
1462
|
-
const res = await fetch(url, {
|
|
1463
|
-
method: "POST",
|
|
1464
|
-
headers: {
|
|
1465
|
-
"Content-Type": "application/json",
|
|
1466
|
-
"x-api-key": config.appApiKey,
|
|
1467
|
-
"project-id": config.projectId
|
|
1468
|
-
},
|
|
1469
|
-
body: JSON.stringify({
|
|
1470
|
-
sandboxId: config.sandboxId,
|
|
1471
|
-
issuedBy: "coding-agent"
|
|
1472
|
-
})
|
|
1473
|
-
});
|
|
1474
|
-
if (!res.ok) {
|
|
1475
|
-
const errorText = await res.text().catch(() => res.statusText);
|
|
1476
|
-
throw new Error(`Failed to get proxy token: HTTP ${res.status} ${errorText}`);
|
|
1477
|
-
}
|
|
1478
|
-
const data = await res.json();
|
|
1479
|
-
cachedToken2 = {
|
|
1480
|
-
token: data.token,
|
|
1481
|
-
expiresAt: new Date(data.expiresAt).getTime()
|
|
1482
|
-
};
|
|
1483
|
-
return data.token;
|
|
1484
|
-
}
|
|
1485
|
-
var inputSchema8 = z8.object({
|
|
1486
|
-
toolUseIntent: z8.string().optional().describe(
|
|
1487
|
-
"Brief description of what you intend to accomplish with this tool call"
|
|
1488
|
-
),
|
|
1489
|
-
connectionId: z8.string().describe("ID of the BigQuery OAuth connection to use")
|
|
1490
|
-
});
|
|
1491
|
-
var outputSchema8 = z8.discriminatedUnion("success", [
|
|
1492
|
-
z8.object({
|
|
1493
|
-
success: z8.literal(true),
|
|
1494
|
-
projects: z8.array(
|
|
1495
|
-
z8.object({
|
|
1496
|
-
projectId: z8.string(),
|
|
1497
|
-
friendlyName: z8.string()
|
|
1498
|
-
})
|
|
1499
|
-
)
|
|
1500
|
-
}),
|
|
1501
|
-
z8.object({
|
|
1502
|
-
success: z8.literal(false),
|
|
1503
|
-
error: z8.string()
|
|
1504
|
-
})
|
|
1505
|
-
]);
|
|
1506
|
-
var listProjectsTool2 = new ConnectorTool({
|
|
1507
|
-
name: "listProjects",
|
|
1508
|
-
description: `List GCP projects accessible with the current OAuth credentials. Returns project IDs and friendly names.`,
|
|
1509
|
-
inputSchema: inputSchema8,
|
|
1510
|
-
outputSchema: outputSchema8,
|
|
1511
|
-
async execute({ connectionId }, connections, config) {
|
|
1512
|
-
const connection = connections.find((c) => c.id === connectionId);
|
|
1513
|
-
if (!connection) {
|
|
1514
|
-
return {
|
|
1515
|
-
success: false,
|
|
1516
|
-
error: `Connection ${connectionId} not found`
|
|
1517
|
-
};
|
|
1518
|
-
}
|
|
1519
|
-
console.log(
|
|
1520
|
-
`[connector-query] bigquery-oauth/${connection.name}: listProjects`
|
|
1521
|
-
);
|
|
1522
|
-
try {
|
|
1523
|
-
const token = await getProxyToken2(config.oauthProxy);
|
|
1524
|
-
const proxyUrl = `https://${config.oauthProxy.sandboxId}.${config.oauthProxy.previewBaseDomain}/_sqcore/connections/${connectionId}/request`;
|
|
1525
|
-
const controller = new AbortController();
|
|
1526
|
-
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS2);
|
|
1527
|
-
try {
|
|
1528
|
-
const response = await fetch(proxyUrl, {
|
|
1529
|
-
method: "POST",
|
|
1530
|
-
headers: {
|
|
1531
|
-
"Content-Type": "application/json",
|
|
1532
|
-
Authorization: `Bearer ${token}`
|
|
1533
|
-
},
|
|
1534
|
-
body: JSON.stringify({
|
|
1535
|
-
url: "https://bigquery.googleapis.com/bigquery/v2/projects",
|
|
1536
|
-
method: "GET"
|
|
1537
|
-
}),
|
|
1538
|
-
signal: controller.signal
|
|
1539
|
-
});
|
|
1540
|
-
const data = await response.json();
|
|
1541
|
-
if (!response.ok) {
|
|
1542
|
-
const errorMessage = typeof data?.error === "string" ? data.error : typeof data?.message === "string" ? data.message : `HTTP ${response.status} ${response.statusText}`;
|
|
1543
|
-
return { success: false, error: errorMessage };
|
|
1544
|
-
}
|
|
1545
|
-
const projects = (data.projects ?? []).map((p) => ({
|
|
1546
|
-
projectId: p.projectReference?.projectId ?? "",
|
|
1547
|
-
friendlyName: p.friendlyName ?? p.projectReference?.projectId ?? ""
|
|
1548
|
-
})).filter((p) => p.projectId !== "");
|
|
1549
|
-
return { success: true, projects };
|
|
1550
|
-
} finally {
|
|
1551
|
-
clearTimeout(timeout);
|
|
1552
|
-
}
|
|
1553
|
-
} catch (err) {
|
|
1554
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1555
|
-
return { success: false, error: msg };
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
|
-
});
|
|
1559
|
-
|
|
1560
1672
|
// src/connectors/bigquery-oauth/index.ts
|
|
1561
1673
|
var tools6 = { executeQuery: executeQueryTool6, listProjects: listProjectsTool2 };
|
|
1562
1674
|
function parseQueryResponse2(data) {
|
|
@@ -1594,6 +1706,25 @@ var bigqueryOauthConnector = new ConnectorPlugin({
|
|
|
1594
1706
|
- List columns: \`SELECT column_name, data_type FROM \\\`project_id.dataset\\\`.INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'xxx'\`
|
|
1595
1707
|
- Always specify project_id explicitly in queries`,
|
|
1596
1708
|
tools: tools6,
|
|
1709
|
+
async checkConnection(params, config) {
|
|
1710
|
+
const { proxyFetch } = config;
|
|
1711
|
+
const projectId = params[parameters6.projectId.slug];
|
|
1712
|
+
const url = `https://bigquery.googleapis.com/bigquery/v2/projects/${projectId}/queries`;
|
|
1713
|
+
try {
|
|
1714
|
+
const res = await proxyFetch(url, {
|
|
1715
|
+
method: "POST",
|
|
1716
|
+
headers: { "Content-Type": "application/json" },
|
|
1717
|
+
body: JSON.stringify({ query: "SELECT 1", useLegacySql: false })
|
|
1718
|
+
});
|
|
1719
|
+
if (!res.ok) {
|
|
1720
|
+
const errorText = await res.text().catch(() => res.statusText);
|
|
1721
|
+
return { success: false, error: `BigQuery query failed: HTTP ${res.status} ${errorText}` };
|
|
1722
|
+
}
|
|
1723
|
+
return { success: true };
|
|
1724
|
+
} catch (error) {
|
|
1725
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
1726
|
+
}
|
|
1727
|
+
},
|
|
1597
1728
|
async query(params, sql, namedParams, context) {
|
|
1598
1729
|
const { proxyFetch } = context;
|
|
1599
1730
|
const projectId = params[parameters6.projectId.slug];
|
|
@@ -1798,6 +1929,62 @@ var awsAthenaConnector = new ConnectorPlugin({
|
|
|
1798
1929
|
- Always include LIMIT in queries
|
|
1799
1930
|
- Query execution is asynchronous and results may take time to retrieve`,
|
|
1800
1931
|
tools: tools7,
|
|
1932
|
+
async checkConnection(params, _config) {
|
|
1933
|
+
try {
|
|
1934
|
+
const {
|
|
1935
|
+
AthenaClient,
|
|
1936
|
+
StartQueryExecutionCommand,
|
|
1937
|
+
GetQueryExecutionCommand
|
|
1938
|
+
} = await import("@aws-sdk/client-athena");
|
|
1939
|
+
const workgroup = params[parameters7.workgroup.slug];
|
|
1940
|
+
const outputLocation = params[parameters7.outputLocation.slug];
|
|
1941
|
+
if (!workgroup && !outputLocation) {
|
|
1942
|
+
return {
|
|
1943
|
+
success: false,
|
|
1944
|
+
error: "Either workgroup or output-location is required"
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
const client = new AthenaClient({
|
|
1948
|
+
region: params[parameters7.awsRegion.slug],
|
|
1949
|
+
credentials: {
|
|
1950
|
+
accessKeyId: params[parameters7.awsAccessKeyId.slug],
|
|
1951
|
+
secretAccessKey: params[parameters7.awsSecretAccessKey.slug]
|
|
1952
|
+
}
|
|
1953
|
+
});
|
|
1954
|
+
const startParams = { QueryString: "SELECT 1" };
|
|
1955
|
+
if (workgroup) startParams.WorkGroup = workgroup;
|
|
1956
|
+
if (outputLocation) {
|
|
1957
|
+
startParams.ResultConfiguration = { OutputLocation: outputLocation };
|
|
1958
|
+
}
|
|
1959
|
+
const { QueryExecutionId } = await client.send(
|
|
1960
|
+
new StartQueryExecutionCommand(startParams)
|
|
1961
|
+
);
|
|
1962
|
+
const startTime = Date.now();
|
|
1963
|
+
while (true) {
|
|
1964
|
+
const exec = await client.send(
|
|
1965
|
+
new GetQueryExecutionCommand({ QueryExecutionId })
|
|
1966
|
+
);
|
|
1967
|
+
const state = exec.QueryExecution?.Status?.State;
|
|
1968
|
+
if (state === "SUCCEEDED") break;
|
|
1969
|
+
if (state === "FAILED" || state === "CANCELLED") {
|
|
1970
|
+
return {
|
|
1971
|
+
success: false,
|
|
1972
|
+
error: exec.QueryExecution?.Status?.StateChangeReason || `Query ${state}`
|
|
1973
|
+
};
|
|
1974
|
+
}
|
|
1975
|
+
if (Date.now() - startTime > 12e4) {
|
|
1976
|
+
return { success: false, error: "Query timed out after 120 seconds" };
|
|
1977
|
+
}
|
|
1978
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
1979
|
+
}
|
|
1980
|
+
return { success: true };
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
return {
|
|
1983
|
+
success: false,
|
|
1984
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
},
|
|
1801
1988
|
async query(params, sql, namedParams) {
|
|
1802
1989
|
const {
|
|
1803
1990
|
AthenaClient,
|
|
@@ -2075,6 +2262,65 @@ var redshiftConnector = new ConnectorPlugin({
|
|
|
2075
2262
|
- Always include LIMIT in queries
|
|
2076
2263
|
- Query execution is asynchronous and results may take time to retrieve`,
|
|
2077
2264
|
tools: tools8,
|
|
2265
|
+
async checkConnection(params, _config) {
|
|
2266
|
+
try {
|
|
2267
|
+
const {
|
|
2268
|
+
RedshiftDataClient,
|
|
2269
|
+
ExecuteStatementCommand,
|
|
2270
|
+
DescribeStatementCommand
|
|
2271
|
+
} = await import("@aws-sdk/client-redshift-data");
|
|
2272
|
+
const clusterIdentifier = params[parameters8.clusterIdentifier.slug];
|
|
2273
|
+
const workgroupName = params[parameters8.workgroupName.slug];
|
|
2274
|
+
const secretArn = params[parameters8.secretArn.slug];
|
|
2275
|
+
const dbUser = params[parameters8.dbUser.slug];
|
|
2276
|
+
if (!clusterIdentifier && !workgroupName) {
|
|
2277
|
+
return {
|
|
2278
|
+
success: false,
|
|
2279
|
+
error: "Either cluster-identifier or workgroup-name is required"
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
const client = new RedshiftDataClient({
|
|
2283
|
+
region: params[parameters8.awsRegion.slug],
|
|
2284
|
+
credentials: {
|
|
2285
|
+
accessKeyId: params[parameters8.awsAccessKeyId.slug],
|
|
2286
|
+
secretAccessKey: params[parameters8.awsSecretAccessKey.slug]
|
|
2287
|
+
}
|
|
2288
|
+
});
|
|
2289
|
+
const { Id: statementId } = await client.send(
|
|
2290
|
+
new ExecuteStatementCommand({
|
|
2291
|
+
Database: params[parameters8.database.slug],
|
|
2292
|
+
Sql: "SELECT 1",
|
|
2293
|
+
...clusterIdentifier && { ClusterIdentifier: clusterIdentifier },
|
|
2294
|
+
...workgroupName && { WorkgroupName: workgroupName },
|
|
2295
|
+
...secretArn && { SecretArn: secretArn },
|
|
2296
|
+
...dbUser && { DbUser: dbUser }
|
|
2297
|
+
})
|
|
2298
|
+
);
|
|
2299
|
+
const startTime = Date.now();
|
|
2300
|
+
while (true) {
|
|
2301
|
+
const desc = await client.send(
|
|
2302
|
+
new DescribeStatementCommand({ Id: statementId })
|
|
2303
|
+
);
|
|
2304
|
+
if (desc.Status === "FINISHED") break;
|
|
2305
|
+
if (desc.Status === "FAILED" || desc.Status === "ABORTED") {
|
|
2306
|
+
return {
|
|
2307
|
+
success: false,
|
|
2308
|
+
error: desc.Error || `Statement ${desc.Status}`
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
if (Date.now() - startTime > 12e4) {
|
|
2312
|
+
return { success: false, error: "Query timed out after 120 seconds" };
|
|
2313
|
+
}
|
|
2314
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
2315
|
+
}
|
|
2316
|
+
return { success: true };
|
|
2317
|
+
} catch (error) {
|
|
2318
|
+
return {
|
|
2319
|
+
success: false,
|
|
2320
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2323
|
+
},
|
|
2078
2324
|
async query(params, sql, namedParams) {
|
|
2079
2325
|
const {
|
|
2080
2326
|
RedshiftDataClient,
|
|
@@ -2263,6 +2509,34 @@ var databricksConnector = new ConnectorPlugin({
|
|
|
2263
2509
|
- List columns: \`DESCRIBE TABLE table_name\`
|
|
2264
2510
|
- Always include LIMIT in queries`,
|
|
2265
2511
|
tools: tools9,
|
|
2512
|
+
async checkConnection(params, _config) {
|
|
2513
|
+
const { DBSQLClient } = await import("@databricks/sql");
|
|
2514
|
+
const client = new DBSQLClient();
|
|
2515
|
+
await client.connect({
|
|
2516
|
+
host: params[parameters9.host.slug],
|
|
2517
|
+
path: params[parameters9.httpPath.slug],
|
|
2518
|
+
token: params[parameters9.token.slug]
|
|
2519
|
+
});
|
|
2520
|
+
let session;
|
|
2521
|
+
let operation;
|
|
2522
|
+
try {
|
|
2523
|
+
session = await client.openSession();
|
|
2524
|
+
operation = await session.executeStatement("SELECT 1", {
|
|
2525
|
+
runAsync: true
|
|
2526
|
+
});
|
|
2527
|
+
await operation.fetchAll();
|
|
2528
|
+
return { success: true };
|
|
2529
|
+
} catch (e) {
|
|
2530
|
+
return { success: false, error: e instanceof Error ? e.message : String(e) };
|
|
2531
|
+
} finally {
|
|
2532
|
+
if (operation) await operation.close().catch(() => {
|
|
2533
|
+
});
|
|
2534
|
+
if (session) await session.close().catch(() => {
|
|
2535
|
+
});
|
|
2536
|
+
await client.close().catch(() => {
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
},
|
|
2266
2540
|
async query(params, sql, namedParams) {
|
|
2267
2541
|
const { DBSQLClient } = await import("@databricks/sql");
|
|
2268
2542
|
const resolvedSql = replaceLiteralParams(sql, namedParams);
|
|
@@ -3124,6 +3398,22 @@ var squadbaseDbConnector = new ConnectorPlugin({
|
|
|
3124
3398
|
- List columns: \`SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'xxx'\`
|
|
3125
3399
|
- Always include LIMIT in queries`,
|
|
3126
3400
|
tools: tools15,
|
|
3401
|
+
async checkConnection(params, _config) {
|
|
3402
|
+
const { Pool } = await import("pg");
|
|
3403
|
+
const pool = new Pool({
|
|
3404
|
+
connectionString: params[parameters15.connectionUrl.slug],
|
|
3405
|
+
ssl: { rejectUnauthorized: false },
|
|
3406
|
+
connectionTimeoutMillis: 1e4
|
|
3407
|
+
});
|
|
3408
|
+
try {
|
|
3409
|
+
await pool.query("SELECT 1");
|
|
3410
|
+
return { success: true };
|
|
3411
|
+
} catch (error) {
|
|
3412
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
3413
|
+
} finally {
|
|
3414
|
+
await pool.end();
|
|
3415
|
+
}
|
|
3416
|
+
},
|
|
3127
3417
|
async query(params, sql, namedParams) {
|
|
3128
3418
|
const { Pool } = await import("pg");
|
|
3129
3419
|
const { text, values } = buildPositionalParams(sql, namedParams);
|