@perfai/mcp 1.0.24
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/LICENSE +21 -0
- package/README.md +352 -0
- package/dist/auth/authManager.d.ts +83 -0
- package/dist/auth/authManager.d.ts.map +1 -0
- package/dist/auth/authManager.js +555 -0
- package/dist/auth/sessionCache.d.ts +5 -0
- package/dist/auth/sessionCache.d.ts.map +1 -0
- package/dist/auth/sessionCache.js +29 -0
- package/dist/auth/sessionStorage.d.ts +53 -0
- package/dist/auth/sessionStorage.d.ts.map +1 -0
- package/dist/auth/sessionStorage.js +234 -0
- package/dist/auth/types.d.ts +28 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +1 -0
- package/dist/config.d.ts +65 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +74 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +144 -0
- package/dist/setup-config.d.ts +4 -0
- package/dist/setup-config.d.ts.map +1 -0
- package/dist/setup-config.js +69 -0
- package/dist/tools/index.d.ts +361 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +275 -0
- package/dist/tools/protected/aiFixDesignIssue.d.ts +17 -0
- package/dist/tools/protected/aiFixDesignIssue.d.ts.map +1 -0
- package/dist/tools/protected/aiFixDesignIssue.js +205 -0
- package/dist/tools/protected/aiFixQualityIssue.d.ts +17 -0
- package/dist/tools/protected/aiFixQualityIssue.d.ts.map +1 -0
- package/dist/tools/protected/aiFixQualityIssue.js +188 -0
- package/dist/tools/protected/aiFixSecurityIssue.d.ts +17 -0
- package/dist/tools/protected/aiFixSecurityIssue.d.ts.map +1 -0
- package/dist/tools/protected/aiFixSecurityIssue.js +205 -0
- package/dist/tools/protected/checkDesignFixes.d.ts +17 -0
- package/dist/tools/protected/checkDesignFixes.d.ts.map +1 -0
- package/dist/tools/protected/checkDesignFixes.js +199 -0
- package/dist/tools/protected/checkQualityFixes.d.ts +17 -0
- package/dist/tools/protected/checkQualityFixes.d.ts.map +1 -0
- package/dist/tools/protected/checkQualityFixes.js +199 -0
- package/dist/tools/protected/checkSecurityFixes.d.ts +17 -0
- package/dist/tools/protected/checkSecurityFixes.d.ts.map +1 -0
- package/dist/tools/protected/checkSecurityFixes.js +177 -0
- package/dist/tools/protected/listApis.d.ts +28 -0
- package/dist/tools/protected/listApis.d.ts.map +1 -0
- package/dist/tools/protected/listApis.js +102 -0
- package/dist/tools/protected/logout.d.ts +11 -0
- package/dist/tools/protected/logout.d.ts.map +1 -0
- package/dist/tools/protected/logout.js +22 -0
- package/dist/tools/protected/manageOrganizations.d.ts +26 -0
- package/dist/tools/protected/manageOrganizations.d.ts.map +1 -0
- package/dist/tools/protected/manageOrganizations.js +147 -0
- package/dist/tools/protected/runDesignTest.d.ts +21 -0
- package/dist/tools/protected/runDesignTest.d.ts.map +1 -0
- package/dist/tools/protected/runDesignTest.js +132 -0
- package/dist/tools/protected/runQualityTest.d.ts +21 -0
- package/dist/tools/protected/runQualityTest.d.ts.map +1 -0
- package/dist/tools/protected/runQualityTest.js +150 -0
- package/dist/tools/protected/runSecurityTest.d.ts +21 -0
- package/dist/tools/protected/runSecurityTest.d.ts.map +1 -0
- package/dist/tools/protected/runSecurityTest.js +107 -0
- package/dist/tools/protected/selectApi.d.ts +24 -0
- package/dist/tools/protected/selectApi.d.ts.map +1 -0
- package/dist/tools/protected/selectApi.js +172 -0
- package/dist/tools/protected/setup.d.ts +11 -0
- package/dist/tools/protected/setup.d.ts.map +1 -0
- package/dist/tools/protected/setup.js +151 -0
- package/dist/tools/protected/showDesignIssues.d.ts +38 -0
- package/dist/tools/protected/showDesignIssues.d.ts.map +1 -0
- package/dist/tools/protected/showDesignIssues.js +201 -0
- package/dist/tools/protected/showFixedIssues.d.ts +11 -0
- package/dist/tools/protected/showFixedIssues.d.ts.map +1 -0
- package/dist/tools/protected/showFixedIssues.js +36 -0
- package/dist/tools/protected/showQualityIssues.d.ts +33 -0
- package/dist/tools/protected/showQualityIssues.d.ts.map +1 -0
- package/dist/tools/protected/showQualityIssues.js +225 -0
- package/dist/tools/protected/showSecurityIssues.d.ts +47 -0
- package/dist/tools/protected/showSecurityIssues.d.ts.map +1 -0
- package/dist/tools/protected/showSecurityIssues.js +212 -0
- package/dist/tools/protected/summarizeIssues.d.ts +11 -0
- package/dist/tools/protected/summarizeIssues.d.ts.map +1 -0
- package/dist/tools/protected/summarizeIssues.js +161 -0
- package/dist/tools/protected/userInfo.d.ts +11 -0
- package/dist/tools/protected/userInfo.d.ts.map +1 -0
- package/dist/tools/protected/userInfo.js +21 -0
- package/dist/tools/protected/visionAiAppLearning.d.ts +37 -0
- package/dist/tools/protected/visionAiAppLearning.d.ts.map +1 -0
- package/dist/tools/protected/visionAiAppLearning.js +122 -0
- package/dist/tools/public/authStatus.d.ts +11 -0
- package/dist/tools/public/authStatus.d.ts.map +1 -0
- package/dist/tools/public/authStatus.js +78 -0
- package/dist/tools/public/login.d.ts +12 -0
- package/dist/tools/public/login.d.ts.map +1 -0
- package/dist/tools/public/login.js +230 -0
- package/dist/types/api.d.ts +12 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +1 -0
- package/dist/utils/dockerRunner.d.ts +44 -0
- package/dist/utils/dockerRunner.d.ts.map +1 -0
- package/dist/utils/dockerRunner.js +300 -0
- package/dist/utils/formatters.d.ts +14 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +510 -0
- package/dist/utils/promptBuilder.d.ts +4 -0
- package/dist/utils/promptBuilder.d.ts.map +1 -0
- package/dist/utils/promptBuilder.js +132 -0
- package/package.json +67 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const listApisTool: {
|
|
2
|
+
readonly name: "list_apps";
|
|
3
|
+
readonly description: "š List all apps in table format (Seq, App Name, Label) - supports filtering by name, environment, and pagination (requires authentication)";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly search: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Filter apps by name or label (optional)";
|
|
10
|
+
};
|
|
11
|
+
readonly environment: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly description: "Filter by environment e.g. 'production', 'staging' (optional)";
|
|
14
|
+
};
|
|
15
|
+
readonly page: {
|
|
16
|
+
readonly type: "number";
|
|
17
|
+
readonly description: "Page number for pagination (default: 1)";
|
|
18
|
+
};
|
|
19
|
+
readonly limit: {
|
|
20
|
+
readonly type: "number";
|
|
21
|
+
readonly description: "Number of apps per page (default: 50, max: 200)";
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
readonly additionalProperties: false;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare function handleListApis(authManager: any, args?: any): Promise<any>;
|
|
28
|
+
//# sourceMappingURL=listApis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listApis.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/listApis.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;CAyBf,CAAC;AAEX,wBAAsB,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,GAAE,GAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAoFnF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { API_ENDPOINTS } from "../../config.js";
|
|
3
|
+
import { formatAppList } from "../../utils/formatters.js";
|
|
4
|
+
export const listApisTool = {
|
|
5
|
+
name: "list_apps",
|
|
6
|
+
description: "š List all apps in table format (Seq, App Name, Label) - supports filtering by name, environment, and pagination (requires authentication)",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
search: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Filter apps by name or label (optional)"
|
|
13
|
+
},
|
|
14
|
+
environment: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Filter by environment e.g. 'production', 'staging' (optional)"
|
|
17
|
+
},
|
|
18
|
+
page: {
|
|
19
|
+
type: "number",
|
|
20
|
+
description: "Page number for pagination (default: 1)"
|
|
21
|
+
},
|
|
22
|
+
limit: {
|
|
23
|
+
type: "number",
|
|
24
|
+
description: "Number of apps per page (default: 50, max: 200)"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
additionalProperties: false,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
export async function handleListApis(authManager, args = {}) {
|
|
31
|
+
try {
|
|
32
|
+
const accessToken = authManager.getAccessToken();
|
|
33
|
+
const tokenType = authManager.getTokenType();
|
|
34
|
+
const orgId = authManager.getSelectedOrgId();
|
|
35
|
+
const search = args.search?.trim();
|
|
36
|
+
const environment = args.environment?.trim();
|
|
37
|
+
const page = args.page && args.page >= 1 ? Math.floor(args.page) : 1;
|
|
38
|
+
const limit = args.limit ? Math.min(Math.max(1, Math.floor(args.limit)), 200) : 50;
|
|
39
|
+
console.error('š Debug listApis:');
|
|
40
|
+
console.error(' - Access token:', accessToken ? 'Present' : 'Missing');
|
|
41
|
+
console.error(' - Org ID:', orgId || 'Missing');
|
|
42
|
+
console.error(' - Filters: search=%s environment=%s page=%d limit=%d', search, environment, page, limit);
|
|
43
|
+
if (!accessToken) {
|
|
44
|
+
throw new Error('No access token available');
|
|
45
|
+
}
|
|
46
|
+
if (!orgId) {
|
|
47
|
+
throw new Error('No organization selected. Please select an organization first using manage_organizations tool.');
|
|
48
|
+
}
|
|
49
|
+
// Build URL with all supported query params
|
|
50
|
+
const params = new URLSearchParams();
|
|
51
|
+
params.set('page', String(page));
|
|
52
|
+
params.set('limit', String(limit));
|
|
53
|
+
if (search)
|
|
54
|
+
params.set('search', search);
|
|
55
|
+
if (environment)
|
|
56
|
+
params.set('environment', environment);
|
|
57
|
+
const url = `${API_ENDPOINTS.API_CATALOG}?${params.toString()}`;
|
|
58
|
+
console.error('š” Request: GET', url);
|
|
59
|
+
const response = await axios.get(url, {
|
|
60
|
+
headers: {
|
|
61
|
+
'Authorization': `${tokenType} ${accessToken}`,
|
|
62
|
+
'Content-Type': 'application/json',
|
|
63
|
+
'X-Org-ID': orgId
|
|
64
|
+
},
|
|
65
|
+
timeout: 30000
|
|
66
|
+
});
|
|
67
|
+
console.error('ā
Response status:', response.status);
|
|
68
|
+
if (response.status !== 200 || !response.data) {
|
|
69
|
+
throw new Error(`APP request failed with status ${response.status}`);
|
|
70
|
+
}
|
|
71
|
+
const responseBody = response.data;
|
|
72
|
+
const apis = Array.isArray(responseBody) ? responseBody : (responseBody?.data ?? responseBody);
|
|
73
|
+
const totalCount = responseBody?.total;
|
|
74
|
+
const hasMore = responseBody?.hasMore ?? (apis.length >= limit);
|
|
75
|
+
const selectedApiId = authManager.getSelectedApiId();
|
|
76
|
+
const selectedApiData = authManager.getSelectedApiData();
|
|
77
|
+
const formattedText = formatAppList(apis, orgId, authManager.getUserInfo(), selectedApiId, selectedApiData, authManager, { search, environment, page, limit, totalCount, hasMore });
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: formattedText,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error?.response) {
|
|
89
|
+
console.error('ā Response status:', error.response.status);
|
|
90
|
+
console.error('ā Response data:', JSON.stringify(error.response.data, null, 2));
|
|
91
|
+
}
|
|
92
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
93
|
+
return {
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
96
|
+
type: "text",
|
|
97
|
+
text: `ā **Error fetching apps**\n\nš“ **Error**: ${errorMessage}\n\nš” **Tip**: Make sure you're authenticated and have an organization selected.\n\nš **Try**: Using manage_organizations tool first to select an organization.`,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const logoutTool: {
|
|
2
|
+
readonly name: "logout";
|
|
3
|
+
readonly description: "šŖ Logout from PerfAI and clear authentication session";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {};
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export declare function handleLogout(authManager: any): Promise<any>;
|
|
11
|
+
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/logout.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;;;;CAQb,CAAC;AAEX,wBAAsB,YAAY,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAcjE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const logoutTool = {
|
|
2
|
+
name: "logout",
|
|
3
|
+
description: "šŖ Logout from PerfAI and clear authentication session",
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object",
|
|
6
|
+
properties: {},
|
|
7
|
+
additionalProperties: false,
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
export async function handleLogout(authManager) {
|
|
11
|
+
const userInfo = authManager.getUserInfo();
|
|
12
|
+
const userEmail = userInfo?.email || 'Unknown user';
|
|
13
|
+
authManager.clearSession();
|
|
14
|
+
return {
|
|
15
|
+
content: [
|
|
16
|
+
{
|
|
17
|
+
type: "text",
|
|
18
|
+
text: `šŖ **Logged Out Successfully**\n\nš Goodbye ${userEmail}!\n\nš Your session has been cleared. To access protected tools again, please run the 'login' tool.\n\nš **Available tools:** Only 'login' and 'auth_status' are now accessible.`,
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const manageOrganizationsTool: {
|
|
2
|
+
readonly name: "manage_organizations";
|
|
3
|
+
readonly description: "š¢ List and manage organizations (requires authentication). Use action=select with sequence (number from the list) or org_id.";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly action: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly enum: readonly ["list", "select", "refresh"];
|
|
10
|
+
readonly description: "Action to perform: list (show orgs), select (choose org by sequence or org_id), refresh (fetch orgs again)";
|
|
11
|
+
readonly default: "list";
|
|
12
|
+
};
|
|
13
|
+
readonly sequence: {
|
|
14
|
+
readonly type: "number";
|
|
15
|
+
readonly description: "Sequence number from the list output (use this instead of org_id)";
|
|
16
|
+
};
|
|
17
|
+
readonly org_id: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Organization ID to select ā use sequence instead when possible";
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
readonly additionalProperties: false;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare function handleManageOrganizations(authManager: any, args: any): Promise<any>;
|
|
26
|
+
//# sourceMappingURL=manageOrganizations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manageOrganizations.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/manageOrganizations.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;CAuB1B,CAAC;AAEX,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAoIzF"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { API_ENDPOINTS } from "../../config.js";
|
|
3
|
+
import { formatOrganizations } from "../../utils/formatters.js";
|
|
4
|
+
export const manageOrganizationsTool = {
|
|
5
|
+
name: "manage_organizations",
|
|
6
|
+
description: "š¢ List and manage organizations (requires authentication). Use action=select with sequence (number from the list) or org_id.",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
action: {
|
|
11
|
+
type: "string",
|
|
12
|
+
enum: ["list", "select", "refresh"],
|
|
13
|
+
description: "Action to perform: list (show orgs), select (choose org by sequence or org_id), refresh (fetch orgs again)",
|
|
14
|
+
default: "list"
|
|
15
|
+
},
|
|
16
|
+
sequence: {
|
|
17
|
+
type: "number",
|
|
18
|
+
description: "Sequence number from the list output (use this instead of org_id)"
|
|
19
|
+
},
|
|
20
|
+
org_id: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Organization ID to select ā use sequence instead when possible"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export async function handleManageOrganizations(authManager, args) {
|
|
29
|
+
try {
|
|
30
|
+
const action = args.action || "list";
|
|
31
|
+
const orgId = args.org_id;
|
|
32
|
+
if (action === "refresh") {
|
|
33
|
+
// Re-fetch organizations
|
|
34
|
+
try {
|
|
35
|
+
const accessToken = authManager.getAccessToken();
|
|
36
|
+
const tokenType = authManager.getTokenType();
|
|
37
|
+
if (!accessToken) {
|
|
38
|
+
throw new Error('No access token available');
|
|
39
|
+
}
|
|
40
|
+
const orgResponse = await axios.get(API_ENDPOINTS.ORGANIZATIONS, {
|
|
41
|
+
headers: { Authorization: `${tokenType} ${accessToken}` }
|
|
42
|
+
});
|
|
43
|
+
const organizations = orgResponse.data.data?.userOrgs || [];
|
|
44
|
+
const currentOrgId = orgResponse.data.data?.currentOrg;
|
|
45
|
+
// Update session with fresh org data
|
|
46
|
+
if (authManager.session) {
|
|
47
|
+
authManager.session.organizations = organizations;
|
|
48
|
+
authManager.session.selectedOrgId = currentOrgId || organizations[0]?.org_id;
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: `š **Organizations Refreshed**\n\nš **Found**: ${organizations.length} organizations\nšÆ **Selected**: ${authManager.session?.selectedOrgId}\n\n${organizations.length > 0 ? 'ā
Organization data updated successfully!' : 'ā ļø No organizations found - you may need to check your account permissions.'}`,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return {
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
63
|
+
type: "text",
|
|
64
|
+
text: `ā **Failed to refresh organizations**\n\nš“ **Error**: ${error instanceof Error ? error.message : String(error)}\n\nš” **Tip**: Check your authentication and network connection.`,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (action === "select") {
|
|
71
|
+
const sequence = args.sequence;
|
|
72
|
+
if (!sequence && !orgId) {
|
|
73
|
+
return {
|
|
74
|
+
content: [
|
|
75
|
+
{
|
|
76
|
+
type: "text",
|
|
77
|
+
text: `ā **Selection Required**\n\nš“ **Error**: Provide a sequence number or org_id when using action=select\n\nš” **Examples**:\n⢠\`manage_organizations {"action": "select", "sequence": 1}\`\n⢠\`manage_organizations {"action": "select", "org_id": "<id>"}\`\n\nRun \`manage_organizations\` (action=list) first to see sequence numbers.`,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const organizations = authManager.getOrganizations();
|
|
83
|
+
let selectedOrg;
|
|
84
|
+
if (sequence) {
|
|
85
|
+
// Resolve by 1-based sequence number
|
|
86
|
+
selectedOrg = organizations[sequence - 1];
|
|
87
|
+
if (!selectedOrg) {
|
|
88
|
+
return {
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: "text",
|
|
92
|
+
text: `ā **Invalid Sequence**\n\nš“ **Error**: Sequence '${sequence}' not found (${organizations.length} org${organizations.length !== 1 ? 's' : ''} available)\n\nš” **Tip**: Run 'manage_organizations' without arguments to see the list.`,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
selectedOrg = organizations.find((org) => org.org_id === orgId);
|
|
100
|
+
if (!selectedOrg) {
|
|
101
|
+
const availableOrgIds = organizations.map((org) => org.org_id).join(', ');
|
|
102
|
+
return {
|
|
103
|
+
content: [
|
|
104
|
+
{
|
|
105
|
+
type: "text",
|
|
106
|
+
text: `ā **Organization Not Found**\n\nš“ **Error**: Organization '${orgId}' not found\n\nš **Available**: ${availableOrgIds || 'None'}\n\nš” **Tip**: Use action=refresh to update organization list`,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const resolvedOrgId = selectedOrg.org_id;
|
|
113
|
+
authManager.setSelectedOrgId(resolvedOrgId);
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: `ā
**Organization Selected**\n\nš¢ **Name**: ${selectedOrg.orgDetails?.name || 'Unknown'}\nš **ID**: ${resolvedOrgId}\n\nš **Status**: Now using this organization for app requests\nš ļø **Ready**: You can now use list_apps and other org-specific tools!`,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Default action: list
|
|
124
|
+
const organizations = authManager.getOrganizations();
|
|
125
|
+
const selectedOrgId = authManager.getSelectedOrgId();
|
|
126
|
+
const formattedText = formatOrganizations(organizations, selectedOrgId);
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "text",
|
|
131
|
+
text: formattedText,
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
138
|
+
return {
|
|
139
|
+
content: [
|
|
140
|
+
{
|
|
141
|
+
type: "text",
|
|
142
|
+
text: `ā **Organization Management Error**\n\nš“ **Error**: ${errorMessage}\n\nš” **Tip**: Make sure you're authenticated and try again.`,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const runDesignTestTool: {
|
|
2
|
+
readonly name: "run_design_test";
|
|
3
|
+
readonly description: "š Run comprehensive design analysis test using Docker (requires authentication and APP selection)";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly spec_url: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "URL to OpenAPI spec";
|
|
10
|
+
};
|
|
11
|
+
readonly local_base_path: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly description: "Base URL of your basepath";
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
readonly required: readonly ["spec_url", "local_base_path"];
|
|
17
|
+
readonly additionalProperties: true;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function handleRunDesignTest(authManager: any, args: any): Promise<any>;
|
|
21
|
+
//# sourceMappingURL=runDesignTest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runDesignTest.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/runDesignTest.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAkBpB,CAAC;AAEX,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CA2HnF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { runDockerDesignTest } from "../../utils/dockerRunner.js";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { API_ENDPOINTS } from "../../config.js";
|
|
4
|
+
export const runDesignTestTool = {
|
|
5
|
+
name: "run_design_test",
|
|
6
|
+
description: "š Run comprehensive design analysis test using Docker (requires authentication and APP selection)",
|
|
7
|
+
inputSchema: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
spec_url: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "URL to OpenAPI spec"
|
|
13
|
+
},
|
|
14
|
+
local_base_path: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Base URL of your basepath"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
required: ["spec_url", "local_base_path"],
|
|
20
|
+
additionalProperties: true,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
export async function handleRunDesignTest(authManager, args) {
|
|
24
|
+
try {
|
|
25
|
+
const specUrl = args.spec_url;
|
|
26
|
+
const localBasePath = args.local_base_path;
|
|
27
|
+
const accessToken = authManager.getAccessToken();
|
|
28
|
+
const tokenType = authManager.getTokenType();
|
|
29
|
+
const orgId = authManager.getSelectedOrgId();
|
|
30
|
+
const selectedAppId = authManager.getSelectedApiId();
|
|
31
|
+
if (!accessToken) {
|
|
32
|
+
throw new Error('No access token available');
|
|
33
|
+
}
|
|
34
|
+
if (!orgId) {
|
|
35
|
+
throw new Error('No organization selected. Please select an organization first using manage_organizations tool.');
|
|
36
|
+
}
|
|
37
|
+
if (!selectedAppId) {
|
|
38
|
+
return {
|
|
39
|
+
content: [
|
|
40
|
+
{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: `ā **No APP Selected**\n\nšÆ **Required**: You must select an APP first to run design tests.\n\nš **Steps**:\n1. Run \`list_apps\` to see available APPs\n2. Run \`select_app\` with an APP ID\n3. Run \`show_design_issues\` to get the design app ID\n4. Then run this tool again`,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// First, get the app details using the catalog ID to get the design app ID
|
|
48
|
+
const catalogUrl = `${API_ENDPOINTS.API_CATALOG_SERVICE_IDS}/${selectedAppId}`;
|
|
49
|
+
let appDetails;
|
|
50
|
+
try {
|
|
51
|
+
const catalogResponse = await axios.get(catalogUrl, {
|
|
52
|
+
headers: {
|
|
53
|
+
'Authorization': `${tokenType} ${accessToken}`,
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
'X-Org-ID': orgId
|
|
56
|
+
},
|
|
57
|
+
timeout: 30000
|
|
58
|
+
});
|
|
59
|
+
if (catalogResponse.status !== 200 || !catalogResponse.data) {
|
|
60
|
+
throw new Error(`Failed to fetch app details with status ${catalogResponse.status}`);
|
|
61
|
+
}
|
|
62
|
+
appDetails = catalogResponse.data;
|
|
63
|
+
if (!appDetails.design_test_appId) {
|
|
64
|
+
throw new Error('No design_test_appId found for this app');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: "text",
|
|
73
|
+
text: `ā **Error fetching app details**\n\nš“ **Error**: ${errorMessage}\n\nš” **Tip**: Make sure the selected app has design testing enabled.`,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Use the design_test_appId for running design tests
|
|
79
|
+
const designAppId = appDetails.design_test_appId;
|
|
80
|
+
if (!specUrl) {
|
|
81
|
+
throw new Error('Spec URL is required');
|
|
82
|
+
}
|
|
83
|
+
if (!localBasePath) {
|
|
84
|
+
throw new Error('Local base path is required');
|
|
85
|
+
}
|
|
86
|
+
// Validate URLs
|
|
87
|
+
try {
|
|
88
|
+
new URL(specUrl);
|
|
89
|
+
new URL(localBasePath);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new Error('Invalid URL format. Please provide valid URLs for spec_url and local_base_path');
|
|
93
|
+
}
|
|
94
|
+
// Run Docker design test using the selected app ID
|
|
95
|
+
console.error('š Running Docker design test...');
|
|
96
|
+
const result = await runDockerDesignTest({
|
|
97
|
+
apiId: designAppId,
|
|
98
|
+
orgId,
|
|
99
|
+
accessToken,
|
|
100
|
+
specUrl,
|
|
101
|
+
localBasePath
|
|
102
|
+
});
|
|
103
|
+
// Wait 40 seconds for the system to process and update design issues
|
|
104
|
+
console.error('ā³ Waiting 40 seconds for system to process design issues...');
|
|
105
|
+
await new Promise(resolve => setTimeout(resolve, 40000));
|
|
106
|
+
console.error('ā
Wait completed, design issues should be processed');
|
|
107
|
+
// Create response based on Docker test result
|
|
108
|
+
const dockerStatus = result.success ? 'ā
**Docker Test**: Completed Successfully' : 'ā **Docker Test**: Failed';
|
|
109
|
+
const dockerOutput = result.success
|
|
110
|
+
? `š **Test Output**:\n\`\`\`\n${result.output || 'Test completed - check your PerfAI dashboard for results'}\n\`\`\``
|
|
111
|
+
: `š **Error Output**:\n\`\`\`\n${result.errors || 'Unknown error occurred'}\n\`\`\``;
|
|
112
|
+
return {
|
|
113
|
+
content: [
|
|
114
|
+
{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `š **Design Test Results**\n\n${dockerStatus}\n\nšÆ **APP**: ${selectedAppId}\nšØ **Spec URL**: ${specUrl}\nš **Base Path**: ${localBasePath}\nš¢ **Organization**: ${orgId}\n\n${dockerOutput}\n\nā³ **Processing Wait**: System waited 40 seconds after Docker test completion to ensure design issues were fully processed and updated.\n\nā
**Status**: Design analysis completed. Results should be available in your PerfAI dashboard.\n\nš” **Next Steps**:\n1. Check your PerfAI dashboard for detailed results\n2. Use \`show_design_issues\` to see any new issues found\n3. Use \`ai_fix_design_issue\` to generate fixes for remaining issues\n4. Use \`check_design_fixes\` to verify which previously fixed issues were actually resolved`,
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
123
|
+
return {
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: `ā **Error running design test**\n\nš“ **Error**: ${errorMessage}\n\nš” **Tip**: Make sure you're authenticated, have an organization selected, and provided valid URLs.\n\nš **Try**: Check your inputs and try again.`,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const runQualityTestTool: {
|
|
2
|
+
readonly name: "run_quality_test";
|
|
3
|
+
readonly description: "š Run comprehensive quality/specification validation analysis test using Docker (requires authentication and APP selection)";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly spec_url: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "URL to OpenAPI spec";
|
|
10
|
+
};
|
|
11
|
+
readonly local_base_path: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly description: "Base URL of your basepath";
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
readonly required: readonly ["spec_url", "local_base_path"];
|
|
17
|
+
readonly additionalProperties: true;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function handleRunQualityTest(authManager: any, args: any): Promise<any>;
|
|
21
|
+
//# sourceMappingURL=runQualityTest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runQualityTest.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/runQualityTest.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;CAkBrB,CAAC;AAEX,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CA+IpF"}
|