@forestadmin/ai-proxy 1.7.4 → 1.9.0
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/forest-integration-client.d.ts +4 -2
- package/dist/forest-integration-client.js +18 -4
- package/dist/integrations/kolar/tools/create-merchant-application.d.ts +3 -0
- package/dist/integrations/kolar/tools/create-merchant-application.js +43 -0
- package/dist/integrations/kolar/tools/get-merchant-application-result.d.ts +3 -0
- package/dist/integrations/kolar/tools/get-merchant-application-result.js +25 -0
- package/dist/integrations/kolar/tools/get-screening-result.d.ts +3 -0
- package/dist/integrations/kolar/tools/get-screening-result.js +21 -0
- package/dist/integrations/kolar/tools/screen-transaction.d.ts +3 -0
- package/dist/integrations/kolar/tools/screen-transaction.js +61 -0
- package/dist/integrations/kolar/tools.d.ts +6 -0
- package/dist/integrations/kolar/tools.js +25 -0
- package/dist/integrations/kolar/utils.d.ts +11 -0
- package/dist/integrations/kolar/utils.js +43 -0
- package/dist/integrations/snowflake/tools/cortex-analyst.d.ts +3 -0
- package/dist/integrations/snowflake/tools/cortex-analyst.js +53 -0
- package/dist/integrations/snowflake/tools/cortex-search.d.ts +3 -0
- package/dist/integrations/snowflake/tools/cortex-search.js +55 -0
- package/dist/integrations/snowflake/tools/execute-query.d.ts +4 -0
- package/dist/integrations/snowflake/tools/execute-query.js +49 -0
- package/dist/integrations/snowflake/tools.d.ts +11 -0
- package/dist/integrations/snowflake/tools.js +24 -0
- package/dist/integrations/snowflake/utils.d.ts +14 -0
- package/dist/integrations/snowflake/utils.js +132 -0
- package/package.json +1 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type RemoteTool from './remote-tool';
|
|
2
2
|
import type { ToolProvider } from './tool-provider';
|
|
3
3
|
import type { Logger } from '@forestadmin/datasource-toolkit';
|
|
4
|
+
import { type KolarConfig } from './integrations/kolar/tools';
|
|
5
|
+
import { type SnowflakeConfig } from './integrations/snowflake/tools';
|
|
4
6
|
import { type ZendeskConfig } from './integrations/zendesk/tools';
|
|
5
|
-
export type CustomConfig = ZendeskConfig;
|
|
6
|
-
export type ForestIntegrationName = 'Zendesk';
|
|
7
|
+
export type CustomConfig = ZendeskConfig | KolarConfig | SnowflakeConfig;
|
|
8
|
+
export type ForestIntegrationName = 'Zendesk' | 'Kolar' | 'Snowflake';
|
|
7
9
|
export interface ForestIntegrationConfig {
|
|
8
10
|
integrationName: ForestIntegrationName;
|
|
9
11
|
config: CustomConfig;
|
|
@@ -5,8 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.isForestIntegrationConfig = isForestIntegrationConfig;
|
|
7
7
|
const errors_1 = require("./errors");
|
|
8
|
-
const tools_1 = __importDefault(require("./integrations/
|
|
9
|
-
const utils_1 = require("./integrations/
|
|
8
|
+
const tools_1 = __importDefault(require("./integrations/kolar/tools"));
|
|
9
|
+
const utils_1 = require("./integrations/kolar/utils");
|
|
10
|
+
const tools_2 = __importDefault(require("./integrations/snowflake/tools"));
|
|
11
|
+
const utils_2 = require("./integrations/snowflake/utils");
|
|
12
|
+
const tools_3 = __importDefault(require("./integrations/zendesk/tools"));
|
|
13
|
+
const utils_3 = require("./integrations/zendesk/utils");
|
|
10
14
|
function isForestIntegrationConfig(config) {
|
|
11
15
|
return ('isForestConnector' in config && config.isForestConnector === true);
|
|
12
16
|
}
|
|
@@ -20,8 +24,14 @@ class ForestIntegrationClient {
|
|
|
20
24
|
this.configs.forEach(({ integrationName, config }) => {
|
|
21
25
|
switch (integrationName) {
|
|
22
26
|
case 'Zendesk':
|
|
27
|
+
tools.push(...(0, tools_3.default)(config));
|
|
28
|
+
break;
|
|
29
|
+
case 'Kolar':
|
|
23
30
|
tools.push(...(0, tools_1.default)(config));
|
|
24
31
|
break;
|
|
32
|
+
case 'Snowflake':
|
|
33
|
+
tools.push(...(0, tools_2.default)(config));
|
|
34
|
+
break;
|
|
25
35
|
default:
|
|
26
36
|
this.logger?.('Warn', `Unsupported integration: ${integrationName}`);
|
|
27
37
|
}
|
|
@@ -32,7 +42,11 @@ class ForestIntegrationClient {
|
|
|
32
42
|
await Promise.all(this.configs.map(({ integrationName, config }) => {
|
|
33
43
|
switch (integrationName) {
|
|
34
44
|
case 'Zendesk':
|
|
35
|
-
return (0,
|
|
45
|
+
return (0, utils_3.validateZendeskConfig)(config);
|
|
46
|
+
case 'Kolar':
|
|
47
|
+
return (0, utils_1.validateKolarConfig)(config);
|
|
48
|
+
case 'Snowflake':
|
|
49
|
+
return (0, utils_2.validateSnowflakeConfig)(config);
|
|
36
50
|
default:
|
|
37
51
|
throw new errors_1.AIBadRequestError(`Unsupported integration: ${integrationName}`);
|
|
38
52
|
}
|
|
@@ -44,4 +58,4 @@ class ForestIntegrationClient {
|
|
|
44
58
|
}
|
|
45
59
|
}
|
|
46
60
|
exports.default = ForestIntegrationClient;
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZXN0LWludGVncmF0aW9uLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9mb3Jlc3QtaW50ZWdyYXRpb24tY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBcUJBLDhEQU1DO0FBdkJELHFDQUE2QztBQUM3Qyx1RUFBNkU7QUFDN0Usc0RBQWlFO0FBQ2pFLDJFQUF5RjtBQUN6RiwwREFBeUU7QUFDekUseUVBQW1GO0FBQ25GLHdEQUFxRTtBQVdyRSxTQUFnQix5QkFBeUIsQ0FDdkMsTUFBeUQ7SUFFekQsT0FBTyxDQUNMLG1CQUFtQixJQUFJLE1BQU0sSUFBSyxNQUFrQyxDQUFDLGlCQUFpQixLQUFLLElBQUksQ0FDaEcsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFxQix1QkFBdUI7SUFJMUMsWUFBWSxPQUFrQyxFQUFFLE1BQWU7UUFDN0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFDckIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztJQUVELEtBQUssQ0FBQyxTQUFTO1FBQ2IsTUFBTSxLQUFLLEdBQWlCLEVBQUUsQ0FBQztRQUUvQixJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7WUFDbkQsUUFBUSxlQUFlLEVBQUUsQ0FBQztnQkFDeEIsS0FBSyxTQUFTO29CQUNaLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFBLGVBQWUsRUFBQyxNQUF1QixDQUFDLENBQUMsQ0FBQztvQkFDeEQsTUFBTTtnQkFDUixLQUFLLE9BQU87b0JBQ1YsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUEsZUFBYSxFQUFDLE1BQXFCLENBQUMsQ0FBQyxDQUFDO29CQUNwRCxNQUFNO2dCQUNSLEtBQUssV0FBVztvQkFDZCxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBQSxlQUFpQixFQUFDLE1BQXlCLENBQUMsQ0FBQyxDQUFDO29CQUM1RCxNQUFNO2dCQUNSO29CQUNFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLEVBQUUsNEJBQTRCLGVBQWUsRUFBRSxDQUFDLENBQUM7WUFDekUsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsS0FBSyxDQUFDLGVBQWU7UUFDbkIsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNmLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtZQUMvQyxRQUFRLGVBQWUsRUFBRSxDQUFDO2dCQUN4QixLQUFLLFNBQVM7b0JBQ1osT0FBTyxJQUFBLDZCQUFxQixFQUFDLE1BQXVCLENBQUMsQ0FBQztnQkFDeEQsS0FBSyxPQUFPO29CQUNWLE9BQU8sSUFBQSwyQkFBbUIsRUFBQyxNQUFxQixDQUFDLENBQUM7Z0JBQ3BELEtBQUssV0FBVztvQkFDZCxPQUFPLElBQUEsK0JBQXVCLEVBQUMsTUFBeUIsQ0FBQyxDQUFDO2dCQUM1RDtvQkFDRSxNQUFNLElBQUksMEJBQWlCLENBQUMsNEJBQTRCLGVBQWUsRUFBRSxDQUFDLENBQUM7WUFDL0UsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUNILENBQUM7UUFFRixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTztRQUNYLHdEQUF3RDtJQUMxRCxDQUFDO0NBQ0Y7QUFyREQsMENBcURDIn0=
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createMerchantApplicationTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createMerchantApplicationTool(headers, baseUrl) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'kolar_create_merchant_application',
|
|
10
|
+
description: 'Submit a merchant application for KYB analysis. Creates the application, triggers analysis, and returns the application ID to use with kolar_get_merchant_application_result.',
|
|
11
|
+
schema: zod_1.z.object({
|
|
12
|
+
companyName: zod_1.z.string().describe('Company legal name'),
|
|
13
|
+
companySiren: zod_1.z.string().describe('Company SIREN number'),
|
|
14
|
+
websiteUrl: zod_1.z.string().describe('Company website URL'),
|
|
15
|
+
legalRepName: zod_1.z.string().describe('Legal representative full name'),
|
|
16
|
+
emailDomain: zod_1.z.string().optional().describe('Company email domain'),
|
|
17
|
+
phone: zod_1.z.string().optional().describe('Company phone number'),
|
|
18
|
+
legalRepDob: zod_1.z.string().optional().describe('Legal representative date of birth (ISO 8601)'),
|
|
19
|
+
expectedMonthlyPaymentVolume: zod_1.z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Expected monthly payment volume'),
|
|
23
|
+
expectedAverageBasketValue: zod_1.z.string().optional().describe('Expected average basket value'),
|
|
24
|
+
businessDescription: zod_1.z.string().optional().describe('Description of the business activity'),
|
|
25
|
+
}),
|
|
26
|
+
func: async (inputs) => {
|
|
27
|
+
const createResponse = await fetch(`${baseUrl}/merchant-application/create`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers,
|
|
30
|
+
body: JSON.stringify(inputs),
|
|
31
|
+
});
|
|
32
|
+
await (0, utils_1.assertResponseOk)(createResponse, 'create merchant application');
|
|
33
|
+
const { id } = await createResponse.json();
|
|
34
|
+
const jobResponse = await fetch(`${baseUrl}/merchant-application-job/create/${id}`, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers,
|
|
37
|
+
});
|
|
38
|
+
await (0, utils_1.assertResponseOk)(jobResponse, 'trigger merchant application analysis');
|
|
39
|
+
return JSON.stringify({ id });
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLW1lcmNoYW50LWFwcGxpY2F0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2ludGVncmF0aW9ucy9rb2xhci90b29scy9jcmVhdGUtbWVyY2hhbnQtYXBwbGljYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSxnREEyQ0M7QUFoREQsaURBQThEO0FBQzlELDZCQUF3QjtBQUV4QixvQ0FBNEM7QUFFNUMsU0FBd0IsNkJBQTZCLENBQ25ELE9BQStCLEVBQy9CLE9BQWU7SUFFZixPQUFPLElBQUksNkJBQXFCLENBQUM7UUFDL0IsSUFBSSxFQUFFLG1DQUFtQztRQUN6QyxXQUFXLEVBQ1QsK0tBQStLO1FBQ2pMLE1BQU0sRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDO1lBQ2YsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUM7WUFDdEQsWUFBWSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUM7WUFDekQsVUFBVSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMscUJBQXFCLENBQUM7WUFDdEQsWUFBWSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsZ0NBQWdDLENBQUM7WUFDbkUsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUM7WUFDbkUsS0FBSyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUM7WUFDN0QsV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsK0NBQStDLENBQUM7WUFDNUYsNEJBQTRCLEVBQUUsT0FBQztpQkFDNUIsTUFBTSxFQUFFO2lCQUNSLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsaUNBQWlDLENBQUM7WUFDOUMsMEJBQTBCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQywrQkFBK0IsQ0FBQztZQUMzRixtQkFBbUIsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLHNDQUFzQyxDQUFDO1NBQzVGLENBQUM7UUFDRixJQUFJLEVBQUUsS0FBSyxFQUFDLE1BQU0sRUFBQyxFQUFFO1lBQ25CLE1BQU0sY0FBYyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsT0FBTyw4QkFBOEIsRUFBRTtnQkFDM0UsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsT0FBTztnQkFDUCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7YUFDN0IsQ0FBQyxDQUFDO1lBRUgsTUFBTSxJQUFBLHdCQUFnQixFQUFDLGNBQWMsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1lBQ3RFLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxNQUFNLGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUUzQyxNQUFNLFdBQVcsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLE9BQU8sb0NBQW9DLEVBQUUsRUFBRSxFQUFFO2dCQUNsRixNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPO2FBQ1IsQ0FBQyxDQUFDO1lBRUgsTUFBTSxJQUFBLHdCQUFnQixFQUFDLFdBQVcsRUFBRSx1Q0FBdUMsQ0FBQyxDQUFDO1lBRTdFLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDaEMsQ0FBQztLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createGetMerchantApplicationResultTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createGetMerchantApplicationResultTool(headers, baseUrl) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'kolar_get_merchant_application_result',
|
|
10
|
+
description: 'Retrieve the KYB analysis result of a merchant application by ID. Returns jobStatus (PENDING, RUNNING, COMPLETED, FAILED) and result with decision (APPROVED, REJECTED, REVIEW), riskScore, and rationale when completed.',
|
|
11
|
+
schema: zod_1.z.object({
|
|
12
|
+
id: zod_1.z
|
|
13
|
+
.number()
|
|
14
|
+
.int()
|
|
15
|
+
.positive()
|
|
16
|
+
.describe('The merchant application ID returned by kolar_create_merchant_application'),
|
|
17
|
+
}),
|
|
18
|
+
func: async ({ id }) => {
|
|
19
|
+
const response = await fetch(`${baseUrl}/merchant-application/${id}/result`, { headers });
|
|
20
|
+
await (0, utils_1.assertResponseOk)(response, 'get merchant application result');
|
|
21
|
+
return JSON.stringify(await response.json());
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LW1lcmNoYW50LWFwcGxpY2F0aW9uLXJlc3VsdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9pbnRlZ3JhdGlvbnMva29sYXIvdG9vbHMvZ2V0LW1lcmNoYW50LWFwcGxpY2F0aW9uLXJlc3VsdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUtBLHlEQXVCQztBQTVCRCxpREFBOEQ7QUFDOUQsNkJBQXdCO0FBRXhCLG9DQUE0QztBQUU1QyxTQUF3QixzQ0FBc0MsQ0FDNUQsT0FBK0IsRUFDL0IsT0FBZTtJQUVmLE9BQU8sSUFBSSw2QkFBcUIsQ0FBQztRQUMvQixJQUFJLEVBQUUsdUNBQXVDO1FBQzdDLFdBQVcsRUFDVCwyTkFBMk47UUFDN04sTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUM7WUFDZixFQUFFLEVBQUUsT0FBQztpQkFDRixNQUFNLEVBQUU7aUJBQ1IsR0FBRyxFQUFFO2lCQUNMLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsMkVBQTJFLENBQUM7U0FDekYsQ0FBQztRQUNGLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO1lBQ3JCLE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsT0FBTyx5QkFBeUIsRUFBRSxTQUFTLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBRTFGLE1BQU0sSUFBQSx3QkFBZ0IsRUFBQyxRQUFRLEVBQUUsaUNBQWlDLENBQUMsQ0FBQztZQUVwRSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMvQyxDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyJ9
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createGetScreeningResultTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createGetScreeningResultTool(headers, baseUrl) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'kolar_get_screening_result',
|
|
10
|
+
description: 'Retrieve the full result of a submitted screening by alert ID, including risk score and match details.',
|
|
11
|
+
schema: zod_1.z.object({
|
|
12
|
+
id: zod_1.z.number().int().positive().describe('The alert ID returned by kolar_screen_transaction'),
|
|
13
|
+
}),
|
|
14
|
+
func: async ({ id }) => {
|
|
15
|
+
const response = await fetch(`${baseUrl}/alert/${id}/result`, { headers });
|
|
16
|
+
await (0, utils_1.assertResponseOk)(response, 'get screening result');
|
|
17
|
+
return JSON.stringify(await response.json());
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXNjcmVlbmluZy1yZXN1bHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL2tvbGFyL3Rvb2xzL2dldC1zY3JlZW5pbmctcmVzdWx0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBS0EsK0NBbUJDO0FBeEJELGlEQUE4RDtBQUM5RCw2QkFBd0I7QUFFeEIsb0NBQTRDO0FBRTVDLFNBQXdCLDRCQUE0QixDQUNsRCxPQUErQixFQUMvQixPQUFlO0lBRWYsT0FBTyxJQUFJLDZCQUFxQixDQUFDO1FBQy9CLElBQUksRUFBRSw0QkFBNEI7UUFDbEMsV0FBVyxFQUNULHdHQUF3RztRQUMxRyxNQUFNLEVBQUUsT0FBQyxDQUFDLE1BQU0sQ0FBQztZQUNmLEVBQUUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLG1EQUFtRCxDQUFDO1NBQzlGLENBQUM7UUFDRixJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUNyQixNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLE9BQU8sVUFBVSxFQUFFLFNBQVMsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFFM0UsTUFBTSxJQUFBLHdCQUFnQixFQUFDLFFBQVEsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO1lBRXpELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLENBQUM7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIn0=
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createScreenTransactionTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createScreenTransactionTool(headers, baseUrl) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'kolar_screen_transaction',
|
|
10
|
+
description: 'Submit a transaction for AML risk screening. Creates an alert and triggers the screening job. Returns the alert ID to use with kolar_get_screening_result.',
|
|
11
|
+
schema: zod_1.z.object({
|
|
12
|
+
clientFirstName: zod_1.z.string().describe('Client first name'),
|
|
13
|
+
clientLastName: zod_1.z.string().describe('Client last name'),
|
|
14
|
+
matchFirstNames: zod_1.z.string().describe('Match first names'),
|
|
15
|
+
matchLastNames: zod_1.z.string().describe('Match last names'),
|
|
16
|
+
matchType: zod_1.z
|
|
17
|
+
.enum(['PEP', 'SL'])
|
|
18
|
+
.describe('Match type: PEP (Politically Exposed Person) or SL (Sanctions List)'),
|
|
19
|
+
clientBirthDate: zod_1.z.string().optional().describe('Client birth date (ISO 8601)'),
|
|
20
|
+
clientBirthPlace: zod_1.z.string().optional().describe('Client birth place'),
|
|
21
|
+
clientIdFirstName: zod_1.z.string().optional().describe('Client ID first name'),
|
|
22
|
+
clientIdLastName: zod_1.z.string().optional().describe('Client ID last name'),
|
|
23
|
+
clientIdBirthDate: zod_1.z.string().optional().describe('Client ID birth date (ISO 8601)'),
|
|
24
|
+
clientIdBirthPlace: zod_1.z.string().optional().describe('Client ID birth place'),
|
|
25
|
+
clientIdCountryCode: zod_1.z.string().optional().describe('Client ID country code'),
|
|
26
|
+
onfidoCountryCode: zod_1.z.string().optional().describe('Onfido country code'),
|
|
27
|
+
clientPhoneCountryCode: zod_1.z.string().optional().describe('Client phone country code'),
|
|
28
|
+
merchantBrand: zod_1.z.string().optional().describe('Merchant brand'),
|
|
29
|
+
paymentIpAddress: zod_1.z.string().optional().describe('Payment IP address'),
|
|
30
|
+
paymentCountry: zod_1.z.string().optional().describe('Payment country'),
|
|
31
|
+
shippingCountry: zod_1.z.string().optional().describe('Shipping country'),
|
|
32
|
+
billingCountry: zod_1.z.string().optional().describe('Billing country'),
|
|
33
|
+
cardHolderName: zod_1.z.string().optional().describe('Card holder name'),
|
|
34
|
+
cardCountryCode: zod_1.z.string().optional().describe('Card country code'),
|
|
35
|
+
bankAccountHolderName: zod_1.z.string().optional().describe('Bank account holder name'),
|
|
36
|
+
bankAccountCountryCode: zod_1.z.string().optional().describe('Bank account country code'),
|
|
37
|
+
matchFullNames: zod_1.z.string().optional().describe('Match full names'),
|
|
38
|
+
matchBirthDate: zod_1.z.string().optional().describe('Match birth date (ISO 8601)'),
|
|
39
|
+
matchBirthPlace: zod_1.z.string().optional().describe('Match birth place'),
|
|
40
|
+
matchCountryCode: zod_1.z.string().optional().describe('Match country code'),
|
|
41
|
+
matchRole: zod_1.z.string().optional().describe('Match role'),
|
|
42
|
+
additionalData: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional().describe('Additional data'),
|
|
43
|
+
}),
|
|
44
|
+
func: async (inputs) => {
|
|
45
|
+
const createResponse = await fetch(`${baseUrl}/alert/create`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers,
|
|
48
|
+
body: JSON.stringify(inputs),
|
|
49
|
+
});
|
|
50
|
+
await (0, utils_1.assertResponseOk)(createResponse, 'create alert');
|
|
51
|
+
const { id } = await createResponse.json();
|
|
52
|
+
const jobResponse = await fetch(`${baseUrl}/alert-job/create/${id}`, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers,
|
|
55
|
+
});
|
|
56
|
+
await (0, utils_1.assertResponseOk)(jobResponse, 'create alert job');
|
|
57
|
+
return JSON.stringify({ id });
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyZWVuLXRyYW5zYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2ludGVncmF0aW9ucy9rb2xhci90b29scy9zY3JlZW4tdHJhbnNhY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSw4Q0E2REM7QUFsRUQsaURBQThEO0FBQzlELDZCQUF3QjtBQUV4QixvQ0FBNEM7QUFFNUMsU0FBd0IsMkJBQTJCLENBQ2pELE9BQStCLEVBQy9CLE9BQWU7SUFFZixPQUFPLElBQUksNkJBQXFCLENBQUM7UUFDL0IsSUFBSSxFQUFFLDBCQUEwQjtRQUNoQyxXQUFXLEVBQ1QsNEpBQTRKO1FBQzlKLE1BQU0sRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDO1lBQ2YsZUFBZSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUM7WUFDekQsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUM7WUFDdkQsZUFBZSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUM7WUFDekQsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUM7WUFDdkQsU0FBUyxFQUFFLE9BQUM7aUJBQ1QsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO2lCQUNuQixRQUFRLENBQUMscUVBQXFFLENBQUM7WUFDbEYsZUFBZSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsOEJBQThCLENBQUM7WUFDL0UsZ0JBQWdCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQztZQUN0RSxpQkFBaUIsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLHNCQUFzQixDQUFDO1lBQ3pFLGdCQUFnQixFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMscUJBQXFCLENBQUM7WUFDdkUsaUJBQWlCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxpQ0FBaUMsQ0FBQztZQUNwRixrQkFBa0IsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLHVCQUF1QixDQUFDO1lBQzNFLG1CQUFtQixFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUM7WUFDN0UsaUJBQWlCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FBQztZQUN4RSxzQkFBc0IsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDO1lBQ25GLGFBQWEsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO1lBQy9ELGdCQUFnQixFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUM7WUFDdEUsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDakUsZUFBZSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUM7WUFDbkUsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUM7WUFDakUsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUM7WUFDbEUsZUFBZSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUM7WUFDcEUscUJBQXFCLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQywwQkFBMEIsQ0FBQztZQUNqRixzQkFBc0IsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLDJCQUEyQixDQUFDO1lBQ25GLGNBQWMsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDO1lBQ2xFLGNBQWMsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLDZCQUE2QixDQUFDO1lBQzdFLGVBQWUsRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDO1lBQ3BFLGdCQUFnQixFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUM7WUFDdEUsU0FBUyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDO1lBQ3ZELGNBQWMsRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxPQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUM7U0FDekYsQ0FBQztRQUNGLElBQUksRUFBRSxLQUFLLEVBQUMsTUFBTSxFQUFDLEVBQUU7WUFDbkIsTUFBTSxjQUFjLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxPQUFPLGVBQWUsRUFBRTtnQkFDNUQsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsT0FBTztnQkFDUCxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7YUFDN0IsQ0FBQyxDQUFDO1lBRUgsTUFBTSxJQUFBLHdCQUFnQixFQUFDLGNBQWMsRUFBRSxjQUFjLENBQUMsQ0FBQztZQUN2RCxNQUFNLEVBQUUsRUFBRSxFQUFFLEdBQUcsTUFBTSxjQUFjLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFM0MsTUFBTSxXQUFXLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxPQUFPLHFCQUFxQixFQUFFLEVBQUUsRUFBRTtnQkFDbkUsTUFBTSxFQUFFLE1BQU07Z0JBQ2QsT0FBTzthQUNSLENBQUMsQ0FBQztZQUVILE1BQU0sSUFBQSx3QkFBZ0IsRUFBQyxXQUFXLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztZQUV4RCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIn0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = getKolarTools;
|
|
7
|
+
const create_merchant_application_1 = __importDefault(require("./tools/create-merchant-application"));
|
|
8
|
+
const get_merchant_application_result_1 = __importDefault(require("./tools/get-merchant-application-result"));
|
|
9
|
+
const get_screening_result_1 = __importDefault(require("./tools/get-screening-result"));
|
|
10
|
+
const screen_transaction_1 = __importDefault(require("./tools/screen-transaction"));
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
const server_remote_tool_1 = __importDefault(require("../../server-remote-tool"));
|
|
13
|
+
function getKolarTools(config) {
|
|
14
|
+
const { baseUrl, headers } = (0, utils_1.getKolarConfig)(config);
|
|
15
|
+
return [
|
|
16
|
+
(0, create_merchant_application_1.default)(headers, baseUrl),
|
|
17
|
+
(0, get_merchant_application_result_1.default)(headers, baseUrl),
|
|
18
|
+
(0, screen_transaction_1.default)(headers, baseUrl),
|
|
19
|
+
(0, get_screening_result_1.default)(headers, baseUrl),
|
|
20
|
+
].map(tool => new server_remote_tool_1.default({
|
|
21
|
+
sourceId: 'kolar',
|
|
22
|
+
tool,
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL2tvbGFyL3Rvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBYUEsZ0NBZUM7QUExQkQsc0dBQWdGO0FBQ2hGLDhHQUE2RjtBQUM3Rix3RkFBd0U7QUFDeEUsb0ZBQXFFO0FBQ3JFLG1DQUF5QztBQUN6QyxrRkFBd0Q7QUFNeEQsU0FBd0IsYUFBYSxDQUFDLE1BQW1CO0lBQ3ZELE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBQSxzQkFBYyxFQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXBELE9BQU87UUFDTCxJQUFBLHFDQUE2QixFQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7UUFDL0MsSUFBQSx5Q0FBc0MsRUFBQyxPQUFPLEVBQUUsT0FBTyxDQUFDO1FBQ3hELElBQUEsNEJBQTJCLEVBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQztRQUM3QyxJQUFBLDhCQUE0QixFQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7S0FDL0MsQ0FBQyxHQUFHLENBQ0gsSUFBSSxDQUFDLEVBQUUsQ0FDTCxJQUFJLDRCQUFnQixDQUFDO1FBQ25CLFFBQVEsRUFBRSxPQUFPO1FBQ2pCLElBQUk7S0FDTCxDQUFDLENBQ0wsQ0FBQztBQUNKLENBQUMifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { KolarConfig } from './tools';
|
|
2
|
+
export declare function getKolarConfig({ apiKey }: KolarConfig): {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
headers: {
|
|
5
|
+
'X-Api-Key': string;
|
|
6
|
+
'Content-Type': string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export declare function assertResponseOk(response: Response, action: string): Promise<void>;
|
|
10
|
+
export declare function validateKolarConfig(config: KolarConfig): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getKolarConfig = getKolarConfig;
|
|
4
|
+
exports.assertResponseOk = assertResponseOk;
|
|
5
|
+
exports.validateKolarConfig = validateKolarConfig;
|
|
6
|
+
const errors_1 = require("../../errors");
|
|
7
|
+
const BASE_URL = 'https://api.kolar.ai';
|
|
8
|
+
function getKolarConfig({ apiKey }) {
|
|
9
|
+
const headers = {
|
|
10
|
+
'X-Api-Key': apiKey,
|
|
11
|
+
'Content-Type': 'application/json',
|
|
12
|
+
};
|
|
13
|
+
return { baseUrl: BASE_URL, headers };
|
|
14
|
+
}
|
|
15
|
+
async function assertResponseOk(response, action) {
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
let errorMessage = response.statusText || 'Unknown error';
|
|
18
|
+
try {
|
|
19
|
+
const json = await response.json();
|
|
20
|
+
errorMessage = json.error || json.message || json.description || errorMessage;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Response body is not JSON
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`Kolar ${action} failed (${response.status}): ${errorMessage}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function validateKolarConfig(config) {
|
|
29
|
+
const { baseUrl, headers } = getKolarConfig(config);
|
|
30
|
+
const response = await fetch(`${baseUrl}/auth/verify`, { headers });
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
let errorMessage = response.statusText || 'Unknown error';
|
|
33
|
+
try {
|
|
34
|
+
const json = await response.json();
|
|
35
|
+
errorMessage = json.message || json.error || errorMessage;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Response body is not JSON
|
|
39
|
+
}
|
|
40
|
+
throw new errors_1.McpConnectionError(`Failed to validate Kolar config: ${errorMessage}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL2tvbGFyL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBTUEsd0NBT0M7QUFFRCw0Q0FhQztBQUVELGtEQWlCQztBQTdDRCx5Q0FBa0Q7QUFFbEQsTUFBTSxRQUFRLEdBQUcsc0JBQXNCLENBQUM7QUFFeEMsU0FBZ0IsY0FBYyxDQUFDLEVBQUUsTUFBTSxFQUFlO0lBQ3BELE1BQU0sT0FBTyxHQUFHO1FBQ2QsV0FBVyxFQUFFLE1BQU07UUFDbkIsY0FBYyxFQUFFLGtCQUFrQjtLQUNuQyxDQUFDO0lBRUYsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7QUFDeEMsQ0FBQztBQUVNLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxRQUFrQixFQUFFLE1BQWM7SUFDdkUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNqQixJQUFJLFlBQVksR0FBRyxRQUFRLENBQUMsVUFBVSxJQUFJLGVBQWUsQ0FBQztRQUUxRCxJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNuQyxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxXQUFXLElBQUksWUFBWSxDQUFDO1FBQ2hGLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCw0QkFBNEI7UUFDOUIsQ0FBQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxNQUFNLFlBQVksUUFBUSxDQUFDLE1BQU0sTUFBTSxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLENBQUM7QUFDSCxDQUFDO0FBRU0sS0FBSyxVQUFVLG1CQUFtQixDQUFDLE1BQW1CO0lBQzNELE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRXBELE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsT0FBTyxjQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBRXBFLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDakIsSUFBSSxZQUFZLEdBQUcsUUFBUSxDQUFDLFVBQVUsSUFBSSxlQUFlLENBQUM7UUFFMUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkMsWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxZQUFZLENBQUM7UUFDNUQsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLDRCQUE0QjtRQUM5QixDQUFDO1FBRUQsTUFBTSxJQUFJLDJCQUFrQixDQUFDLG9DQUFvQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBQ25GLENBQUM7QUFDSCxDQUFDIn0=
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createCortexAnalystTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const errors_1 = require("../../../errors");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
function createCortexAnalystTool(headers, baseUrl) {
|
|
9
|
+
return new tools_1.DynamicStructuredTool({
|
|
10
|
+
name: 'snowflake_cortex_analyst',
|
|
11
|
+
description: 'Ask a natural-language analytical question against a Snowflake semantic model or ' +
|
|
12
|
+
'semantic view using Cortex Analyst. Returns a generated SQL query and the answer. ' +
|
|
13
|
+
'Exactly one of `semantic_model_file` or `semantic_view` must be provided.',
|
|
14
|
+
schema: zod_1.z.object({
|
|
15
|
+
question: zod_1.z.string().min(1).describe('The natural-language analytical question'),
|
|
16
|
+
semantic_model_file: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Stage path to the YAML semantic model file ' +
|
|
20
|
+
'(e.g. "@my_db.my_schema.my_stage/model.yaml")'),
|
|
21
|
+
semantic_view: zod_1.z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Fully qualified semantic view name (e.g. "my_db.my_schema.my_view")'),
|
|
25
|
+
}),
|
|
26
|
+
func: async ({ question, semantic_model_file, semantic_view }) => {
|
|
27
|
+
if (!semantic_model_file && !semantic_view) {
|
|
28
|
+
throw new errors_1.AIBadRequestError('Either `semantic_model_file` or `semantic_view` must be provided.');
|
|
29
|
+
}
|
|
30
|
+
if (semantic_model_file && semantic_view) {
|
|
31
|
+
throw new errors_1.AIBadRequestError('Provide only one of `semantic_model_file` or `semantic_view`, not both.');
|
|
32
|
+
}
|
|
33
|
+
const body = {
|
|
34
|
+
messages: [
|
|
35
|
+
{
|
|
36
|
+
role: 'user',
|
|
37
|
+
content: [{ type: 'text', text: question }],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
...(semantic_model_file && { semantic_model_file }),
|
|
41
|
+
...(semantic_view && { semantic_view }),
|
|
42
|
+
};
|
|
43
|
+
const response = await fetch(`${baseUrl}/api/v2/cortex/analyst/message`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers,
|
|
46
|
+
body: JSON.stringify(body),
|
|
47
|
+
});
|
|
48
|
+
await (0, utils_1.assertResponseOk)(response, 'cortex analyst');
|
|
49
|
+
return JSON.stringify(await response.json());
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ydGV4LWFuYWx5c3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL3Nub3dmbGFrZS90b29scy9jb3J0ZXgtYW5hbHlzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU1BLDBDQTJEQztBQWpFRCxpREFBOEQ7QUFDOUQsNkJBQXdCO0FBRXhCLDRDQUFvRDtBQUNwRCxvQ0FBNEM7QUFFNUMsU0FBd0IsdUJBQXVCLENBQzdDLE9BQStCLEVBQy9CLE9BQWU7SUFFZixPQUFPLElBQUksNkJBQXFCLENBQUM7UUFDL0IsSUFBSSxFQUFFLDBCQUEwQjtRQUNoQyxXQUFXLEVBQ1QsbUZBQW1GO1lBQ25GLG9GQUFvRjtZQUNwRiwyRUFBMkU7UUFDN0UsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUM7WUFDZixRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsMENBQTBDLENBQUM7WUFDaEYsbUJBQW1CLEVBQUUsT0FBQztpQkFDbkIsTUFBTSxFQUFFO2lCQUNSLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQ1AsNkNBQTZDO2dCQUMzQywrQ0FBK0MsQ0FDbEQ7WUFDSCxhQUFhLEVBQUUsT0FBQztpQkFDYixNQUFNLEVBQUU7aUJBQ1IsUUFBUSxFQUFFO2lCQUNWLFFBQVEsQ0FBQyxxRUFBcUUsQ0FBQztTQUNuRixDQUFDO1FBQ0YsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxtQkFBbUIsRUFBRSxhQUFhLEVBQUUsRUFBRSxFQUFFO1lBQy9ELElBQUksQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUMzQyxNQUFNLElBQUksMEJBQWlCLENBQ3pCLG1FQUFtRSxDQUNwRSxDQUFDO1lBQ0osQ0FBQztZQUVELElBQUksbUJBQW1CLElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sSUFBSSwwQkFBaUIsQ0FDekIseUVBQXlFLENBQzFFLENBQUM7WUFDSixDQUFDO1lBRUQsTUFBTSxJQUFJLEdBQTRCO2dCQUNwQyxRQUFRLEVBQUU7b0JBQ1I7d0JBQ0UsSUFBSSxFQUFFLE1BQU07d0JBQ1osT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQztxQkFDNUM7aUJBQ0Y7Z0JBQ0QsR0FBRyxDQUFDLG1CQUFtQixJQUFJLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztnQkFDbkQsR0FBRyxDQUFDLGFBQWEsSUFBSSxFQUFFLGFBQWEsRUFBRSxDQUFDO2FBQ3hDLENBQUM7WUFFRixNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLE9BQU8sZ0NBQWdDLEVBQUU7Z0JBQ3ZFLE1BQU0sRUFBRSxNQUFNO2dCQUNkLE9BQU87Z0JBQ1AsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2FBQzNCLENBQUMsQ0FBQztZQUVILE1BQU0sSUFBQSx3QkFBZ0IsRUFBQyxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUVuRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMvQyxDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyJ9
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createCortexSearchTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createCortexSearchTool(headers, baseUrl) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'snowflake_cortex_search',
|
|
10
|
+
description: 'Search data using a Snowflake Cortex Search service. ' +
|
|
11
|
+
'Returns semantic search results ranked by relevance. ' +
|
|
12
|
+
'The caller must provide the fully qualified service identifier (database, schema, service).',
|
|
13
|
+
schema: zod_1.z.object({
|
|
14
|
+
database: zod_1.z.string().min(1).describe('Name of the database containing the search service'),
|
|
15
|
+
schema: zod_1.z.string().min(1).describe('Name of the schema containing the search service'),
|
|
16
|
+
service: zod_1.z.string().min(1).describe('Name of the Cortex Search service'),
|
|
17
|
+
query: zod_1.z.string().min(1).describe('The natural-language search query'),
|
|
18
|
+
columns: zod_1.z
|
|
19
|
+
.array(zod_1.z.string().min(1))
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Columns to include in the search results'),
|
|
22
|
+
filter: zod_1.z
|
|
23
|
+
.record(zod_1.z.string(), zod_1.z.unknown())
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('Optional filter expression as a JSON object'),
|
|
26
|
+
limit: zod_1.z
|
|
27
|
+
.number()
|
|
28
|
+
.int()
|
|
29
|
+
.positive()
|
|
30
|
+
.max(1000)
|
|
31
|
+
.optional()
|
|
32
|
+
.describe('Maximum number of results to return (default: service-defined)'),
|
|
33
|
+
}),
|
|
34
|
+
func: async ({ database, schema, service, query, columns, filter, limit }) => {
|
|
35
|
+
const url = `${baseUrl}/api/v2/databases/${encodeURIComponent(database)}` +
|
|
36
|
+
`/schemas/${encodeURIComponent(schema)}` +
|
|
37
|
+
`/cortex-search-services/${encodeURIComponent(service)}:query`;
|
|
38
|
+
const body = { query };
|
|
39
|
+
if (columns)
|
|
40
|
+
body.columns = columns;
|
|
41
|
+
if (filter)
|
|
42
|
+
body.filter = filter;
|
|
43
|
+
if (limit !== undefined)
|
|
44
|
+
body.limit = limit;
|
|
45
|
+
const response = await fetch(url, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers,
|
|
48
|
+
body: JSON.stringify(body),
|
|
49
|
+
});
|
|
50
|
+
await (0, utils_1.assertResponseOk)(response, 'cortex search');
|
|
51
|
+
return JSON.stringify(await response.json());
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ydGV4LXNlYXJjaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9pbnRlZ3JhdGlvbnMvc25vd2ZsYWtlL3Rvb2xzL2NvcnRleC1zZWFyY2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFLQSx5Q0FxREM7QUExREQsaURBQThEO0FBQzlELDZCQUF3QjtBQUV4QixvQ0FBNEM7QUFFNUMsU0FBd0Isc0JBQXNCLENBQzVDLE9BQStCLEVBQy9CLE9BQWU7SUFFZixPQUFPLElBQUksNkJBQXFCLENBQUM7UUFDL0IsSUFBSSxFQUFFLHlCQUF5QjtRQUMvQixXQUFXLEVBQ1QsdURBQXVEO1lBQ3ZELHVEQUF1RDtZQUN2RCw2RkFBNkY7UUFDL0YsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUM7WUFDZixRQUFRLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsb0RBQW9ELENBQUM7WUFDMUYsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLGtEQUFrRCxDQUFDO1lBQ3RGLE9BQU8sRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxtQ0FBbUMsQ0FBQztZQUN4RSxLQUFLLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsbUNBQW1DLENBQUM7WUFDdEUsT0FBTyxFQUFFLE9BQUM7aUJBQ1AsS0FBSyxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ3hCLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsMENBQTBDLENBQUM7WUFDdkQsTUFBTSxFQUFFLE9BQUM7aUJBQ04sTUFBTSxDQUFDLE9BQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxPQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7aUJBQy9CLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsNkNBQTZDLENBQUM7WUFDMUQsS0FBSyxFQUFFLE9BQUM7aUJBQ0wsTUFBTSxFQUFFO2lCQUNSLEdBQUcsRUFBRTtpQkFDTCxRQUFRLEVBQUU7aUJBQ1YsR0FBRyxDQUFDLElBQUksQ0FBQztpQkFDVCxRQUFRLEVBQUU7aUJBQ1YsUUFBUSxDQUFDLGdFQUFnRSxDQUFDO1NBQzlFLENBQUM7UUFDRixJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUMzRSxNQUFNLEdBQUcsR0FDUCxHQUFHLE9BQU8scUJBQXFCLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxFQUFFO2dCQUM3RCxZQUFZLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUN4QywyQkFBMkIsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztZQUVqRSxNQUFNLElBQUksR0FBNEIsRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRCxJQUFJLE9BQU87Z0JBQUUsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7WUFDcEMsSUFBSSxNQUFNO2dCQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQ2pDLElBQUksS0FBSyxLQUFLLFNBQVM7Z0JBQUUsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7WUFFNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFO2dCQUNoQyxNQUFNLEVBQUUsTUFBTTtnQkFDZCxPQUFPO2dCQUNQLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQzthQUMzQixDQUFDLENBQUM7WUFFSCxNQUFNLElBQUEsd0JBQWdCLEVBQUMsUUFBUSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBRWxELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLENBQUM7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIn0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SnowflakeConfig } from '../tools';
|
|
2
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
3
|
+
export default function createExecuteQueryTool(headers: Record<string, string>, baseUrl: string, config: SnowflakeConfig): DynamicStructuredTool;
|
|
4
|
+
//# sourceMappingURL=execute-query.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createExecuteQueryTool;
|
|
4
|
+
const tools_1 = require("@langchain/core/tools");
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
function createExecuteQueryTool(headers, baseUrl, config) {
|
|
8
|
+
return new tools_1.DynamicStructuredTool({
|
|
9
|
+
name: 'snowflake_execute_query',
|
|
10
|
+
description: 'Execute a read-only SQL query on Snowflake and return the results. ' +
|
|
11
|
+
'Only SELECT, SHOW, DESCRIBE, and EXPLAIN statements are allowed. ' +
|
|
12
|
+
'Multiple statements are not permitted.',
|
|
13
|
+
schema: zod_1.z.object({
|
|
14
|
+
statement: zod_1.z.string().min(1).describe('The read-only SQL statement to execute'),
|
|
15
|
+
warehouse: zod_1.z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe('Warehouse to use for this query (overrides the default)'),
|
|
19
|
+
database: zod_1.z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Database to use for this query (overrides the default)'),
|
|
23
|
+
schema: zod_1.z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Schema to use for this query (overrides the default)'),
|
|
27
|
+
role: zod_1.z.string().optional().describe('Role to use for this query (overrides the default)'),
|
|
28
|
+
}),
|
|
29
|
+
func: async ({ statement, warehouse, database, schema, role }) => {
|
|
30
|
+
(0, utils_1.assertReadOnlySql)(statement);
|
|
31
|
+
const body = {
|
|
32
|
+
statement,
|
|
33
|
+
...(0, utils_1.buildSessionContext)(config),
|
|
34
|
+
...(warehouse && { warehouse }),
|
|
35
|
+
...(database && { database }),
|
|
36
|
+
...(schema && { schema }),
|
|
37
|
+
...(role && { role }),
|
|
38
|
+
};
|
|
39
|
+
const response = await fetch(`${baseUrl}/api/v2/statements`, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers,
|
|
42
|
+
body: JSON.stringify(body),
|
|
43
|
+
});
|
|
44
|
+
await (0, utils_1.assertResponseOk)(response, 'execute query');
|
|
45
|
+
return JSON.stringify(await response.json());
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlY3V0ZS1xdWVyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9pbnRlZ3JhdGlvbnMvc25vd2ZsYWtlL3Rvb2xzL2V4ZWN1dGUtcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFPQSx5Q0FrREM7QUF2REQsaURBQThEO0FBQzlELDZCQUF3QjtBQUV4QixvQ0FBb0Y7QUFFcEYsU0FBd0Isc0JBQXNCLENBQzVDLE9BQStCLEVBQy9CLE9BQWUsRUFDZixNQUF1QjtJQUV2QixPQUFPLElBQUksNkJBQXFCLENBQUM7UUFDL0IsSUFBSSxFQUFFLHlCQUF5QjtRQUMvQixXQUFXLEVBQ1QscUVBQXFFO1lBQ3JFLG1FQUFtRTtZQUNuRSx3Q0FBd0M7UUFDMUMsTUFBTSxFQUFFLE9BQUMsQ0FBQyxNQUFNLENBQUM7WUFDZixTQUFTLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsd0NBQXdDLENBQUM7WUFDL0UsU0FBUyxFQUFFLE9BQUM7aUJBQ1QsTUFBTSxFQUFFO2lCQUNSLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMseURBQXlELENBQUM7WUFDdEUsUUFBUSxFQUFFLE9BQUM7aUJBQ1IsTUFBTSxFQUFFO2lCQUNSLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsd0RBQXdELENBQUM7WUFDckUsTUFBTSxFQUFFLE9BQUM7aUJBQ04sTUFBTSxFQUFFO2lCQUNSLFFBQVEsRUFBRTtpQkFDVixRQUFRLENBQUMsc0RBQXNELENBQUM7WUFDbkUsSUFBSSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0RBQW9ELENBQUM7U0FDM0YsQ0FBQztRQUNGLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUMvRCxJQUFBLHlCQUFpQixFQUFDLFNBQVMsQ0FBQyxDQUFDO1lBRTdCLE1BQU0sSUFBSSxHQUFHO2dCQUNYLFNBQVM7Z0JBQ1QsR0FBRyxJQUFBLDJCQUFtQixFQUFDLE1BQU0sQ0FBQztnQkFDOUIsR0FBRyxDQUFDLFNBQVMsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO2dCQUMvQixHQUFHLENBQUMsUUFBUSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7Z0JBQzdCLEdBQUcsQ0FBQyxNQUFNLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztnQkFDekIsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQ3RCLENBQUM7WUFFRixNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLE9BQU8sb0JBQW9CLEVBQUU7Z0JBQzNELE1BQU0sRUFBRSxNQUFNO2dCQUNkLE9BQU87Z0JBQ1AsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO2FBQzNCLENBQUMsQ0FBQztZQUVILE1BQU0sSUFBQSx3QkFBZ0IsRUFBQyxRQUFRLEVBQUUsZUFBZSxDQUFDLENBQUM7WUFFbEQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDL0MsQ0FBQztLQUNGLENBQUMsQ0FBQztBQUNMLENBQUMifQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type RemoteTool from '../../remote-tool';
|
|
2
|
+
export interface SnowflakeConfig {
|
|
3
|
+
accountIdentifier: string;
|
|
4
|
+
programmaticAccessToken: string;
|
|
5
|
+
defaultWarehouse?: string;
|
|
6
|
+
defaultDatabase?: string;
|
|
7
|
+
defaultSchema?: string;
|
|
8
|
+
defaultRole?: string;
|
|
9
|
+
}
|
|
10
|
+
export default function getSnowflakeTools(config: SnowflakeConfig): RemoteTool[];
|
|
11
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.default = getSnowflakeTools;
|
|
7
|
+
const server_remote_tool_1 = __importDefault(require("../../server-remote-tool"));
|
|
8
|
+
const cortex_analyst_1 = __importDefault(require("./tools/cortex-analyst"));
|
|
9
|
+
const cortex_search_1 = __importDefault(require("./tools/cortex-search"));
|
|
10
|
+
const execute_query_1 = __importDefault(require("./tools/execute-query"));
|
|
11
|
+
const utils_1 = require("./utils");
|
|
12
|
+
function getSnowflakeTools(config) {
|
|
13
|
+
const headers = (0, utils_1.getSnowflakeAuthHeaders)(config);
|
|
14
|
+
const baseUrl = (0, utils_1.getSnowflakeBaseUrl)(config.accountIdentifier);
|
|
15
|
+
return [
|
|
16
|
+
(0, cortex_search_1.default)(headers, baseUrl),
|
|
17
|
+
(0, cortex_analyst_1.default)(headers, baseUrl),
|
|
18
|
+
(0, execute_query_1.default)(headers, baseUrl, config),
|
|
19
|
+
].map(tool => new server_remote_tool_1.default({
|
|
20
|
+
sourceId: 'snowflake',
|
|
21
|
+
tool,
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL3Nub3dmbGFrZS90b29scy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQWlCQSxvQ0FlQztBQTlCRCxrRkFBd0Q7QUFDeEQsNEVBQTZEO0FBQzdELDBFQUEyRDtBQUMzRCwwRUFBMkQ7QUFDM0QsbUNBQXVFO0FBV3ZFLFNBQXdCLGlCQUFpQixDQUFDLE1BQXVCO0lBQy9ELE1BQU0sT0FBTyxHQUFHLElBQUEsK0JBQXVCLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEQsTUFBTSxPQUFPLEdBQUcsSUFBQSwyQkFBbUIsRUFBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUU5RCxPQUFPO1FBQ0wsSUFBQSx1QkFBc0IsRUFBQyxPQUFPLEVBQUUsT0FBTyxDQUFDO1FBQ3hDLElBQUEsd0JBQXVCLEVBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQztRQUN6QyxJQUFBLHVCQUFzQixFQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDO0tBQ2pELENBQUMsR0FBRyxDQUNILElBQUksQ0FBQyxFQUFFLENBQ0wsSUFBSSw0QkFBZ0IsQ0FBQztRQUNuQixRQUFRLEVBQUUsV0FBVztRQUNyQixJQUFJO0tBQ0wsQ0FBQyxDQUNMLENBQUM7QUFDSixDQUFDIn0=
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SnowflakeConfig } from './tools';
|
|
2
|
+
export declare function assertValidAccountIdentifier(accountIdentifier: string): void;
|
|
3
|
+
export declare function getSnowflakeAuthHeaders(config: SnowflakeConfig): Record<string, string>;
|
|
4
|
+
export declare function getSnowflakeBaseUrl(accountIdentifier: string): string;
|
|
5
|
+
export declare function buildSessionContext(config: SnowflakeConfig): {
|
|
6
|
+
role: string;
|
|
7
|
+
schema: string;
|
|
8
|
+
database: string;
|
|
9
|
+
warehouse: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function assertReadOnlySql(statement: string): void;
|
|
12
|
+
export declare function assertResponseOk(response: Response, action: string): Promise<void>;
|
|
13
|
+
export declare function validateSnowflakeConfig(config: SnowflakeConfig): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertValidAccountIdentifier = assertValidAccountIdentifier;
|
|
4
|
+
exports.getSnowflakeAuthHeaders = getSnowflakeAuthHeaders;
|
|
5
|
+
exports.getSnowflakeBaseUrl = getSnowflakeBaseUrl;
|
|
6
|
+
exports.buildSessionContext = buildSessionContext;
|
|
7
|
+
exports.assertReadOnlySql = assertReadOnlySql;
|
|
8
|
+
exports.assertResponseOk = assertResponseOk;
|
|
9
|
+
exports.validateSnowflakeConfig = validateSnowflakeConfig;
|
|
10
|
+
const errors_1 = require("../../errors");
|
|
11
|
+
const READ_ONLY_LEADING_KEYWORD_RE = /^\s*(select|show|describe|desc|explain)\b/i;
|
|
12
|
+
const FORBIDDEN_KEYWORD_RE = /\b(insert|update|delete|merge|drop|create|alter|truncate|rename|undrop|swap|grant|revoke|call|execute|copy|put|get|use|set|unset|begin|commit|rollback|with)\b/i;
|
|
13
|
+
// Snowflake account identifiers are alphanumeric segments optionally separated by `.` or `-`
|
|
14
|
+
// (org-account or locator.region.cloud). Anything else could redirect URL building to an
|
|
15
|
+
// attacker-controlled host (e.g. `attack.com#` makes `#` start the URL fragment).
|
|
16
|
+
const ACCOUNT_IDENTIFIER_RE = /^[A-Za-z0-9_-]{1,128}(\.[A-Za-z0-9_-]{1,128}){0,3}$/;
|
|
17
|
+
function assertValidAccountIdentifier(accountIdentifier) {
|
|
18
|
+
if (typeof accountIdentifier !== 'string' || !ACCOUNT_IDENTIFIER_RE.test(accountIdentifier)) {
|
|
19
|
+
throw new errors_1.AIBadRequestError(`Invalid Snowflake account identifier: ${JSON.stringify(accountIdentifier)}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function getSnowflakeAuthHeaders(config) {
|
|
23
|
+
return {
|
|
24
|
+
Authorization: `Bearer ${config.programmaticAccessToken}`,
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
Accept: 'application/json',
|
|
27
|
+
'X-Snowflake-Authorization-Token-Type': 'PROGRAMMATIC_ACCESS_TOKEN',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function getSnowflakeBaseUrl(accountIdentifier) {
|
|
31
|
+
assertValidAccountIdentifier(accountIdentifier);
|
|
32
|
+
return `https://${accountIdentifier}.snowflakecomputing.com`;
|
|
33
|
+
}
|
|
34
|
+
function buildSessionContext(config) {
|
|
35
|
+
return {
|
|
36
|
+
...(config.defaultWarehouse && { warehouse: config.defaultWarehouse }),
|
|
37
|
+
...(config.defaultDatabase && { database: config.defaultDatabase }),
|
|
38
|
+
...(config.defaultSchema && { schema: config.defaultSchema }),
|
|
39
|
+
...(config.defaultRole && { role: config.defaultRole }),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Single-pass lexer: a regex pipeline cannot disambiguate `--` inside a string
|
|
43
|
+
// from a comment containing `'`, so it is unsafe for security checks.
|
|
44
|
+
function normalizeSql(statement) {
|
|
45
|
+
let result = '';
|
|
46
|
+
let i = 0;
|
|
47
|
+
while (i < statement.length) {
|
|
48
|
+
const c = statement[i];
|
|
49
|
+
const next = statement[i + 1];
|
|
50
|
+
if (c === '/' && next === '*') {
|
|
51
|
+
const end = statement.indexOf('*/', i + 2);
|
|
52
|
+
i = end === -1 ? statement.length : end + 2;
|
|
53
|
+
}
|
|
54
|
+
else if (c === '-' && next === '-') {
|
|
55
|
+
const end = statement.indexOf('\n', i + 2);
|
|
56
|
+
i = end === -1 ? statement.length : end;
|
|
57
|
+
}
|
|
58
|
+
else if (c === "'" || c === '"') {
|
|
59
|
+
result += c === "'" ? "''" : '""';
|
|
60
|
+
i += 1;
|
|
61
|
+
while (i < statement.length) {
|
|
62
|
+
if (statement[i] === c && statement[i + 1] === c) {
|
|
63
|
+
i += 2;
|
|
64
|
+
}
|
|
65
|
+
else if (statement[i] === c) {
|
|
66
|
+
i += 1;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
i += 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
result += c;
|
|
76
|
+
i += 1;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result.trim();
|
|
80
|
+
}
|
|
81
|
+
function assertReadOnlySql(statement) {
|
|
82
|
+
const normalized = normalizeSql(statement);
|
|
83
|
+
if (!normalized) {
|
|
84
|
+
throw new errors_1.AIBadRequestError('SQL statement is empty');
|
|
85
|
+
}
|
|
86
|
+
const withoutTrailingSemicolon = normalized.replace(/;\s*$/, '');
|
|
87
|
+
if (withoutTrailingSemicolon.includes(';')) {
|
|
88
|
+
throw new errors_1.AIBadRequestError('Only a single SQL statement is allowed. Multiple statements are not permitted.');
|
|
89
|
+
}
|
|
90
|
+
if (!READ_ONLY_LEADING_KEYWORD_RE.test(withoutTrailingSemicolon)) {
|
|
91
|
+
throw new errors_1.AIBadRequestError('Only read-only statements (SELECT, SHOW, DESCRIBE, EXPLAIN) are allowed.');
|
|
92
|
+
}
|
|
93
|
+
const forbiddenMatch = withoutTrailingSemicolon.match(FORBIDDEN_KEYWORD_RE);
|
|
94
|
+
if (forbiddenMatch) {
|
|
95
|
+
throw new errors_1.AIBadRequestError(`SQL statement contains a disallowed keyword: ${forbiddenMatch[0].toUpperCase()}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function extractErrorMessage(response) {
|
|
99
|
+
const fallback = response.statusText || 'Unknown error';
|
|
100
|
+
try {
|
|
101
|
+
const json = await response.json();
|
|
102
|
+
return json.message || json.error || json.code || fallback;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return fallback;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function assertResponseOk(response, action) {
|
|
109
|
+
if (response.ok)
|
|
110
|
+
return;
|
|
111
|
+
const errorMessage = await extractErrorMessage(response);
|
|
112
|
+
throw new errors_1.AIToolUnprocessableError(`Snowflake ${action} failed (${response.status}): ${errorMessage}`);
|
|
113
|
+
}
|
|
114
|
+
async function validateSnowflakeConfig(config) {
|
|
115
|
+
const baseUrl = getSnowflakeBaseUrl(config.accountIdentifier);
|
|
116
|
+
const headers = getSnowflakeAuthHeaders(config);
|
|
117
|
+
const body = {
|
|
118
|
+
statement: 'SELECT 1',
|
|
119
|
+
...buildSessionContext(config),
|
|
120
|
+
};
|
|
121
|
+
const url = `${baseUrl}/api/v2/statements`;
|
|
122
|
+
const response = await fetch(url, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
headers,
|
|
125
|
+
body: JSON.stringify(body),
|
|
126
|
+
});
|
|
127
|
+
if (response.ok)
|
|
128
|
+
return;
|
|
129
|
+
const errorMessage = await extractErrorMessage(response);
|
|
130
|
+
throw new errors_1.McpConnectionError(`Failed to validate Snowflake config (HTTP ${response.status} on ${url}): ${errorMessage}`);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW50ZWdyYXRpb25zL3Nub3dmbGFrZS91dGlscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVlBLG9FQU1DO0FBRUQsMERBT0M7QUFFRCxrREFJQztBQUVELGtEQU9DO0FBMkNELDhDQTRCQztBQWNELDRDQVFDO0FBRUQsMERBc0JDO0FBN0pELHlDQUErRjtBQUUvRixNQUFNLDRCQUE0QixHQUFHLDRDQUE0QyxDQUFDO0FBQ2xGLE1BQU0sb0JBQW9CLEdBQ3hCLGlLQUFpSyxDQUFDO0FBQ3BLLDZGQUE2RjtBQUM3Rix5RkFBeUY7QUFDekYsa0ZBQWtGO0FBQ2xGLE1BQU0scUJBQXFCLEdBQUcscURBQXFELENBQUM7QUFFcEYsU0FBZ0IsNEJBQTRCLENBQUMsaUJBQXlCO0lBQ3BFLElBQUksT0FBTyxpQkFBaUIsS0FBSyxRQUFRLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1FBQzVGLE1BQU0sSUFBSSwwQkFBaUIsQ0FDekIseUNBQXlDLElBQUksQ0FBQyxTQUFTLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUM3RSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUM7QUFFRCxTQUFnQix1QkFBdUIsQ0FBQyxNQUF1QjtJQUM3RCxPQUFPO1FBQ0wsYUFBYSxFQUFFLFVBQVUsTUFBTSxDQUFDLHVCQUF1QixFQUFFO1FBQ3pELGNBQWMsRUFBRSxrQkFBa0I7UUFDbEMsTUFBTSxFQUFFLGtCQUFrQjtRQUMxQixzQ0FBc0MsRUFBRSwyQkFBMkI7S0FDcEUsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFnQixtQkFBbUIsQ0FBQyxpQkFBeUI7SUFDM0QsNEJBQTRCLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUVoRCxPQUFPLFdBQVcsaUJBQWlCLHlCQUF5QixDQUFDO0FBQy9ELENBQUM7QUFFRCxTQUFnQixtQkFBbUIsQ0FBQyxN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
|