@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.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +352 -0
  3. package/dist/auth/authManager.d.ts +83 -0
  4. package/dist/auth/authManager.d.ts.map +1 -0
  5. package/dist/auth/authManager.js +555 -0
  6. package/dist/auth/sessionCache.d.ts +5 -0
  7. package/dist/auth/sessionCache.d.ts.map +1 -0
  8. package/dist/auth/sessionCache.js +29 -0
  9. package/dist/auth/sessionStorage.d.ts +53 -0
  10. package/dist/auth/sessionStorage.d.ts.map +1 -0
  11. package/dist/auth/sessionStorage.js +234 -0
  12. package/dist/auth/types.d.ts +28 -0
  13. package/dist/auth/types.d.ts.map +1 -0
  14. package/dist/auth/types.js +1 -0
  15. package/dist/config.d.ts +65 -0
  16. package/dist/config.d.ts.map +1 -0
  17. package/dist/config.js +74 -0
  18. package/dist/server.d.ts +3 -0
  19. package/dist/server.d.ts.map +1 -0
  20. package/dist/server.js +144 -0
  21. package/dist/setup-config.d.ts +4 -0
  22. package/dist/setup-config.d.ts.map +1 -0
  23. package/dist/setup-config.js +69 -0
  24. package/dist/tools/index.d.ts +361 -0
  25. package/dist/tools/index.d.ts.map +1 -0
  26. package/dist/tools/index.js +275 -0
  27. package/dist/tools/protected/aiFixDesignIssue.d.ts +17 -0
  28. package/dist/tools/protected/aiFixDesignIssue.d.ts.map +1 -0
  29. package/dist/tools/protected/aiFixDesignIssue.js +205 -0
  30. package/dist/tools/protected/aiFixQualityIssue.d.ts +17 -0
  31. package/dist/tools/protected/aiFixQualityIssue.d.ts.map +1 -0
  32. package/dist/tools/protected/aiFixQualityIssue.js +188 -0
  33. package/dist/tools/protected/aiFixSecurityIssue.d.ts +17 -0
  34. package/dist/tools/protected/aiFixSecurityIssue.d.ts.map +1 -0
  35. package/dist/tools/protected/aiFixSecurityIssue.js +205 -0
  36. package/dist/tools/protected/checkDesignFixes.d.ts +17 -0
  37. package/dist/tools/protected/checkDesignFixes.d.ts.map +1 -0
  38. package/dist/tools/protected/checkDesignFixes.js +199 -0
  39. package/dist/tools/protected/checkQualityFixes.d.ts +17 -0
  40. package/dist/tools/protected/checkQualityFixes.d.ts.map +1 -0
  41. package/dist/tools/protected/checkQualityFixes.js +199 -0
  42. package/dist/tools/protected/checkSecurityFixes.d.ts +17 -0
  43. package/dist/tools/protected/checkSecurityFixes.d.ts.map +1 -0
  44. package/dist/tools/protected/checkSecurityFixes.js +177 -0
  45. package/dist/tools/protected/listApis.d.ts +28 -0
  46. package/dist/tools/protected/listApis.d.ts.map +1 -0
  47. package/dist/tools/protected/listApis.js +102 -0
  48. package/dist/tools/protected/logout.d.ts +11 -0
  49. package/dist/tools/protected/logout.d.ts.map +1 -0
  50. package/dist/tools/protected/logout.js +22 -0
  51. package/dist/tools/protected/manageOrganizations.d.ts +26 -0
  52. package/dist/tools/protected/manageOrganizations.d.ts.map +1 -0
  53. package/dist/tools/protected/manageOrganizations.js +147 -0
  54. package/dist/tools/protected/runDesignTest.d.ts +21 -0
  55. package/dist/tools/protected/runDesignTest.d.ts.map +1 -0
  56. package/dist/tools/protected/runDesignTest.js +132 -0
  57. package/dist/tools/protected/runQualityTest.d.ts +21 -0
  58. package/dist/tools/protected/runQualityTest.d.ts.map +1 -0
  59. package/dist/tools/protected/runQualityTest.js +150 -0
  60. package/dist/tools/protected/runSecurityTest.d.ts +21 -0
  61. package/dist/tools/protected/runSecurityTest.d.ts.map +1 -0
  62. package/dist/tools/protected/runSecurityTest.js +107 -0
  63. package/dist/tools/protected/selectApi.d.ts +24 -0
  64. package/dist/tools/protected/selectApi.d.ts.map +1 -0
  65. package/dist/tools/protected/selectApi.js +172 -0
  66. package/dist/tools/protected/setup.d.ts +11 -0
  67. package/dist/tools/protected/setup.d.ts.map +1 -0
  68. package/dist/tools/protected/setup.js +151 -0
  69. package/dist/tools/protected/showDesignIssues.d.ts +38 -0
  70. package/dist/tools/protected/showDesignIssues.d.ts.map +1 -0
  71. package/dist/tools/protected/showDesignIssues.js +201 -0
  72. package/dist/tools/protected/showFixedIssues.d.ts +11 -0
  73. package/dist/tools/protected/showFixedIssues.d.ts.map +1 -0
  74. package/dist/tools/protected/showFixedIssues.js +36 -0
  75. package/dist/tools/protected/showQualityIssues.d.ts +33 -0
  76. package/dist/tools/protected/showQualityIssues.d.ts.map +1 -0
  77. package/dist/tools/protected/showQualityIssues.js +225 -0
  78. package/dist/tools/protected/showSecurityIssues.d.ts +47 -0
  79. package/dist/tools/protected/showSecurityIssues.d.ts.map +1 -0
  80. package/dist/tools/protected/showSecurityIssues.js +212 -0
  81. package/dist/tools/protected/summarizeIssues.d.ts +11 -0
  82. package/dist/tools/protected/summarizeIssues.d.ts.map +1 -0
  83. package/dist/tools/protected/summarizeIssues.js +161 -0
  84. package/dist/tools/protected/userInfo.d.ts +11 -0
  85. package/dist/tools/protected/userInfo.d.ts.map +1 -0
  86. package/dist/tools/protected/userInfo.js +21 -0
  87. package/dist/tools/protected/visionAiAppLearning.d.ts +37 -0
  88. package/dist/tools/protected/visionAiAppLearning.d.ts.map +1 -0
  89. package/dist/tools/protected/visionAiAppLearning.js +122 -0
  90. package/dist/tools/public/authStatus.d.ts +11 -0
  91. package/dist/tools/public/authStatus.d.ts.map +1 -0
  92. package/dist/tools/public/authStatus.js +78 -0
  93. package/dist/tools/public/login.d.ts +12 -0
  94. package/dist/tools/public/login.d.ts.map +1 -0
  95. package/dist/tools/public/login.js +230 -0
  96. package/dist/types/api.d.ts +12 -0
  97. package/dist/types/api.d.ts.map +1 -0
  98. package/dist/types/api.js +1 -0
  99. package/dist/utils/dockerRunner.d.ts +44 -0
  100. package/dist/utils/dockerRunner.d.ts.map +1 -0
  101. package/dist/utils/dockerRunner.js +300 -0
  102. package/dist/utils/formatters.d.ts +14 -0
  103. package/dist/utils/formatters.d.ts.map +1 -0
  104. package/dist/utils/formatters.js +510 -0
  105. package/dist/utils/promptBuilder.d.ts +4 -0
  106. package/dist/utils/promptBuilder.d.ts.map +1 -0
  107. package/dist/utils/promptBuilder.js +132 -0
  108. package/package.json +67 -0
