@skyramp/mcp 0.2.6 → 0.2.8-rc.1
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 +6 -4
- 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 +24 -5
- 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/sut-setup/modes/adaptWorkflowPrompt.d.ts +2 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +114 -0
- package/build/prompts/sut-setup/modes/dockerComposePrompt.d.ts +2 -0
- package/build/prompts/sut-setup/modes/dockerComposePrompt.js +292 -0
- package/build/prompts/sut-setup/shared.d.ts +39 -0
- package/build/prompts/sut-setup/shared.js +132 -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-maintenance/driftAnalysisSections.js +9 -3
- package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +84 -0
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +1 -1
- 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 +83 -18
- 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 +97 -99
- package/build/prompts/testbot/testbot-prompts.d.ts +26 -0
- package/build/prompts/testbot/testbot-prompts.js +301 -46
- package/build/prompts/testbot/testbot-prompts.test.d.ts +1 -0
- package/build/prompts/testbot/testbot-prompts.test.js +109 -117
- package/build/resources/analysisResources.d.ts +17 -0
- package/build/resources/progressResource.d.ts +2 -0
- package/build/resources/sutSetupResource.d.ts +2 -0
- package/build/resources/sutSetupResource.js +45 -0
- package/build/resources/testbotResource.d.ts +2 -0
- package/build/resources/testbotResource.js +2 -2
- 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.js +22 -12
- package/build/services/TestDiscoveryService.test.d.ts +1 -0
- package/build/services/TestDiscoveryService.test.js +4 -3
- package/build/services/TestExecutionService.d.ts +55 -0
- package/build/services/TestExecutionService.js +158 -26
- package/build/services/TestExecutionService.test.d.ts +1 -0
- package/build/services/TestExecutionService.test.js +339 -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/executeSkyrampTestTool.js +26 -7
- package/build/tools/fixErrorTool.d.ts +2 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +45 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +1 -1
- 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 +394 -0
- package/build/tools/submitReportTool.js +250 -41
- package/build/tools/submitReportTool.test.d.ts +1 -0
- package/build/tools/submitReportTool.test.js +511 -55
- package/build/tools/test-management/actionsTool.d.ts +10 -0
- package/build/tools/test-management/actionsTool.js +21 -7
- package/build/tools/test-management/analyzeChangesTool.d.ts +27 -0
- package/build/tools/test-management/analyzeChangesTool.js +150 -48
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +1 -0
- package/build/tools/test-management/analyzeChangesTool.test.js +95 -78
- package/build/tools/test-management/analyzeTestHealthTool.d.ts +2 -0
- package/build/tools/test-management/analyzeTestHealthTool.js +16 -9
- 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.js +39 -22
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +1 -0
- package/build/tools/workspace/initializeWorkspaceTool.test.js +134 -0
- package/build/tools/workspace/serviceUpsert.d.ts +12 -0
- package/build/tools/workspace/serviceUpsert.js +23 -0
- package/build/tools/workspace/serviceUpsert.test.d.ts +1 -0
- package/build/tools/workspace/serviceUpsert.test.js +50 -0
- package/build/types/OneClickCommands.d.ts +68 -0
- package/build/types/RepositoryAnalysis.d.ts +3004 -0
- package/build/types/TestAnalysis.d.ts +97 -0
- package/build/types/TestExecution.d.ts +63 -0
- package/build/types/TestExecution.js +11 -1
- package/build/types/TestRecommendation.d.ts +12 -0
- package/build/types/TestTypes.d.ts +234 -0
- package/build/types/TestbotReport.d.ts +68 -0
- package/build/types/TestbotReport.js +1 -0
- package/build/types/index.d.ts +4 -0
- package/build/types/index.js +3 -0
- package/build/utils/AnalysisStateManager.d.ts +242 -0
- package/build/utils/AnalysisStateManager.js +144 -3
- package/build/utils/AnalysisStateManager.test.d.ts +1 -0
- package/build/utils/AnalysisStateManager.test.js +98 -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 +53 -0
- package/build/utils/routeParsers.js +31 -38
- package/build/utils/routeParsers.test.d.ts +1 -0
- package/build/utils/scenarioDrafting.d.ts +71 -0
- package/build/utils/scenarioDrafting.js +23 -1
- 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 +45 -0
- package/build/utils/utils.js +10 -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.js +7 -7
- package/build/workspace/workspace.test.d.ts +1 -0
- package/build/workspace/workspace.test.js +6 -6
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -13
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +88 -15
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -3
- package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +23 -126
- package/node_modules/playwright/node_modules/playwright-core/lib/generated/injectedScriptSource.js +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +79 -19
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/aliasRemapper.js +84 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +15 -4
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-CPZKmjFR.js → codeMirrorModule-D0BjbCb7.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +193 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-B0JOjboO.js → codeMirrorModule-Cqp3cwEJ.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{defaultSettingsView-1anWeyDf.js → defaultSettingsView-CYf9adZh.js} +79 -79
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.Cc5029a3.js → index.B_7ywgmr.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{uiMode.Wo5yvvVh.js → uiMode.u4_8VnCV.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/generated/injectedScriptSource.ts +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +129 -43
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/aliasRemapper.ts +119 -0
- package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +33 -10
- package/node_modules/playwright/package.json +1 -1
- package/package.json +16 -4
- package/build/tools/test-management/uiAnalyzeChangesTool.js +0 -155
- package/build/tools/test-management/uiAnalyzeChangesTool.test.js +0 -147
- package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.bin/node-which +0 -52
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/is-docker +0 -5
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/mime +0 -46
- package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/yaml +0 -11
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-CsgPR2wy.js +0 -193
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.CP3Y8Zsb.js +0 -2
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
// @ts-nocheck - Jest ESM mock type inference issues
|
|
2
|
+
import { jest } from "@jest/globals";
|
|
2
3
|
const REPO = "/some/repo";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
4
|
+
const twoServiceConfig = {
|
|
5
|
+
services: [
|
|
6
|
+
{
|
|
7
|
+
serviceName: "backend",
|
|
8
|
+
language: "python",
|
|
9
|
+
testDirectory: "backend/tests",
|
|
10
|
+
api: { baseUrl: "http://localhost:8000" },
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
serviceName: "frontend",
|
|
14
|
+
language: "typescript",
|
|
15
|
+
testDirectory: "frontend/tests",
|
|
16
|
+
api: { baseUrl: "http://localhost:5173" },
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
jest.unstable_mockModule("../workspace/workspace.js", () => ({
|
|
21
|
+
WorkspaceConfigManager: jest.fn().mockImplementation(() => ({
|
|
22
|
+
exists: jest.fn().mockResolvedValue(true),
|
|
23
|
+
read: jest.fn().mockResolvedValue(twoServiceConfig),
|
|
24
|
+
})),
|
|
25
|
+
}));
|
|
26
|
+
const { getWorkspaceBaseUrl } = await import("./workspaceAuth.js");
|
|
27
27
|
describe("getWorkspaceBaseUrl", () => {
|
|
28
28
|
it("should return no match when testFile is not provided", async () => {
|
|
29
29
|
const result = await getWorkspaceBaseUrl(REPO);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./workspace.js";
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const WORKSPACE_DIR = ".skyramp";
|
|
3
|
+
export declare const WORKSPACE_FILENAME = "workspace.yml";
|
|
4
|
+
export declare const serviceSchema: z.ZodObject<{
|
|
5
|
+
serviceName: z.ZodString;
|
|
6
|
+
repository: z.ZodOptional<z.ZodString>;
|
|
7
|
+
language: z.ZodOptional<z.ZodEnum<["python", "typescript", "javascript", "java"]>>;
|
|
8
|
+
framework: z.ZodOptional<z.ZodEnum<["playwright", "pytest", "robot", "junit"]>>;
|
|
9
|
+
testDirectory: z.ZodOptional<z.ZodString>;
|
|
10
|
+
api: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
schemaPath: z.ZodOptional<z.ZodString>;
|
|
12
|
+
authType: z.ZodOptional<z.ZodEnum<["bearer", "basic", "oauth", "apiKey", "cookie", "session", "token", "none"]>>;
|
|
13
|
+
authHeader: z.ZodOptional<z.ZodString>;
|
|
14
|
+
authScheme: z.ZodOptional<z.ZodString>;
|
|
15
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, "strict", z.ZodTypeAny, {
|
|
17
|
+
authHeader?: string | undefined;
|
|
18
|
+
authScheme?: string | undefined;
|
|
19
|
+
schemaPath?: string | undefined;
|
|
20
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
21
|
+
baseUrl?: string | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
authHeader?: string | undefined;
|
|
24
|
+
authScheme?: string | undefined;
|
|
25
|
+
schemaPath?: string | undefined;
|
|
26
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
27
|
+
baseUrl?: string | undefined;
|
|
28
|
+
}>>;
|
|
29
|
+
runtimeDetails: z.ZodOptional<z.ZodObject<{
|
|
30
|
+
serverStartCommand: z.ZodOptional<z.ZodString>;
|
|
31
|
+
runtime: z.ZodEnum<["local", "docker", "k8s"]>;
|
|
32
|
+
dockerNetwork: z.ZodOptional<z.ZodString>;
|
|
33
|
+
k8sNamespace: z.ZodOptional<z.ZodString>;
|
|
34
|
+
k8sContext: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, "strict", z.ZodTypeAny, {
|
|
36
|
+
runtime: "local" | "docker" | "k8s";
|
|
37
|
+
dockerNetwork?: string | undefined;
|
|
38
|
+
k8sNamespace?: string | undefined;
|
|
39
|
+
k8sContext?: string | undefined;
|
|
40
|
+
serverStartCommand?: string | undefined;
|
|
41
|
+
}, {
|
|
42
|
+
runtime: "local" | "docker" | "k8s";
|
|
43
|
+
dockerNetwork?: string | undefined;
|
|
44
|
+
k8sNamespace?: string | undefined;
|
|
45
|
+
k8sContext?: string | undefined;
|
|
46
|
+
serverStartCommand?: string | undefined;
|
|
47
|
+
}>>;
|
|
48
|
+
}, "strict", z.ZodTypeAny, {
|
|
49
|
+
serviceName: string;
|
|
50
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
51
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
52
|
+
repository?: string | undefined;
|
|
53
|
+
testDirectory?: string | undefined;
|
|
54
|
+
api?: {
|
|
55
|
+
authHeader?: string | undefined;
|
|
56
|
+
authScheme?: string | undefined;
|
|
57
|
+
schemaPath?: string | undefined;
|
|
58
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
59
|
+
baseUrl?: string | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
runtimeDetails?: {
|
|
62
|
+
runtime: "local" | "docker" | "k8s";
|
|
63
|
+
dockerNetwork?: string | undefined;
|
|
64
|
+
k8sNamespace?: string | undefined;
|
|
65
|
+
k8sContext?: string | undefined;
|
|
66
|
+
serverStartCommand?: string | undefined;
|
|
67
|
+
} | undefined;
|
|
68
|
+
}, {
|
|
69
|
+
serviceName: string;
|
|
70
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
71
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
72
|
+
repository?: string | undefined;
|
|
73
|
+
testDirectory?: string | undefined;
|
|
74
|
+
api?: {
|
|
75
|
+
authHeader?: string | undefined;
|
|
76
|
+
authScheme?: string | undefined;
|
|
77
|
+
schemaPath?: string | undefined;
|
|
78
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
79
|
+
baseUrl?: string | undefined;
|
|
80
|
+
} | undefined;
|
|
81
|
+
runtimeDetails?: {
|
|
82
|
+
runtime: "local" | "docker" | "k8s";
|
|
83
|
+
dockerNetwork?: string | undefined;
|
|
84
|
+
k8sNamespace?: string | undefined;
|
|
85
|
+
k8sContext?: string | undefined;
|
|
86
|
+
serverStartCommand?: string | undefined;
|
|
87
|
+
} | undefined;
|
|
88
|
+
}>;
|
|
89
|
+
export declare const workspaceConfigSchema: z.ZodObject<{
|
|
90
|
+
workspace: z.ZodOptional<z.ZodObject<{
|
|
91
|
+
repoName: z.ZodOptional<z.ZodString>;
|
|
92
|
+
repoUrl: z.ZodOptional<z.ZodString>;
|
|
93
|
+
}, "strict", z.ZodTypeAny, {
|
|
94
|
+
repoName?: string | undefined;
|
|
95
|
+
repoUrl?: string | undefined;
|
|
96
|
+
}, {
|
|
97
|
+
repoName?: string | undefined;
|
|
98
|
+
repoUrl?: string | undefined;
|
|
99
|
+
}>>;
|
|
100
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
101
|
+
schemaVersion: z.ZodString;
|
|
102
|
+
mcpVersion: z.ZodString;
|
|
103
|
+
executorVersion: z.ZodString;
|
|
104
|
+
createdAt: z.ZodString;
|
|
105
|
+
updatedAt: z.ZodString;
|
|
106
|
+
}, "strict", z.ZodTypeAny, {
|
|
107
|
+
createdAt: string;
|
|
108
|
+
schemaVersion: string;
|
|
109
|
+
mcpVersion: string;
|
|
110
|
+
executorVersion: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
}, {
|
|
113
|
+
createdAt: string;
|
|
114
|
+
schemaVersion: string;
|
|
115
|
+
mcpVersion: string;
|
|
116
|
+
executorVersion: string;
|
|
117
|
+
updatedAt: string;
|
|
118
|
+
}>>;
|
|
119
|
+
services: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
120
|
+
serviceName: z.ZodString;
|
|
121
|
+
repository: z.ZodOptional<z.ZodString>;
|
|
122
|
+
language: z.ZodOptional<z.ZodEnum<["python", "typescript", "javascript", "java"]>>;
|
|
123
|
+
framework: z.ZodOptional<z.ZodEnum<["playwright", "pytest", "robot", "junit"]>>;
|
|
124
|
+
testDirectory: z.ZodOptional<z.ZodString>;
|
|
125
|
+
api: z.ZodOptional<z.ZodObject<{
|
|
126
|
+
schemaPath: z.ZodOptional<z.ZodString>;
|
|
127
|
+
authType: z.ZodOptional<z.ZodEnum<["bearer", "basic", "oauth", "apiKey", "cookie", "session", "token", "none"]>>;
|
|
128
|
+
authHeader: z.ZodOptional<z.ZodString>;
|
|
129
|
+
authScheme: z.ZodOptional<z.ZodString>;
|
|
130
|
+
baseUrl: z.ZodOptional<z.ZodString>;
|
|
131
|
+
}, "strict", z.ZodTypeAny, {
|
|
132
|
+
authHeader?: string | undefined;
|
|
133
|
+
authScheme?: string | undefined;
|
|
134
|
+
schemaPath?: string | undefined;
|
|
135
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
136
|
+
baseUrl?: string | undefined;
|
|
137
|
+
}, {
|
|
138
|
+
authHeader?: string | undefined;
|
|
139
|
+
authScheme?: string | undefined;
|
|
140
|
+
schemaPath?: string | undefined;
|
|
141
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
142
|
+
baseUrl?: string | undefined;
|
|
143
|
+
}>>;
|
|
144
|
+
runtimeDetails: z.ZodOptional<z.ZodObject<{
|
|
145
|
+
serverStartCommand: z.ZodOptional<z.ZodString>;
|
|
146
|
+
runtime: z.ZodEnum<["local", "docker", "k8s"]>;
|
|
147
|
+
dockerNetwork: z.ZodOptional<z.ZodString>;
|
|
148
|
+
k8sNamespace: z.ZodOptional<z.ZodString>;
|
|
149
|
+
k8sContext: z.ZodOptional<z.ZodString>;
|
|
150
|
+
}, "strict", z.ZodTypeAny, {
|
|
151
|
+
runtime: "local" | "docker" | "k8s";
|
|
152
|
+
dockerNetwork?: string | undefined;
|
|
153
|
+
k8sNamespace?: string | undefined;
|
|
154
|
+
k8sContext?: string | undefined;
|
|
155
|
+
serverStartCommand?: string | undefined;
|
|
156
|
+
}, {
|
|
157
|
+
runtime: "local" | "docker" | "k8s";
|
|
158
|
+
dockerNetwork?: string | undefined;
|
|
159
|
+
k8sNamespace?: string | undefined;
|
|
160
|
+
k8sContext?: string | undefined;
|
|
161
|
+
serverStartCommand?: string | undefined;
|
|
162
|
+
}>>;
|
|
163
|
+
}, "strict", z.ZodTypeAny, {
|
|
164
|
+
serviceName: string;
|
|
165
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
166
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
167
|
+
repository?: string | undefined;
|
|
168
|
+
testDirectory?: string | undefined;
|
|
169
|
+
api?: {
|
|
170
|
+
authHeader?: string | undefined;
|
|
171
|
+
authScheme?: string | undefined;
|
|
172
|
+
schemaPath?: string | undefined;
|
|
173
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
174
|
+
baseUrl?: string | undefined;
|
|
175
|
+
} | undefined;
|
|
176
|
+
runtimeDetails?: {
|
|
177
|
+
runtime: "local" | "docker" | "k8s";
|
|
178
|
+
dockerNetwork?: string | undefined;
|
|
179
|
+
k8sNamespace?: string | undefined;
|
|
180
|
+
k8sContext?: string | undefined;
|
|
181
|
+
serverStartCommand?: string | undefined;
|
|
182
|
+
} | undefined;
|
|
183
|
+
}, {
|
|
184
|
+
serviceName: string;
|
|
185
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
186
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
187
|
+
repository?: string | undefined;
|
|
188
|
+
testDirectory?: string | undefined;
|
|
189
|
+
api?: {
|
|
190
|
+
authHeader?: string | undefined;
|
|
191
|
+
authScheme?: string | undefined;
|
|
192
|
+
schemaPath?: string | undefined;
|
|
193
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
194
|
+
baseUrl?: string | undefined;
|
|
195
|
+
} | undefined;
|
|
196
|
+
runtimeDetails?: {
|
|
197
|
+
runtime: "local" | "docker" | "k8s";
|
|
198
|
+
dockerNetwork?: string | undefined;
|
|
199
|
+
k8sNamespace?: string | undefined;
|
|
200
|
+
k8sContext?: string | undefined;
|
|
201
|
+
serverStartCommand?: string | undefined;
|
|
202
|
+
} | undefined;
|
|
203
|
+
}>, "many">>;
|
|
204
|
+
}, "strict", z.ZodTypeAny, {
|
|
205
|
+
metadata?: {
|
|
206
|
+
createdAt: string;
|
|
207
|
+
schemaVersion: string;
|
|
208
|
+
mcpVersion: string;
|
|
209
|
+
executorVersion: string;
|
|
210
|
+
updatedAt: string;
|
|
211
|
+
} | undefined;
|
|
212
|
+
workspace?: {
|
|
213
|
+
repoName?: string | undefined;
|
|
214
|
+
repoUrl?: string | undefined;
|
|
215
|
+
} | undefined;
|
|
216
|
+
services?: {
|
|
217
|
+
serviceName: string;
|
|
218
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
219
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
220
|
+
repository?: string | undefined;
|
|
221
|
+
testDirectory?: string | undefined;
|
|
222
|
+
api?: {
|
|
223
|
+
authHeader?: string | undefined;
|
|
224
|
+
authScheme?: string | undefined;
|
|
225
|
+
schemaPath?: string | undefined;
|
|
226
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
227
|
+
baseUrl?: string | undefined;
|
|
228
|
+
} | undefined;
|
|
229
|
+
runtimeDetails?: {
|
|
230
|
+
runtime: "local" | "docker" | "k8s";
|
|
231
|
+
dockerNetwork?: string | undefined;
|
|
232
|
+
k8sNamespace?: string | undefined;
|
|
233
|
+
k8sContext?: string | undefined;
|
|
234
|
+
serverStartCommand?: string | undefined;
|
|
235
|
+
} | undefined;
|
|
236
|
+
}[] | undefined;
|
|
237
|
+
}, {
|
|
238
|
+
metadata?: {
|
|
239
|
+
createdAt: string;
|
|
240
|
+
schemaVersion: string;
|
|
241
|
+
mcpVersion: string;
|
|
242
|
+
executorVersion: string;
|
|
243
|
+
updatedAt: string;
|
|
244
|
+
} | undefined;
|
|
245
|
+
workspace?: {
|
|
246
|
+
repoName?: string | undefined;
|
|
247
|
+
repoUrl?: string | undefined;
|
|
248
|
+
} | undefined;
|
|
249
|
+
services?: {
|
|
250
|
+
serviceName: string;
|
|
251
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
252
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
253
|
+
repository?: string | undefined;
|
|
254
|
+
testDirectory?: string | undefined;
|
|
255
|
+
api?: {
|
|
256
|
+
authHeader?: string | undefined;
|
|
257
|
+
authScheme?: string | undefined;
|
|
258
|
+
schemaPath?: string | undefined;
|
|
259
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
260
|
+
baseUrl?: string | undefined;
|
|
261
|
+
} | undefined;
|
|
262
|
+
runtimeDetails?: {
|
|
263
|
+
runtime: "local" | "docker" | "k8s";
|
|
264
|
+
dockerNetwork?: string | undefined;
|
|
265
|
+
k8sNamespace?: string | undefined;
|
|
266
|
+
k8sContext?: string | undefined;
|
|
267
|
+
serverStartCommand?: string | undefined;
|
|
268
|
+
} | undefined;
|
|
269
|
+
}[] | undefined;
|
|
270
|
+
}>;
|
|
271
|
+
export type Service = z.infer<typeof serviceSchema>;
|
|
272
|
+
export type ServiceApi = NonNullable<Service["api"]>;
|
|
273
|
+
export type ServiceRuntimeDetails = NonNullable<Service["runtimeDetails"]>;
|
|
274
|
+
export type WorkspaceConfig = z.infer<typeof workspaceConfigSchema>;
|
|
275
|
+
export type WorkspaceSection = NonNullable<WorkspaceConfig["workspace"]>;
|
|
276
|
+
export type MetadataSection = NonNullable<WorkspaceConfig["metadata"]>;
|
|
277
|
+
/** Validates a workspace configuration object against the Zod schema. */
|
|
278
|
+
export declare function validateWorkspaceConfig(config: unknown): z.SafeParseReturnType<{
|
|
279
|
+
metadata?: {
|
|
280
|
+
createdAt: string;
|
|
281
|
+
schemaVersion: string;
|
|
282
|
+
mcpVersion: string;
|
|
283
|
+
executorVersion: string;
|
|
284
|
+
updatedAt: string;
|
|
285
|
+
} | undefined;
|
|
286
|
+
workspace?: {
|
|
287
|
+
repoName?: string | undefined;
|
|
288
|
+
repoUrl?: string | undefined;
|
|
289
|
+
} | undefined;
|
|
290
|
+
services?: {
|
|
291
|
+
serviceName: string;
|
|
292
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
293
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
294
|
+
repository?: string | undefined;
|
|
295
|
+
testDirectory?: string | undefined;
|
|
296
|
+
api?: {
|
|
297
|
+
authHeader?: string | undefined;
|
|
298
|
+
authScheme?: string | undefined;
|
|
299
|
+
schemaPath?: string | undefined;
|
|
300
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
301
|
+
baseUrl?: string | undefined;
|
|
302
|
+
} | undefined;
|
|
303
|
+
runtimeDetails?: {
|
|
304
|
+
runtime: "local" | "docker" | "k8s";
|
|
305
|
+
dockerNetwork?: string | undefined;
|
|
306
|
+
k8sNamespace?: string | undefined;
|
|
307
|
+
k8sContext?: string | undefined;
|
|
308
|
+
serverStartCommand?: string | undefined;
|
|
309
|
+
} | undefined;
|
|
310
|
+
}[] | undefined;
|
|
311
|
+
}, {
|
|
312
|
+
metadata?: {
|
|
313
|
+
createdAt: string;
|
|
314
|
+
schemaVersion: string;
|
|
315
|
+
mcpVersion: string;
|
|
316
|
+
executorVersion: string;
|
|
317
|
+
updatedAt: string;
|
|
318
|
+
} | undefined;
|
|
319
|
+
workspace?: {
|
|
320
|
+
repoName?: string | undefined;
|
|
321
|
+
repoUrl?: string | undefined;
|
|
322
|
+
} | undefined;
|
|
323
|
+
services?: {
|
|
324
|
+
serviceName: string;
|
|
325
|
+
language?: "python" | "typescript" | "javascript" | "java" | undefined;
|
|
326
|
+
framework?: "playwright" | "pytest" | "robot" | "junit" | undefined;
|
|
327
|
+
repository?: string | undefined;
|
|
328
|
+
testDirectory?: string | undefined;
|
|
329
|
+
api?: {
|
|
330
|
+
authHeader?: string | undefined;
|
|
331
|
+
authScheme?: string | undefined;
|
|
332
|
+
schemaPath?: string | undefined;
|
|
333
|
+
authType?: "none" | "token" | "bearer" | "basic" | "oauth" | "apiKey" | "cookie" | "session" | undefined;
|
|
334
|
+
baseUrl?: string | undefined;
|
|
335
|
+
} | undefined;
|
|
336
|
+
runtimeDetails?: {
|
|
337
|
+
runtime: "local" | "docker" | "k8s";
|
|
338
|
+
dockerNetwork?: string | undefined;
|
|
339
|
+
k8sNamespace?: string | undefined;
|
|
340
|
+
k8sContext?: string | undefined;
|
|
341
|
+
serverStartCommand?: string | undefined;
|
|
342
|
+
} | undefined;
|
|
343
|
+
}[] | undefined;
|
|
344
|
+
}>;
|
|
345
|
+
/** Creates a default workspace config with empty sections and timestamps. */
|
|
346
|
+
export declare function createDefaultConfig(): WorkspaceConfig;
|
|
347
|
+
/**
|
|
348
|
+
* High-level manager for .skyramp/workspace.yml.
|
|
349
|
+
*
|
|
350
|
+
* Provides three focused mutation methods:
|
|
351
|
+
* 1. initialize() — create workspace file with repo info
|
|
352
|
+
* 2. updateMetadata() — update metadata section
|
|
353
|
+
* 3. addService() — upsert a single service entry
|
|
354
|
+
*/
|
|
355
|
+
export declare class WorkspaceConfigManager {
|
|
356
|
+
private workspacePath;
|
|
357
|
+
private skyrampDir;
|
|
358
|
+
private configPath;
|
|
359
|
+
constructor(workspacePath: string);
|
|
360
|
+
/** Check if workspace config file exists */
|
|
361
|
+
exists(): Promise<boolean>;
|
|
362
|
+
/** Get the absolute path to the config file */
|
|
363
|
+
getConfigPath(): string;
|
|
364
|
+
/** Get the workspace root path */
|
|
365
|
+
getWorkspacePath(): string;
|
|
366
|
+
/** Read and parse workspace config from disk. */
|
|
367
|
+
read(): Promise<WorkspaceConfig>;
|
|
368
|
+
/**
|
|
369
|
+
* Initialize workspace — creates .skyramp/workspace.yml with repo info.
|
|
370
|
+
* Auto-detects repoName and repoUrl from git when not provided.
|
|
371
|
+
* Produces an empty services array and default metadata timestamps.
|
|
372
|
+
*/
|
|
373
|
+
initialize(workspaceInfo?: WorkspaceSection): Promise<WorkspaceConfig>;
|
|
374
|
+
/**
|
|
375
|
+
* Update the metadata section of an existing workspace config.
|
|
376
|
+
* Only the provided fields are merged; metadata.updatedAt is refreshed
|
|
377
|
+
* automatically.
|
|
378
|
+
*/
|
|
379
|
+
updateMetadata(metadata: Partial<MetadataSection>): Promise<WorkspaceConfig>;
|
|
380
|
+
/**
|
|
381
|
+
* Add a single service entry to the services array.
|
|
382
|
+
* If a service with the same identity already exists it is replaced
|
|
383
|
+
* (upsert semantics), otherwise the new entry is appended. Service identity
|
|
384
|
+
* is the composite (repo, serviceName) — a service's `repo` (absent → primary)
|
|
385
|
+
* is part of its key, so the same serviceName can coexist across repos in a
|
|
386
|
+
* unified multi-repo workspace.
|
|
387
|
+
* metadata.updatedAt is refreshed automatically.
|
|
388
|
+
*/
|
|
389
|
+
addService(service: Service): Promise<WorkspaceConfig>;
|
|
390
|
+
}
|
|
@@ -27,9 +27,9 @@ export const serviceSchema = z
|
|
|
27
27
|
.object({
|
|
28
28
|
serviceName: z.string(),
|
|
29
29
|
// owner/repo this service belongs to (multi-repo workspaces). Absent → the
|
|
30
|
-
// primary repo. Service identity is the composite (
|
|
31
|
-
// same serviceName can appear once per repo without colliding.
|
|
32
|
-
|
|
30
|
+
// primary repo. Service identity is the composite (repository, serviceName),
|
|
31
|
+
// so the same serviceName can appear once per repo without colliding.
|
|
32
|
+
repository: z.string().optional(),
|
|
33
33
|
language: z.enum(["python", "typescript", "javascript", "java"]).optional(),
|
|
34
34
|
framework: z.enum(["playwright", "pytest", "robot", "junit"]).optional(),
|
|
35
35
|
testDirectory: z.string().optional(),
|
|
@@ -318,11 +318,11 @@ export class WorkspaceConfigManager {
|
|
|
318
318
|
const validatedService = svcResult.data;
|
|
319
319
|
const config = await this.read();
|
|
320
320
|
const services = config.services || [];
|
|
321
|
-
// Upsert keyed on the composite (
|
|
322
|
-
// to "" (primary) so a primary service and a same-named
|
|
321
|
+
// Upsert keyed on the composite (repository, serviceName). Absent repository
|
|
322
|
+
// normalizes to "" (primary) so a primary service and a same-named related-repo
|
|
323
323
|
// service are distinct entries.
|
|
324
|
-
const repoKey = validatedService.
|
|
325
|
-
const idx = services.findIndex((s) => (s.
|
|
324
|
+
const repoKey = validatedService.repository || "";
|
|
325
|
+
const idx = services.findIndex((s) => (s.repository || "") === repoKey &&
|
|
326
326
|
s.serviceName === validatedService.serviceName);
|
|
327
327
|
if (idx >= 0) {
|
|
328
328
|
services[idx] = validatedService;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,10 +6,10 @@ import yaml from "js-yaml";
|
|
|
6
6
|
import { serviceSchema, WorkspaceConfigManager, validateWorkspaceConfig, createDefaultConfig, WORKSPACE_DIR, WORKSPACE_FILENAME, } from "./workspace.js";
|
|
7
7
|
describe("workspace module (ported from @skyramp/skyramp, SKYR-3794)", () => {
|
|
8
8
|
describe("serviceSchema", () => {
|
|
9
|
-
it("accepts an optional
|
|
10
|
-
expect(serviceSchema.safeParse({ serviceName: "api",
|
|
9
|
+
it("accepts an optional repository and rejects a non-string repository", () => {
|
|
10
|
+
expect(serviceSchema.safeParse({ serviceName: "api", repository: "org/api" }).success).toBe(true);
|
|
11
11
|
expect(serviceSchema.safeParse({ serviceName: "api" }).success).toBe(true);
|
|
12
|
-
expect(serviceSchema.safeParse({ serviceName: "api",
|
|
12
|
+
expect(serviceSchema.safeParse({ serviceName: "api", repository: 123 }).success).toBe(false);
|
|
13
13
|
});
|
|
14
14
|
it("rejects unknown fields (strict)", () => {
|
|
15
15
|
expect(serviceSchema.safeParse({ serviceName: "api", bogus: true }).success).toBe(false);
|
|
@@ -42,12 +42,12 @@ describe("workspace module (ported from @skyramp/skyramp, SKYR-3794)", () => {
|
|
|
42
42
|
const mgr = new WorkspaceConfigManager(repoDir);
|
|
43
43
|
await mgr.initialize();
|
|
44
44
|
await mgr.addService({ serviceName: "svc", testDirectory: "tests/primary" });
|
|
45
|
-
await mgr.addService({ serviceName: "svc",
|
|
45
|
+
await mgr.addService({ serviceName: "svc", repository: "letsramp/api-insight", testDirectory: "tests/py" });
|
|
46
46
|
await mgr.addService({ serviceName: "svc", testDirectory: "tests/primary-v2" }); // upsert primary
|
|
47
47
|
const cfg = read();
|
|
48
48
|
expect(cfg.services).toHaveLength(2);
|
|
49
|
-
expect(cfg.services.find((s) => !s.
|
|
50
|
-
expect(cfg.services.find((s) => s.
|
|
49
|
+
expect(cfg.services.find((s) => !s.repository).testDirectory).toBe("tests/primary-v2");
|
|
50
|
+
expect(cfg.services.find((s) => s.repository === "letsramp/api-insight").testDirectory).toBe("tests/py");
|
|
51
51
|
// repoName auto-detected from the git remote.
|
|
52
52
|
expect(cfg.workspace.repoName).toBe("letsramp/primary");
|
|
53
53
|
});
|
|
@@ -36,20 +36,23 @@ const loadTraceSchema = {
|
|
|
36
36
|
name: "skyramp_load_trace",
|
|
37
37
|
title: "Load and replay a Skyramp trace",
|
|
38
38
|
description: [
|
|
39
|
-
"Load a previously recorded Skyramp trace (.zip or .jsonl/.txt) and replay its actions against the live browser to restore state, then continue recording from that point.",
|
|
40
|
-
"The replayed actions are merged into the current recording, so subsequent browser_* steps append to them and skyramp_export_zip writes a combined trace.",
|
|
41
|
-
"
|
|
42
|
-
"-
|
|
39
|
+
"Load a previously recorded Skyramp trace (.zip or .jsonl/.txt) and replay a range of its actions against the live browser to restore state, then continue recording from that point.",
|
|
40
|
+
"The replayed actions are merged into the current recording, so subsequent browser_* steps append to them and skyramp_export_zip writes a combined trace. You can record some steps FIRST, then load a trace to insert an already-recorded fragment at the current point.",
|
|
41
|
+
"STARTING LATER (skip a stale prefix): set startAtStep to begin replay partway in, skipping earlier steps. Use this when the live browser is already past the trace's opening steps - e.g. the login page changed, you recorded the NEW login manually, and now want to append only the still-valid post-login part of the old trace. Omit to start from step 1.",
|
|
42
|
+
"- startAtStep: begin replay at step N (1-based, from the numbered step list); steps 1..N-1 are skipped (neither replayed nor recorded).",
|
|
43
|
+
"STOPPING EARLY: when the user wants to stop partway through the loaded trace before continuing, set ONE of stopAtStep / stopAtUrl / stopBefore based on their prompt. Omit all three to replay to the end.",
|
|
44
|
+
"- stopAtStep: replay up to and including step N then stop (N is 1-based, from the numbered step list).",
|
|
43
45
|
"- stopAtUrl: stop once the active page URL matches this glob/regex/substring (checked after each action).",
|
|
44
46
|
'- stopBefore: stop right BEFORE the first action whose description contains this text (case-insensitive), e.g. "Checkout" to stop before clicking Checkout.',
|
|
45
|
-
"If unsure where to stop, first call with dryRun:true to read the numbered step list, then call again with the chosen stop
|
|
47
|
+
"If unsure where to start/stop, first call with dryRun:true to read the numbered step list, then call again with the chosen start/stop parameters."
|
|
46
48
|
].join(" "),
|
|
47
49
|
inputSchema: import_mcpBundle.z.object({
|
|
48
50
|
path: import_mcpBundle.z.string().describe("Absolute path to the trace file (.zip, .jsonl, or .txt)."),
|
|
49
|
-
|
|
51
|
+
startAtStep: import_mcpBundle.z.number().int().positive().optional().describe("Begin replay at step N (1-based); skip steps 1..N-1. Use to skip a stale prefix (e.g. old login)."),
|
|
52
|
+
stopAtStep: import_mcpBundle.z.number().int().positive().optional().describe("Replay up to and including step N (1-based), then stop before continuing."),
|
|
50
53
|
stopAtUrl: import_mcpBundle.z.string().optional().describe("Stop once the active page URL matches this glob/regex/substring."),
|
|
51
54
|
stopBefore: import_mcpBundle.z.string().optional().describe("Stop before the first action whose description contains this text (case-insensitive)."),
|
|
52
|
-
dryRun: import_mcpBundle.z.boolean().optional().describe("Parse and list the steps WITHOUT replaying. Use to choose
|
|
55
|
+
dryRun: import_mcpBundle.z.boolean().optional().describe("Parse and list the steps WITHOUT replaying. Use to choose start/stop points."),
|
|
53
56
|
speed: import_mcpBundle.z.enum(["fast", "slow"]).optional().describe('Replay speed. "slow" adds a 1s delay between actions (default "fast").')
|
|
54
57
|
}),
|
|
55
58
|
// Replaying drives the live browser and mutates the recording, so this is an
|
|
@@ -134,17 +137,30 @@ function describeStopReason(result) {
|
|
|
134
137
|
async function replayActions(actionsList, callbacks, params) {
|
|
135
138
|
const delay = params.speed === "slow" ? 1e3 : 0;
|
|
136
139
|
const stopBefore = params.stopBefore?.toLowerCase();
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
const startIndex = params.startAtStep ? Math.max(0, Math.min(params.startAtStep - 1, actionsList.length)) : 0;
|
|
141
|
+
let completedCount = startIndex;
|
|
142
|
+
for (let i = startIndex; i < actionsList.length; i++) {
|
|
139
143
|
const action = actionsList[i];
|
|
140
144
|
if (stopBefore && describeStep(action, i).toLowerCase().includes(stopBefore))
|
|
141
|
-
return { completedCount, stopIndex: i, stopReason: "stopBefore" };
|
|
145
|
+
return { completedCount, startIndex, stopIndex: i, stopReason: "stopBefore" };
|
|
146
|
+
try {
|
|
147
|
+
callbacks.beforeAction?.(action);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
return {
|
|
150
|
+
completedCount,
|
|
151
|
+
startIndex,
|
|
152
|
+
stopIndex: i,
|
|
153
|
+
stopReason: "error",
|
|
154
|
+
error: { message: e.message, actionName: action.action.name, stepIndex: i + 1 }
|
|
155
|
+
};
|
|
156
|
+
}
|
|
142
157
|
const alias = action.frame.pageAlias || "page";
|
|
143
158
|
const page = callbacks.pageForAlias(alias);
|
|
144
159
|
if (!METADATA_ONLY_ACTIONS.has(action.action.name)) {
|
|
145
160
|
if (!page) {
|
|
146
161
|
return {
|
|
147
162
|
completedCount,
|
|
163
|
+
startIndex,
|
|
148
164
|
stopIndex: i,
|
|
149
165
|
stopReason: "error",
|
|
150
166
|
error: { message: `No live page for alias "${alias}"`, actionName: action.action.name, stepIndex: i + 1 }
|
|
@@ -152,9 +168,11 @@ async function replayActions(actionsList, callbacks, params) {
|
|
|
152
168
|
}
|
|
153
169
|
try {
|
|
154
170
|
await performClientAction(page, action);
|
|
171
|
+
await callbacks.afterAction?.(action);
|
|
155
172
|
} catch (e) {
|
|
156
173
|
return {
|
|
157
174
|
completedCount,
|
|
175
|
+
startIndex,
|
|
158
176
|
stopIndex: i,
|
|
159
177
|
stopReason: "error",
|
|
160
178
|
error: { message: e.message, actionName: action.action.name, stepIndex: i + 1 }
|
|
@@ -163,16 +181,16 @@ async function replayActions(actionsList, callbacks, params) {
|
|
|
163
181
|
}
|
|
164
182
|
completedCount = i + 1;
|
|
165
183
|
if (params.stopAtStep !== void 0 && completedCount >= params.stopAtStep)
|
|
166
|
-
return { completedCount, stopIndex: i + 1, stopReason: "stopAtStep" };
|
|
184
|
+
return { completedCount, startIndex, stopIndex: i + 1, stopReason: "stopAtStep" };
|
|
167
185
|
if (params.stopAtUrl) {
|
|
168
186
|
const currentUrl = page?.url() ?? "";
|
|
169
187
|
if (urlMatchesPattern(currentUrl, params.stopAtUrl))
|
|
170
|
-
return { completedCount, stopIndex: i + 1, stopReason: "stopAtUrl" };
|
|
188
|
+
return { completedCount, startIndex, stopIndex: i + 1, stopReason: "stopAtUrl" };
|
|
171
189
|
}
|
|
172
190
|
if (delay)
|
|
173
191
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
174
192
|
}
|
|
175
|
-
return { completedCount, stopIndex: actionsList.length, stopReason: "done" };
|
|
193
|
+
return { completedCount, startIndex, stopIndex: actionsList.length, stopReason: "done" };
|
|
176
194
|
}
|
|
177
195
|
function urlMatchesPattern(currentUrl, pattern) {
|
|
178
196
|
const regexLiteral = /^\/(.*)\/([a-z]*)$/i.exec(pattern);
|