@skyramp/mcp 0.0.64-rc.7 → 0.0.64-rc.8
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 +2 -0
- package/build/prompts/testbot/testbot-prompts.js +9 -4
- package/build/resources/progressResource.js +14 -0
- package/build/tool-phase-coverage.test.js +41 -0
- package/build/tool-phases.js +42 -0
- package/build/tools/generate-tests/generateContractRestTool.js +9 -0
- package/package.json +6 -1
package/build/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import { registerSubmitReportTool } from "./tools/submitReportTool.js";
|
|
|
30
30
|
import { registerInitializeWorkspaceTool } from "./tools/workspace/initializeWorkspaceTool.js";
|
|
31
31
|
import { registerOneClickTool } from "./tools/one-click/oneClickTool.js";
|
|
32
32
|
import { registerAnalysisResources } from "./resources/analysisResources.js";
|
|
33
|
+
import { registerProgressResource } from "./resources/progressResource.js";
|
|
33
34
|
import { AnalyticsService } from "./services/AnalyticsService.js";
|
|
34
35
|
import { initCheck } from "./utils/initAgent.js";
|
|
35
36
|
import { registerPlaywrightTools, registerTraceRecordingPrompt, getPlaywrightTraceService, } from "./playwright/index.js";
|
|
@@ -196,6 +197,7 @@ const codeQualityTools = [
|
|
|
196
197
|
codeQualityTools.forEach((registerTool) => registerTool(server));
|
|
197
198
|
// Register analysis resources (MCP Resources for enriched data access)
|
|
198
199
|
registerAnalysisResources(server);
|
|
200
|
+
registerProgressResource(server);
|
|
199
201
|
// Register unified test-management tools (replaces separate test-maintenance tools)
|
|
200
202
|
registerAnalyzeChangesTool(server);
|
|
201
203
|
registerAnalyzeTestHealthTool(server);
|
|
@@ -152,12 +152,17 @@ If a test generation tool call fails:
|
|
|
152
152
|
5. Log skipped candidates in \`issuesFound\` with the error message.
|
|
153
153
|
|
|
154
154
|
### UI Test Execution Fix-up
|
|
155
|
-
If a generated UI test fails with a timeout waiting for an element after navigation (e.g. \`TimeoutError\` on \`getByTestId\` or \`locator\`), add a
|
|
155
|
+
If a generated UI test fails with a timeout waiting for an element after navigation (e.g. \`TimeoutError\` on \`getByTestId\` or \`locator\`), add a dynamic wait after each \`page.goto()\` call that waits for the page to be ready instead of using a fixed delay:
|
|
156
156
|
\`\`\`
|
|
157
|
-
// Wait for
|
|
158
|
-
await page.
|
|
157
|
+
// Wait for the page to fully load and hydrate before interacting
|
|
158
|
+
await page.waitForLoadState('networkidle');
|
|
159
159
|
\`\`\`
|
|
160
|
-
|
|
160
|
+
If the test still fails, wait for the specific element the test needs before interacting:
|
|
161
|
+
\`\`\`
|
|
162
|
+
// Wait for a visible element that indicates the page content has loaded
|
|
163
|
+
await page.locator('[data-testid="some-element"]').waitFor({ state: 'visible', timeout: 10000 });
|
|
164
|
+
\`\`\`
|
|
165
|
+
Do NOT use \`page.waitForTimeout()\` with fixed delays — these are flaky in CI where container startup and network latency vary. Always prefer \`waitForLoadState\` or \`waitFor\` on a specific locator.
|
|
161
166
|
|
|
162
167
|
**After generation, you MUST do exactly two things — nothing more, nothing less:**
|
|
163
168
|
1. **Fix chaining**: replace hardcoded IDs with dynamic response values — path params like \`id = 'id'\` → \`skyramp.get_response_value(prev_response, "id")\`, and hardcoded IDs in request bodies → dynamic values from prior responses.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TOOL_PHASE_MAP } from "../tool-phases.js";
|
|
2
|
+
export function registerProgressResource(server) {
|
|
3
|
+
server.registerResource("progress_tool_phases", "skyramp://progress/tool-phases", {
|
|
4
|
+
title: "Tool Phase Mapping",
|
|
5
|
+
description: "Maps Skyramp MCP tool names to testbot progress phases.",
|
|
6
|
+
mimeType: "application/json",
|
|
7
|
+
}, () => ({
|
|
8
|
+
contents: [{
|
|
9
|
+
uri: "skyramp://progress/tool-phases",
|
|
10
|
+
mimeType: "application/json",
|
|
11
|
+
text: JSON.stringify(TOOL_PHASE_MAP),
|
|
12
|
+
}],
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { TOOL_PHASE_MAP, TOOLS_WITHOUT_PHASE } from "./tool-phases.js";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
function findAllToolNames() {
|
|
5
|
+
const toolNames = [];
|
|
6
|
+
function walk(dir) {
|
|
7
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
8
|
+
const full = path.join(dir, entry.name);
|
|
9
|
+
if (entry.isDirectory()) {
|
|
10
|
+
walk(full);
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (!entry.name.endsWith(".ts"))
|
|
14
|
+
continue;
|
|
15
|
+
const content = fs.readFileSync(full, "utf-8");
|
|
16
|
+
const matches = content.matchAll(/const TOOL_NAME\s*=\s*["']([^"']+)["']/g);
|
|
17
|
+
for (const m of matches)
|
|
18
|
+
toolNames.push(m[1]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
walk(path.resolve(__dirname, "./tools"));
|
|
22
|
+
return toolNames;
|
|
23
|
+
}
|
|
24
|
+
describe("tool-phase-coverage", () => {
|
|
25
|
+
it("every registered tool has a phase or is explicitly excluded", () => {
|
|
26
|
+
const allTools = findAllToolNames();
|
|
27
|
+
expect(allTools.length).toBeGreaterThan(0);
|
|
28
|
+
const missing = allTools.filter(name => !(name in TOOL_PHASE_MAP) && !TOOLS_WITHOUT_PHASE.has(name));
|
|
29
|
+
if (missing.length > 0) {
|
|
30
|
+
throw new Error(`These tools are not in TOOL_PHASE_MAP or TOOLS_WITHOUT_PHASE in src/tool-phases.ts:\n` +
|
|
31
|
+
missing.map(n => ` - ${n}`).join("\n") +
|
|
32
|
+
`\nAdd them to the appropriate export in src/tool-phases.ts`);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
it("TOOL_PHASE_MAP contains only valid phases", () => {
|
|
36
|
+
const validPhases = new Set(["analyzing", "generating", "executing", "maintaining", "reporting"]);
|
|
37
|
+
for (const [tool, phase] of Object.entries(TOOL_PHASE_MAP)) {
|
|
38
|
+
expect(validPhases.has(phase)).toBe(true);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical mapping of Skyramp MCP tool names to testbot progress phases.
|
|
3
|
+
*
|
|
4
|
+
* The testbot progress UI reads this map at runtime to know which tool calls
|
|
5
|
+
* correspond to which progress steps. When adding or renaming tools, update
|
|
6
|
+
* this map so the progress UI stays accurate.
|
|
7
|
+
*
|
|
8
|
+
* Tools not in this map must be listed in TOOLS_WITHOUT_PHASE.
|
|
9
|
+
*
|
|
10
|
+
* Phases: analyzing, generating, executing, maintaining, reporting
|
|
11
|
+
*/
|
|
12
|
+
export const TOOL_PHASE_MAP = {
|
|
13
|
+
skyramp_recommend_tests: "analyzing",
|
|
14
|
+
skyramp_analyze_changes: "analyzing",
|
|
15
|
+
skyramp_smoke_test_generation: "generating",
|
|
16
|
+
skyramp_fuzz_test_generation: "generating",
|
|
17
|
+
skyramp_contract_test_generation: "generating",
|
|
18
|
+
skyramp_load_test_generation: "generating",
|
|
19
|
+
skyramp_integration_test_generation: "generating",
|
|
20
|
+
skyramp_e2e_test_generation: "generating",
|
|
21
|
+
skyramp_ui_test_generation: "generating",
|
|
22
|
+
skyramp_scenario_test_generation: "generating",
|
|
23
|
+
skyramp_mock_generation: "generating",
|
|
24
|
+
skyramp_execute_test: "executing",
|
|
25
|
+
skyramp_execute_tests: "executing",
|
|
26
|
+
skyramp_analyze_test_health: "maintaining",
|
|
27
|
+
skyramp_submit_report: "reporting",
|
|
28
|
+
};
|
|
29
|
+
/** Tools that intentionally have no progress phase (infrastructure/utility). */
|
|
30
|
+
export const TOOLS_WITHOUT_PHASE = new Set([
|
|
31
|
+
"skyramp_login",
|
|
32
|
+
"skyramp_logout",
|
|
33
|
+
"skyramp_initialize_workspace",
|
|
34
|
+
"skyramp_one_click_tool",
|
|
35
|
+
"skyramp_actions",
|
|
36
|
+
"skyramp_state_cleanup",
|
|
37
|
+
"skyramp_start_trace_collection",
|
|
38
|
+
"skyramp_stop_trace_collection",
|
|
39
|
+
"skyramp_fix_errors",
|
|
40
|
+
"skyramp_modularization",
|
|
41
|
+
"skyramp_reuse_code",
|
|
42
|
+
]);
|
|
@@ -92,6 +92,15 @@ export class ContractTestService extends TestGenerationService {
|
|
|
92
92
|
getTestType() {
|
|
93
93
|
return TestType.CONTRACT;
|
|
94
94
|
}
|
|
95
|
+
async handleApiAnalysis(params, generateOptions) {
|
|
96
|
+
// When apiSchema is provided, path parameters are resolved via parentRequestData
|
|
97
|
+
// provisioning — skip the base-class path-parameter validation prompt.
|
|
98
|
+
// Without apiSchema, fall through to normal validation.
|
|
99
|
+
if (params.apiSchema) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return super.handleApiAnalysis(params, generateOptions);
|
|
103
|
+
}
|
|
95
104
|
async generateTest(params) {
|
|
96
105
|
const result = await super.generateTest(params);
|
|
97
106
|
if (result.isError)
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyramp/mcp",
|
|
3
|
-
"version": "0.0.64-rc.
|
|
3
|
+
"version": "0.0.64-rc.8",
|
|
4
4
|
"main": "build/index.js",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./build/index.js",
|
|
7
|
+
"./tool-phases": "./build/tool-phases.js",
|
|
8
|
+
"./build/*": "./build/*"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
12
|
"mcp": "./build/index.js"
|