@performance-agent/mcp-server 1.0.1 â 1.0.6
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/README.md +400 -25
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +783 -47
- package/dist/index.js.map +1 -1
- package/dist/prompts/jmx_prompt.txt +262 -0
- package/dist/prompts/prompts/jmx_prompt.txt +262 -0
- package/dist/tools/azure-infra/config-parser.d.ts +14 -0
- package/dist/tools/azure-infra/config-parser.d.ts.map +1 -0
- package/dist/tools/azure-infra/config-parser.js +361 -0
- package/dist/tools/azure-infra/config-parser.js.map +1 -0
- package/dist/tools/azure-infra/index.d.ts +52 -0
- package/dist/tools/azure-infra/index.d.ts.map +1 -0
- package/dist/tools/azure-infra/index.js +448 -0
- package/dist/tools/azure-infra/index.js.map +1 -0
- package/dist/tools/azure-infra/terraform-generator.d.ts +19 -0
- package/dist/tools/azure-infra/terraform-generator.d.ts.map +1 -0
- package/dist/tools/azure-infra/terraform-generator.js +458 -0
- package/dist/tools/azure-infra/terraform-generator.js.map +1 -0
- package/dist/tools/azure-infra/types.d.ts +123 -0
- package/dist/tools/azure-infra/types.d.ts.map +1 -0
- package/dist/tools/azure-infra/types.js +95 -0
- package/dist/tools/azure-infra/types.js.map +1 -0
- package/dist/tools/cloud-executor/index.d.ts +78 -0
- package/dist/tools/cloud-executor/index.d.ts.map +1 -0
- package/dist/tools/cloud-executor/index.js +528 -0
- package/dist/tools/cloud-executor/index.js.map +1 -0
- package/dist/tools/cloud-executor/result-analyzer.d.ts +65 -0
- package/dist/tools/cloud-executor/result-analyzer.d.ts.map +1 -0
- package/dist/tools/cloud-executor/result-analyzer.js +367 -0
- package/dist/tools/cloud-executor/result-analyzer.js.map +1 -0
- package/dist/tools/cloud-executor/vm-metrics.d.ts +87 -0
- package/dist/tools/cloud-executor/vm-metrics.d.ts.map +1 -0
- package/dist/tools/cloud-executor/vm-metrics.js +506 -0
- package/dist/tools/cloud-executor/vm-metrics.js.map +1 -0
- package/dist/tools/jmx-generator/index.d.ts +20 -0
- package/dist/tools/jmx-generator/index.d.ts.map +1 -0
- package/dist/tools/jmx-generator/index.js +115 -0
- package/dist/tools/jmx-generator/index.js.map +1 -0
- package/dist/tools/jmx-generator/sanitizer.d.ts +19 -0
- package/dist/tools/jmx-generator/sanitizer.d.ts.map +1 -0
- package/dist/tools/jmx-generator/sanitizer.js +166 -0
- package/dist/tools/jmx-generator/sanitizer.js.map +1 -0
- package/package.json +5 -2
- package/scripts/copy-prompts.js +46 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JMX Generator - Generate JMeter scripts from Swagger/OpenAPI specifications using Azure OpenAI
|
|
3
|
+
*
|
|
4
|
+
* This module provides direct OpenAI integration for JMX generation, eliminating the need
|
|
5
|
+
* for the Flask backend API.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { sanitizeJMX } from './sanitizer.js';
|
|
11
|
+
// ES module equivalent of __dirname
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
// Azure OpenAI configuration from environment variables
|
|
15
|
+
const OPENAI_ENDPOINT = process.env.OPENAI_ENDPOINT || process.env.AZURE_OPENAI_ENDPOINT || '';
|
|
16
|
+
const OPENAI_API_KEY = process.env.OPENAI_API_KEY || process.env.AZURE_OPENAI_KEY || '';
|
|
17
|
+
const OPENAI_DEPLOYMENT = process.env.OPENAI_DEPLOYMENT || process.env.AZURE_OPENAI_DEPLOYMENT || 'gpt-4';
|
|
18
|
+
const OPENAI_API_VERSION = process.env.OPENAI_API_VERSION || '2024-02-15-preview';
|
|
19
|
+
/**
|
|
20
|
+
* Generate JMeter JMX script from Swagger/OpenAPI specification
|
|
21
|
+
* @param swaggerContent Swagger/OpenAPI JSON object
|
|
22
|
+
* @param repoName Optional repository name for logging
|
|
23
|
+
* @returns Result object with success status and JMX script or error
|
|
24
|
+
*/
|
|
25
|
+
export async function generateJMX(swaggerContent, repoName) {
|
|
26
|
+
try {
|
|
27
|
+
console.log(`[JMX Generator] Starting JMX generation${repoName ? ` for repo: ${repoName}` : ''}...`);
|
|
28
|
+
// Validate Azure OpenAI configuration
|
|
29
|
+
if (!OPENAI_ENDPOINT || !OPENAI_API_KEY) {
|
|
30
|
+
const error = 'Azure OpenAI configuration missing. Set OPENAI_ENDPOINT and OPENAI_API_KEY environment variables.';
|
|
31
|
+
console.error(`[JMX Generator] ${error}`);
|
|
32
|
+
return { success: false, error };
|
|
33
|
+
}
|
|
34
|
+
// Load JMX prompt template
|
|
35
|
+
const promptPath = join(__dirname, '../../prompts/jmx_prompt.txt');
|
|
36
|
+
let promptTemplate;
|
|
37
|
+
try {
|
|
38
|
+
promptTemplate = readFileSync(promptPath, 'utf-8');
|
|
39
|
+
console.log('[JMX Generator] Loaded JMX prompt template');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const error = `Failed to load JMX prompt template from ${promptPath}: ${err}`;
|
|
43
|
+
console.error(`[JMX Generator] ${error}`);
|
|
44
|
+
return { success: false, error };
|
|
45
|
+
}
|
|
46
|
+
// Format prompt with Swagger content
|
|
47
|
+
const swaggerText = JSON.stringify(swaggerContent, null, 2);
|
|
48
|
+
const formattedPrompt = promptTemplate.replace('{swagger_text}', swaggerText);
|
|
49
|
+
console.log(`[JMX Generator] Formatted prompt (${formattedPrompt.length} chars, Swagger: ${swaggerText.length} chars)`);
|
|
50
|
+
// Call Azure OpenAI API using fetch
|
|
51
|
+
console.log(`[JMX Generator] Calling Azure OpenAI at ${OPENAI_ENDPOINT}...`);
|
|
52
|
+
const url = `${OPENAI_ENDPOINT}/openai/deployments/${OPENAI_DEPLOYMENT}/chat/completions?api-version=${OPENAI_API_VERSION}`;
|
|
53
|
+
const response = await fetch(url, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
'api-key': OPENAI_API_KEY,
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
messages: [
|
|
61
|
+
{
|
|
62
|
+
role: 'user',
|
|
63
|
+
content: formattedPrompt,
|
|
64
|
+
},
|
|
65
|
+
]
|
|
66
|
+
}),
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const errorText = await response.text();
|
|
70
|
+
const error = `Azure OpenAI API error (${response.status}): ${errorText}`;
|
|
71
|
+
console.error(`[JMX Generator] ${error}`);
|
|
72
|
+
return { success: false, error };
|
|
73
|
+
}
|
|
74
|
+
const data = await response.json();
|
|
75
|
+
if (!data.choices || data.choices.length === 0) {
|
|
76
|
+
const error = 'Azure OpenAI returned no choices';
|
|
77
|
+
console.error(`[JMX Generator] ${error}`);
|
|
78
|
+
return { success: false, error };
|
|
79
|
+
}
|
|
80
|
+
let jmxScript = data.choices[0].message?.content?.trim() || '';
|
|
81
|
+
console.log(`[JMX Generator] Received response from OpenAI (${jmxScript.length} chars)`);
|
|
82
|
+
// Remove markdown code blocks if present
|
|
83
|
+
if (jmxScript.startsWith('```')) {
|
|
84
|
+
console.log('[JMX Generator] Removing markdown code blocks...');
|
|
85
|
+
jmxScript = jmxScript
|
|
86
|
+
.replace(/^```xml\n?/i, '')
|
|
87
|
+
.replace(/^```\n?/, '')
|
|
88
|
+
.replace(/\n?```$/, '')
|
|
89
|
+
.trim();
|
|
90
|
+
}
|
|
91
|
+
// Sanitize the JMX script
|
|
92
|
+
console.log('[JMX Generator] Sanitizing JMX script...');
|
|
93
|
+
jmxScript = sanitizeJMX(jmxScript);
|
|
94
|
+
// Validate that we have XML content
|
|
95
|
+
if (!jmxScript.startsWith('<?xml')) {
|
|
96
|
+
const error = 'Generated content is not valid XML';
|
|
97
|
+
console.error(`[JMX Generator] ${error}. Content preview: ${jmxScript.substring(0, 200)}`);
|
|
98
|
+
return { success: false, error };
|
|
99
|
+
}
|
|
100
|
+
console.log(`[JMX Generator] Successfully generated JMX script (${jmxScript.length} chars)`);
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
jmx_script: jmxScript,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const errorMsg = `JMX generation failed: ${error}`;
|
|
108
|
+
console.error(`[JMX Generator] ${errorMsg}`);
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: errorMsg,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/jmx-generator/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JMX Sanitizer - Cleans up common invalid JMeter XML patterns in AI output
|
|
3
|
+
*
|
|
4
|
+
* This module sanitizes JMX (JMeter XML) files to fix common issues:
|
|
5
|
+
* - Adds missing guiclass attributes for test elements
|
|
6
|
+
* - Replaces ArrayList-based HTTP file args with proper HTTPFileArgs container
|
|
7
|
+
* - Removes ArrayList elementProp entries that cause casting errors
|
|
8
|
+
* - Fixes invalid <argument> tags into proper <elementProp elementType="Argument">
|
|
9
|
+
* - Ensures Arguments blocks have <collectionProp> wrapper
|
|
10
|
+
* - Normalizes enabled="true" attributes
|
|
11
|
+
* - Ensures every major element is followed by <hashTree/>
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Sanitize JMeter XML to fix common AI-generated errors
|
|
15
|
+
* @param xmlText Raw XML text from AI model
|
|
16
|
+
* @returns Sanitized XML text that's loadable in JMeter
|
|
17
|
+
*/
|
|
18
|
+
export declare function sanitizeJMX(xmlText: string): string;
|
|
19
|
+
//# sourceMappingURL=sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../../src/tools/jmx-generator/sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA4PnD"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JMX Sanitizer - Cleans up common invalid JMeter XML patterns in AI output
|
|
3
|
+
*
|
|
4
|
+
* This module sanitizes JMX (JMeter XML) files to fix common issues:
|
|
5
|
+
* - Adds missing guiclass attributes for test elements
|
|
6
|
+
* - Replaces ArrayList-based HTTP file args with proper HTTPFileArgs container
|
|
7
|
+
* - Removes ArrayList elementProp entries that cause casting errors
|
|
8
|
+
* - Fixes invalid <argument> tags into proper <elementProp elementType="Argument">
|
|
9
|
+
* - Ensures Arguments blocks have <collectionProp> wrapper
|
|
10
|
+
* - Normalizes enabled="true" attributes
|
|
11
|
+
* - Ensures every major element is followed by <hashTree/>
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Sanitize JMeter XML to fix common AI-generated errors
|
|
15
|
+
* @param xmlText Raw XML text from AI model
|
|
16
|
+
* @returns Sanitized XML text that's loadable in JMeter
|
|
17
|
+
*/
|
|
18
|
+
export function sanitizeJMX(xmlText) {
|
|
19
|
+
if (!xmlText) {
|
|
20
|
+
return xmlText;
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
console.log('[JMX Sanitizer] Starting sanitization...');
|
|
24
|
+
// Fix invalid root structure: jmeterTestPlan should not have testclass/guiclass
|
|
25
|
+
xmlText = xmlText.replace(/<jmeterTestPlan\s+guiclass="[^"]*"\s+testclass="[^"]*"\s+testname="[^"]*"\s+enabled="[^"]*"/g, '<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3"');
|
|
26
|
+
// Fix: Extract user-defined variables from TestPlan property and create separate Arguments element
|
|
27
|
+
const userVarsMatch = xmlText.match(/<stringProp name="TestPlan\.user_defined_variables">\s*((?:<elementProp[^>]*>.*?<\/elementProp>\s*)+)<\/stringProp>/s);
|
|
28
|
+
if (userVarsMatch) {
|
|
29
|
+
console.log('[JMX Sanitizer] Extracting user-defined variables to separate Arguments element...');
|
|
30
|
+
const variablesContent = userVarsMatch[1];
|
|
31
|
+
// Create proper Arguments element with collectionProp wrapper
|
|
32
|
+
const argumentsElement = `<Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
|
|
33
|
+
<collectionProp name="Arguments.arguments">
|
|
34
|
+
${variablesContent.trim()}
|
|
35
|
+
</collectionProp>
|
|
36
|
+
</Arguments>
|
|
37
|
+
<hashTree/>`;
|
|
38
|
+
// Remove the TestPlan.user_defined_variables property
|
|
39
|
+
xmlText = xmlText.replace(/<stringProp name="TestPlan\.user_defined_variables">.*?<\/stringProp>\s*/s, '');
|
|
40
|
+
// Insert the Arguments element as first child in TestPlan's hashTree
|
|
41
|
+
xmlText = xmlText.replace(/(<\/TestPlan>\s*<\/hashTree>)/, `</TestPlan>\n <hashTree>\n ${argumentsElement}\n `);
|
|
42
|
+
const varCount = (variablesContent.match(/elementProp/g) || []).length;
|
|
43
|
+
console.log(`[JMX Sanitizer] Created separate User Defined Variables with ${varCount} variables`);
|
|
44
|
+
}
|
|
45
|
+
// Fix missing TestPlan wrapper after jmeterTestPlan
|
|
46
|
+
if (/<jmeterTestPlan[^>]*>\s*<hashTree\/>\s*<stringProp/.test(xmlText)) {
|
|
47
|
+
console.log('[JMX Sanitizer] Fixing missing TestPlan wrapper...');
|
|
48
|
+
xmlText = xmlText.replace(/(<jmeterTestPlan[^>]*>)\s*<hashTree\/>\s*(<stringProp)/, '$1\n <hashTree>\n <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="API Test Plan" enabled="true">\n $2');
|
|
49
|
+
}
|
|
50
|
+
// Ensure TestPlan properties are wrapped correctly
|
|
51
|
+
if (/<\/TestPlan>\s*<hashTree\/>\s*<elementProp name="User Defined Variables"/.test(xmlText)) {
|
|
52
|
+
console.log('[JMX Sanitizer] Moving User Defined Variables inside TestPlan...');
|
|
53
|
+
xmlText = xmlText.replace(/(<\/TestPlan>)\s*<hashTree\/>\s*(<elementProp name="User Defined Variables"[^>]*>.*?<\/elementProp>)/s, '$2\n <boolProp name="TestPlan.functional_mode">false</boolProp>\n <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>\n $1');
|
|
54
|
+
}
|
|
55
|
+
// Fix invalid elementType values
|
|
56
|
+
xmlText = xmlText.replace(/elementType="StringParameter"/g, 'elementType="Argument"');
|
|
57
|
+
// Fix invalid property type names
|
|
58
|
+
if (xmlText.includes('booleanProp')) {
|
|
59
|
+
console.log('[JMX Sanitizer] Fixing booleanProp -> boolProp...');
|
|
60
|
+
xmlText = xmlText.replace(/<booleanProp/g, '<boolProp');
|
|
61
|
+
xmlText = xmlText.replace(/<\/booleanProp>/g, '</boolProp>');
|
|
62
|
+
}
|
|
63
|
+
// Fix common XML nesting errors in ResponseAssertion
|
|
64
|
+
xmlText = xmlText.replace(/(<collectionProp[^>]*>)\s*(<stringProp[^>]*>[^<]*<\/stringProp>)\s*<\/stringProp>/g, '$1\n $2');
|
|
65
|
+
// Fix: <collectionProp> closed with </stringProp>
|
|
66
|
+
xmlText = xmlText.replace(/(<collectionProp[^>]*>.*?)<\/stringProp>(\s*<\/ResponseAssertion>)/gs, '$1</collectionProp>$2');
|
|
67
|
+
// Fix: <stringProp> closed with </collectionProp> in ResponseAssertion
|
|
68
|
+
if (xmlText.includes('Assertion.test_field')) {
|
|
69
|
+
xmlText = xmlText.replace(/(<stringProp name="Assertion\.test_field">[^<]*)<\/collectionProp>/g, '$1</stringProp>');
|
|
70
|
+
console.log('[JMX Sanitizer] Fixed mismatched closing tag for Assertion.test_field');
|
|
71
|
+
}
|
|
72
|
+
// General fix: <stringProp> incorrectly closed with </collectionProp>
|
|
73
|
+
xmlText = xmlText.replace(/(<stringProp[^>]*>[^<]*)<\/collectionProp>/g, '$1</stringProp>');
|
|
74
|
+
// Fix: Remove invalid elementProp with elementType="Assertion" inside ResponseAssertion
|
|
75
|
+
if (xmlText.includes('elementType="Assertion"')) {
|
|
76
|
+
console.log('[JMX Sanitizer] Fixing invalid elementType="Assertion" in ResponseAssertion...');
|
|
77
|
+
xmlText = xmlText.replace(/<elementProp[^>]*elementType="Assertion"[^>]*>\s*(<stringProp[^>]*>[^<]*<\/stringProp>)\s*<\/elementProp>/g, '$1');
|
|
78
|
+
}
|
|
79
|
+
// Fix stray <argument> tags into proper elementProp Argument
|
|
80
|
+
if (xmlText.includes('<argument>')) {
|
|
81
|
+
console.log('[JMX Sanitizer] Fixing <argument> tags to proper elementProp...');
|
|
82
|
+
// Pattern 1: <argument><name>...</name><value>...</value></argument>
|
|
83
|
+
xmlText = xmlText.replace(/<argument>\s*<name>([^<]+)<\/name>\s*<value>([^<]*)<\/value>\s*<\/argument>/g, `<elementProp name="$1" elementType="Argument">
|
|
84
|
+
<stringProp name="Argument.name">$1</stringProp>
|
|
85
|
+
<stringProp name="Argument.value">$2</stringProp>
|
|
86
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
|
87
|
+
</elementProp>`);
|
|
88
|
+
// Pattern 2: Simple <argument>value</argument>
|
|
89
|
+
xmlText = xmlText.replace(/<argument>([^<]*)<\/argument>/g, `<elementProp name="arg" elementType="Argument">
|
|
90
|
+
<stringProp name="Argument.name">arg</stringProp>
|
|
91
|
+
<stringProp name="Argument.value">$1</stringProp>
|
|
92
|
+
<stringProp name="Argument.metadata">=</stringProp>
|
|
93
|
+
</elementProp>`);
|
|
94
|
+
}
|
|
95
|
+
// Fix duplicate/malformed collectionProp on same line
|
|
96
|
+
xmlText = xmlText.replace(/<collectionProp name="Arguments\.arguments">\s*<collectionProp name="Arguments\.arguments">/g, '<collectionProp name="Arguments.arguments">');
|
|
97
|
+
console.log('[JMX Sanitizer] Checked for duplicate collectionProp tags');
|
|
98
|
+
// Fix Argument -> HTTPArgument inside HTTPsampler.Arguments
|
|
99
|
+
xmlText = xmlText.replace(/<elementProp name="HTTPsampler\.Arguments"[^>]*>.*?<\/elementProp>/gs, (match) => {
|
|
100
|
+
let content = match;
|
|
101
|
+
if (content.includes('elementType="Argument"') && content.includes('HTTPsampler.Arguments')) {
|
|
102
|
+
console.log('[JMX Sanitizer] Fixing Argument -> HTTPArgument in HTTPsampler.Arguments...');
|
|
103
|
+
content = content.replace(/<elementProp\s+name="[^"]*"\s+elementType="Argument">/g, (m) => m.replace('elementType="Argument"', 'elementType="HTTPArgument"'));
|
|
104
|
+
if (!content.includes('HTTPArgument.always_encode')) {
|
|
105
|
+
content = content.replace(/(<elementProp[^>]*elementType="HTTPArgument">)/, '$1\n <boolProp name="HTTPArgument.always_encode">false</boolProp>');
|
|
106
|
+
}
|
|
107
|
+
if (!content.includes('HTTPArgument.use_equals')) {
|
|
108
|
+
content = content.replace(/(<\/elementProp>)(?=.*HTTPArgument)/, ' <boolProp name="HTTPArgument.use_equals">true</boolProp>\n $1');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return content;
|
|
112
|
+
});
|
|
113
|
+
// Fix common hashTree structure issues
|
|
114
|
+
xmlText = xmlText.replace(/<hashTree>\s*<hashTree\/>\s*<\/hashTree>/g, '<hashTree/>');
|
|
115
|
+
xmlText = xmlText.replace(/<hashTree>\s*<hashTree>\s*<\/hashTree>\s*<\/hashTree>/g, '<hashTree/>');
|
|
116
|
+
// Ensure every major test element is followed by hashTree
|
|
117
|
+
const elements = ['HTTPSamplerProxy', 'HeaderManager', 'ResponseAssertion', 'ThreadGroup', 'Arguments'];
|
|
118
|
+
for (const element of elements) {
|
|
119
|
+
const pattern = new RegExp(`(</${element}>)(?!\\s*<hashTree)`, 'g');
|
|
120
|
+
xmlText = xmlText.replace(pattern, '$1\n <hashTree/>');
|
|
121
|
+
}
|
|
122
|
+
// Fix missing guiclass attributes
|
|
123
|
+
const guiclassMappings = {
|
|
124
|
+
'<TestPlan\\s+testclass="TestPlan"(?!\\s+guiclass=)': '<TestPlan testclass="TestPlan" guiclass="TestPlanGui"',
|
|
125
|
+
'<ThreadGroup\\s+testclass="ThreadGroup"(?!\\s+guiclass=)': '<ThreadGroup testclass="ThreadGroup" guiclass="ThreadGroupGui"',
|
|
126
|
+
'<HTTPSamplerProxy\\s+testclass="HTTPSamplerProxy"(?!\\s+guiclass=)': '<HTTPSamplerProxy testclass="HTTPSamplerProxy" guiclass="HttpTestSampleGui"',
|
|
127
|
+
'<Arguments\\s+testclass="Arguments"(?!\\s+guiclass=)': '<Arguments testclass="Arguments" guiclass="ArgumentsPanel"',
|
|
128
|
+
'<ResponseAssertion\\s+testclass="ResponseAssertion"(?!\\s+guiclass=)': '<ResponseAssertion testclass="ResponseAssertion" guiclass="AssertionGui"',
|
|
129
|
+
'<HeaderManager\\s+testclass="HeaderManager"(?!\\s+guiclass=)': '<HeaderManager testclass="HeaderManager" guiclass="HeaderPanel"',
|
|
130
|
+
'<LoopController\\s+testclass="LoopController"(?!\\s+guiclass=)': '<LoopController testclass="LoopController" guiclass="LoopControlPanel"',
|
|
131
|
+
};
|
|
132
|
+
for (const [pattern, replacement] of Object.entries(guiclassMappings)) {
|
|
133
|
+
xmlText = xmlText.replace(new RegExp(pattern, 'g'), replacement);
|
|
134
|
+
}
|
|
135
|
+
// Normalize enabled="true" attributes
|
|
136
|
+
const elementsToNormalize = ['TestPlan', 'ThreadGroup', 'HTTPSamplerProxy', 'Arguments', 'ResponseAssertion', 'HeaderManager'];
|
|
137
|
+
for (const element of elementsToNormalize) {
|
|
138
|
+
xmlText = xmlText.replace(new RegExp(`(<${element}[^>]*)(?<!enabled="true")>`, 'g'), '$1 enabled="true">');
|
|
139
|
+
}
|
|
140
|
+
// Fix ArrayList issues - comprehensive check
|
|
141
|
+
if (xmlText.includes('ArrayList')) {
|
|
142
|
+
console.log('[JMX Sanitizer] Found ArrayList references, fixing...');
|
|
143
|
+
// Fix HTTPsampler.Files with ArrayList
|
|
144
|
+
xmlText = xmlText.replace(/<elementProp name="HTTPsampler\.Files" elementType="ArrayList"\/>/g, '<elementProp name="HTTPsampler.Files" elementType="HTTPFileArgs">\n <collectionProp name="HTTPFileArgs.files"/>\n </elementProp>');
|
|
145
|
+
xmlText = xmlText.replace(/<elementProp name="HTTPsampler\.Files" elementType="ArrayList"[^>]*>.*?<\/elementProp>/gs, '<elementProp name="HTTPsampler.Files" elementType="HTTPFileArgs">\n <collectionProp name="HTTPFileArgs.files"/>\n </elementProp>');
|
|
146
|
+
// Remove any other ArrayList elementProp (self-closing or with content)
|
|
147
|
+
xmlText = xmlText.replace(/<elementProp[^>]*elementType="ArrayList"[^>]*\/>/g, '');
|
|
148
|
+
xmlText = xmlText.replace(/<elementProp[^>]*elementType="ArrayList"[^>]*>.*?<\/elementProp>/gs, '');
|
|
149
|
+
// Fix any collectionProp that might contain ArrayList references
|
|
150
|
+
xmlText = xmlText.replace(/<collectionProp name="Arguments\.arguments">\s*<ArrayList\/>/g, '<collectionProp name="Arguments.arguments">');
|
|
151
|
+
xmlText = xmlText.replace(/<collectionProp name="Arguments\.arguments">\s*<ArrayList>.*?<\/ArrayList>/gs, '<collectionProp name="Arguments.arguments">');
|
|
152
|
+
// Remove any standalone <ArrayList> tags
|
|
153
|
+
xmlText = xmlText.replace(/<ArrayList\s*\/>/g, '');
|
|
154
|
+
xmlText = xmlText.replace(/<ArrayList>.*?<\/ArrayList>/gs, '');
|
|
155
|
+
console.log('[JMX Sanitizer] ArrayList references removed');
|
|
156
|
+
}
|
|
157
|
+
console.log('[JMX Sanitizer] Sanitization complete');
|
|
158
|
+
// Note: XML validation is skipped in TypeScript version
|
|
159
|
+
// JMeter will validate when loading the file
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error(`[JMX Sanitizer] Error during sanitization: ${error}`);
|
|
163
|
+
}
|
|
164
|
+
return xmlText;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../../src/tools/jmx-generator/sanitizer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@performance-agent/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "MCP Server for Performance Testing Agent - JMX generation, test execution, and result analysis",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"performance-agent-mcp": "./dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc &&
|
|
11
|
+
"build": "tsc && node scripts/copy-prompts.js",
|
|
12
12
|
"dev": "tsx src/index.ts",
|
|
13
13
|
"prepare": "npm run build",
|
|
14
14
|
"test": "jest"
|
|
@@ -34,11 +34,14 @@
|
|
|
34
34
|
"escomplex": "^2.0.0-alpha",
|
|
35
35
|
"fs-extra": "^11.2.0",
|
|
36
36
|
"glob": "^10.3.0",
|
|
37
|
+
"openai": "^6.16.0",
|
|
37
38
|
"simple-git": "^3.21.0"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/fs-extra": "^11.0.4",
|
|
41
42
|
"@types/node": "^20.10.0",
|
|
43
|
+
"cpy-cli": "^6.0.0",
|
|
44
|
+
"cross-env": "^10.1.0",
|
|
42
45
|
"tsx": "^4.7.0",
|
|
43
46
|
"typescript": "^5.3.0"
|
|
44
47
|
},
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cross-platform script to copy prompts directory
|
|
5
|
+
* Works on Windows, macOS, and Linux
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs-extra';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
16
|
+
const srcPrompts = path.join(projectRoot, 'src', 'prompts');
|
|
17
|
+
const distPrompts = path.join(projectRoot, 'dist', 'prompts');
|
|
18
|
+
const distIndex = path.join(projectRoot, 'dist', 'index.js');
|
|
19
|
+
|
|
20
|
+
async function copyPrompts() {
|
|
21
|
+
try {
|
|
22
|
+
// Copy prompts directory
|
|
23
|
+
console.log('đ Copying prompts directory...');
|
|
24
|
+
await fs.copy(srcPrompts, distPrompts, { overwrite: true });
|
|
25
|
+
console.log('â
Prompts copied successfully');
|
|
26
|
+
|
|
27
|
+
// Make index.js executable (Unix/Linux/macOS only, no-op on Windows)
|
|
28
|
+
if (process.platform !== 'win32') {
|
|
29
|
+
try {
|
|
30
|
+
await fs.chmod(distIndex, 0o755);
|
|
31
|
+
console.log('â
Made index.js executable');
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.warn('â ī¸ Could not make index.js executable (not critical):', err.message);
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
console.log('âšī¸ Skipping chmod on Windows (not needed)');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('đ Build post-processing complete!');
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('â Error during build post-processing:', error);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
copyPrompts();
|