@skyramp/mcp 0.0.44 → 0.0.46
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/build/index.js +57 -12
- package/build/prompts/code-reuse.js +1 -1
- package/build/prompts/driftAnalysisPrompt.js +159 -0
- package/build/prompts/modularization/ui-test-modularization.js +2 -0
- package/build/prompts/testGenerationPrompt.js +2 -2
- package/build/prompts/testHealthPrompt.js +82 -0
- package/build/services/AnalyticsService.js +86 -0
- package/build/services/DriftAnalysisService.js +928 -0
- package/build/services/ModularizationService.js +16 -1
- package/build/services/TestDiscoveryService.js +237 -0
- package/build/services/TestExecutionService.js +504 -0
- package/build/services/TestGenerationService.js +16 -2
- package/build/services/TestHealthService.js +656 -0
- package/build/tools/auth/loginTool.js +13 -3
- package/build/tools/auth/logoutTool.js +13 -3
- package/build/tools/code-refactor/codeReuseTool.js +46 -18
- package/build/tools/code-refactor/modularizationTool.js +44 -11
- package/build/tools/executeSkyrampTestTool.js +29 -125
- package/build/tools/fixErrorTool.js +38 -14
- package/build/tools/generate-tests/generateContractRestTool.js +8 -2
- package/build/tools/generate-tests/generateE2ERestTool.js +9 -3
- package/build/tools/generate-tests/generateFuzzRestTool.js +9 -3
- package/build/tools/generate-tests/generateIntegrationRestTool.js +8 -2
- package/build/tools/generate-tests/generateLoadRestTool.js +9 -3
- package/build/tools/generate-tests/generateScenarioRestTool.js +8 -2
- package/build/tools/generate-tests/generateSmokeRestTool.js +9 -3
- package/build/tools/generate-tests/generateUIRestTool.js +9 -3
- package/build/tools/test-maintenance/actionsTool.js +230 -0
- package/build/tools/test-maintenance/analyzeTestDriftTool.js +197 -0
- package/build/tools/test-maintenance/calculateHealthScoresTool.js +257 -0
- package/build/tools/test-maintenance/discoverTestsTool.js +143 -0
- package/build/tools/test-maintenance/executeBatchTestsTool.js +198 -0
- package/build/tools/test-maintenance/stateCleanupTool.js +153 -0
- package/build/tools/test-recommendation/analyzeRepositoryTool.js +27 -3
- package/build/tools/test-recommendation/mapTestsTool.js +9 -2
- package/build/tools/test-recommendation/recommendTestsTool.js +21 -5
- package/build/tools/trace/startTraceCollectionTool.js +18 -5
- package/build/tools/trace/stopTraceCollectionTool.js +28 -4
- package/build/types/TestAnalysis.js +1 -0
- package/build/types/TestDriftAnalysis.js +1 -0
- package/build/types/TestExecution.js +6 -0
- package/build/types/TestHealth.js +4 -0
- package/build/utils/AnalysisStateManager.js +240 -0
- package/build/utils/utils.test.js +25 -9
- package/package.json +6 -3
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { SkyrampClient } from "@skyramp/skyramp";
|
|
3
3
|
import { logger } from "../../utils/logger.js";
|
|
4
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
5
|
+
const TOOL_NAME = "skyramp_login";
|
|
4
6
|
export function registerLoginTool(server) {
|
|
5
|
-
server.registerTool(
|
|
7
|
+
server.registerTool(TOOL_NAME, {
|
|
6
8
|
description: `Login to Skyramp platform
|
|
7
9
|
|
|
8
10
|
Logging into Skyramp provides access to additional platform features and services.
|
|
@@ -12,10 +14,11 @@ Logging into Skyramp provides access to additional platform features and service
|
|
|
12
14
|
.string()
|
|
13
15
|
.describe("The prompt user provided to login to Skyramp"),
|
|
14
16
|
},
|
|
15
|
-
|
|
17
|
+
_meta: {
|
|
16
18
|
keywords: ["login", "authenticate", "skyramp login"],
|
|
17
19
|
},
|
|
18
20
|
}, async (params) => {
|
|
21
|
+
let errorResult;
|
|
19
22
|
logger.info("Logging in to Skyramp", {
|
|
20
23
|
prompt: params.prompt,
|
|
21
24
|
});
|
|
@@ -34,7 +37,7 @@ Logging into Skyramp provides access to additional platform features and service
|
|
|
34
37
|
}
|
|
35
38
|
catch (error) {
|
|
36
39
|
const errorMessage = `Login to Skyramp failed: ${error.message}`;
|
|
37
|
-
|
|
40
|
+
errorResult = {
|
|
38
41
|
content: [
|
|
39
42
|
{
|
|
40
43
|
type: "text",
|
|
@@ -43,6 +46,13 @@ Logging into Skyramp provides access to additional platform features and service
|
|
|
43
46
|
],
|
|
44
47
|
isError: true,
|
|
45
48
|
};
|
|
49
|
+
return errorResult;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
const recordParams = {
|
|
53
|
+
prompt: params.prompt,
|
|
54
|
+
};
|
|
55
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, recordParams);
|
|
46
56
|
}
|
|
47
57
|
});
|
|
48
58
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { SkyrampClient } from "@skyramp/skyramp";
|
|
3
3
|
import { logger } from "../../utils/logger.js";
|
|
4
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
5
|
+
const TOOL_NAME = "skyramp_logout";
|
|
4
6
|
export function registerLogoutTool(server) {
|
|
5
|
-
server.registerTool(
|
|
7
|
+
server.registerTool(TOOL_NAME, {
|
|
6
8
|
description: `Logout from Skyramp platform
|
|
7
9
|
|
|
8
10
|
Logout from Skyramp platform to end your authenticated session.`,
|
|
@@ -11,10 +13,11 @@ Logout from Skyramp platform to end your authenticated session.`,
|
|
|
11
13
|
.string()
|
|
12
14
|
.describe("The prompt user provided to logout from Skyramp"),
|
|
13
15
|
},
|
|
14
|
-
|
|
16
|
+
_meta: {
|
|
15
17
|
keywords: ["logout", "sign out", "skyramp logout"],
|
|
16
18
|
},
|
|
17
19
|
}, async (params) => {
|
|
20
|
+
let errorResult;
|
|
18
21
|
logger.info("Logging out from Skyramp", {
|
|
19
22
|
prompt: params.prompt,
|
|
20
23
|
});
|
|
@@ -32,7 +35,7 @@ Logout from Skyramp platform to end your authenticated session.`,
|
|
|
32
35
|
}
|
|
33
36
|
catch (error) {
|
|
34
37
|
const errorMessage = `Logout from Skyramp failed: ${error.message}`;
|
|
35
|
-
|
|
38
|
+
errorResult = {
|
|
36
39
|
content: [
|
|
37
40
|
{
|
|
38
41
|
type: "text",
|
|
@@ -41,6 +44,13 @@ Logout from Skyramp platform to end your authenticated session.`,
|
|
|
41
44
|
],
|
|
42
45
|
isError: true,
|
|
43
46
|
};
|
|
47
|
+
return errorResult;
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
const recordParams = {
|
|
51
|
+
prompt: params.prompt,
|
|
52
|
+
};
|
|
53
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, recordParams);
|
|
44
54
|
}
|
|
45
55
|
});
|
|
46
56
|
}
|
|
@@ -3,6 +3,7 @@ import { logger } from "../../utils/logger.js";
|
|
|
3
3
|
import { getCodeReusePrompt } from "../../prompts/code-reuse.js";
|
|
4
4
|
import { codeRefactoringSchema, languageSchema, } from "../../types/TestTypes.js";
|
|
5
5
|
import { SKYRAMP_UTILS_HEADER } from "../../utils/utils.js";
|
|
6
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
6
7
|
const codeReuseSchema = z.object({
|
|
7
8
|
testFile: z
|
|
8
9
|
.string()
|
|
@@ -14,8 +15,9 @@ const codeReuseSchema = z.object({
|
|
|
14
15
|
.string()
|
|
15
16
|
.describe("The code content to analyze and optimize for code reuse"),
|
|
16
17
|
});
|
|
18
|
+
const TOOL_NAME = "skyramp_reuse_code";
|
|
17
19
|
export function registerCodeReuseTool(server) {
|
|
18
|
-
server.registerTool(
|
|
20
|
+
server.registerTool(TOOL_NAME, {
|
|
19
21
|
description: `Analyzes code for reuse opportunities and enforces code reuse principles.
|
|
20
22
|
|
|
21
23
|
This tool helps identify and reuse ONLY EXISTING helper functions from other test files (grep based on "${SKYRAMP_UTILS_HEADER}").
|
|
@@ -37,16 +39,18 @@ export function registerCodeReuseTool(server) {
|
|
|
37
39
|
3. **ONLY IF** reusable helpers are found in OTHER test files → move to utils and update imports
|
|
38
40
|
4. **IF NO** existing utils or reusable helpers are found in test files then reuse is complete, without creating any files or changes to the test files
|
|
39
41
|
5. Verify no duplicate code remains and tests work as expected
|
|
40
|
-
6. **MANDATORY**: After code reuse is complete, proceed to modularization by calling skyramp_modularization tool
|
|
42
|
+
6. **MANDATORY**: After code reuse is complete, proceed to modularization by calling skyramp_modularization tool ONLY for UI, E2E, INTEGRATION or LOAD tests generated from traces.
|
|
41
43
|
|
|
42
44
|
**WHEN TO SKIP (DO NOTHING):**
|
|
43
45
|
- Other test files only have repetitive patterns, no helper functions
|
|
44
46
|
- Other test files are essentially identical to current file
|
|
45
47
|
- No actual function definitions found in other test files
|
|
46
|
-
|
|
48
|
+
|
|
49
|
+
**MANDATORY**: ONLY ALLOW CODE REUSE IF THE IS TRACE BASED FLAG IS SET TO TRUE ELSE DO NOT ALLOW CODE REUSE AND LEAVE THE TEST FILE AS IS.
|
|
50
|
+
**CRITICAL**: NON TRACE BASED TESTS ARE ALREADY MODULARIZED AND DO NOT NEED CODE REUSE.
|
|
47
51
|
The tool will provide step-by-step instructions that MUST be followed exactly.`,
|
|
48
52
|
inputSchema: codeReuseSchema.shape,
|
|
49
|
-
|
|
53
|
+
_meta: {
|
|
50
54
|
keywords: [
|
|
51
55
|
"code reuse",
|
|
52
56
|
"duplicate code",
|
|
@@ -56,19 +60,43 @@ export function registerCodeReuseTool(server) {
|
|
|
56
60
|
],
|
|
57
61
|
},
|
|
58
62
|
}, async (params) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
let errorResult;
|
|
64
|
+
try {
|
|
65
|
+
logger.info("Analyzing code for reuse opportunities", {
|
|
66
|
+
testFile: params.testFile,
|
|
67
|
+
language: params.language,
|
|
68
|
+
framework: params.framework,
|
|
69
|
+
});
|
|
70
|
+
const codeReusePrompt = getCodeReusePrompt(params.testFile, params.language);
|
|
71
|
+
return {
|
|
72
|
+
content: [
|
|
73
|
+
{
|
|
74
|
+
type: "text",
|
|
75
|
+
text: codeReusePrompt,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const errorMessage = `Code reuse analysis failed: ${error.message}`;
|
|
82
|
+
errorResult = {
|
|
83
|
+
content: [
|
|
84
|
+
{
|
|
85
|
+
type: "text",
|
|
86
|
+
text: errorMessage,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
isError: true,
|
|
90
|
+
};
|
|
91
|
+
return errorResult;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
|
|
95
|
+
prompt: params.prompt,
|
|
96
|
+
testFile: params.testFile,
|
|
97
|
+
language: params.language,
|
|
98
|
+
framework: params.framework,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
73
101
|
});
|
|
74
102
|
}
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { logger } from "../../utils/logger.js";
|
|
3
3
|
import { TestType } from "../../types/TestTypes.js";
|
|
4
4
|
import { ModularizationService, } from "../../services/ModularizationService.js";
|
|
5
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
5
6
|
const modularizationSchema = {
|
|
6
7
|
testFile: z
|
|
7
8
|
.string()
|
|
@@ -10,22 +11,29 @@ const modularizationSchema = {
|
|
|
10
11
|
testType: z
|
|
11
12
|
.enum([TestType.UI, TestType.E2E, TestType.INTEGRATION])
|
|
12
13
|
.describe("Specifies the type of test (UI, E2E, or Integration). DO NOT USE TEST NAME/DESCRIPTION AS TEST TYPE. ONLY USE UI, E2E, OR INTEGRATION."),
|
|
14
|
+
isTraceBased: z
|
|
15
|
+
.boolean()
|
|
16
|
+
.default(false)
|
|
17
|
+
.describe("Whether the test is generated from traces. Scan the test file and check if the test is generated from traces."),
|
|
13
18
|
prompt: z
|
|
14
19
|
.string()
|
|
15
20
|
.describe("The prompt or code content to process with modularization principles applied"),
|
|
16
21
|
};
|
|
22
|
+
const TOOL_NAME = "skyramp_modularization";
|
|
17
23
|
export function registerModularizationTool(server) {
|
|
18
|
-
server.registerTool(
|
|
24
|
+
server.registerTool(TOOL_NAME, {
|
|
19
25
|
description: `Provides modularization instructions and test file content. YOU MUST immediately modularize the code and write it back to the file. The tool returns:
|
|
20
26
|
1. Complete modularization instructions
|
|
21
27
|
2. The current test file content
|
|
22
28
|
3. Step-by-step requirements you must complete
|
|
23
29
|
|
|
30
|
+
**MANDATORY**: ONLY MODULARIZE THE TEST IF THE IS TRACE BASED FLAG IS SET TO TRUE ELSE DO NOT MODULARIZE THE TEST AND LEAVE THE TEST FILE AS IS.
|
|
31
|
+
**CRITICAL**: NON TRACE BASED TESTS ARE ALREADY MODULARIZED AND DO NOT NEED MODULARIZATION.
|
|
24
32
|
After modularization, if errors remain, call skyramp_fix_errors.
|
|
25
33
|
|
|
26
|
-
CRITICAL
|
|
34
|
+
**CRITICAL**: This tool expects you to complete the modularization by writing the refactored code back to the file.`,
|
|
27
35
|
inputSchema: modularizationSchema,
|
|
28
|
-
|
|
36
|
+
_meta: {
|
|
29
37
|
keywords: [
|
|
30
38
|
"modularization",
|
|
31
39
|
"code organization",
|
|
@@ -34,13 +42,38 @@ CRITICAL: This tool expects you to complete the modularization by writing the re
|
|
|
34
42
|
],
|
|
35
43
|
},
|
|
36
44
|
}, async (params) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
let errorResult;
|
|
46
|
+
try {
|
|
47
|
+
logger.info("Generating modularization", {
|
|
48
|
+
testFile: params.testFile,
|
|
49
|
+
language: params.language,
|
|
50
|
+
prompt: params.prompt,
|
|
51
|
+
testType: params.testType,
|
|
52
|
+
});
|
|
53
|
+
const service = new ModularizationService();
|
|
54
|
+
return await service.processModularizationRequest(params);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const errorMessage = `Modularization failed: ${error.message}`;
|
|
58
|
+
logger.error(errorMessage, error);
|
|
59
|
+
errorResult = {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: errorMessage,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
isError: true,
|
|
67
|
+
};
|
|
68
|
+
return errorResult;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
|
|
72
|
+
prompt: params.prompt,
|
|
73
|
+
testFile: params.testFile,
|
|
74
|
+
language: params.language,
|
|
75
|
+
testType: params.testType,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
45
78
|
});
|
|
46
79
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import Docker from "dockerode";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { Writable } from "stream";
|
|
5
|
-
import { logger } from "../utils/logger.js";
|
|
6
2
|
import { stripVTControlCharacters } from "util";
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
const
|
|
3
|
+
import { TestExecutionService } from "../services/TestExecutionService.js";
|
|
4
|
+
import { AnalyticsService } from "../services/AnalyticsService.js";
|
|
5
|
+
const TOOL_NAME = "skyramp_execute_test";
|
|
10
6
|
export function registerExecuteSkyrampTestTool(server) {
|
|
11
|
-
server.registerTool(
|
|
7
|
+
server.registerTool(TOOL_NAME, {
|
|
12
8
|
description: `Execute a Skyramp-generated test in isolated containerized environments for reliable, deterministic testing.
|
|
13
9
|
|
|
14
10
|
Skyramp is a comprehensive testing platform that generates reliable, out-of-the-box functional and performance tests with AI-powered scaffolding. The test execution engine runs your generated tests in controlled, isolated environments to ensure consistent results.
|
|
@@ -51,145 +47,44 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
|
|
|
51
47
|
.string()
|
|
52
48
|
.describe("Skyramp authentication token for test execution. USE EMPTY STRING WHEN USER CONFIRMS 'No token required'"),
|
|
53
49
|
},
|
|
54
|
-
|
|
50
|
+
_meta: {
|
|
55
51
|
keywords: ["run test", "execute test"],
|
|
56
52
|
},
|
|
57
53
|
}, async (params) => {
|
|
58
|
-
|
|
59
|
-
const containerMountPath = "/home/user";
|
|
60
|
-
// Use path.basename for safer filename extraction
|
|
61
|
-
const filename = path.basename(params.testFile);
|
|
62
|
-
if (!filename) {
|
|
63
|
-
throw new Error("Invalid test file path: could not extract filename");
|
|
64
|
-
}
|
|
65
|
-
const dockerSocketPath = "/var/run/docker.sock";
|
|
66
|
-
//remove workspace path from test file path
|
|
67
|
-
let testFilePath = path.relative(params.workspacePath, params.testFile);
|
|
68
|
-
testFilePath = path.resolve(containerMountPath, testFilePath);
|
|
69
|
-
var command = [
|
|
70
|
-
"./root/runner.sh",
|
|
71
|
-
params.language,
|
|
72
|
-
testFilePath,
|
|
73
|
-
params.testType,
|
|
74
|
-
];
|
|
75
|
-
const workspacePath = path.resolve(params.workspacePath);
|
|
76
|
-
// check if workspace valid path
|
|
77
|
-
// Validate that the workspace path exists and is accessible
|
|
78
|
-
try {
|
|
79
|
-
fs.accessSync(workspacePath, fs.constants.R_OK);
|
|
80
|
-
}
|
|
81
|
-
catch (err) {
|
|
82
|
-
throw new Error(`Workspace path does not exist or is not readable: ${workspacePath}`);
|
|
83
|
-
}
|
|
84
|
-
const hostConfig = {
|
|
85
|
-
ExtraHosts: ["host.docker.internal:host-gateway"],
|
|
86
|
-
Mounts: [
|
|
87
|
-
{
|
|
88
|
-
Type: "bind",
|
|
89
|
-
Target: dockerSocketPath,
|
|
90
|
-
Source: dockerSocketPath,
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
};
|
|
94
|
-
//lets mount the files and directories inside the workspace path to the container and exclude package-lock.json, package.json and node_modules directory
|
|
95
|
-
const workspaceFiles = fs.readdirSync(workspacePath);
|
|
96
|
-
const filesToMount = workspaceFiles.filter((file) => file !== "package-lock.json" &&
|
|
97
|
-
file !== "package.json" &&
|
|
98
|
-
file !== "node_modules");
|
|
99
|
-
hostConfig.Mounts?.push(...filesToMount.map((file) => ({
|
|
100
|
-
Type: "bind",
|
|
101
|
-
Target: path.join(containerMountPath, file),
|
|
102
|
-
Source: path.join(workspacePath, file),
|
|
103
|
-
})));
|
|
104
|
-
const env = [
|
|
105
|
-
"SKYRAMP_TEST_TOKEN=" + params.token,
|
|
106
|
-
"SKYRAMP_IN_DOCKER=true",
|
|
107
|
-
];
|
|
108
|
-
if (process.env.SKYRAMP_DEBUG) {
|
|
109
|
-
env.push("SKYRAMP_DEBUG=" + process.env.SKYRAMP_DEBUG);
|
|
110
|
-
}
|
|
111
|
-
if (process.env.API_KEY) {
|
|
112
|
-
env.push("API_KEY=" + process.env.API_KEY);
|
|
113
|
-
}
|
|
114
|
-
var output = "";
|
|
115
|
-
class DockerStream extends Writable {
|
|
116
|
-
_write(data, encode, cb) {
|
|
117
|
-
output += data.toString();
|
|
118
|
-
cb();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
var stream = new DockerStream();
|
|
54
|
+
let errorResult;
|
|
122
55
|
try {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// Pull the image if it does not exist
|
|
131
|
-
await new Promise((resolve, reject) => {
|
|
132
|
-
docker.pull(EXECUTOR_DOCKER_IMAGE, { platform: DOCKER_PLATFORM }, (err, stream) => {
|
|
133
|
-
if (err)
|
|
134
|
-
return reject(err);
|
|
135
|
-
if (!stream)
|
|
136
|
-
return reject(new Error("No stream received from docker pull"));
|
|
137
|
-
docker.modem.followProgress(stream, (err, res) => {
|
|
138
|
-
if (err)
|
|
139
|
-
return reject(err);
|
|
140
|
-
resolve(res);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
await docker
|
|
146
|
-
.run(EXECUTOR_DOCKER_IMAGE, command, stream, {
|
|
147
|
-
Env: env,
|
|
148
|
-
HostConfig: hostConfig,
|
|
149
|
-
})
|
|
150
|
-
.then(function (data) {
|
|
151
|
-
var result = data[0];
|
|
152
|
-
var container = data[1];
|
|
153
|
-
stream.end();
|
|
154
|
-
statusCode = result.StatusCode;
|
|
155
|
-
logger.debug("Docker container execution completed");
|
|
156
|
-
return container.remove();
|
|
157
|
-
})
|
|
158
|
-
.then(function (data) {
|
|
159
|
-
logger.debug("Docker container removed successfully");
|
|
160
|
-
})
|
|
161
|
-
.catch(function (err) {
|
|
162
|
-
logger.error("Docker container execution failed", {
|
|
163
|
-
error: err.message,
|
|
164
|
-
});
|
|
165
|
-
throw err;
|
|
166
|
-
});
|
|
167
|
-
logger.info("Test execution completed", {
|
|
168
|
-
output: output.substring(0, 200) + (output.length > 200 ? "..." : ""),
|
|
169
|
-
statusCode,
|
|
56
|
+
const executionService = new TestExecutionService();
|
|
57
|
+
const result = await executionService.executeTest({
|
|
58
|
+
testFile: params.testFile,
|
|
59
|
+
workspacePath: params.workspacePath,
|
|
60
|
+
language: params.language,
|
|
61
|
+
testType: params.testType,
|
|
62
|
+
token: params.token,
|
|
170
63
|
});
|
|
171
|
-
if (
|
|
172
|
-
|
|
64
|
+
if (!result.passed) {
|
|
65
|
+
errorResult = {
|
|
173
66
|
content: [
|
|
174
67
|
{
|
|
175
68
|
type: "text",
|
|
176
|
-
text: `Test execution failed: ${stripVTControlCharacters(output)}
|
|
69
|
+
text: `Test execution failed: ${stripVTControlCharacters(result.output || "")}
|
|
177
70
|
**IMPORTANT: IF THE EXECUTION FAILED BECAUSE OF A 401 STATUS CODE, ASK THE USER TO PROVIDE THE AUTHENTICATION TOKEN TO THE TOOL OR A PLACE FROM WHERE WE CAN READ THE TOKEN. DO NOT UPDATE THE GENERATED TEST FILE.**`,
|
|
178
71
|
},
|
|
179
72
|
],
|
|
73
|
+
isError: true,
|
|
180
74
|
};
|
|
75
|
+
return errorResult;
|
|
181
76
|
}
|
|
182
77
|
return {
|
|
183
78
|
content: [
|
|
184
79
|
{
|
|
185
80
|
type: "text",
|
|
186
|
-
text: `Test execution result: ${stripVTControlCharacters(output)}`,
|
|
81
|
+
text: `Test execution result: ${stripVTControlCharacters(result.output || "")}`,
|
|
187
82
|
},
|
|
188
83
|
],
|
|
189
84
|
};
|
|
190
85
|
}
|
|
191
86
|
catch (err) {
|
|
192
|
-
|
|
87
|
+
errorResult = {
|
|
193
88
|
content: [
|
|
194
89
|
{
|
|
195
90
|
type: "text",
|
|
@@ -198,6 +93,15 @@ For detailed documentation visit: https://www.skyramp.dev/docs/quickstart`,
|
|
|
198
93
|
],
|
|
199
94
|
isError: true,
|
|
200
95
|
};
|
|
96
|
+
return errorResult;
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
|
|
100
|
+
testFile: params.testFile,
|
|
101
|
+
workspacePath: params.workspacePath,
|
|
102
|
+
language: params.language,
|
|
103
|
+
testType: params.testType,
|
|
104
|
+
});
|
|
201
105
|
}
|
|
202
106
|
});
|
|
203
107
|
}
|
|
@@ -3,6 +3,7 @@ import { logger } from "../utils/logger.js";
|
|
|
3
3
|
import { getFixErrorsPrompt } from "../prompts/fix-error-prompt.js";
|
|
4
4
|
import { languageSchema } from "../types/TestTypes.js";
|
|
5
5
|
import { getLanguageSteps } from "../utils/language-helper.js";
|
|
6
|
+
import { AnalyticsService } from "../services/AnalyticsService.js";
|
|
6
7
|
const fixErrorSchema = z.object({
|
|
7
8
|
testFile: z
|
|
8
9
|
.string()
|
|
@@ -13,11 +14,12 @@ const fixErrorSchema = z.object({
|
|
|
13
14
|
.string()
|
|
14
15
|
.describe("The prompt or code content to process with modularization principles applied"),
|
|
15
16
|
});
|
|
17
|
+
const TOOL_NAME = "skyramp_fix_errors";
|
|
16
18
|
export function registerFixErrorTool(server) {
|
|
17
|
-
server.registerTool(
|
|
19
|
+
server.registerTool(TOOL_NAME, {
|
|
18
20
|
description: `Review the provided code for errors, inconsistencies, or missing pieces. If any are found, return corrected code. Otherwise, return the code unchanged.`,
|
|
19
21
|
inputSchema: fixErrorSchema.shape,
|
|
20
|
-
|
|
22
|
+
_meta: {
|
|
21
23
|
keywords: [
|
|
22
24
|
"modularization",
|
|
23
25
|
"code organization",
|
|
@@ -26,19 +28,41 @@ export function registerFixErrorTool(server) {
|
|
|
26
28
|
],
|
|
27
29
|
},
|
|
28
30
|
}, async (params) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
let errorResult;
|
|
32
|
+
try {
|
|
33
|
+
logger.info("Generating modularization", {
|
|
34
|
+
prompt: params.prompt,
|
|
35
|
+
testFile: params.testFile,
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: `
|
|
38
42
|
${getFixErrorsPrompt()}
|
|
39
43
|
${getLanguageSteps(params)}`,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const errorMessage = `Fix error generation failed: ${error.message}`;
|
|
50
|
+
errorResult = {
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
type: "text",
|
|
54
|
+
text: errorMessage,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
return errorResult;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, errorResult, {
|
|
63
|
+
prompt: params.prompt,
|
|
64
|
+
testFile: params.testFile,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
43
67
|
});
|
|
44
68
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { baseTestSchema, TestType } from "../../types/TestTypes.js";
|
|
3
3
|
import { TestGenerationService, } from "../../services/TestGenerationService.js";
|
|
4
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
4
5
|
const contractTestSchema = {
|
|
5
6
|
...baseTestSchema,
|
|
6
7
|
assertOptions: z
|
|
@@ -23,14 +24,19 @@ export class ContractTestService extends TestGenerationService {
|
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
const TOOL_NAME = "skyramp_contract_test_generation";
|
|
26
28
|
export function registerContractTestTool(server) {
|
|
27
|
-
server.registerTool(
|
|
29
|
+
server.registerTool(TOOL_NAME, {
|
|
28
30
|
description: `Generate a contract test using Skyramp's deterministic test generation platform.
|
|
29
31
|
|
|
30
32
|
Contract tests ensure your API implementation matches its OpenAPI/Swagger specification exactly. They validate request/response schemas, status codes, headers, and data types to prevent contract violations and API breaking changes.`,
|
|
31
33
|
inputSchema: contractTestSchema,
|
|
32
34
|
}, async (params) => {
|
|
33
35
|
const service = new ContractTestService();
|
|
34
|
-
|
|
36
|
+
const result = await service.generateTest(params);
|
|
37
|
+
AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
|
|
38
|
+
console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
|
|
39
|
+
});
|
|
40
|
+
return result;
|
|
35
41
|
});
|
|
36
42
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { baseSchema, baseTraceSchema, TestType, codeRefactoringSchema, } from "../../types/TestTypes.js";
|
|
3
3
|
import { TestGenerationService, } from "../../services/TestGenerationService.js";
|
|
4
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
4
5
|
const e2eTestSchema = {
|
|
5
6
|
...baseTraceSchema.shape,
|
|
6
7
|
playwrightInput: z
|
|
@@ -24,8 +25,9 @@ export class E2ETestService extends TestGenerationService {
|
|
|
24
25
|
return null;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
28
|
+
const TOOL_NAME = "skyramp_e2e_test_generation";
|
|
27
29
|
export function registerE2ETestTool(server) {
|
|
28
|
-
server.registerTool(
|
|
30
|
+
server.registerTool(TOOL_NAME, {
|
|
29
31
|
description: `Generate an End-to-End (E2E) test using Skyramp's deterministic test generation platform.
|
|
30
32
|
|
|
31
33
|
End-to-End tests validate complete user journeys by testing the entire application flow from frontend UI interactions to backend API responses. They ensure that all components work together correctly in realistic user scenarios, providing the highest confidence in application functionality.
|
|
@@ -33,11 +35,15 @@ End-to-End tests validate complete user journeys by testing the entire applicati
|
|
|
33
35
|
TRACE & UI INTEGRATION:
|
|
34
36
|
E2E tests require both trace files (capturing backend API interactions) and Playwright recordings (capturing UI interactions captured using start_trace_collection tool) to generate comprehensive tests that validate the complete user experience.`,
|
|
35
37
|
inputSchema: e2eTestSchema,
|
|
36
|
-
|
|
38
|
+
_meta: {
|
|
37
39
|
keywords: ["e2e test", "end-to-end test"],
|
|
38
40
|
},
|
|
39
41
|
}, async (params) => {
|
|
40
42
|
const service = new E2ETestService();
|
|
41
|
-
|
|
43
|
+
const result = await service.generateTest(params);
|
|
44
|
+
AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
|
|
45
|
+
console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
|
|
46
|
+
});
|
|
47
|
+
return result;
|
|
42
48
|
});
|
|
43
49
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { baseTestSchema, TestType } from "../../types/TestTypes.js";
|
|
2
2
|
import { TestGenerationService, } from "../../services/TestGenerationService.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
4
5
|
const fuzzTestSchema = {
|
|
5
6
|
...baseTestSchema,
|
|
6
7
|
responseData: z
|
|
@@ -19,17 +20,22 @@ export class FuzzTestService extends TestGenerationService {
|
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
const TOOL_NAME = "skyramp_fuzz_test_generation";
|
|
22
24
|
export function registerFuzzTestTool(server) {
|
|
23
|
-
server.registerTool(
|
|
25
|
+
server.registerTool(TOOL_NAME, {
|
|
24
26
|
description: `Generate a fuzz test using Skyramp's deterministic test generation platform.
|
|
25
27
|
|
|
26
28
|
Fuzz tests improve application security and reliability by sending invalid, malformed, or unexpected data to your API endpoints. They help discover edge cases, input validation issues, error handling problems, and potential security vulnerabilities.`,
|
|
27
29
|
inputSchema: fuzzTestSchema,
|
|
28
|
-
|
|
30
|
+
_meta: {
|
|
29
31
|
keywords: ["negative test", "random test"],
|
|
30
32
|
},
|
|
31
33
|
}, async (params) => {
|
|
32
34
|
const service = new FuzzTestService();
|
|
33
|
-
|
|
35
|
+
const result = await service.generateTest(params);
|
|
36
|
+
AnalyticsService.pushTestGenerationToolEvent(TOOL_NAME, result, params).catch((error) => {
|
|
37
|
+
console.error(`Error pushing tool event ${TOOL_NAME}`, { error });
|
|
38
|
+
});
|
|
39
|
+
return result;
|
|
34
40
|
});
|
|
35
41
|
}
|