@skyramp/mcp 0.0.49 → 0.0.51
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/prompts/startTraceCollectionPrompts.js +4 -1
- package/build/prompts/testGenerationPrompt.js +4 -1
- package/build/prompts/testHealthPrompt.js +4 -1
- package/build/services/DriftAnalysisService.js +31 -10
- package/build/services/TestExecutionService.js +39 -1
- package/build/services/TestGenerationService.js +1 -1
- package/build/tools/executeSkyrampTestTool.js +5 -0
- package/build/tools/generate-tests/generateE2ERestTool.js +4 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.js +5 -2
- package/build/tools/generate-tests/generateLoadRestTool.js +4 -1
- package/build/tools/generate-tests/generateScenarioRestTool.js +8 -1
- package/build/tools/test-maintenance/actionsTool.js +56 -45
- package/build/tools/test-maintenance/analyzeTestDriftTool.js +5 -4
- package/build/tools/test-maintenance/calculateHealthScoresTool.js +12 -33
- package/build/tools/test-maintenance/discoverTestsTool.js +3 -3
- package/build/tools/test-maintenance/executeBatchTestsTool.js +5 -4
- package/build/tools/test-maintenance/stateCleanupTool.js +13 -8
- package/build/tools/test-recommendation/analyzeRepositoryTool.js +5 -1
- package/build/tools/test-recommendation/mapTestsTool.js +29 -19
- package/build/tools/test-recommendation/recommendTestsTool.js +27 -30
- package/build/tools/trace/startTraceCollectionTool.js +73 -18
- package/build/tools/trace/stopTraceCollectionTool.js +1 -1
- package/build/types/TestTypes.js +7 -1
- package/build/utils/AnalysisStateManager.js +73 -62
- package/package.json +7 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { StateManager } from "../../utils/AnalysisStateManager.js";
|
|
3
3
|
import { logger } from "../../utils/logger.js";
|
|
4
4
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
5
5
|
const TOOL_NAME = "skyramp_state_cleanup";
|
|
@@ -11,13 +11,17 @@ const TOOL_NAME = "skyramp_state_cleanup";
|
|
|
11
11
|
*/
|
|
12
12
|
export function registerStateCleanupTool(server) {
|
|
13
13
|
server.registerTool(TOOL_NAME, {
|
|
14
|
-
description: `Manage and cleanup
|
|
14
|
+
description: `Manage and cleanup Skyramp state files.
|
|
15
15
|
|
|
16
16
|
**WHAT IT DOES:**
|
|
17
|
-
- List all existing state files with details (size, age, session ID)
|
|
17
|
+
- List all existing state files with details (size, age, session ID, type)
|
|
18
18
|
- Delete state files older than specified age
|
|
19
19
|
- Show disk space usage by state files
|
|
20
20
|
|
|
21
|
+
**STATE TYPES MANAGED:**
|
|
22
|
+
- analysis: Test maintenance workflow (discovery, drift, execution, health)
|
|
23
|
+
- recommendation: Test recommendation workflow (analyze repo, map tests, recommend)
|
|
24
|
+
|
|
21
25
|
**WHEN TO USE:**
|
|
22
26
|
- Periodically to clean up old analysis sessions
|
|
23
27
|
- To check current state files in the system
|
|
@@ -45,8 +49,8 @@ Information about state files and cleanup results.`,
|
|
|
45
49
|
try {
|
|
46
50
|
logger.info(`State file ${args.action} requested`);
|
|
47
51
|
if (args.action === "list") {
|
|
48
|
-
// List all state files
|
|
49
|
-
const stateFiles = await
|
|
52
|
+
// List all state files (analysis, recommendation)
|
|
53
|
+
const stateFiles = await StateManager.listStateFiles();
|
|
50
54
|
if (stateFiles.length === 0) {
|
|
51
55
|
return {
|
|
52
56
|
content: [
|
|
@@ -72,6 +76,7 @@ Information about state files and cleanup results.`,
|
|
|
72
76
|
};
|
|
73
77
|
const fileDetails = stateFiles.map((file) => ({
|
|
74
78
|
sessionId: file.sessionId,
|
|
79
|
+
stateType: file.stateType,
|
|
75
80
|
path: file.path,
|
|
76
81
|
size: formatSize(file.size),
|
|
77
82
|
sizeBytes: file.size,
|
|
@@ -96,12 +101,12 @@ Information about state files and cleanup results.`,
|
|
|
96
101
|
};
|
|
97
102
|
}
|
|
98
103
|
else if (args.action === "cleanup") {
|
|
99
|
-
// Cleanup old state files
|
|
104
|
+
// Cleanup old state files (all types: analysis, recommendation)
|
|
100
105
|
const maxAgeHours = args.maxAgeHours || 24;
|
|
101
|
-
const deletedCount = await
|
|
106
|
+
const deletedCount = await StateManager.cleanupOldStateFiles(maxAgeHours);
|
|
102
107
|
logger.info(`Cleaned up ${deletedCount} state files older than ${maxAgeHours} hours`);
|
|
103
108
|
// Get remaining files
|
|
104
|
-
const remainingFiles = await
|
|
109
|
+
const remainingFiles = await StateManager.listStateFiles();
|
|
105
110
|
return {
|
|
106
111
|
content: [
|
|
107
112
|
{
|
|
@@ -96,7 +96,11 @@ Use the following tools to gather information:
|
|
|
96
96
|
|
|
97
97
|
${analysisPrompt}
|
|
98
98
|
|
|
99
|
-
After gathering all information
|
|
99
|
+
After gathering all information:
|
|
100
|
+
1. Return the RepositoryAnalysis JSON in your response
|
|
101
|
+
2. Then call \`skyramp_map_tests\` with:
|
|
102
|
+
- repositoryPath: \`${params.repositoryPath}\`
|
|
103
|
+
- analysisReport: <the JSON you just created>`,
|
|
100
104
|
},
|
|
101
105
|
],
|
|
102
106
|
isError: false,
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import { repositoryAnalysisSchema } from "../../types/RepositoryAnalysis.js";
|
|
3
3
|
import { TestType } from "../../types/TestTypes.js";
|
|
4
4
|
import { ScoringEngine } from "../../utils/scoring-engine.js";
|
|
5
|
+
import { StateManager, } from "../../utils/AnalysisStateManager.js";
|
|
5
6
|
import { logger } from "../../utils/logger.js";
|
|
6
7
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
7
8
|
/**
|
|
@@ -9,6 +10,9 @@ import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
|
9
10
|
* MCP tool for calculating test priority scores
|
|
10
11
|
*/
|
|
11
12
|
const mapTestsSchema = z.object({
|
|
13
|
+
repositoryPath: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe("Absolute path to the repository that was analyzed (used for saving results)"),
|
|
12
16
|
analysisReport: z
|
|
13
17
|
.union([z.string(), repositoryAnalysisSchema])
|
|
14
18
|
.describe("Repository analysis result (JSON string or object from skyramp_analyze_repository)"),
|
|
@@ -38,9 +42,10 @@ The scoring algorithm considers:
|
|
|
38
42
|
- Available artifacts (OpenAPI specs, Playwright recordings)
|
|
39
43
|
- Security requirements (authentication, sensitive data)
|
|
40
44
|
|
|
41
|
-
Example usage
|
|
45
|
+
Example usage:
|
|
42
46
|
\`\`\`
|
|
43
47
|
{
|
|
48
|
+
"repositoryPath": "/Users/dev/my-api",
|
|
44
49
|
"analysisReport": "<RepositoryAnalysis JSON from skyramp_analyze_repository>",
|
|
45
50
|
"customWeights": {
|
|
46
51
|
"load": 1.5,
|
|
@@ -49,13 +54,10 @@ Example usage (direct JSON):
|
|
|
49
54
|
}
|
|
50
55
|
\`\`\`
|
|
51
56
|
|
|
52
|
-
**
|
|
53
|
-
|
|
54
|
-
- DO NOT create or save any files (no test_mapping.json or .json/.md files).
|
|
55
|
-
- DO NOT use file write tools or save analysis to disk.
|
|
56
|
-
- Output the complete analysis JSON inline in your response.
|
|
57
|
+
**OUTPUT**:
|
|
58
|
+
Returns the state file path to pass to skyramp_recommend_tests
|
|
57
59
|
|
|
58
|
-
Output: TestMappingResult
|
|
60
|
+
Output: TestMappingResult with priority scores, and state file path for next step.`,
|
|
59
61
|
inputSchema: mapTestsSchema.shape,
|
|
60
62
|
}, async (params) => {
|
|
61
63
|
let errorResult;
|
|
@@ -142,14 +144,23 @@ Output: TestMappingResult JSON with priority scores, feasibility, and reasoning
|
|
|
142
144
|
contextFactors,
|
|
143
145
|
summary: { highPriority, mediumPriority, lowPriority },
|
|
144
146
|
};
|
|
147
|
+
// Save results using StateManager (stores in /tmp)
|
|
148
|
+
const stateManager = new StateManager("recommendation");
|
|
149
|
+
const stateData = {
|
|
150
|
+
repositoryPath: params.repositoryPath,
|
|
151
|
+
analysis,
|
|
152
|
+
mapping,
|
|
153
|
+
};
|
|
154
|
+
await stateManager.writeData(stateData, {
|
|
155
|
+
repositoryPath: params.repositoryPath,
|
|
156
|
+
step: "map-tests",
|
|
157
|
+
});
|
|
158
|
+
const stateFilePath = stateManager.getStatePath();
|
|
159
|
+
const sessionId = stateManager.getSessionId();
|
|
160
|
+
const stateSize = await stateManager.getSizeFormatted();
|
|
161
|
+
logger.info(`Saved test mapping to: ${stateFilePath} (${stateSize})`);
|
|
145
162
|
// Format output
|
|
146
|
-
const output =
|
|
147
|
-
- Return the JSON object directly in your response text.
|
|
148
|
-
- DO NOT create or save any files (no repository_analysis.json or .md files).
|
|
149
|
-
- DO NOT use file write tools or save analysis to disk.
|
|
150
|
-
- Output the complete analysis JSON inline in your response.
|
|
151
|
-
|
|
152
|
-
# Test Priority Mapping
|
|
163
|
+
const output = `# Test Priority Mapping
|
|
153
164
|
|
|
154
165
|
## Summary
|
|
155
166
|
- **High Priority**: ${mapping.summary.highPriority.join(", ") || "None"}
|
|
@@ -173,13 +184,12 @@ ${mapping.contextFactors.applied
|
|
|
173
184
|
.map((factor) => `- **${factor.factor}**: ${factor.impact} (×${factor.multiplier})`)
|
|
174
185
|
.join("\n")}
|
|
175
186
|
|
|
176
|
-
##
|
|
187
|
+
## Results Saved
|
|
177
188
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
\`\`\`
|
|
189
|
+
**State File**: \`${stateFilePath}\`
|
|
190
|
+
**Session ID**: \`${sessionId}\`
|
|
181
191
|
|
|
182
|
-
**Next Step**:
|
|
192
|
+
**Next Step**: Call \`skyramp_recommend_tests\` with stateFile: \`${stateFilePath}\``;
|
|
183
193
|
return {
|
|
184
194
|
content: [
|
|
185
195
|
{
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { testMappingResultSchema } from "../../types/TestMapping.js";
|
|
3
|
-
import { repositoryAnalysisSchema } from "../../types/RepositoryAnalysis.js";
|
|
4
2
|
import { getTestRecommendationPrompt } from "../../prompts/test-recommendation/test-recommendation-prompt.js";
|
|
3
|
+
import { StateManager, } from "../../utils/AnalysisStateManager.js";
|
|
5
4
|
import { logger } from "../../utils/logger.js";
|
|
6
5
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
7
6
|
/**
|
|
@@ -9,12 +8,9 @@ import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
|
9
8
|
* MCP tool for generating actionable test recommendations
|
|
10
9
|
*/
|
|
11
10
|
const recommendTestsSchema = z.object({
|
|
12
|
-
|
|
13
|
-
.
|
|
14
|
-
.describe("
|
|
15
|
-
analysisReport: z
|
|
16
|
-
.union([z.string(), repositoryAnalysisSchema])
|
|
17
|
-
.describe("Repository analysis result (JSON string or object from skyramp_analyze_repository)"),
|
|
11
|
+
stateFile: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe("Path to state file from skyramp_map_tests (contains both analysis and mapping results)"),
|
|
18
14
|
topN: z
|
|
19
15
|
.number()
|
|
20
16
|
.default(7)
|
|
@@ -29,7 +25,9 @@ export function registerRecommendTestsTool(server) {
|
|
|
29
25
|
server.registerTool(TOOL_NAME, {
|
|
30
26
|
description: `Generate actionable test recommendations with ready-to-use generation prompts.
|
|
31
27
|
|
|
32
|
-
|
|
28
|
+
**PREREQUISITE**: Call skyramp_map_tests first to get the stateFile path.
|
|
29
|
+
|
|
30
|
+
This tool reads the saved test mapping results and generates:
|
|
33
31
|
- Ordered list of recommended test types (high/medium/low priority)
|
|
34
32
|
- Specific test scenarios based on actual repository endpoints and flows
|
|
35
33
|
- Artifact availability status and guidance for missing artifacts
|
|
@@ -56,41 +54,37 @@ For each recommended test type, you'll get:
|
|
|
56
54
|
- THE PRIORITY SHOULD ONLY BE DEFINED AS HIGH, MEDIUM, OR LOW NOTHING ELSE.
|
|
57
55
|
- DO NOT SHOW ANY PRIORITY BREAKDOWN IN THE OUTPUT.
|
|
58
56
|
- DON'T MARK ANY TEST BLOCKED EVEN IF REQUIRED ARTIFACTS ARE MISSING.
|
|
59
|
-
- DO NOT SHOW RESULTS IN .MD OR .JSON OR ANY OTHER FILE FORMAT.
|
|
60
57
|
|
|
61
|
-
Output: TestRecommendation
|
|
58
|
+
Output: TestRecommendation with prioritized, actionable test recommendations.
|
|
62
59
|
**CRITICAL:** At the end of the tool execution, MUST display the below message:
|
|
63
60
|
** This tool is currently in Early Preview stage. Please verify the results. **`,
|
|
64
61
|
inputSchema: recommendTestsSchema.shape,
|
|
65
62
|
}, async (params) => {
|
|
66
63
|
let errorResult;
|
|
67
|
-
let prompt;
|
|
68
64
|
try {
|
|
69
65
|
logger.info("Recommend tests tool invoked", {
|
|
66
|
+
stateFile: params.stateFile,
|
|
70
67
|
topN: params.topN,
|
|
71
68
|
minScore: params.minScore,
|
|
72
69
|
});
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
throw new Error("priorityScores must be valid JSON string or TestMappingResult object");
|
|
82
|
-
}
|
|
70
|
+
// Read state file using StateManager
|
|
71
|
+
if (!params.stateFile) {
|
|
72
|
+
throw new Error("stateFile is required");
|
|
73
|
+
}
|
|
74
|
+
const stateManager = StateManager.fromStatePath(params.stateFile);
|
|
75
|
+
if (!stateManager.exists()) {
|
|
76
|
+
throw new Error(`State file not found: ${params.stateFile}. Run skyramp_map_tests first.`);
|
|
83
77
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
78
|
+
const stateData = await stateManager.readData();
|
|
79
|
+
if (!stateData) {
|
|
80
|
+
throw new Error(`Failed to read state file: ${params.stateFile}. Run skyramp_map_tests first.`);
|
|
81
|
+
}
|
|
82
|
+
const { analysis, mapping, repositoryPath } = stateData;
|
|
83
|
+
if (!analysis || !mapping) {
|
|
84
|
+
throw new Error("State file is missing required data (analysis or mapping)");
|
|
91
85
|
}
|
|
92
86
|
// Generate the prompt for LLM to create dynamic recommendations
|
|
93
|
-
prompt = getTestRecommendationPrompt(mapping, analysis, params.topN);
|
|
87
|
+
const prompt = getTestRecommendationPrompt(mapping, analysis, params.topN);
|
|
94
88
|
// Return prompt for LLM to execute
|
|
95
89
|
return {
|
|
96
90
|
content: [
|
|
@@ -98,6 +92,9 @@ Output: TestRecommendation JSON with prioritized, actionable test recommendation
|
|
|
98
92
|
type: "text",
|
|
99
93
|
text: `# Test Recommendation Request
|
|
100
94
|
|
|
95
|
+
**State File**: \`${params.stateFile}\`
|
|
96
|
+
**Repository**: \`${repositoryPath}\`
|
|
97
|
+
|
|
101
98
|
Please generate actionable test recommendations based on the priority scores and repository analysis.
|
|
102
99
|
|
|
103
100
|
${prompt}
|
|
@@ -3,8 +3,9 @@ import { SkyrampClient } from "@skyramp/skyramp";
|
|
|
3
3
|
import openProxyTerminalTracked from "../../utils/proxy-terminal.js";
|
|
4
4
|
import { TELEMETRY_entrypoint_FIELD_NAME } from "../../utils/utils.js";
|
|
5
5
|
import { logger } from "../../utils/logger.js";
|
|
6
|
-
import { basePlaywrightSchema } from "../../types/TestTypes.js";
|
|
6
|
+
import { basePlaywrightSchema, baseSchema, DEFAULT_SESSION_STORAGE_PATH, SESSION_STORAGE_FILENAME, } from "../../types/TestTypes.js";
|
|
7
7
|
import { AnalyticsService } from "../../services/AnalyticsService.js";
|
|
8
|
+
import path from "path";
|
|
8
9
|
const TOOL_NAME = "skyramp_start_trace_collection";
|
|
9
10
|
export function registerTraceTool(server) {
|
|
10
11
|
server.registerTool(TOOL_NAME, {
|
|
@@ -30,6 +31,7 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
30
31
|
.describe("Whether to enable Playwright for trace collection. Set to true for UI interactions, false for API-only tracing")
|
|
31
32
|
.default(true),
|
|
32
33
|
playwrightStoragePath: basePlaywrightSchema.shape.playwrightStoragePath,
|
|
34
|
+
playwrightSaveStoragePath: basePlaywrightSchema.shape.playwrightSaveStoragePath,
|
|
33
35
|
playwrightViewportSize: basePlaywrightSchema.shape.playwrightViewportSize,
|
|
34
36
|
runtime: z
|
|
35
37
|
.string()
|
|
@@ -55,6 +57,7 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
55
57
|
.number()
|
|
56
58
|
.default(35142)
|
|
57
59
|
.describe("Port number for the Docker worker service during trace collection"),
|
|
60
|
+
outputDir: baseSchema.shape.outputDir,
|
|
58
61
|
prompt: z
|
|
59
62
|
.string()
|
|
60
63
|
.describe("The prompt user provided to start trace collection"),
|
|
@@ -62,8 +65,24 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
62
65
|
_meta: {
|
|
63
66
|
keywords: ["start trace", "trace collection", "trace generation"],
|
|
64
67
|
},
|
|
65
|
-
}, async (params) => {
|
|
68
|
+
}, async (params, extra) => {
|
|
66
69
|
let errorResult;
|
|
70
|
+
// Helper to send progress notifications to the MCP client
|
|
71
|
+
const sendProgress = async (progress, total, message) => {
|
|
72
|
+
const progressToken = extra._meta?.progressToken;
|
|
73
|
+
if (progressToken !== undefined) {
|
|
74
|
+
const notification = {
|
|
75
|
+
method: "notifications/progress",
|
|
76
|
+
params: {
|
|
77
|
+
progressToken,
|
|
78
|
+
progress,
|
|
79
|
+
total,
|
|
80
|
+
message,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
await extra.sendNotification(notification);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
67
86
|
logger.info("Starting trace collection", {
|
|
68
87
|
playwright: params.playwright,
|
|
69
88
|
runtime: params.runtime,
|
|
@@ -72,25 +91,57 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
72
91
|
noProxy: params.noProxy,
|
|
73
92
|
dockerNetwork: params.dockerNetwork,
|
|
74
93
|
dockerWorkerPort: params.dockerWorkerPort,
|
|
94
|
+
outputDir: params.outputDir,
|
|
75
95
|
prompt: params.prompt,
|
|
76
96
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
generateInclude: params.include,
|
|
84
|
-
generateExclude: params.exclude,
|
|
85
|
-
generateNoProxy: params.noProxy,
|
|
86
|
-
unblock: true,
|
|
87
|
-
playwright: params.playwright,
|
|
88
|
-
playwrightStoragePath: params.playwrightStoragePath,
|
|
89
|
-
playwrightViewportSize: params.playwrightViewportSize,
|
|
90
|
-
entrypoint: TELEMETRY_entrypoint_FIELD_NAME,
|
|
91
|
-
};
|
|
97
|
+
// Resolve playwrightSaveStoragePath to outputDir if it's the default relative path
|
|
98
|
+
let saveStoragePath = params.playwrightSaveStoragePath;
|
|
99
|
+
if (params.outputDir &&
|
|
100
|
+
saveStoragePath === DEFAULT_SESSION_STORAGE_PATH) {
|
|
101
|
+
saveStoragePath = path.join(params.outputDir, SESSION_STORAGE_FILENAME);
|
|
102
|
+
}
|
|
92
103
|
try {
|
|
93
|
-
|
|
104
|
+
// Send initial progress
|
|
105
|
+
await sendProgress(0, 100, "Initializing trace collection...");
|
|
106
|
+
const client = new SkyrampClient();
|
|
107
|
+
const generateOptions = {
|
|
108
|
+
testType: "trace",
|
|
109
|
+
runtime: params.runtime,
|
|
110
|
+
dockerNetwork: params.dockerNetwork,
|
|
111
|
+
dockerWorkerPort: params.dockerWorkerPort.toString(),
|
|
112
|
+
generateInclude: params.include,
|
|
113
|
+
generateExclude: params.exclude,
|
|
114
|
+
generateNoProxy: params.noProxy,
|
|
115
|
+
unblock: true,
|
|
116
|
+
playwright: params.playwright,
|
|
117
|
+
playwrightStoragePath: params.playwrightStoragePath,
|
|
118
|
+
playwrightViewportSize: params.playwrightViewportSize,
|
|
119
|
+
entrypoint: TELEMETRY_entrypoint_FIELD_NAME,
|
|
120
|
+
};
|
|
121
|
+
// Send progress for configuration
|
|
122
|
+
const traceMode = params.playwright ? "UI + Backend" : "Backend-only";
|
|
123
|
+
await sendProgress(30, 100, `Configuring ${traceMode} trace collection...`);
|
|
124
|
+
// Start periodic progress updates during the long-running operation
|
|
125
|
+
const startTime = Date.now();
|
|
126
|
+
let progressTick = 0;
|
|
127
|
+
const progressInterval = setInterval(() => {
|
|
128
|
+
progressTick++;
|
|
129
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
130
|
+
// Progress moves from 30% to 65% during service startup
|
|
131
|
+
const percent = Math.min(30 + progressTick * 5, 65);
|
|
132
|
+
sendProgress(percent, 100, `Starting trace collection service... (${elapsed}s elapsed)`).catch(() => {
|
|
133
|
+
// Ignore progress notification errors
|
|
134
|
+
});
|
|
135
|
+
// Also log to server for visibility
|
|
136
|
+
logger.info(`Trace collection progress: ${percent}% (${elapsed}s elapsed)`);
|
|
137
|
+
}, 10000); // 10 seconds
|
|
138
|
+
let result;
|
|
139
|
+
try {
|
|
140
|
+
result = await client.generateRestTest(generateOptions);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
clearInterval(progressInterval);
|
|
144
|
+
}
|
|
94
145
|
if (result.toLowerCase().includes("failed")) {
|
|
95
146
|
errorResult = {
|
|
96
147
|
content: [
|
|
@@ -103,7 +154,11 @@ For detailed documentation visit: https://www.skyramp.dev/docs/load-test/advance
|
|
|
103
154
|
};
|
|
104
155
|
return errorResult;
|
|
105
156
|
}
|
|
157
|
+
// Send progress for opening proxy terminal
|
|
158
|
+
await sendProgress(70, 100, "Opening proxy terminal...");
|
|
106
159
|
await openProxyTerminalTracked();
|
|
160
|
+
// Send completion progress
|
|
161
|
+
await sendProgress(100, 100, "Trace collection started successfully");
|
|
107
162
|
errorResult = {
|
|
108
163
|
content: [
|
|
109
164
|
{
|
package/build/types/TestTypes.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
export const SESSION_STORAGE_FILENAME = "skyramp_session_storage.json";
|
|
3
|
+
export const DEFAULT_SESSION_STORAGE_PATH = `./${SESSION_STORAGE_FILENAME}`;
|
|
2
4
|
export var TestType;
|
|
3
5
|
(function (TestType) {
|
|
4
6
|
TestType["SMOKE"] = "smoke";
|
|
@@ -86,7 +88,11 @@ export const basePlaywrightSchema = z.object({
|
|
|
86
88
|
playwrightStoragePath: z
|
|
87
89
|
.string()
|
|
88
90
|
.optional()
|
|
89
|
-
.describe("Path to playwright session storage for trace collection with playwright enabled. THE PATH MUST BE AN ABSOLUTE PATH LIKE /Users/<path>/<filename>.json"),
|
|
91
|
+
.describe("Path to playwright session storage to load for trace collection with playwright enabled. THE PATH MUST BE AN ABSOLUTE PATH LIKE /Users/<path>/<filename>.json"),
|
|
92
|
+
playwrightSaveStoragePath: z
|
|
93
|
+
.string()
|
|
94
|
+
.default(DEFAULT_SESSION_STORAGE_PATH)
|
|
95
|
+
.describe(`Path to SAVE Playwright session storage after trace collection. When user says 'with session storage' or 'save session' without specifying a path, use the default '${DEFAULT_SESSION_STORAGE_PATH}'. This SAVES authentication state (cookies, localStorage, sessionStorage) when the browser closes. To LOAD existing auth state, use playwrightStoragePath instead. Can be relative (e.g., 'auth.json') or absolute path.`),
|
|
90
96
|
playwrightViewportSize: z
|
|
91
97
|
.string()
|
|
92
98
|
.default("")
|