@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
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
// @ts-nocheck - Jest ESM type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
1
3
|
// Mock logger before importing docker module
|
|
2
|
-
jest.
|
|
4
|
+
const mockInspect = jest.fn();
|
|
5
|
+
const mockGetImage = jest.fn(() => ({ inspect: mockInspect }));
|
|
6
|
+
const mockFollowProgress = jest.fn();
|
|
7
|
+
const mockPull = jest.fn();
|
|
8
|
+
const mockModem = { followProgress: mockFollowProgress };
|
|
9
|
+
jest.unstable_mockModule("./logger.js", () => ({
|
|
3
10
|
logger: {
|
|
4
11
|
debug: jest.fn(),
|
|
5
12
|
info: jest.fn(),
|
|
@@ -7,18 +14,12 @@ jest.mock("./logger.js", () => ({
|
|
|
7
14
|
warning: jest.fn(),
|
|
8
15
|
},
|
|
9
16
|
}));
|
|
10
|
-
// Mock dockerode before importing docker module
|
|
11
|
-
const mockInspect = jest.fn();
|
|
12
|
-
const mockGetImage = jest.fn(() => ({ inspect: mockInspect }));
|
|
13
|
-
const mockFollowProgress = jest.fn();
|
|
14
|
-
const mockPull = jest.fn();
|
|
15
|
-
const mockModem = { followProgress: mockFollowProgress };
|
|
16
17
|
jest.mock("dockerode", () => jest.fn().mockImplementation(() => ({
|
|
17
18
|
getImage: mockGetImage,
|
|
18
19
|
pull: mockPull,
|
|
19
20
|
modem: mockModem,
|
|
20
21
|
})));
|
|
21
|
-
|
|
22
|
+
const { dockerImageExistsLocally, pullDockerImage } = await import("./docker.js");
|
|
22
23
|
// Helper: make docker.pull succeed (stream ends without error)
|
|
23
24
|
function mockPullSuccess() {
|
|
24
25
|
const fakeStream = {};
|
|
@@ -54,7 +55,7 @@ describe("dockerImageExistsLocally", () => {
|
|
|
54
55
|
});
|
|
55
56
|
});
|
|
56
57
|
describe("pullDockerImage", () => {
|
|
57
|
-
const IMAGE = "skyramp/executor:v1.3.
|
|
58
|
+
const IMAGE = "skyramp/executor:v1.3.28";
|
|
58
59
|
beforeEach(() => jest.clearAllMocks());
|
|
59
60
|
describe("on amd64 host", () => {
|
|
60
61
|
const originalArch = process.arch;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature flag helpers.
|
|
3
|
+
*
|
|
4
|
+
* Each helper in this module reads a `SKYRAMP_FEATURE_*` env var and returns
|
|
5
|
+
* a boolean. These helpers treat a flag as ON only when the env var is
|
|
6
|
+
* exactly `"1"`; anything else (unset, empty, "0", "true", "false", etc.) is
|
|
7
|
+
* treated as OFF.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Gates BOTH consumer-side contract tests AND the SDK's "default mode"
|
|
11
|
+
* fallback (where omitting both `providerMode` and `consumerMode` causes the
|
|
12
|
+
* SDK to generate BOTH provider and consumer tests).
|
|
13
|
+
*
|
|
14
|
+
* `providerMode` itself is exposed regardless of this flag.
|
|
15
|
+
*
|
|
16
|
+
* When OFF (default):
|
|
17
|
+
* - `skyramp_contract_test_generation` only exposes provider-mode
|
|
18
|
+
* parameters in its input schema, and the tool description, validation,
|
|
19
|
+
* and post-generation instructions all assume provider-only behavior.
|
|
20
|
+
* - The SDK is always invoked with `providerMode: true`, so the
|
|
21
|
+
* "neither mode set ⇒ generate both" default cannot leak through. Only
|
|
22
|
+
* a provider contract test is ever generated.
|
|
23
|
+
* - Testbot recommendation prompts no longer suggest `consumerMode: true`
|
|
24
|
+
* contract tests.
|
|
25
|
+
*
|
|
26
|
+
* When ON (`SKYRAMP_FEATURE_CONTRACT_CONSUMER_MODE=1`):
|
|
27
|
+
* - Restores the previous behavior: `consumerMode` / `consumerOutput` are
|
|
28
|
+
* exposed on the input schema, recommendation prompts mention consumer
|
|
29
|
+
* contract tests, and the SDK's "no mode set ⇒ generate both" default
|
|
30
|
+
* is preserved.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isContractConsumerModeEnabled(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Returns true when running inside a TestBot environment
|
|
35
|
+
* (SKYRAMP_FEATURE_TESTBOT=1).
|
|
36
|
+
*/
|
|
37
|
+
export declare function isTestbotEnabled(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check whether `child` is inside `parent` using resolved paths with
|
|
3
|
+
* a trailing separator to avoid prefix false positives (e.g. /tmp/test-repo2
|
|
4
|
+
* should not match /tmp/test-repo).
|
|
5
|
+
*/
|
|
6
|
+
export declare function isInsideDir(child: string, parent: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* In cross-repo mode, redirects an outputDir to be under the test repo clone
|
|
9
|
+
* if it isn't already. Returns the original path unchanged when testsRepoDir
|
|
10
|
+
* is unset or the path is already inside it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveOutputDir(outputDir: string, testsRepoDir: string | undefined): string;
|
|
13
|
+
/**
|
|
14
|
+
* Stages a file path an MCP tool just wrote into the git index by
|
|
15
|
+
* running `git add -- <path>`.
|
|
16
|
+
*
|
|
17
|
+
* Automatically detects the git root of the target path so that staging
|
|
18
|
+
* works correctly in cross-repo mode (test repo clone separate from the
|
|
19
|
+
* source repo).
|
|
20
|
+
*
|
|
21
|
+
* Gated by the SKYRAMP_FEATURE_TESTBOT=1 env var, which is set only
|
|
22
|
+
* inside a testbot CI run.
|
|
23
|
+
*/
|
|
24
|
+
export declare function stageGeneratedPaths(filePath: string, cwd?: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
jest
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
const execFileMock = jest.fn();
|
|
3
|
+
const execFileSyncMock = jest.fn();
|
|
4
|
+
jest.unstable_mockModule("./logger.js", () => ({
|
|
2
5
|
logger: {
|
|
3
6
|
debug: jest.fn(),
|
|
4
7
|
info: jest.fn(),
|
|
@@ -6,14 +9,17 @@ jest.mock("./logger.js", () => ({
|
|
|
6
9
|
error: jest.fn(),
|
|
7
10
|
},
|
|
8
11
|
}));
|
|
9
|
-
jest.
|
|
12
|
+
jest.unstable_mockModule("fs", () => ({
|
|
13
|
+
default: {
|
|
14
|
+
statSync: (p) => ({
|
|
15
|
+
isDirectory: () => !p.includes("."),
|
|
16
|
+
}),
|
|
17
|
+
},
|
|
10
18
|
statSync: (p) => ({
|
|
11
19
|
isDirectory: () => !p.includes("."),
|
|
12
20
|
}),
|
|
13
21
|
}));
|
|
14
|
-
|
|
15
|
-
const execFileSyncMock = jest.fn();
|
|
16
|
-
jest.mock("child_process", () => ({
|
|
22
|
+
jest.unstable_mockModule("child_process", () => ({
|
|
17
23
|
execFile: (cmd, args, opts, cb) => {
|
|
18
24
|
const result = execFileMock(cmd, args, opts);
|
|
19
25
|
const cbErr = result && typeof result === "object" && "err" in result
|
|
@@ -26,8 +32,8 @@ jest.mock("child_process", () => ({
|
|
|
26
32
|
},
|
|
27
33
|
execFileSync: (cmd, args, opts) => execFileSyncMock(cmd, args, opts),
|
|
28
34
|
}));
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
const { stageGeneratedPaths } = await import("./gitStaging.js");
|
|
36
|
+
const { logger } = await import("./logger.js");
|
|
31
37
|
const loggerInfoMock = logger.info;
|
|
32
38
|
let originalTestbotEnv;
|
|
33
39
|
beforeAll(() => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared HTTP method defaults used across scenario drafting and test generation.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Returns the conventional success status code for a given HTTP method.
|
|
6
|
+
* POST → 201 Created
|
|
7
|
+
* DELETE → 204 No Content
|
|
8
|
+
* other → 200 OK
|
|
9
|
+
*/
|
|
10
|
+
export declare function inferExpectedStatus(method: string): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WORKER_DOCKER_IMAGE } from "./versions.js";
|
|
2
|
+
export { WORKER_DOCKER_IMAGE };
|
|
3
|
+
/**
|
|
4
|
+
* Install or refresh SKYRAMP_MD_CONTENT at global skill discovery paths only (~/.claude, ~/.cursor, ~/.github/skills).
|
|
5
|
+
* No workspace path required. Creates files if missing; overwrites if content differs.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ensureSkyrampMdInstalled(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Skyramp init:
|
|
10
|
+
* install/refresh global skill files (~/.claude, ~/.cursor, ~/.github/skills) (errors logged but do not block init),
|
|
11
|
+
* check which images are missing, then kick off any needed pulls in the background and return immediately.
|
|
12
|
+
* Deduplication for the MCP oninitialized path is handled by registerInitTriggerOnMCPInitialized in this module.
|
|
13
|
+
*
|
|
14
|
+
* Pull improvements over the previous SkyrampClient.initAgent() FFI approach:
|
|
15
|
+
* - Skip-if-present: each image is checked independently via a fast daemon inspect (~5ms)
|
|
16
|
+
* before any pull is attempted, avoiding unnecessary network calls.
|
|
17
|
+
* - Pull only what is missing: if one image is already present, only the other is pulled.
|
|
18
|
+
* Previously both images were always pulled regardless.
|
|
19
|
+
* - Parallel pulls: missing images are pulled concurrently via Promise.all, halving
|
|
20
|
+
* wall-clock time when both need to be downloaded.
|
|
21
|
+
* - Arch-aware: pull platform is detected from process.arch (linux/arm64 on Apple Silicon,
|
|
22
|
+
* linux/amd64 otherwise) with an automatic amd64 fallback if no arm64 manifest exists
|
|
23
|
+
* (e.g. skyramp/executor is amd64-only; skyramp/worker supports both).
|
|
24
|
+
* - No FFI overhead: direct Dockerode calls replace the Go shared-library bridge,
|
|
25
|
+
* removing the cost of loading the .so and marshalling output through a C string.
|
|
26
|
+
* - Cleaner error propagation: structured errors from Dockerode replace parsing a
|
|
27
|
+
* stringified Go output from the C FFI boundary.
|
|
28
|
+
*/
|
|
29
|
+
export declare function initCheck(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Runs initCheck asynchronously after the MCP handshake completes.
|
|
32
|
+
* Prevents duplicate concurrent runs and skips future runs after a successful init.
|
|
33
|
+
* If initCheck fails, a later call can retry within the same process.
|
|
34
|
+
* Assign to server.server.oninitialized in main().
|
|
35
|
+
*/
|
|
36
|
+
export declare function registerInitTriggerOnMCPInitialized(): Promise<void>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class McpLogger {
|
|
2
|
+
private loggerName;
|
|
3
|
+
constructor(loggerName?: string);
|
|
4
|
+
private sendLogMessage;
|
|
5
|
+
debug(message: string, data?: any): void;
|
|
6
|
+
info(message: string, data?: any): void;
|
|
7
|
+
warning(message: string, data?: any): void;
|
|
8
|
+
error(message: string, data?: any): void;
|
|
9
|
+
critical(message: string, data?: any): void;
|
|
10
|
+
}
|
|
11
|
+
export declare const logger: McpLogger;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize tool parameters to handle common LLM mistakes:
|
|
3
|
+
* - Case-insensitive language/framework values
|
|
4
|
+
* - Common parameter name aliases
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Normalize language and framework to lowercase accepted values.
|
|
8
|
+
*/
|
|
9
|
+
export declare function normalizeLanguageParams(params: Record<string, any>): void;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve common parameter name aliases that LLMs use.
|
|
12
|
+
* e.g., zipPath -> playwrightInput, testFilePath -> testFile
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveParamAliases(params: Record<string, any>, aliases: Record<string, string>): void;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure `expect` is imported from `@skyramp/skyramp` rather than `@playwright/test`.
|
|
3
|
+
* - Strips `expect` from any `@playwright/test` import (keeps other identifiers).
|
|
4
|
+
* - If the file uses `expect(...)`, ensures an `@skyramp/skyramp` import carries `expect`.
|
|
5
|
+
* Returns the original string if no rewrite was needed.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeSkyrampExpectImport(source: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Normalize the `expect` import in a file on disk. No-op if the file is missing,
|
|
10
|
+
* unreadable, or already correct. Errors are swallowed — this is a safety net,
|
|
11
|
+
* not a blocking step.
|
|
12
|
+
*/
|
|
13
|
+
export declare function normalizeSkyrampImportsInFile(testFile: string | undefined): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Comment Parser — extracts TestBot history from GitHub PR comments.
|
|
3
|
+
*
|
|
4
|
+
* Parses previous Skyramp TestBot comments on a PR to build context
|
|
5
|
+
* about what has already been recommended, implemented, and tested.
|
|
6
|
+
* This prevents re-recommendations and enables contextual awareness
|
|
7
|
+
* across the PR lifecycle.
|
|
8
|
+
*/
|
|
9
|
+
export interface PRTestContext {
|
|
10
|
+
prNumber: number;
|
|
11
|
+
previousRecommendations: Array<{
|
|
12
|
+
testType: string;
|
|
13
|
+
endpoint: string;
|
|
14
|
+
scenarioName?: string;
|
|
15
|
+
status: "recommended" | "implemented" | "dismissed";
|
|
16
|
+
commentId: string;
|
|
17
|
+
}>;
|
|
18
|
+
implementedTestFiles: string[];
|
|
19
|
+
executionResults: Array<{
|
|
20
|
+
testFile: string;
|
|
21
|
+
status: "pass" | "fail" | "skipped";
|
|
22
|
+
timestamp: string;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch and parse PR comments to build TestBot history context.
|
|
27
|
+
*
|
|
28
|
+
* Uses the `gh` CLI (available in CI and local dev environments with
|
|
29
|
+
* GitHub CLI installed). Falls back gracefully if `gh` is unavailable.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parsePRComments(repoOwner: string, repoName: string, prNumber: number, _token?: string): Promise<PRTestContext>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
jest.
|
|
4
|
-
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
// Mock child_process before importing the module under test
|
|
3
|
+
const mockedExecFileSync = jest.fn();
|
|
4
|
+
jest.unstable_mockModule("child_process", () => ({
|
|
5
|
+
execFileSync: mockedExecFileSync,
|
|
5
6
|
}));
|
|
6
|
-
const
|
|
7
|
+
const { parsePRComments } = await import("./pr-comment-parser.js");
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
8
9
|
// Fixture helpers — build PR comment bodies matching the real renderReport()
|
|
9
10
|
// output wrapped in the progress comment from testbot/src/progress.ts.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ProjectType = "rest-api" | "frontend" | "full-stack" | "microservices" | "library" | "cli" | "other";
|
|
2
|
+
export type DeploymentPattern = "microservices" | "full-stack" | "containerized-monolith" | "traditional" | "unknown";
|
|
3
|
+
export interface ProjectMeta {
|
|
4
|
+
projectType: ProjectType;
|
|
5
|
+
primaryLanguage: string;
|
|
6
|
+
primaryFramework: string;
|
|
7
|
+
deploymentPattern: DeploymentPattern;
|
|
8
|
+
languages: string[];
|
|
9
|
+
frameworks: string[];
|
|
10
|
+
runtime: string;
|
|
11
|
+
isContainerized: boolean;
|
|
12
|
+
hasDockerCompose: boolean;
|
|
13
|
+
hasCiCd: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function detectProjectMetadata(repositoryPath: string): ProjectMeta;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ScannedEndpoint {
|
|
2
|
+
path: string;
|
|
3
|
+
methods: string[];
|
|
4
|
+
sourceFile: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Returns the relative paths of entry-point files that define the routing
|
|
8
|
+
* hierarchy for this repository. The LLM reads these files in Step 1.5 to
|
|
9
|
+
* trace router/module nesting and build an authoritative path resolution table.
|
|
10
|
+
*
|
|
11
|
+
* Intentionally returns only file paths — no extracted lines. Static regex
|
|
12
|
+
* extraction is fragile and framework-specific; the LLM reads the files directly
|
|
13
|
+
* and understands any framework's routing syntax.
|
|
14
|
+
*/
|
|
15
|
+
export declare function grepRouterMountingContext(repositoryPath: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Return relative paths of all source files that are likely to define API
|
|
18
|
+
* routes. Two-pass strategy:
|
|
19
|
+
* 1. Fast: filename matches ROUTE_FILE_PATTERN (no file I/O needed).
|
|
20
|
+
* 2. Content: files not matched by name are read and checked for both a
|
|
21
|
+
* URL-path literal AND an HTTP method registration. This covers any
|
|
22
|
+
* framework the filename filter misses — Axum, Ktor, .NET, Hono, etc.
|
|
23
|
+
* Result is capped at MAX_CANDIDATE_FILES to keep the LLM prompt bounded.
|
|
24
|
+
*/
|
|
25
|
+
export declare function findCandidateRouteFiles(repositoryPath: string): string[];
|
|
26
|
+
export declare function scanAllRepoEndpoints(repositoryPath: string): ScannedEndpoint[];
|
|
27
|
+
export declare function scanRelatedEndpoints(repositoryPath: string, changedFiles: string[]): ScannedEndpoint[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { BranchDiffData } from "./branchDiff.js";
|
|
2
|
+
import type { ScannedEndpoint } from "./repoScanner.js";
|
|
3
|
+
export interface ParsedDiffEndpoint {
|
|
4
|
+
method: string;
|
|
5
|
+
path: string;
|
|
6
|
+
sourceFile: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function nextjsFileToApiPath(filePath: string): string | null;
|
|
9
|
+
export declare const UI_FILE_EXTENSIONS: readonly ["tsx", "jsx", "vue", "svelte", "html", "xml"];
|
|
10
|
+
export declare const UI_FILE_GIT_PATHSPEC: string;
|
|
11
|
+
export declare const UI_FILE_EXTENSIONS_PIPED: string;
|
|
12
|
+
export declare function parseRouteLine(line: string, sourceFile: string): ParsedDiffEndpoint | null;
|
|
13
|
+
/**
|
|
14
|
+
* Scan all route definitions in a single source file, combining prefix declarations
|
|
15
|
+
* with method-level annotations. Two orthogonal state machines run in parallel:
|
|
16
|
+
*
|
|
17
|
+
* 1. Class-prefix (Spring, NestJS, ASP.NET, Kotlin):
|
|
18
|
+
* @Controller/@RestController/@RequestMapping (class level) + class declaration →
|
|
19
|
+
* activates classPrefix, applied to all @Get/@Post/@GetMapping etc. below.
|
|
20
|
+
*
|
|
21
|
+
* 2. Router-variable prefix (FastAPI, Flask Blueprint):
|
|
22
|
+
* varName = APIRouter(prefix=...) or Blueprint(url_prefix=...) — handles both
|
|
23
|
+
* single-line and multi-line declarations — maps the variable name to its prefix.
|
|
24
|
+
* Applied when @varName.method(...) is seen.
|
|
25
|
+
*
|
|
26
|
+
* Falls back to pure parseRouteLine for all other frameworks (Express inline, Gin,
|
|
27
|
+
* Rails, Laravel, Actix, Hapi, Go stdlib, etc.), which remain unaffected.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseFileEndpoints(content: string, sourceFile: string): ParsedDiffEndpoint[];
|
|
30
|
+
export declare const SKIP_PATH_SEGMENTS: Set<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Extract the primary resource key from an endpoint path for use as a dedup key.
|
|
33
|
+
*
|
|
34
|
+
* For top-level resources (e.g. "/api/v1/orders/{id}") returns the resource name ("orders").
|
|
35
|
+
* For sub-resources (e.g. "/orders/{id}/items") returns "orders_items" — including the
|
|
36
|
+
* parent prevents "/orders/{id}/items" and "/products/{id}/items" from colliding on "items".
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractResourceFromPath(endpointPath: string): string;
|
|
39
|
+
export interface ClassifiedEndpoints {
|
|
40
|
+
/** Endpoints in scanned catalog whose sourceFile is in changedFiles (not new/deleted). */
|
|
41
|
+
changedEndpoints: ScannedEndpoint[];
|
|
42
|
+
/** Endpoints whose sourceFile is in a newly-created file. */
|
|
43
|
+
newEndpoints: ScannedEndpoint[];
|
|
44
|
+
/** Endpoints whose sourceFile is in a deleted file (recovered from base branch). */
|
|
45
|
+
removedEndpoints: ScannedEndpoint[];
|
|
46
|
+
/** Changed files that don't map to any scanned endpoint. */
|
|
47
|
+
unmatchedFiles: string[];
|
|
48
|
+
changedFiles: string[];
|
|
49
|
+
currentBranch: string;
|
|
50
|
+
baseBranch: string;
|
|
51
|
+
affectedServices: string[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Classify endpoints by cross-referencing `changedFiles` against `scannedEndpoints[].sourceFile`.
|
|
55
|
+
*
|
|
56
|
+
* This replaces `parseEndpointsFromDiff` — instead of regex-parsing diff hunks for route
|
|
57
|
+
* annotations (fragile for 15+ frameworks), it uses the already-scanned endpoint catalog
|
|
58
|
+
* which has full, resolved paths and concrete HTTP methods.
|
|
59
|
+
*
|
|
60
|
+
* For deleted files, the caller must supply endpoints recovered from the base branch
|
|
61
|
+
* (via `parseFileEndpoints` on `git show base:<file>`) in `deletedFileEndpoints`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function classifyEndpointsByChangedFiles(diffData: BranchDiffData, scannedEndpoints: ScannedEndpoint[], deletedFileEndpoints?: ScannedEndpoint[]): ClassifiedEndpoints;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { DraftedScenario } from "../types/RepositoryAnalysis.js";
|
|
2
|
+
import { WorkspaceAuthType } from "./workspaceAuth.js";
|
|
3
|
+
export declare function isRealResource(r: string): boolean;
|
|
4
|
+
type MethodInput = string | {
|
|
5
|
+
method: string;
|
|
6
|
+
sourceFile?: string;
|
|
7
|
+
interactions?: Array<{
|
|
8
|
+
request?: {
|
|
9
|
+
body?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
type EndpointInput = {
|
|
14
|
+
path: string;
|
|
15
|
+
methods: Array<MethodInput>;
|
|
16
|
+
};
|
|
17
|
+
type EndpointRef = {
|
|
18
|
+
method: string;
|
|
19
|
+
path: string;
|
|
20
|
+
sourceFile?: string;
|
|
21
|
+
};
|
|
22
|
+
type ScenarioDraftOptions = {
|
|
23
|
+
/** Existing endpoints touched by a security/destructive diff; used only for attack-surface expansion. */
|
|
24
|
+
changedEndpoints?: Array<EndpointRef>;
|
|
25
|
+
/** Gate sibling destructive expansion to diffs with auth/permission/admin-key signals. */
|
|
26
|
+
securityRelevantDiff?: boolean;
|
|
27
|
+
};
|
|
28
|
+
export type ResourceRelationships = Map<string, Set<string>>;
|
|
29
|
+
/**
|
|
30
|
+
* Infer parent→child resource relationships from two signals already present
|
|
31
|
+
* in the endpoint data — no source code scanning required.
|
|
32
|
+
*
|
|
33
|
+
* Signal 1 — path nesting (always available):
|
|
34
|
+
* /collections/{id}/links → links depends on collections
|
|
35
|
+
*
|
|
36
|
+
* Signal 2 — request body FK fields (available when trace data is merged):
|
|
37
|
+
* POST /orders body: { product_id: "..." } → orders depends on products
|
|
38
|
+
*
|
|
39
|
+
* Returns a map of `dependent → Set<parent>`. Only confirmed, real-resource
|
|
40
|
+
* pairs are included. When no signal is found the map is empty, which tells
|
|
41
|
+
* the caller to fall back to heuristic pairing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function inferResourceRelationships(endpoints: Array<EndpointInput>): ResourceRelationships;
|
|
44
|
+
export declare function draftScenariosFromEndpoints(endpoints: Array<EndpointInput>, newEndpoints?: Array<EndpointRef>, wsAuthType?: WorkspaceAuthType, options?: ScenarioDraftOptions): DraftedScenario[];
|
|
45
|
+
/**
|
|
46
|
+
* Draft scenarios that directly test each new endpoint in the branch diff.
|
|
47
|
+
*
|
|
48
|
+
* For each new endpoint, method-specific scenarios are produced:
|
|
49
|
+
* PUT/PATCH → mutation-recalc integration, boundary-values integration, contract, not-found
|
|
50
|
+
* POST → lifecycle integration (create + optional GET), contract, validation error
|
|
51
|
+
* DELETE → lifecycle integration (create + delete + 404), contract
|
|
52
|
+
* GET /{id} → contract, not-found
|
|
53
|
+
* GET /coll → contract + collection-list integration (create-then-GET) or contract-only
|
|
54
|
+
*
|
|
55
|
+
* Additionally, PUT/PATCH/DELETE methods get an auth-boundary scenario
|
|
56
|
+
* (category "security_boundary" → HIGH priority, not CRITICAL) so it
|
|
57
|
+
* lands in ADDITIONAL deterministically instead of depending on LLM
|
|
58
|
+
* supplement. GET is excluded (often public); POST is excluded because
|
|
59
|
+
* the security-boundary supplement tier covers it. Exception: execution
|
|
60
|
+
* endpoints (/execute, /run, /trigger, etc.) include auth-boundary for
|
|
61
|
+
* all non-GET methods (including POST) since they are high-value targets.
|
|
62
|
+
*/
|
|
63
|
+
export declare function draftDiffDirectScenarios(newEndpoints: Array<{
|
|
64
|
+
method: string;
|
|
65
|
+
path: string;
|
|
66
|
+
}>, resourceGroups: Map<string, {
|
|
67
|
+
basePath: string;
|
|
68
|
+
methods: Set<string>;
|
|
69
|
+
paramPath?: string;
|
|
70
|
+
}>, wsAuthType?: WorkspaceAuthType): DraftedScenario[];
|
|
71
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill content for skyramp.md — installed at auto-discovery paths: ~/.claude/skills/skyramp/SKILLS.md, ~/.cursor/skills/skyramp/SKILLS.md, ~/.github/skills/skyramp.md
|
|
3
|
+
* Follows the SKILL.md specification: https://agentskills.io/what-are-skills#the-skill-md-file
|
|
4
|
+
*/
|
|
5
|
+
export declare const SKYRAMP_MD_CONTENT = "---\nname: skyramp\ndescription: Generate, execute, and maintain API tests (smoke, contract, fuzz, load, integration, E2E, UI) using Skyramp MCP tools.\n---\n\n# Skyramp\n\n## When to use this skill\nUse this skill whenever the user asks to generate, run, or maintain API tests. Always read `<workspace-root>/.skyramp/workspace.yml` first to get `language`, `framework`, `outputDir`, and `api.baseUrl` \u2014 do not ask the user for values already present.\n\n---\n\n## Tools\n\n### Workspace Setup\n1. **`skyramp_initialize_workspace`** \u2014 Create or update `.skyramp/workspace.yml` in a git repository workspace. Scan the repo for all services before calling. Required before any other Skyramp tool.\n\n### Test Generation\n2. **`skyramp_smoke_test_generation`** \u2014 Verify an endpoint is reachable and returns a valid response.\n3. **`skyramp_contract_test_generation`** \u2014 Validate implementation matches OpenAPI/Swagger schema.\n4. **`skyramp_fuzz_test_generation`** \u2014 Send malformed or boundary inputs to find edge cases and security issues.\n5. **`skyramp_load_test_generation`** \u2014 Test performance under concurrent load. Optional: `loadDuration`, `loadNumThreads`. Accepts `trace` instead of `apiSchema`/`endpointURL`.\n6. **`skyramp_integration_test_generation`** \u2014 Multi-step workflows across one or more services. Supply one of: `apiSchema`+`endpointURL`, `trace`, or `scenarioFile`. Do not combine them.\n7. **`skyramp_e2e_test_generation`** \u2014 Full user journey covering UI and backend. Requires `trace` and `playwrightInput` zip. Do not pass `apiSchema` or `endpointURL`.\n8. **`skyramp_ui_test_generation`** \u2014 UI-only tests from Playwright recordings. Requires `playwrightInput` zip.\n\n### Trace Generation\n9. **`skyramp_start_trace_collection`** \u2014 Start capturing backend traffic. Set `playwright: true` for UI or E2E tests. Use an absolute path for `outputDir`.\n10. **`skyramp_stop_trace_collection`** \u2014 Stop capture and save the trace. Use the same `outputDir` and `playwrightEnabled` values as start.\n11. **`skyramp_scenario_test_generation`** \u2014 Scenario trace generation. Describe a multi-step flow in natural language to produce a scenario file. Pass output to `skyramp_integration_test_generation` via `scenarioFile`.\n\n### Test Execution\n12. **`skyramp_execute_test`** \u2014 Run a single Skyramp-generated test file. Required: `workspacePath`, `language`, `testType`, `testFile`. Optional: `stateFile` (writes execution results back for health analysis). For multiple tests, call sequentially to avoid env var conflicts.\n\n### Test Analysis & Maintenance\n13. **`skyramp_analyze_changes`** \u2014 Unified entry point: scans endpoints, discovers tests, computes diff. Takes `repositoryPath` and `scope`. Returns `stateFile` + recommendations.\n14. **`skyramp_analyze_test_health`** \u2014 Drift and health assessment for existing tests. Takes `stateFile`. Returns LLM prompt for scoring.\n15. **`skyramp_actions`** \u2014 Execute UPDATE / REGENERATE / VERIFY / DELETE actions. Takes `stateFile`. Call after analyze_test_health.\n\n### Code Quality\n16. **`skyramp_fix_errors`** \u2014 Fix compilation or runtime errors in a generated test file.\n17. **`skyramp_modularization`** \u2014 Refactor a test file into reusable modules. Set `isTraceBased: true` for trace-based tests.\n18. **`skyramp_reuse_code`** \u2014 Pull shared helpers from other Skyramp tests. Only when `code_reuse` was `true` at generation time.\n\n### Authentication\n19. **`skyramp_login`** \u2014 Log in to the Skyramp platform.\n20. **`skyramp_logout`** \u2014 Log out from the Skyramp platform.\n\n---\n\n## Prompts\n\nPrefer invoking a prompt over manually chaining tools \u2014 prompts run the full workflow automatically.\n\n- **`skyramp_trace_prompt`** \u2014 Trace collection setup and execution.\n- **`skyramp_test_health_analysis`** \u2014 Full maintenance flow (discover \u2192 drift \u2192 health \u2192 actions).\n- **`skyramp_testbot`** \u2014 PR-scoped recommendations + maintenance + report. Required: `prTitle`, `prDescription`, `summaryOutputFile`, `repositoryPath`.\n\n---\n\n## Workflows\n\nUse these when a prompt is not available.\n\n**Generate and run a test**\nRead `.skyramp/workspace.yml` \u2192 Call appropriate generation tool \u2192 `skyramp_execute_test`\n\n**Trace-based test (integration / load / E2E / UI)**\n`skyramp_start_trace_collection` (set `playwright: true` for UI/E2E) \u2192 User exercises the app \u2192 `skyramp_stop_trace_collection` \u2192 Call target generation tool with `trace` (and `playwrightInput` for E2E/UI)\n\n**Scenario \u2192 integration test**\n`skyramp_scenario_test_generation` \u2192 `skyramp_integration_test_generation` with `scenarioFile`\n\n**Recommend tests for a PR**\n`skyramp_analyze_changes` (with `scope: \"branch_diff\"`) \u2192 follow enrichment steps \u2192 `skyramp_recommend_tests` \u2192 Generate recommended tests\n\n**Maintain existing tests**\n`skyramp_analyze_changes` \u2192 `skyramp_analyze_test_health` \u2192 *(optional)* execute tests via `skyramp_execute_test` with `stateFile` param (writes results back) \u2192 `skyramp_actions` (do not skip)\n\n---\n\n## Conventions\n\n- **`endpointURL`** \u2014 Full URL to a specific endpoint, not just the base URL. Build from `api.baseUrl` + path (e.g. `http://localhost:8000/api/v1/users`).\n- **`outputDir`** \u2014 Use absolute paths for both test output and trace collection.\n- **Mutually exclusive inputs** \u2014 `apiSchema`/`endpointURL`, `trace`, and `scenarioFile` are mutually exclusive for integration and load tests. Use exactly one.\n- **Sequential execution** \u2014 Execute tests sequentially (not in parallel) to avoid environment variable conflicts with `SKYRAMP_TEST_BASE_URL`.\n";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source-grounded route extraction — strategy 2 of the candidate UI page ladder.
|
|
3
|
+
*
|
|
4
|
+
* Given a repo path, walks router/App files with the TypeScript Compiler API
|
|
5
|
+
* to find route declarations in three forms:
|
|
6
|
+
*
|
|
7
|
+
* 1. React-style JSX route elements:
|
|
8
|
+
* <Route path="/cart" element={<Cart/>} />
|
|
9
|
+
* <SentryRoute path={WORKSPACE_URL} component={Workspaces} />
|
|
10
|
+
*
|
|
11
|
+
* 2. Vue Router object literals:
|
|
12
|
+
* const routes = [{ path: '/login', component: Login }, …]
|
|
13
|
+
*
|
|
14
|
+
* 3. Directus `defineModule({ id, routes: [...] })`:
|
|
15
|
+
* defineModule({ id: 'notifications', routes: [{ path: '', component: X }] })
|
|
16
|
+
* → URL = "/notifications" (module id prefix + nested path)
|
|
17
|
+
*
|
|
18
|
+
* Path attribute values are resolved through:
|
|
19
|
+
* - String literals (`path="/cart"`)
|
|
20
|
+
* - Local const declarations (`const X = "/cart"; path={X}`)
|
|
21
|
+
* - Cross-file imports + named exports (`import { X } from './constants'`)
|
|
22
|
+
* - Template literals composed of resolvable parts (`` `${BASE}/foo` ``)
|
|
23
|
+
*
|
|
24
|
+
* Why TS Compiler API rather than regex: route declarations span multiple
|
|
25
|
+
* lines with attributes interleaved, paths reference constants that must be
|
|
26
|
+
* cross-file resolved, and tag names vary (Route, SentryRoute, PrivateRoute,
|
|
27
|
+
* …). The AST gives us the structure for free; regex would have to be
|
|
28
|
+
* deliberately permissive at the cost of false matches.
|
|
29
|
+
*/
|
|
30
|
+
/** A route declaration discovered in source. */
|
|
31
|
+
export interface SourceRoute {
|
|
32
|
+
/** URL path string from the route declaration. */
|
|
33
|
+
path: string;
|
|
34
|
+
/** Component identifier referenced by `element={<X/>}` or `component: X`. */
|
|
35
|
+
componentName: string;
|
|
36
|
+
/** Resolved component source file (absolute path), if the import was found. */
|
|
37
|
+
componentFile?: string;
|
|
38
|
+
/** Router file the declaration was found in (absolute path). */
|
|
39
|
+
declaredIn: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Walk the repo, parse candidate router files, return all route declarations.
|
|
43
|
+
*
|
|
44
|
+
* Best-effort by design: a parse error on one file shouldn't block discovery
|
|
45
|
+
* across the rest. Returns empty when no router files match — callers should
|
|
46
|
+
* treat that as "strategy 2 inapplicable" and fall through to the next one.
|
|
47
|
+
*/
|
|
48
|
+
export declare function extractSourceRoutes(repositoryPath: string): SourceRoute[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare function getEntryPoint(): string;
|
|
2
|
+
/**
|
|
3
|
+
* Detects the CI/CD platform from environment variables.
|
|
4
|
+
* Returns undefined when not running in CI.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getCIPlatform(): string | undefined;
|
|
7
|
+
export interface RepositoryInfo {
|
|
8
|
+
repository?: string;
|
|
9
|
+
repositoryOwner?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parses "owner/repo" out of a git remote URL. Handles both HTTPS
|
|
13
|
+
* (https://github.com/owner/repo.git) and SSH (git@github.com:owner/repo.git)
|
|
14
|
+
* forms, with or without the trailing ".git". Returns undefined if no match.
|
|
15
|
+
*/
|
|
16
|
+
export declare function parseRepositoryFromRemoteUrl(remoteUrl: string): RepositoryInfo | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves source-repository attribution for telemetry, segmenting usage per
|
|
19
|
+
* customer/repo.
|
|
20
|
+
*
|
|
21
|
+
* - In GitHub Actions (testbot), reads GITHUB_REPOSITORY / GITHUB_REPOSITORY_OWNER
|
|
22
|
+
* which the MCP subprocess inherits — fast, no shelling out.
|
|
23
|
+
* - In local/IDE usage, derives "owner/repo" from `git remote get-url origin`.
|
|
24
|
+
* The lookup directory is the caller-supplied `cwd` (a tool's repositoryPath
|
|
25
|
+
* or workspacePath) when available, since the MCP server's own process.cwd()
|
|
26
|
+
* is set by the IDE and is not necessarily the user's repo. Falls back to
|
|
27
|
+
* process.cwd(). Cached per directory so git is invoked at most once each.
|
|
28
|
+
*
|
|
29
|
+
* Returns an empty object when attribution can't be determined (e.g. not a git
|
|
30
|
+
* repo, no origin remote).
|
|
31
|
+
*/
|
|
32
|
+
export declare function getRepositoryInfo(cwd?: string): Promise<RepositoryInfo>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type TraceFormat = "skyramp" | "har" | "unknown";
|
|
2
|
+
interface ParsedTraceEntry {
|
|
3
|
+
method: string;
|
|
4
|
+
path: string;
|
|
5
|
+
statusCode: number;
|
|
6
|
+
requestHeaders?: Record<string, string>;
|
|
7
|
+
requestBody?: Record<string, any>;
|
|
8
|
+
queryParams?: Record<string, string[]>;
|
|
9
|
+
responseHeaders?: Record<string, string>;
|
|
10
|
+
responseBody?: Record<string, any>;
|
|
11
|
+
timestamp: string;
|
|
12
|
+
}
|
|
13
|
+
interface ParsedUserFlow {
|
|
14
|
+
flowId: string;
|
|
15
|
+
entries: ParsedTraceEntry[];
|
|
16
|
+
durationMs: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TraceParseResult {
|
|
19
|
+
entries: ParsedTraceEntry[];
|
|
20
|
+
userFlows: ParsedUserFlow[];
|
|
21
|
+
format: TraceFormat;
|
|
22
|
+
}
|
|
23
|
+
export declare function parseTraceFile(filePath: string): Promise<TraceParseResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Discover trace JSON files in a repository path.
|
|
26
|
+
*/
|
|
27
|
+
export declare function discoverTraceFiles(repositoryPath: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Discover Playwright recording zip files in a repository path.
|
|
30
|
+
*/
|
|
31
|
+
export declare function discoverPlaywrightZips(repositoryPath: string): string[];
|
|
32
|
+
export {};
|