@skyramp/mcp 0.2.5 → 0.2.7
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/commands/commandLibrary.d.ts +12 -0
- package/build/commands/recommendTestsAndExecuteCommand.d.ts +2 -0
- package/build/commands/testThisEndpointCommand.d.ts +2 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +1 -2
- package/build/playwright/PlaywrightTraceService.d.ts +32 -0
- package/build/playwright/index.d.ts +3 -0
- package/build/playwright/registerPlaywrightTools.d.ts +8 -0
- package/build/playwright/registerPlaywrightTools.js +12 -11
- package/build/playwright/traceRecordingPrompt.d.ts +13 -0
- package/build/playwright/traceRecordingPrompt.js +3 -11
- package/build/prompts/code-reuse.d.ts +1 -0
- package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +15 -0
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +2 -0
- package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +14 -3
- package/build/prompts/fix-error-prompt.d.ts +1 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.d.ts +1 -0
- package/build/prompts/modularization/integration-test-modularization.d.ts +1 -0
- package/build/prompts/modularization/ui-test-modularization.d.ts +1 -0
- package/build/prompts/personas.d.ts +21 -0
- package/build/prompts/pom-aware-code-reuse.d.ts +1 -0
- package/build/prompts/startTraceCollectionPrompts.d.ts +2 -0
- package/build/prompts/test-maintenance/actionsInstructions.d.ts +35 -0
- package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +4 -0
- package/build/prompts/test-maintenance/driftAnalysisSections.d.ts +13 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +84 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +1 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +1 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +17 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.js +7 -16
- package/build/prompts/test-recommendation/fullRepoCatalog.d.ts +7 -0
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +1 -0
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +1 -0
- package/build/prompts/test-recommendation/promptPlan.d.ts +203 -0
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +1 -0
- package/build/prompts/test-recommendation/recommendationSections.d.ts +35 -0
- package/build/prompts/test-recommendation/recommendationShared.d.ts +31 -0
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +7 -0
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +55 -0
- package/build/prompts/test-recommendation/scopeAssessment.js +2 -2
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +1 -0
- package/build/prompts/test-recommendation/scopeAssessment.test.js +1 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +6 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +4 -4
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +1 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +6 -99
- package/build/prompts/testbot/testbot-prompts.d.ts +11 -0
- package/build/prompts/testbot/testbot-prompts.js +198 -34
- package/build/prompts/testbot/testbot-prompts.test.d.ts +1 -0
- package/build/prompts/testbot/testbot-prompts.test.js +15 -73
- package/build/resources/analysisResources.d.ts +17 -0
- package/build/resources/progressResource.d.ts +2 -0
- package/build/resources/testbotResource.d.ts +2 -0
- package/build/services/AnalyticsService.d.ts +13 -0
- package/build/services/AnalyticsService.test.d.ts +1 -0
- package/build/services/AnalyticsService.test.js +86 -0
- package/build/services/ModularizationService.d.ts +11 -0
- package/build/services/ScenarioGenerationService.d.ts +37 -0
- package/build/services/ScenarioGenerationService.integration.test.d.ts +1 -0
- package/build/services/ScenarioGenerationService.integration.test.js +4 -0
- package/build/services/ScenarioGenerationService.test.d.ts +1 -0
- package/build/services/TestDiscoveryService.d.ts +128 -0
- package/build/services/TestDiscoveryService.test.d.ts +1 -0
- package/build/services/TestDiscoveryService.test.js +4 -3
- package/build/services/TestExecutionService.d.ts +46 -0
- package/build/services/TestExecutionService.test.d.ts +1 -0
- package/build/services/TestExecutionService.test.js +33 -25
- package/build/services/TestGenerationService.d.ts +56 -0
- package/build/services/TestGenerationService.test.d.ts +1 -0
- package/build/services/TestGenerationService.test.js +10 -8
- package/build/services/containerEnv.d.ts +14 -0
- package/build/tool-phase-coverage.test.d.ts +1 -0
- package/build/tool-phase-coverage.test.js +2 -0
- package/build/tool-phases.d.ts +38 -0
- package/build/tools/auth/loginTool.d.ts +2 -0
- package/build/tools/auth/logoutTool.d.ts +2 -0
- package/build/tools/code-refactor/codeReuseTool.d.ts +2 -0
- package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +2 -0
- package/build/tools/code-refactor/modularizationTool.d.ts +2 -0
- package/build/tools/executeSkyrampTestTool.d.ts +2 -0
- package/build/tools/fixErrorTool.d.ts +2 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +45 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +1 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +11 -9
- package/build/tools/generate-tests/generateContractRestTool.d.ts +31 -0
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +13 -0
- package/build/tools/generate-tests/generateFuzzRestTool.d.ts +10 -0
- package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +16 -0
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +18 -0
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +1 -0
- package/build/tools/generate-tests/generateMockRestTool.d.ts +64 -0
- package/build/tools/generate-tests/generateSmokeRestTool.d.ts +8 -0
- package/build/tools/generate-tests/generateUIRestTool.d.ts +14 -0
- package/build/tools/generate-tests/generateUIRestTool.js +1 -1
- package/build/tools/generate-tests/loadTestSchema.d.ts +39 -0
- package/build/tools/one-click/oneClickTool.d.ts +11 -0
- package/build/tools/submitReportTool.d.ts +384 -0
- package/build/tools/submitReportTool.js +144 -2
- package/build/tools/submitReportTool.test.d.ts +1 -0
- package/build/tools/submitReportTool.test.js +215 -5
- package/build/tools/test-management/actionsTool.d.ts +10 -0
- package/build/tools/test-management/analyzeChangesTool.d.ts +27 -0
- package/build/tools/test-management/analyzeChangesTool.js +44 -7
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +1 -0
- package/build/tools/test-management/analyzeChangesTool.test.js +76 -39
- package/build/tools/test-management/analyzeTestHealthTool.d.ts +2 -0
- package/build/tools/test-management/index.d.ts +3 -0
- package/build/tools/test-management/index.js +0 -1
- package/build/tools/trace/resolveSaveStoragePath.d.ts +7 -0
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +1 -0
- package/build/tools/trace/resolveSessionPaths.d.ts +40 -0
- package/build/tools/trace/resolveSessionPaths.test.d.ts +1 -0
- package/build/tools/trace/sessionState.d.ts +2 -0
- package/build/tools/trace/sessionState.test.d.ts +1 -0
- package/build/tools/trace/startTraceCollectionTool.d.ts +2 -0
- package/build/tools/trace/stopTraceCollectionTool.d.ts +2 -0
- package/build/tools/workspace/initScanWorkspaceTool.d.ts +4 -0
- package/build/tools/workspace/initializeWorkspaceTool.d.ts +2 -0
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +1 -0
- package/build/tools/workspace/initializeWorkspaceTool.test.js +134 -0
- package/build/types/OneClickCommands.d.ts +68 -0
- package/build/types/RepositoryAnalysis.d.ts +3004 -0
- package/build/types/TestAnalysis.d.ts +96 -0
- package/build/types/TestExecution.d.ts +53 -0
- package/build/types/TestRecommendation.d.ts +12 -0
- package/build/types/TestTypes.d.ts +234 -0
- package/build/utils/AnalysisStateManager.d.ts +182 -0
- package/build/utils/AnalysisStateManager.test.d.ts +1 -0
- package/build/utils/analyze-openapi.d.ts +1 -0
- package/build/utils/branchDiff.d.ts +18 -0
- package/build/utils/dartRouteExtractor.d.ts +45 -0
- package/build/utils/dartRouteExtractor.test.d.ts +1 -0
- package/build/utils/docker.d.ts +19 -0
- package/build/utils/docker.test.d.ts +1 -0
- package/build/utils/docker.test.js +10 -9
- package/build/utils/featureFlags.d.ts +37 -0
- package/build/utils/featureFlags.test.d.ts +1 -0
- package/build/utils/gitStaging.d.ts +24 -0
- package/build/utils/gitStaging.test.d.ts +1 -0
- package/build/utils/gitStaging.test.js +13 -7
- package/build/utils/httpDefaults.d.ts +10 -0
- package/build/utils/httpDefaults.test.d.ts +1 -0
- package/build/utils/initAgent.d.ts +36 -0
- package/build/utils/language-helper.d.ts +6 -0
- package/build/utils/logger.d.ts +11 -0
- package/build/utils/normalizeParams.d.ts +14 -0
- package/build/utils/normalizeSkyrampImports.d.ts +13 -0
- package/build/utils/pr-comment-parser.d.ts +31 -0
- package/build/utils/pr-comment-parser.test.d.ts +1 -0
- package/build/utils/pr-comment-parser.test.js +6 -5
- package/build/utils/projectMetadata.d.ts +15 -0
- package/build/utils/projectMetadata.test.d.ts +1 -0
- package/build/utils/proxy-terminal.d.ts +2 -0
- package/build/utils/repoScanner.d.ts +27 -0
- package/build/utils/repoScanner.test.d.ts +1 -0
- package/build/utils/routeParsers.d.ts +63 -0
- package/build/utils/routeParsers.test.d.ts +1 -0
- package/build/utils/scenarioDrafting.d.ts +71 -0
- package/build/utils/scenarioDrafting.test.d.ts +1 -0
- package/build/utils/skyrampMdContent.d.ts +5 -0
- package/build/utils/sourceRouteExtractor.d.ts +48 -0
- package/build/utils/sourceRouteExtractor.test.d.ts +1 -0
- package/build/utils/telemetry.d.ts +32 -0
- package/build/utils/telemetry.test.d.ts +1 -0
- package/build/utils/trace-parser.d.ts +32 -0
- package/build/utils/trace-parser.test.d.ts +6 -0
- package/build/utils/uiPageEnumerator.d.ts +146 -0
- package/build/utils/uiPageEnumerator.js +58 -14
- package/build/utils/uiPageEnumerator.test.d.ts +1 -0
- package/build/utils/uiPageEnumerator.test.js +223 -43
- package/build/utils/utils.d.ts +39 -0
- package/build/utils/utils.test.d.ts +1 -0
- package/build/utils/versions.d.ts +3 -0
- package/build/utils/versions.js +1 -1
- package/build/utils/workspaceAuth.d.ts +127 -0
- package/build/utils/workspaceAuth.test.d.ts +1 -0
- package/build/utils/workspaceAuth.test.js +25 -25
- package/build/workspace/index.d.ts +1 -0
- package/build/workspace/workspace.d.ts +390 -0
- package/build/workspace/workspace.test.d.ts +1 -0
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +14 -2
- package/package.json +8 -3
- package/build/tools/test-management/uiAnalyzeChangesTool.js +0 -155
- package/build/tools/test-management/uiAnalyzeChangesTool.test.js +0 -147
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
// AnalyticsService resolves the MCP version with
|
|
7
|
+
// `fileURLToPath(import.meta.url)` at module scope. Under ts-jest's old
|
|
8
|
+
// CommonJS transform that top-level import.meta failed to compile with TS1343,
|
|
9
|
+
// so this module — and therefore this test — could not exist. The native-ESM
|
|
10
|
+
// Jest config (SKYR-3799) is what makes it loadable.
|
|
11
|
+
// pushToolEvent lives in @skyramp/skyramp, which pulls the native dylib. Mock
|
|
12
|
+
// it so we can assert on the event payload without loading the binary. Under
|
|
13
|
+
// native ESM jest.mock is not hoisted — use unstable_mockModule + dynamic
|
|
14
|
+
// import of the subject below.
|
|
15
|
+
const pushToolEvent = jest.fn();
|
|
16
|
+
jest.unstable_mockModule("@skyramp/skyramp", () => ({ pushToolEvent }));
|
|
17
|
+
jest.unstable_mockModule("../utils/telemetry.js", () => ({
|
|
18
|
+
getEntryPoint: jest.fn(() => "mcp"),
|
|
19
|
+
getCIPlatform: jest.fn(() => undefined),
|
|
20
|
+
getRepositoryInfo: jest.fn(async () => ({})),
|
|
21
|
+
}));
|
|
22
|
+
jest.unstable_mockModule("../utils/logger.js", () => ({
|
|
23
|
+
logger: { info: jest.fn(), error: jest.fn(), debug: jest.fn(), warn: jest.fn() },
|
|
24
|
+
}));
|
|
25
|
+
const { AnalyticsService } = await import("./AnalyticsService.js");
|
|
26
|
+
const telemetry = await import("../utils/telemetry.js");
|
|
27
|
+
// The version the production code should resolve: package.json two levels up
|
|
28
|
+
// from this module's own location — the same lookup getMCPPackageVersion does
|
|
29
|
+
// via import.meta.url. Computing it the same way here proves the test harness
|
|
30
|
+
// itself supports import.meta now.
|
|
31
|
+
const expectedVersion = JSON.parse(fs.readFileSync(path.join(path.dirname(fileURLToPath(import.meta.url)), "../../package.json"), "utf8")).version;
|
|
32
|
+
describe("AnalyticsService — import.meta-based version resolution", () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
jest.clearAllMocks();
|
|
35
|
+
telemetry.getEntryPoint.mockReturnValue("mcp");
|
|
36
|
+
telemetry.getCIPlatform.mockReturnValue(undefined);
|
|
37
|
+
telemetry.getRepositoryInfo.mockResolvedValue({});
|
|
38
|
+
});
|
|
39
|
+
it("stamps the package.json version (resolved via import.meta.url) into the event params", async () => {
|
|
40
|
+
const params = {};
|
|
41
|
+
await AnalyticsService.pushMCPToolEvent("skyramp_smoke_test_generation", undefined, params);
|
|
42
|
+
expect(pushToolEvent).toHaveBeenCalledTimes(1);
|
|
43
|
+
const [, toolName, , sentParams] = pushToolEvent.mock.calls[0];
|
|
44
|
+
expect(toolName).toBe("skyramp_smoke_test_generation");
|
|
45
|
+
expect(sentParams.mcpServerVersion).toBe(expectedVersion);
|
|
46
|
+
// Sanity: a real semver-ish string, not an empty/undefined fallback.
|
|
47
|
+
expect(sentParams.mcpServerVersion).toMatch(/^\d+\.\d+\.\d+/);
|
|
48
|
+
});
|
|
49
|
+
it("concatenates error text from an isError result into the event error message", async () => {
|
|
50
|
+
const result = {
|
|
51
|
+
isError: true,
|
|
52
|
+
content: [
|
|
53
|
+
{ type: "text", text: "first failure" },
|
|
54
|
+
{ type: "text", text: "second failure" },
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
await AnalyticsService.pushMCPToolEvent("skyramp_execute_test", result, {});
|
|
58
|
+
const [, , errorMessage] = pushToolEvent.mock.calls[0];
|
|
59
|
+
expect(errorMessage).toBe("first failure, second failure");
|
|
60
|
+
});
|
|
61
|
+
it("sends an empty error message for a successful result", async () => {
|
|
62
|
+
const result = { isError: false, content: [{ type: "text", text: "ok" }] };
|
|
63
|
+
await AnalyticsService.pushMCPToolEvent("skyramp_execute_test", result, {});
|
|
64
|
+
const [, , errorMessage] = pushToolEvent.mock.calls[0];
|
|
65
|
+
expect(errorMessage).toBe("");
|
|
66
|
+
});
|
|
67
|
+
it("includes ciPlatform in the params when running in CI", async () => {
|
|
68
|
+
telemetry.getCIPlatform.mockReturnValue("github_actions");
|
|
69
|
+
const params = {};
|
|
70
|
+
await AnalyticsService.pushMCPToolEvent("skyramp_init_workspace", undefined, params);
|
|
71
|
+
const [, , , sentParams] = pushToolEvent.mock.calls[0];
|
|
72
|
+
expect(sentParams.ciPlatform).toBe("github_actions");
|
|
73
|
+
});
|
|
74
|
+
it("merges repository info into the params", async () => {
|
|
75
|
+
telemetry.getRepositoryInfo.mockResolvedValue({ repoName: "letsramp/mcp", repoOwner: "letsramp" });
|
|
76
|
+
const params = { repositoryPath: "/repo" };
|
|
77
|
+
await AnalyticsService.pushMCPToolEvent("skyramp_analyze_changes", undefined, params);
|
|
78
|
+
expect(telemetry.getRepositoryInfo).toHaveBeenCalledWith("/repo");
|
|
79
|
+
const [, , , sentParams] = pushToolEvent.mock.calls[0];
|
|
80
|
+
expect(sentParams.repoName).toBe("letsramp/mcp");
|
|
81
|
+
});
|
|
82
|
+
it("swallows errors from pushToolEvent (telemetry must never break a tool call)", async () => {
|
|
83
|
+
pushToolEvent.mockRejectedValueOnce(new Error("network down"));
|
|
84
|
+
await expect(AnalyticsService.pushMCPToolEvent("skyramp_smoke_test_generation", undefined, {})).resolves.toBeUndefined();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export interface ModularizationParams {
|
|
3
|
+
testFile: string;
|
|
4
|
+
testType?: string;
|
|
5
|
+
language?: string;
|
|
6
|
+
isTraceBased?: boolean;
|
|
7
|
+
prompt?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class ModularizationService {
|
|
10
|
+
processModularizationRequest(params: ModularizationParams): Promise<CallToolResult>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export interface TraceRequest {
|
|
3
|
+
Source: string;
|
|
4
|
+
Destination: string;
|
|
5
|
+
RequestBody: string;
|
|
6
|
+
ResponseBody: string;
|
|
7
|
+
RequestHeaders: Record<string, string[]>;
|
|
8
|
+
ResponseHeaders: Record<string, string[]>;
|
|
9
|
+
Method: string;
|
|
10
|
+
Path: string;
|
|
11
|
+
QueryParams: Record<string, string[]>;
|
|
12
|
+
StatusCode: number;
|
|
13
|
+
Port: number;
|
|
14
|
+
Timestamp: string;
|
|
15
|
+
Scheme: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ScenarioParams {
|
|
18
|
+
scenarioName: string;
|
|
19
|
+
destination: string;
|
|
20
|
+
apiSchema?: string;
|
|
21
|
+
baseURL?: string;
|
|
22
|
+
method: string;
|
|
23
|
+
path: string;
|
|
24
|
+
requestBody?: string;
|
|
25
|
+
queryParams?: string;
|
|
26
|
+
responseBody?: string;
|
|
27
|
+
statusCode?: number;
|
|
28
|
+
outputDir: string;
|
|
29
|
+
authHeader?: string;
|
|
30
|
+
authScheme?: string;
|
|
31
|
+
authToken?: string;
|
|
32
|
+
responseHeaders?: Record<string, string[]>;
|
|
33
|
+
}
|
|
34
|
+
export declare class ScenarioGenerationService {
|
|
35
|
+
parseScenario(params: ScenarioParams): Promise<CallToolResult>;
|
|
36
|
+
generateTraceRequestFromInput(params: ScenarioParams): TraceRequest | null;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Requires: @skyramp/skyramp native dylib (skips if not available)
|
|
6
6
|
*/
|
|
7
|
+
import { jest } from "@jest/globals";
|
|
7
8
|
import fs from "fs";
|
|
8
9
|
import path from "path";
|
|
9
10
|
import os from "os";
|
|
11
|
+
import { createRequire } from "module";
|
|
10
12
|
import { ScenarioGenerationService } from "./ScenarioGenerationService.js";
|
|
13
|
+
// Native dylib is a CommonJS addon — load it via createRequire under ESM.
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
11
15
|
let SkyrampClient;
|
|
12
16
|
try {
|
|
13
17
|
SkyrampClient = require("@skyramp/skyramp").SkyrampClient;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { TestAnalysisResult } from "../types/TestAnalysis.js";
|
|
2
|
+
interface TestDiscoveryResult {
|
|
3
|
+
tests: TestAnalysisResult[];
|
|
4
|
+
/** Paths of external files that were deemed relevant to the PR (score > 0). */
|
|
5
|
+
relevantExternalTestPaths: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface TestDiscoveryOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Resource names derived from endpoints in changed files (e.g. ["orders", "products"]).
|
|
10
|
+
* - Non-empty array: external files partitioned by relevance; only relevant files
|
|
11
|
+
* get full endpoint extraction. May be the sentinel `["unknown"]` when endpoints
|
|
12
|
+
* exist but resource names are unresolvable — treated as "endpoints present" to
|
|
13
|
+
* avoid skipping external coverage. Also used for "add field" PRs where the changed
|
|
14
|
+
* files have no endpoint definitions but the scanner found related endpoints nearby.
|
|
15
|
+
* - Empty array `[]`: PR mode with no endpoints from diff or scanner — external
|
|
16
|
+
* tests are skipped entirely to avoid flooding context.
|
|
17
|
+
* - `undefined`: full-repo mode — external tests capped at MAX_EXTERNAL_FULL_REPO.
|
|
18
|
+
*/
|
|
19
|
+
changedResources?: string[];
|
|
20
|
+
}
|
|
21
|
+
export declare class TestDiscoveryService {
|
|
22
|
+
private readonly EXCLUDED_DIRS;
|
|
23
|
+
private readonly SKYRAMP_MARKER;
|
|
24
|
+
private readonly SUPPORTED_EXTENSIONS;
|
|
25
|
+
private readonly MAX_CONCURRENT_OPERATIONS;
|
|
26
|
+
private readonly MAX_EXTERNAL_FULL_REPO;
|
|
27
|
+
private readonly TEST_FILE_PATTERNS;
|
|
28
|
+
private readonly TEST_DIR_PATTERNS;
|
|
29
|
+
/**
|
|
30
|
+
* Discover all tests under testDir — both Skyramp-generated and external (user-written).
|
|
31
|
+
* Uses fast-glob for cross-platform file scanning, then classifies discovered files
|
|
32
|
+
* as Skyramp-generated tests, external tests, or not-a-test during processing.
|
|
33
|
+
*
|
|
34
|
+
* External test handling depends on `options.changedResources`:
|
|
35
|
+
* - `string[]` with entries (PR mode, endpoints detected): partition by relevance.
|
|
36
|
+
* - `[]` empty array (PR mode, scanner found no endpoints): skip external tests entirely
|
|
37
|
+
* rather than flooding context with irrelevant files.
|
|
38
|
+
* - `undefined` (full-repo mode, no diff): cap at MAX_EXTERNAL_FULL_REPO.
|
|
39
|
+
*/
|
|
40
|
+
discoverTests(testDir: string, options?: TestDiscoveryOptions): Promise<TestDiscoveryResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Score an external test file's relevance to a set of changed resource names.
|
|
43
|
+
* Tokenises the last two segments of the file path (split by /, \, -, _, .)
|
|
44
|
+
* and counts overlapping tokens with the changed resources.
|
|
45
|
+
* Example: "test_orders_api.py" vs ["orders"] → score 1.
|
|
46
|
+
*/
|
|
47
|
+
private scoreRelevance;
|
|
48
|
+
/**
|
|
49
|
+
* Partition external test files into relevant (score > 0) and low-relevance (score = 0)
|
|
50
|
+
* based on file path/name overlap with the changed resource names from the PR diff.
|
|
51
|
+
*/
|
|
52
|
+
private partitionByRelevance;
|
|
53
|
+
/**
|
|
54
|
+
* Process test files in parallel batches with concurrency control
|
|
55
|
+
* @param isExternal When true, uses external test metadata extraction
|
|
56
|
+
* @param contentCache Optional pre-read file contents from classification pass
|
|
57
|
+
*/
|
|
58
|
+
private processFilesInBatches;
|
|
59
|
+
/**
|
|
60
|
+
* Classify candidate files as skyramp (has marker), external (test file without
|
|
61
|
+
* marker), or not-a-test. Caches file contents so downstream metadata extraction
|
|
62
|
+
* doesn't need to re-read from disk.
|
|
63
|
+
*/
|
|
64
|
+
private classifyTestFiles;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a file is an external (non-Skyramp) test file based on naming convention
|
|
67
|
+
* or directory placement.
|
|
68
|
+
*/
|
|
69
|
+
private isExternalTestFile;
|
|
70
|
+
/**
|
|
71
|
+
* Extract metadata from a test file
|
|
72
|
+
* File is already confirmed to contain Skyramp marker by file search
|
|
73
|
+
* @param cachedContent Optional pre-read content from classification pass
|
|
74
|
+
*/
|
|
75
|
+
private extractTestMetadata;
|
|
76
|
+
/**
|
|
77
|
+
* Extract the HTTP methods and paths covered by this test file.
|
|
78
|
+
* Returns a comma-separated string like "GET /orders/{id}, DELETE /orders/{id}".
|
|
79
|
+
* Handles Python (send_request / check_schema) and TypeScript/JS (sendRequest).
|
|
80
|
+
*/
|
|
81
|
+
private extractCoveredEndpoints;
|
|
82
|
+
/**
|
|
83
|
+
* Extract metadata from an external (non-Skyramp) test file.
|
|
84
|
+
* Uses heuristic patterns for endpoint extraction, test type, and framework detection.
|
|
85
|
+
* @param cachedContent Optional pre-read content from classification pass
|
|
86
|
+
*/
|
|
87
|
+
private extractExternalTestMetadata;
|
|
88
|
+
/**
|
|
89
|
+
* Extract HTTP endpoints from external (non-Skyramp) test files.
|
|
90
|
+
* Matches common patterns: requests.get, axios.post, fetch, supertest, RestAssured.
|
|
91
|
+
*/
|
|
92
|
+
private extractExternalEndpoints;
|
|
93
|
+
/**
|
|
94
|
+
* Normalize an endpoint path extracted from test code.
|
|
95
|
+
* Strips base URL prefixes and returns only the path portion.
|
|
96
|
+
* Returns null if the path doesn't look like an API endpoint.
|
|
97
|
+
*/
|
|
98
|
+
private normalizeEndpointPath;
|
|
99
|
+
/**
|
|
100
|
+
* Detect test type from external test file path and content.
|
|
101
|
+
* Falls back to directory/filename heuristics since external tests lack Skyramp command lines.
|
|
102
|
+
*/
|
|
103
|
+
private detectExternalTestType;
|
|
104
|
+
/**
|
|
105
|
+
* Detect test framework from external test file content by checking imports.
|
|
106
|
+
*/
|
|
107
|
+
private detectExternalFramework;
|
|
108
|
+
/**
|
|
109
|
+
* Detect programming language from file extension
|
|
110
|
+
*/
|
|
111
|
+
private detectLanguage;
|
|
112
|
+
/**
|
|
113
|
+
* Detect test type from file content and name
|
|
114
|
+
* Checks Skyramp command line, filename, and content patterns
|
|
115
|
+
*/
|
|
116
|
+
private detectTestType;
|
|
117
|
+
/**
|
|
118
|
+
* Extract API schema path from test content
|
|
119
|
+
* Looks for Skyramp command line first, then fallback to other patterns
|
|
120
|
+
*/
|
|
121
|
+
private extractApiSchema;
|
|
122
|
+
/**
|
|
123
|
+
* Extract Framework from test content
|
|
124
|
+
* Looks for Skyramp command line first, then fallback to other patterns
|
|
125
|
+
*/
|
|
126
|
+
private extractFramework;
|
|
127
|
+
}
|
|
128
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
1
3
|
// Mock heavy dependencies
|
|
2
4
|
jest.mock("simple-git", () => ({
|
|
3
5
|
simpleGit: jest.fn(() => ({
|
|
4
6
|
checkIsRepo: jest.fn().mockResolvedValue(false),
|
|
5
7
|
})),
|
|
6
8
|
}));
|
|
7
|
-
jest.
|
|
9
|
+
jest.unstable_mockModule("../utils/logger.js", () => ({
|
|
8
10
|
logger: {
|
|
9
11
|
info: jest.fn(),
|
|
10
12
|
debug: jest.fn(),
|
|
@@ -14,12 +16,11 @@ jest.mock("../utils/logger.js", () => ({
|
|
|
14
16
|
}));
|
|
15
17
|
// fast-glob must return real file paths from the temp directory.
|
|
16
18
|
// We use the real implementation by not mocking it.
|
|
17
|
-
// Jest resolves .js → .ts via moduleNameMapper in jest.config.
|
|
18
19
|
import * as fs from "fs";
|
|
19
20
|
import * as path from "path";
|
|
20
21
|
import * as os from "os";
|
|
21
|
-
import { TestDiscoveryService } from "./TestDiscoveryService.js";
|
|
22
22
|
import { TestSource } from "../types/TestAnalysis.js";
|
|
23
|
+
const { TestDiscoveryService } = await import("./TestDiscoveryService.js");
|
|
23
24
|
describe("TestDiscoveryService", () => {
|
|
24
25
|
let service;
|
|
25
26
|
let tmpDir;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TestExecutionResult, BatchExecutionResult, TestExecutionOptions, ProgressCallback } from "../types/TestExecution.js";
|
|
2
|
+
export declare const EXECUTOR_DOCKER_IMAGE = "skyramp/executor:v1.3.28";
|
|
3
|
+
export declare const PLAYWRIGHT_CONFIG_FILES: string[];
|
|
4
|
+
export declare const EXCLUDED_MOUNT_ITEMS: string[];
|
|
5
|
+
export declare const MOUNT_NULL_ITEMS: string[];
|
|
6
|
+
/**
|
|
7
|
+
* Detect session file paths referenced in test files
|
|
8
|
+
* Looks for storageState patterns in TypeScript/JavaScript/Python/Java/C# test files
|
|
9
|
+
* Excludes matches found in comments
|
|
10
|
+
*
|
|
11
|
+
* Also handles the codegen pattern `path.join(__dirname, '<filename>')` (TS/JS) —
|
|
12
|
+
* the filename is resolved relative to the test file's directory on the host so
|
|
13
|
+
* the existing absolute-path mount branch makes it visible at the same path
|
|
14
|
+
* inside the container (Playwright's TS loader resolves __dirname to the host
|
|
15
|
+
* workspace path at runtime).
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectSessionFiles(testFilePath: string): string[];
|
|
18
|
+
export declare class TestExecutionService {
|
|
19
|
+
private docker;
|
|
20
|
+
private imageReady;
|
|
21
|
+
constructor();
|
|
22
|
+
/**
|
|
23
|
+
* Execute multiple tests in parallel batches
|
|
24
|
+
*/
|
|
25
|
+
executeBatch(testOptions: TestExecutionOptions[]): Promise<BatchExecutionResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Execute a single test
|
|
28
|
+
* @param options Test execution options
|
|
29
|
+
* @param onProgress Optional callback for progress updates
|
|
30
|
+
*/
|
|
31
|
+
executeTest(options: TestExecutionOptions, onProgress?: ProgressCallback): Promise<TestExecutionResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Ensure Docker image is available
|
|
34
|
+
* @param onProgress Optional callback for progress updates during pull
|
|
35
|
+
* @returns Object indicating whether image was cached or pulled
|
|
36
|
+
*/
|
|
37
|
+
private ensureDockerImage;
|
|
38
|
+
/**
|
|
39
|
+
* Parse errors from test output
|
|
40
|
+
*/
|
|
41
|
+
private parseErrors;
|
|
42
|
+
/**
|
|
43
|
+
* Parse warnings from test output
|
|
44
|
+
*/
|
|
45
|
+
private parseWarnings;
|
|
46
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,28 +1,43 @@
|
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
1
3
|
import { buildContainerEnv, rewriteLocalhostForDocker } from "./containerEnv.js";
|
|
2
4
|
// Mock dockerode before importing TestExecutionService
|
|
3
5
|
const mockRun = jest.fn();
|
|
4
6
|
const mockListImages = jest.fn();
|
|
5
|
-
jest.
|
|
6
|
-
|
|
7
|
+
jest.unstable_mockModule("dockerode", () => ({
|
|
8
|
+
default: jest.fn().mockImplementation(() => ({
|
|
7
9
|
run: mockRun,
|
|
8
10
|
listImages: mockListImages,
|
|
9
|
-
}))
|
|
11
|
+
})),
|
|
12
|
+
}));
|
|
13
|
+
// Get actual fs for spreading, then mock specific methods
|
|
14
|
+
const actualFs = await import("fs");
|
|
15
|
+
const mockAccessSync = jest.fn();
|
|
16
|
+
const mockExistsSync = jest.fn().mockReturnValue(true);
|
|
17
|
+
const mockReaddirSync = jest.fn().mockImplementation((_path, options) => {
|
|
18
|
+
if (options?.withFileTypes) {
|
|
19
|
+
return [{ name: "test_file.py", isFile: () => true, isDirectory: () => false }];
|
|
20
|
+
}
|
|
21
|
+
return ["test_file.py"];
|
|
10
22
|
});
|
|
11
|
-
|
|
12
|
-
jest.
|
|
13
|
-
...
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
+
const mockReadFileSync = jest.fn().mockReturnValue("");
|
|
24
|
+
jest.unstable_mockModule("fs", () => ({
|
|
25
|
+
...actualFs,
|
|
26
|
+
default: {
|
|
27
|
+
...actualFs.default,
|
|
28
|
+
accessSync: mockAccessSync,
|
|
29
|
+
existsSync: mockExistsSync,
|
|
30
|
+
readdirSync: mockReaddirSync,
|
|
31
|
+
readFileSync: mockReadFileSync,
|
|
32
|
+
constants: actualFs.default.constants,
|
|
33
|
+
},
|
|
34
|
+
accessSync: mockAccessSync,
|
|
35
|
+
existsSync: mockExistsSync,
|
|
36
|
+
readdirSync: mockReaddirSync,
|
|
37
|
+
readFileSync: mockReadFileSync,
|
|
23
38
|
}));
|
|
24
39
|
// Mock logger
|
|
25
|
-
jest.
|
|
40
|
+
jest.unstable_mockModule("../utils/logger.js", () => ({
|
|
26
41
|
logger: {
|
|
27
42
|
debug: jest.fn(),
|
|
28
43
|
info: jest.fn(),
|
|
@@ -145,12 +160,9 @@ describe("buildContainerEnv", () => {
|
|
|
145
160
|
describe("detectSessionFiles", () => {
|
|
146
161
|
// Import after mocks are set up so the fs mock applies
|
|
147
162
|
let detectSessionFiles;
|
|
148
|
-
let mockReadFileSync;
|
|
149
163
|
beforeAll(async () => {
|
|
150
164
|
const mod = await import("./TestExecutionService.js");
|
|
151
165
|
detectSessionFiles = mod.detectSessionFiles;
|
|
152
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
153
|
-
mockReadFileSync = require("fs").readFileSync;
|
|
154
166
|
});
|
|
155
167
|
it("detects string-literal storageState (TS/JS)", () => {
|
|
156
168
|
mockReadFileSync.mockReturnValueOnce(`test.use({ storageState: '/abs/path/session.json' });`);
|
|
@@ -258,9 +270,7 @@ describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
|
258
270
|
// resolve correctly inside the executor regardless of which path-shape the
|
|
259
271
|
// codegen happens to emit.
|
|
260
272
|
it("mirrors each workspace file mount at both /home/user/<f> and the host-absolute path", async () => {
|
|
261
|
-
|
|
262
|
-
const fs = require("fs");
|
|
263
|
-
fs.readdirSync.mockImplementation((_path, options) => {
|
|
273
|
+
mockReaddirSync.mockImplementation((_path, options) => {
|
|
264
274
|
if (options?.withFileTypes) {
|
|
265
275
|
return [
|
|
266
276
|
{ name: "xdr_dashboard.spec.ts", isFile: () => true, isDirectory: () => false },
|
|
@@ -288,9 +298,7 @@ describe("TestExecutionService.executeTest - Docker env forwarding", () => {
|
|
|
288
298
|
expect(targets).toContain("/Users/pedro/projects/cisco-xdr-tests/skyramp_session_storage.json");
|
|
289
299
|
});
|
|
290
300
|
it("does not double-mount when workspacePath equals /home/user", async () => {
|
|
291
|
-
|
|
292
|
-
const fs = require("fs");
|
|
293
|
-
fs.readdirSync.mockImplementation((_path, options) => {
|
|
301
|
+
mockReaddirSync.mockImplementation((_path, options) => {
|
|
294
302
|
if (options?.withFileTypes) {
|
|
295
303
|
return [{ name: "test_file.py", isFile: () => true, isDirectory: () => false }];
|
|
296
304
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SkyrampClient } from "@skyramp/skyramp";
|
|
2
|
+
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
import { TestType } from "../types/TestTypes.js";
|
|
4
|
+
export interface BaseTestParams {
|
|
5
|
+
endpointURL?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
apiSchema?: string;
|
|
8
|
+
language?: string;
|
|
9
|
+
framework?: string;
|
|
10
|
+
output?: string;
|
|
11
|
+
outputDir: string;
|
|
12
|
+
force: boolean;
|
|
13
|
+
deployDashboard?: boolean;
|
|
14
|
+
runtime?: string;
|
|
15
|
+
dockerNetwork?: string;
|
|
16
|
+
dockerWorkerPort?: number;
|
|
17
|
+
k8sNamespace?: string;
|
|
18
|
+
k8sConfig?: string;
|
|
19
|
+
k8sContext?: string;
|
|
20
|
+
authHeader?: string;
|
|
21
|
+
authScheme?: string;
|
|
22
|
+
pathParams?: string;
|
|
23
|
+
queryParams?: string;
|
|
24
|
+
formParams?: string;
|
|
25
|
+
requestData?: string;
|
|
26
|
+
responseStatusCode?: string;
|
|
27
|
+
trace?: string;
|
|
28
|
+
include?: string[];
|
|
29
|
+
exclude?: string[];
|
|
30
|
+
insecure?: boolean;
|
|
31
|
+
prompt?: string;
|
|
32
|
+
codeReuse?: boolean;
|
|
33
|
+
modularizeCode?: boolean;
|
|
34
|
+
chainingKey?: string;
|
|
35
|
+
scenarioFile?: string;
|
|
36
|
+
mockPort?: number;
|
|
37
|
+
optionalFields?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare abstract class TestGenerationService {
|
|
40
|
+
protected client: SkyrampClient;
|
|
41
|
+
constructor();
|
|
42
|
+
generateTest(params: BaseTestParams & Record<string, any>): Promise<CallToolResult>;
|
|
43
|
+
protected validateInputs(params: BaseTestParams): CallToolResult;
|
|
44
|
+
protected abstract buildGenerationOptions(params: BaseTestParams & Record<string, any>): any;
|
|
45
|
+
protected abstract getTestType(): TestType;
|
|
46
|
+
protected handleApiAnalysis(params: BaseTestParams): Promise<CallToolResult | null>;
|
|
47
|
+
private static readonly STANDARD_HEADERS;
|
|
48
|
+
private static simpleWildcardMatch;
|
|
49
|
+
private static traceMatchesFilters;
|
|
50
|
+
protected extractAuthFromTrace(traceFilePath: string, include?: string[], exclude?: string[]): {
|
|
51
|
+
authHeader: string;
|
|
52
|
+
authScheme: string;
|
|
53
|
+
} | null;
|
|
54
|
+
protected executeGeneration(generateOptions: any): Promise<string>;
|
|
55
|
+
protected buildBaseGenerationOptions(params: BaseTestParams): any;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
jest.mock("@skyramp/skyramp", () => ({
|
|
4
|
-
SkyrampClient: jest.fn().mockImplementation(() => ({})),
|
|
5
|
-
}));
|
|
6
|
-
import { TestGenerationService } from "./TestGenerationService.js";
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
7
3
|
import { TestType } from "../types/TestTypes.js";
|
|
8
4
|
import { AUTH_PLACEHOLDER_TOKEN } from "../types/TestTypes.js";
|
|
9
5
|
import fs from "fs";
|
|
10
6
|
import os from "os";
|
|
11
7
|
import path from "path";
|
|
8
|
+
// Mock @skyramp/skyramp before importing TestGenerationService to avoid
|
|
9
|
+
// pulling in playwright (dynamic imports fail on Node 18 in CI). Under native
|
|
10
|
+
// ESM, jest.mock is not hoisted — use unstable_mockModule + dynamic import.
|
|
11
|
+
jest.unstable_mockModule("@skyramp/skyramp", () => ({
|
|
12
|
+
SkyrampClient: jest.fn().mockImplementation(() => ({})),
|
|
13
|
+
}));
|
|
14
|
+
const { TestGenerationService, BaseTestParams } = await import("./TestGenerationService.js");
|
|
15
|
+
const { SkyrampClient } = await import("@skyramp/skyramp");
|
|
12
16
|
class StubService extends TestGenerationService {
|
|
13
17
|
buildGenerationOptions() {
|
|
14
18
|
return {};
|
|
@@ -87,7 +91,6 @@ describe("TestGenerationService — authType/authScheme not passed to library",
|
|
|
87
91
|
let mockGenerateRestTest;
|
|
88
92
|
beforeEach(() => {
|
|
89
93
|
mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
|
|
90
|
-
const { SkyrampClient } = require("@skyramp/skyramp");
|
|
91
94
|
SkyrampClient.mockImplementation(() => ({
|
|
92
95
|
generateRestTest: mockGenerateRestTest,
|
|
93
96
|
}));
|
|
@@ -333,7 +336,6 @@ describe("TestGenerationService — trace-based auth in executeGeneration", () =
|
|
|
333
336
|
let tmpDir;
|
|
334
337
|
beforeEach(() => {
|
|
335
338
|
mockGenerateRestTest = jest.fn().mockResolvedValue("Test generation success");
|
|
336
|
-
const { SkyrampClient } = require("@skyramp/skyramp");
|
|
337
339
|
SkyrampClient.mockImplementation(() => ({
|
|
338
340
|
generateRestTest: mockGenerateRestTest,
|
|
339
341
|
}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TestExecutionOptions } from "../types/TestExecution.js";
|
|
2
|
+
/**
|
|
3
|
+
* Rewrite localhost / 127.0.0.1 URLs to host.docker.internal so the Docker
|
|
4
|
+
* executor container can reach services running on the host machine.
|
|
5
|
+
*
|
|
6
|
+
* Only applied when NOT using host networking (bridge mode), because in bridge
|
|
7
|
+
* mode the container's localhost is its own loopback, not the host's.
|
|
8
|
+
* host.docker.internal is mapped via ExtraHosts in TestExecutionService.
|
|
9
|
+
*/
|
|
10
|
+
export declare function rewriteLocalhostForDocker(url: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Build the environment variable array for the Docker executor container.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildContainerEnv(options: Pick<TestExecutionOptions, "token" | "language" | "useHostNetwork">, saveStoragePath?: string, hostEnv?: Record<string, string | undefined>): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { TOOL_PHASE_MAP, TOOLS_WITHOUT_PHASE } from "./tool-phases.js";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
4
6
|
function findAllToolNames() {
|
|
5
7
|
const toolNames = [];
|
|
6
8
|
function walk(dir) {
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
* ## Static vs context-dependent mappings
|
|
13
|
+
*
|
|
14
|
+
* - **Static** (`string`): the tool always maps to this phase.
|
|
15
|
+
* - **Context-dependent** (`{ before, after }`): the phase depends on whether
|
|
16
|
+
* the "generating" boundary has been crossed. The consumer tracks a boolean
|
|
17
|
+
* flag (`generationSeen`), initially `false`. When any tool in
|
|
18
|
+
* `GENERATING_TOOLS` is encountered, set `generationSeen = true`.
|
|
19
|
+
* - While `generationSeen` is `false`, resolve to the `before` phase.
|
|
20
|
+
* - Once `generationSeen` is `true`, resolve to the `after` phase.
|
|
21
|
+
*
|
|
22
|
+
* Example: `skyramp_execute_test` maps to `{ before: "maintaining", after: "executing" }`.
|
|
23
|
+
* Before any generation tool is seen, execution calls are part of
|
|
24
|
+
* maintenance (baseline runs). After generation, they are final test execution.
|
|
25
|
+
*
|
|
26
|
+
* Reset `generationSeen` to `false` at the start of each session/run.
|
|
27
|
+
*/
|
|
28
|
+
export type PhaseMapping = string | {
|
|
29
|
+
before: string;
|
|
30
|
+
after: string;
|
|
31
|
+
};
|
|
32
|
+
export declare const TOOL_PHASE_MAP: Record<string, PhaseMapping>;
|
|
33
|
+
/** Tools whose phase depends on context — listed here for consumer discovery. */
|
|
34
|
+
export declare const CONTEXT_DEPENDENT_TOOLS: Set<string>;
|
|
35
|
+
/** All tools that belong to the "generating" phase — used as the boundary. */
|
|
36
|
+
export declare const GENERATING_TOOLS: Set<string>;
|
|
37
|
+
/** Tools that intentionally have no progress phase (infrastructure/utility). */
|
|
38
|
+
export declare const TOOLS_WITHOUT_PHASE: Set<string>;
|