@@ -0,0 +1,199 @@
1
+ import axios from "axios";
2
+ import { API_ENDPOINTS } from "../../config.js";
3
+ // Function to compare fixed design issues with current design issues
4
+ function compareAndCountFixedDesignIssues(previousIssues, currentIssues) {
5
+ let fixedCount = 0;
6
+ const fixedIssues = [];
7
+ const stillExistsIssues = [];
8
+ // Loop through each design issue we attempted to fix
9
+ for (const previousIssue of previousIssues) {
10
+ // Check if this previous issue still exists in current issues
11
+ const stillExists = currentIssues.some((currentIssue) => currentIssue.method === previousIssue.method &&
12
+ currentIssue.path === previousIssue.path &&
13
+ currentIssue.category === previousIssue.category);
14
+ // If the issue no longer exists in current issues, it was fixed
15
+ if (!stillExists) {
16
+ fixedCount++;
17
+ fixedIssues.push(previousIssue);
18
+ }
19
+ else {
20
+ stillExistsIssues.push(previousIssue);
21
+ }
22
+ }
23
+ return { fixedCount, fixedIssues, stillExistsIssues };
24
+ }
25
+ // Function to fetch current design issues
26
+ async function fetchDesignIssues(accessToken, tokenType, orgId, designAppId) {
27
+ const url = `${API_ENDPOINTS.DESIGN_ISSUES_BY_APP}?app_id=${encodeURIComponent(designAppId)}&limit=100`;
28
+ const response = await axios.get(url, {
29
+ headers: {
30
+ 'Authorization': `${tokenType} ${accessToken}`,
31
+ 'Content-Type': 'application/json',
32
+ 'X-Org-ID': orgId
33
+ },
34
+ timeout: 30000
35
+ });
36
+ if (response.status !== 200 || !response.data) {
37
+ throw new Error(`Failed to fetch design issues: ${response.status}`);
38
+ }
39
+ return response.data.issues || [];
40
+ }
41
+ export const checkDesignFixesTool = {
42
+ name: "check_design_fixes",
43
+ description: "šŸ” Check which previously fixed design issues were actually resolved (auto-triggered after run_design_test)",
44
+ inputSchema: {
45
+ type: "object",
46
+ properties: {
47
+ wait_seconds: {
48
+ type: "number",
49
+ description: "Wait time before checking issues (default: 15 seconds)",
50
+ default: 15
51
+ }
52
+ },
53
+ additionalProperties: false,
54
+ },
55
+ };
56
+ export async function handleCheckDesignFixes(authManager, args) {
57
+ try {
58
+ const waitSeconds = args.wait_seconds || 15;
59
+ const accessToken = authManager.getAccessToken();
60
+ const tokenType = authManager.getTokenType();
61
+ const orgId = authManager.getSelectedOrgId();
62
+ const selectedAppId = authManager.getSelectedApiId();
63
+ if (!accessToken) {
64
+ throw new Error('No access token available');
65
+ }
66
+ if (!orgId) {
67
+ throw new Error('No organization selected. Please select an organization first using manage_organizations tool.');
68
+ }
69
+ if (!selectedAppId) {
70
+ return {
71
+ content: [
72
+ {
73
+ type: "text",
74
+ text: `āŒ **No APP Selected**\n\nšŸŽÆ **Required**: You must select an APP first to check design fixes.\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 see design issues\n4. Then run this tool again`,
75
+ },
76
+ ],
77
+ };
78
+ }
79
+ // First, get the app details using the catalog ID to get the design app ID
80
+ const catalogUrl = `${API_ENDPOINTS.API_CATALOG_SERVICE_IDS}/${selectedAppId}`;
81
+ let appDetails;
82
+ try {
83
+ const catalogResponse = await axios.get(catalogUrl, {
84
+ headers: {
85
+ 'Authorization': `${tokenType} ${accessToken}`,
86
+ 'Content-Type': 'application/json',
87
+ 'X-Org-ID': orgId
88
+ },
89
+ timeout: 30000
90
+ });
91
+ if (catalogResponse.status !== 200 || !catalogResponse.data) {
92
+ throw new Error(`Failed to fetch app details with status ${catalogResponse.status}`);
93
+ }
94
+ appDetails = catalogResponse.data;
95
+ if (!appDetails.design_test_appId) {
96
+ throw new Error('No design_test_appId found for this app');
97
+ }
98
+ }
99
+ catch (error) {
100
+ const errorMessage = error instanceof Error ? error.message : String(error);
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: `āŒ **Error fetching app details**\n\nšŸ”“ **Error**: ${errorMessage}\n\nšŸ’” **Tip**: Make sure the selected app has design testing enabled.`,
106
+ },
107
+ ],
108
+ };
109
+ }
110
+ // Use the design_test_appId for fetching design issues
111
+ const designAppId = appDetails.design_test_appId;
112
+ // Get current fixed design issues from session
113
+ const fixedIssues = authManager.getFixedDesignIssues();
114
+ const previousIssues = fixedIssues.map((fi) => fi.issue);
115
+ if (previousIssues.length === 0) {
116
+ return {
117
+ content: [
118
+ {
119
+ type: "text",
120
+ text: `ā„¹ļø **No Fixed Design Issues to Check**\n\nšŸŽÆ **Status**: No previously fixed design issues found in session.\n\nšŸ’” **Tip**: Use \`ai_fix_design_issue\` to fix some design issues first, then run \`run_design_test\`, and then this tool.`,
121
+ },
122
+ ],
123
+ };
124
+ }
125
+ console.error(`šŸ” Found ${previousIssues.length} previously fixed design issues to check`);
126
+ // Wait for specified time for system to process
127
+ console.error(`ā³ Waiting ${waitSeconds} seconds for system to process design issues...`);
128
+ await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
129
+ console.error('āœ… Wait completed, fetching updated design issues...');
130
+ // Fetch current design issues
131
+ console.error('šŸ” Fetching current design issues...');
132
+ const currentIssues = await fetchDesignIssues(accessToken, tokenType, orgId, designAppId);
133
+ console.error(`šŸ“Š Found ${currentIssues.length} current design issues`);
134
+ // Compare fixed issues with current issues
135
+ const comparison = compareAndCountFixedDesignIssues(previousIssues, currentIssues);
136
+ // Create comparison table
137
+ const createComparisonTable = () => {
138
+ const lines = [];
139
+ if (comparison.fixedCount > 0) {
140
+ lines.push('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
141
+ lines.push('│ Fixed Design Issues │ Endpoint │ Status │');
142
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
143
+ comparison.fixedIssues.forEach((issue, index) => {
144
+ const issueType = issue.category || issue.label || 'Unknown Issue';
145
+ const method = issue.method || 'MULTIPLE';
146
+ const path = issue.path || '/unknown';
147
+ const endpoint = `${method} ${path}`;
148
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
149
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
150
+ const paddedIssueType = truncatedIssueType.padEnd(60);
151
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
152
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āœ… FIXED │`);
153
+ });
154
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
155
+ }
156
+ if (comparison.stillExistsIssues.length > 0) {
157
+ lines.push('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
158
+ lines.push('│ Still Existing Design Issues │ Endpoint │ Status │');
159
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
160
+ comparison.stillExistsIssues.forEach((issue, index) => {
161
+ const issueType = issue.category || issue.label || 'Unknown Issue';
162
+ const method = issue.method || 'MULTIPLE';
163
+ const path = issue.path || '/unknown';
164
+ const endpoint = `${method} ${path}`;
165
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
166
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
167
+ const paddedIssueType = truncatedIssueType.padEnd(60);
168
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
169
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āŒ STILL EXISTS │`);
170
+ });
171
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
172
+ }
173
+ return lines.join('\n');
174
+ };
175
+ const comparisonTable = createComparisonTable();
176
+ // Clear fixed design issues after comparison is done
177
+ console.error('šŸ—‘ļø Clearing fixed design issues after comparison...');
178
+ authManager.clearFixedDesignIssues();
179
+ return {
180
+ content: [
181
+ {
182
+ type: "text",
183
+ text: `šŸ” **Design Fixes Check Results**\n\nšŸŽÆ **APP**: ${selectedAppId}\nšŸŽØ **Organization**: ${orgId}\n\nšŸ“Š **Issue Comparison Results**:\n\n**Previously Fixed Design Issues**: ${previousIssues.length}\n**Current Design Issues**: ${currentIssues.length}\n**Actually Fixed**: ${comparison.fixedCount}\n**Still Existing**: ${comparison.stillExistsIssues.length}\n\n${comparisonTable}\n\nā³ **Processing Wait**: System waited ${waitSeconds} seconds to ensure design issues were fully processed and updated.\n\nšŸ—‘ļø **Fixed Design Issues Cleared**: All previously fixed design issues have been cleared from session after comparison.\n\nāœ… **Status**: Design fix verification completed.\n\nšŸ’” **Next Steps**:\n1. Review the comparison results above\n2. For still existing issues, use \`ai_fix_design_issue\` to generate new fixes\n3. Run \`run_design_test\` again to test new fixes\n4. Use \`check_design_fixes\` to verify the new fixes`,
184
+ },
185
+ ],
186
+ };
187
+ }
188
+ catch (error) {
189
+ const errorMessage = error instanceof Error ? error.message : String(error);
190
+ return {
191
+ content: [
192
+ {
193
+ type: "text",
194
+ text: `āŒ **Error checking design fixes**\n\nšŸ”“ **Error**: ${errorMessage}\n\nšŸ’” **Tip**: Make sure you're authenticated, have an organization selected, and have run \`run_design_test\` first.\n\nšŸ”„ **Try**: Check your inputs and try again.`,
195
+ },
196
+ ],
197
+ };
198
+ }
199
+ }
@@ -0,0 +1,17 @@
1
+ export declare const checkQualityFixesTool: {
2
+ readonly name: "check_quality_fixes";
3
+ readonly description: "šŸ” Check which previously fixed quality issues were actually resolved (auto-triggered after run_quality_test)";
4
+ readonly inputSchema: {
5
+ readonly type: "object";
6
+ readonly properties: {
7
+ readonly wait_seconds: {
8
+ readonly type: "number";
9
+ readonly description: "Wait time before checking issues (default: 15 seconds)";
10
+ readonly default: 15;
11
+ };
12
+ };
13
+ readonly additionalProperties: false;
14
+ };
15
+ };
16
+ export declare function handleCheckQualityFixes(authManager: any, args: any): Promise<any>;
17
+ //# sourceMappingURL=checkQualityFixes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkQualityFixes.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/checkQualityFixes.ts"],"names":[],"mappings":"AAkDA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;CAcxB,CAAC;AAEX,wBAAsB,uBAAuB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CA8KvF"}
@@ -0,0 +1,199 @@
1
+ import axios from "axios";
2
+ import { API_ENDPOINTS } from "../../config.js";
3
+ // Function to compare fixed quality issues with current quality issues
4
+ function compareAndCountFixedQualityIssues(previousIssues, currentIssues) {
5
+ let fixedCount = 0;
6
+ const fixedIssues = [];
7
+ const stillExistsIssues = [];
8
+ // Loop through each quality issue we attempted to fix
9
+ for (const previousIssue of previousIssues) {
10
+ // Check if this previous issue still exists in current issues
11
+ const stillExists = currentIssues.some((currentIssue) => currentIssue.method === previousIssue.method &&
12
+ currentIssue.path === previousIssue.path &&
13
+ currentIssue.category === previousIssue.category);
14
+ // If the issue no longer exists in current issues, it was fixed
15
+ if (!stillExists) {
16
+ fixedCount++;
17
+ fixedIssues.push(previousIssue);
18
+ }
19
+ else {
20
+ stillExistsIssues.push(previousIssue);
21
+ }
22
+ }
23
+ return { fixedCount, fixedIssues, stillExistsIssues };
24
+ }
25
+ // Function to fetch current quality issues
26
+ async function fetchQualityIssues(accessToken, tokenType, orgId, qualityAppId) {
27
+ const url = `${API_ENDPOINTS.QUALITY_ISSUES_BY_APP}/${qualityAppId}?page=1&pageSize=100`;
28
+ const response = await axios.get(url, {
29
+ headers: {
30
+ 'Authorization': `${tokenType} ${accessToken}`,
31
+ 'Content-Type': 'application/json',
32
+ 'X-Org-ID': orgId
33
+ },
34
+ timeout: 30000
35
+ });
36
+ if (response.status !== 200 || !response.data) {
37
+ throw new Error(`Failed to fetch quality issues: ${response.status}`);
38
+ }
39
+ return response.data.tests || [];
40
+ }
41
+ export const checkQualityFixesTool = {
42
+ name: "check_quality_fixes",
43
+ description: "šŸ” Check which previously fixed quality issues were actually resolved (auto-triggered after run_quality_test)",
44
+ inputSchema: {
45
+ type: "object",
46
+ properties: {
47
+ wait_seconds: {
48
+ type: "number",
49
+ description: "Wait time before checking issues (default: 15 seconds)",
50
+ default: 15
51
+ }
52
+ },
53
+ additionalProperties: false,
54
+ },
55
+ };
56
+ export async function handleCheckQualityFixes(authManager, args) {
57
+ try {
58
+ const waitSeconds = args.wait_seconds || 15;
59
+ const accessToken = authManager.getAccessToken();
60
+ const tokenType = authManager.getTokenType();
61
+ const orgId = authManager.getSelectedOrgId();
62
+ const selectedAppId = authManager.getSelectedApiId();
63
+ if (!accessToken) {
64
+ throw new Error('No access token available');
65
+ }
66
+ if (!orgId) {
67
+ throw new Error('No organization selected. Please select an organization first using manage_organizations tool.');
68
+ }
69
+ if (!selectedAppId) {
70
+ return {
71
+ content: [
72
+ {
73
+ type: "text",
74
+ text: `āŒ **No APP Selected**\n\nšŸŽÆ **Required**: You must select an APP first to check quality fixes.\n\nšŸ“‹ **Steps**:\n1. Run \`list_apps\` to see available APPs\n2. Run \`select_app\` with an APP ID\n3. Run \`show_quality_issues\` to see quality issues\n4. Then run this tool again`,
75
+ },
76
+ ],
77
+ };
78
+ }
79
+ // First, get the app details using the catalog ID to get the quality app ID
80
+ const catalogUrl = `${API_ENDPOINTS.API_CATALOG_SERVICE_IDS}/${selectedAppId}`;
81
+ let appDetails;
82
+ try {
83
+ const catalogResponse = await axios.get(catalogUrl, {
84
+ headers: {
85
+ 'Authorization': `${tokenType} ${accessToken}`,
86
+ 'Content-Type': 'application/json',
87
+ 'X-Org-ID': orgId
88
+ },
89
+ timeout: 30000
90
+ });
91
+ if (catalogResponse.status !== 200 || !catalogResponse.data) {
92
+ throw new Error(`Failed to fetch app details with status ${catalogResponse.status}`);
93
+ }
94
+ appDetails = catalogResponse.data;
95
+ if (!appDetails.quality_test_appId) {
96
+ throw new Error('No quality_test_appId found for this app');
97
+ }
98
+ }
99
+ catch (error) {
100
+ const errorMessage = error instanceof Error ? error.message : String(error);
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: `āŒ **Error fetching app details**\n\nšŸ”“ **Error**: ${errorMessage}\n\nšŸ’” **Tip**: Make sure the selected app has quality testing enabled.`,
106
+ },
107
+ ],
108
+ };
109
+ }
110
+ // Use the quality_test_appId for fetching quality issues
111
+ const qualityAppId = appDetails.quality_test_appId;
112
+ // Get current fixed quality issues from session
113
+ const fixedIssues = authManager.getFixedQualityIssues();
114
+ const previousIssues = fixedIssues.map((fi) => fi.issue);
115
+ if (previousIssues.length === 0) {
116
+ return {
117
+ content: [
118
+ {
119
+ type: "text",
120
+ text: `ā„¹ļø **No Fixed Quality Issues to Check**\n\nšŸŽÆ **Status**: No previously fixed quality issues found in session.\n\nšŸ’” **Tip**: Use \`ai_fix_quality_issue\` to fix some quality issues first, then run \`run_quality_test\`, and then this tool.`,
121
+ },
122
+ ],
123
+ };
124
+ }
125
+ console.error(`šŸ” Found ${previousIssues.length} previously fixed quality issues to check`);
126
+ // Wait for specified time for system to process
127
+ console.error(`ā³ Waiting ${waitSeconds} seconds for system to process quality issues...`);
128
+ await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
129
+ console.error('āœ… Wait completed, fetching updated quality issues...');
130
+ // Fetch current quality issues
131
+ console.error('šŸ” Fetching current quality issues...');
132
+ const currentIssues = await fetchQualityIssues(accessToken, tokenType, orgId, qualityAppId);
133
+ console.error(`šŸ“Š Found ${currentIssues.length} current quality issues`);
134
+ // Compare fixed issues with current issues
135
+ const comparison = compareAndCountFixedQualityIssues(previousIssues, currentIssues);
136
+ // Create comparison table
137
+ const createComparisonTable = () => {
138
+ const lines = [];
139
+ if (comparison.fixedCount > 0) {
140
+ lines.push('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
141
+ lines.push('│ Fixed Quality Issues │ Endpoint │ Status │');
142
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
143
+ comparison.fixedIssues.forEach((issue, index) => {
144
+ const issueType = issue.category || issue.label || 'Unknown Issue';
145
+ const method = issue.method || 'MULTIPLE';
146
+ const path = issue.path || '/unknown';
147
+ const endpoint = `${method} ${path}`;
148
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
149
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
150
+ const paddedIssueType = truncatedIssueType.padEnd(60);
151
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
152
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āœ… FIXED │`);
153
+ });
154
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
155
+ }
156
+ if (comparison.stillExistsIssues.length > 0) {
157
+ lines.push('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
158
+ lines.push('│ Still Existing Quality Issues │ Endpoint │ Status │');
159
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
160
+ comparison.stillExistsIssues.forEach((issue, index) => {
161
+ const issueType = issue.category || issue.label || 'Unknown Issue';
162
+ const method = issue.method || 'MULTIPLE';
163
+ const path = issue.path || '/unknown';
164
+ const endpoint = `${method} ${path}`;
165
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
166
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
167
+ const paddedIssueType = truncatedIssueType.padEnd(60);
168
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
169
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āŒ STILL EXISTS │`);
170
+ });
171
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
172
+ }
173
+ return lines.join('\n');
174
+ };
175
+ const comparisonTable = createComparisonTable();
176
+ // Clear fixed quality issues after comparison is done
177
+ console.error('šŸ—‘ļø Clearing fixed quality issues after comparison...');
178
+ authManager.clearFixedQualityIssues();
179
+ return {
180
+ content: [
181
+ {
182
+ type: "text",
183
+ text: `šŸ” **Quality Fixes Check Results**\n\nšŸŽÆ **APP**: ${selectedAppId}\nšŸ” **Quality App ID**: ${qualityAppId}\nšŸ¢ **Organization**: ${orgId}\n\nšŸ“Š **Issue Comparison Results**:\n\n**Previously Fixed Quality Issues**: ${previousIssues.length}\n**Current Quality Issues**: ${currentIssues.length}\n**Actually Fixed**: ${comparison.fixedCount}\n**Still Existing**: ${comparison.stillExistsIssues.length}\n\n${comparisonTable}\n\nā³ **Processing Wait**: System waited ${waitSeconds} seconds to ensure quality issues were fully processed and updated.\n\nšŸ—‘ļø **Fixed Quality Issues Cleared**: All previously fixed quality issues have been cleared from session after comparison.\n\nāœ… **Status**: Quality fix verification completed.\n\nšŸ’” **Next Steps**:\n1. Review the comparison results above\n2. For still existing issues, use \`ai_fix_quality_issue\` to generate new fixes\n3. Run \`run_quality_test\` again to test new fixes\n4. Use \`check_quality_fixes\` to verify the new fixes`,
184
+ },
185
+ ],
186
+ };
187
+ }
188
+ catch (error) {
189
+ const errorMessage = error instanceof Error ? error.message : String(error);
190
+ return {
191
+ content: [
192
+ {
193
+ type: "text",
194
+ text: `āŒ **Error checking quality fixes**\n\nšŸ”“ **Error**: ${errorMessage}\n\nšŸ’” **Tip**: Make sure you're authenticated, have an organization selected, and have run \`run_quality_test\` first.\n\nšŸ”„ **Try**: Check your inputs and try again.`,
195
+ },
196
+ ],
197
+ };
198
+ }
199
+ }
@@ -0,0 +1,17 @@
1
+ export declare const checkSecurityFixesTool: {
2
+ readonly name: "check_security_fixes";
3
+ readonly description: "šŸ” Check which previously fixed security issues were actually resolved (auto-triggered after run_security_test)";
4
+ readonly inputSchema: {
5
+ readonly type: "object";
6
+ readonly properties: {
7
+ readonly wait_seconds: {
8
+ readonly type: "number";
9
+ readonly description: "Wait time before checking issues (default: 15 seconds)";
10
+ readonly default: 15;
11
+ };
12
+ };
13
+ readonly additionalProperties: false;
14
+ };
15
+ };
16
+ export declare function handleCheckSecurityFixes(authManager: any, args: any): Promise<any>;
17
+ //# sourceMappingURL=checkSecurityFixes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkSecurityFixes.d.ts","sourceRoot":"","sources":["../../../src/tools/protected/checkSecurityFixes.ts"],"names":[],"mappings":"AAkDA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;CAczB,CAAC;AAEX,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAoJxF"}
@@ -0,0 +1,177 @@
1
+ import axios from "axios";
2
+ import { API_ENDPOINTS } from "../../config.js";
3
+ // Function to compare fixed issues with current issues
4
+ function compareAndCountFixedIssues(previousIssues, currentIssues) {
5
+ let fixedCount = 0;
6
+ const fixedIssues = [];
7
+ const stillExistsIssues = [];
8
+ // Loop through each issue we attempted to fix
9
+ for (const previousIssue of previousIssues) {
10
+ // Check if this previous issue still exists in current issues
11
+ const stillExists = currentIssues.some((currentIssue) => currentIssue.method === previousIssue.method &&
12
+ currentIssue.path === previousIssue.path &&
13
+ currentIssue.label === previousIssue.label);
14
+ // If the issue no longer exists in current issues, it was fixed
15
+ if (!stillExists) {
16
+ fixedCount++;
17
+ fixedIssues.push(previousIssue);
18
+ }
19
+ else {
20
+ stillExistsIssues.push(previousIssue);
21
+ }
22
+ }
23
+ return { fixedCount, fixedIssues, stillExistsIssues };
24
+ }
25
+ // Function to fetch current security issues
26
+ async function fetchSecurityIssues(securityAppId, accessToken, tokenType, orgId) {
27
+ const url = `${API_ENDPOINTS.SECURITY_ISSUES_BY_APP}?app_id=${encodeURIComponent(securityAppId)}&limit=100`;
28
+ const response = await axios.get(url, {
29
+ headers: {
30
+ 'Authorization': `${tokenType} ${accessToken}`,
31
+ 'Content-Type': 'application/json',
32
+ 'X-Org-ID': orgId
33
+ },
34
+ timeout: 30000
35
+ });
36
+ if (response.status !== 200 || !response.data) {
37
+ throw new Error(`Failed to fetch security issues: ${response.status}`);
38
+ }
39
+ return response.data.data || [];
40
+ }
41
+ export const checkSecurityFixesTool = {
42
+ name: "check_security_fixes",
43
+ description: "šŸ” Check which previously fixed security issues were actually resolved (auto-triggered after run_security_test)",
44
+ inputSchema: {
45
+ type: "object",
46
+ properties: {
47
+ wait_seconds: {
48
+ type: "number",
49
+ description: "Wait time before checking issues (default: 15 seconds)",
50
+ default: 15
51
+ }
52
+ },
53
+ additionalProperties: false,
54
+ },
55
+ };
56
+ export async function handleCheckSecurityFixes(authManager, args) {
57
+ try {
58
+ const waitSeconds = args.wait_seconds || 15;
59
+ const accessToken = authManager.getAccessToken();
60
+ const tokenType = authManager.getTokenType();
61
+ const orgId = authManager.getSelectedOrgId();
62
+ const selectedAppId = authManager.getSelectedApiId();
63
+ const securityAppId = authManager.getSelectedSecurityAppId();
64
+ if (!accessToken) {
65
+ throw new Error('No access token available');
66
+ }
67
+ if (!orgId) {
68
+ throw new Error('No organization selected. Please select an organization first using manage_organizations tool.');
69
+ }
70
+ if (!selectedAppId) {
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: `āŒ **No APP Selected**\n\nšŸŽÆ **Required**: You must select an APP first to check security fixes.\n\nšŸ“‹ **Steps**:\n1. Run \`list_apps\` to see available APPs\n2. Run \`select_app\` with an APP ID\n3. Run \`show_security_issues\` to get the security app ID\n4. Then run this tool again`,
76
+ },
77
+ ],
78
+ };
79
+ }
80
+ if (!securityAppId) {
81
+ return {
82
+ content: [
83
+ {
84
+ type: "text",
85
+ text: `āŒ **No Security App ID Available**\n\nšŸŽÆ **Required**: You must run \`show_security_issues\` first to get the security app ID.\n\nšŸ“‹ **Steps**:\n1. Make sure you have an APP selected\n2. Run \`show_security_issues\` to fetch and store the security app ID\n3. Then run this tool again`,
86
+ },
87
+ ],
88
+ };
89
+ }
90
+ // Get current fixed issues from session
91
+ const fixedIssues = authManager.getFixedIssues();
92
+ const previousIssues = fixedIssues.map((fi) => fi.issue);
93
+ if (previousIssues.length === 0) {
94
+ return {
95
+ content: [
96
+ {
97
+ type: "text",
98
+ text: `ā„¹ļø **No Fixed Issues to Check**\n\nšŸŽÆ **Status**: No previously fixed issues found in session.\n\nšŸ’” **Tip**: Use \`ai_fix_security_issue\` to fix some issues first, then run \`run_security_test\`, and then this tool.`,
99
+ },
100
+ ],
101
+ };
102
+ }
103
+ console.error(`šŸ” Found ${previousIssues.length} previously fixed issues to check`);
104
+ // Wait for specified time for system to process
105
+ console.error(`ā³ Waiting ${waitSeconds} seconds for system to process security issues...`);
106
+ await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
107
+ console.error('āœ… Wait completed, fetching updated security issues...');
108
+ // Fetch current security issues
109
+ console.error('šŸ” Fetching current security issues...');
110
+ const currentIssues = await fetchSecurityIssues(securityAppId, accessToken, tokenType, orgId);
111
+ console.error(`šŸ“Š Found ${currentIssues.length} current security issues`);
112
+ // Compare fixed issues with current issues
113
+ const comparison = compareAndCountFixedIssues(previousIssues, currentIssues);
114
+ // Create comparison table
115
+ const createComparisonTable = () => {
116
+ const lines = [];
117
+ if (comparison.fixedCount > 0) {
118
+ lines.push('ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
119
+ lines.push('│ Fixed Issues │ Endpoint │ Status │');
120
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
121
+ comparison.fixedIssues.forEach((issue, index) => {
122
+ const issueType = issue.label || 'Unknown Issue';
123
+ const method = issue.method || 'MULTIPLE';
124
+ const path = issue.path || '/unknown';
125
+ const endpoint = `${method} ${path}`;
126
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
127
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
128
+ const paddedIssueType = truncatedIssueType.padEnd(60);
129
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
130
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āœ… FIXED │`);
131
+ });
132
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
133
+ }
134
+ if (comparison.stillExistsIssues.length > 0) {
135
+ lines.push('\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”');
136
+ lines.push('│ Still Existing Issues │ Endpoint │ Status │');
137
+ lines.push('ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤');
138
+ comparison.stillExistsIssues.forEach((issue, index) => {
139
+ const issueType = issue.label || 'Unknown Issue';
140
+ const method = issue.method || 'MULTIPLE';
141
+ const path = issue.path || '/unknown';
142
+ const endpoint = `${method} ${path}`;
143
+ const truncatedIssueType = issueType.length > 60 ? issueType.substring(0, 57) + '...' : issueType;
144
+ const truncatedEndpoint = endpoint.length > 60 ? endpoint.substring(0, 57) + '...' : endpoint;
145
+ const paddedIssueType = truncatedIssueType.padEnd(60);
146
+ const paddedEndpoint = truncatedEndpoint.padEnd(60);
147
+ lines.push(`│ ${paddedIssueType} │ ${paddedEndpoint} │ āŒ STILL EXISTS │`);
148
+ });
149
+ lines.push('ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜');
150
+ }
151
+ return lines.join('\n');
152
+ };
153
+ const comparisonTable = createComparisonTable();
154
+ // Clear fixed issues after comparison is done
155
+ console.error('šŸ—‘ļø Clearing fixed issues after comparison...');
156
+ authManager.clearFixedIssues();
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: `šŸ” **Security Fixes Check Results**\n\nšŸŽÆ **APP**: ${selectedAppId}\nšŸ”’ **Security App ID**: ${securityAppId}\nšŸ¢ **Organization**: ${orgId}\n\nšŸ“Š **Issue Comparison Results**:\n\n**Previously Fixed Issues**: ${previousIssues.length}\n**Current Security Issues**: ${currentIssues.length}\n**Actually Fixed**: ${comparison.fixedCount}\n**Still Existing**: ${comparison.stillExistsIssues.length}\n\n${comparisonTable}\n\nā³ **Processing Wait**: System waited ${waitSeconds} seconds to ensure security issues were fully processed and updated.\n\nšŸ—‘ļø **Fixed Issues Cleared**: All previously fixed issues have been cleared from session after comparison.\n\nāœ… **Status**: Security fix verification completed.\n\nšŸ’” **Next Steps**:\n1. Review the comparison results above\n2. For still existing issues, use \`ai_fix_security_issue\` to generate new fixes\n3. Run \`run_security_test\` again to test new fixes\n4. Use \`check_security_fixes\` to verify the new fixes`,
162
+ },
163
+ ],
164
+ };
165
+ }
166
+ catch (error) {
167
+ const errorMessage = error instanceof Error ? error.message : String(error);
168
+ return {
169
+ content: [
170
+ {
171
+ type: "text",
172
+ text: `āŒ **Error checking security fixes**\n\nšŸ”“ **Error**: ${errorMessage}\n\nšŸ’” **Tip**: Make sure you're authenticated, have an organization selected, and have run \`run_security_test\` first.\n\nšŸ”„ **Try**: Check your inputs and try again.`,
173
+ },
174
+ ],
175
+ };
176
+ }
177
+ }