@skyramp/mcp 0.3.2-rc.pom-3 → 0.3.2
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 +1 -0
- package/build/commands/commandLibrary.js +19 -13
- package/build/commands/localDevTestChangesCommand.d.ts +15 -0
- package/build/commands/localDevTestChangesCommand.js +201 -0
- package/build/index.js +80 -6
- package/build/prompts/code-reuse.js +3 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
- package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
- package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
- package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
- package/build/prompts/local-dev/local-dev-plan.js +429 -0
- package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
- package/build/prompts/local-dev/local-dev-prompts.js +190 -0
- package/build/prompts/pom-aware-code-reuse.js +12 -0
- package/build/prompts/prompt-utils.d.ts +8 -0
- package/build/prompts/prompt-utils.js +33 -0
- package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
- package/build/prompts/sut-setup/shared.js +16 -12
- package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
- package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
- package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
- package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
- package/build/prompts/testbot/testbot-prompts.js +32 -52
- package/build/recommendation/planRanker.d.ts +15 -2
- package/build/recommendation/planRanker.js +76 -5
- package/build/resources/testbotResource.js +2 -1
- package/build/services/AnalyticsService.d.ts +1 -1
- package/build/services/TestExecutionService.d.ts +2 -1
- package/build/services/TestExecutionService.js +8 -3
- package/build/services/TestGenerationService.d.ts +2 -2
- package/build/services/TestGenerationService.js +39 -21
- package/build/services/containerEnv.js +3 -1
- package/build/tool-phases.js +6 -0
- package/build/tools/code-refactor/codeReuseTool.js +43 -4
- package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
- package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
- package/build/tools/code-refactor/reuse-outcome.js +158 -0
- package/build/tools/code-refactor/reuse-state.d.ts +45 -0
- package/build/tools/code-refactor/reuse-state.js +140 -0
- package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
- package/build/tools/enrichTestWithMocksTool.js +726 -0
- package/build/tools/executeSkyrampTestTool.d.ts +11 -0
- package/build/tools/executeSkyrampTestTool.js +62 -21
- package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
- package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
- package/build/tools/generate-tests/generateContractRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
- package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
- package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
- package/build/tools/generate-tests/generateMockRestTool.js +391 -22
- package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
- package/build/tools/generate-tests/planGuard.js +2 -22
- package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
- package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
- package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
- package/build/tools/localDevWorkerComposeTool.js +264 -0
- package/build/tools/one-click/oneClickTool.d.ts +13 -0
- package/build/tools/one-click/oneClickTool.js +195 -24
- package/build/tools/preflightMockCheckTool.d.ts +2 -0
- package/build/tools/preflightMockCheckTool.js +96 -0
- package/build/tools/queryProxyMocksTool.d.ts +70 -0
- package/build/tools/queryProxyMocksTool.js +522 -0
- package/build/tools/runExistingTestsTool.d.ts +31 -0
- package/build/tools/runExistingTestsTool.js +214 -13
- package/build/tools/submitReportTool.js +38 -3
- package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
- package/build/tools/test-management/analyzeChangesTool.js +63 -40
- package/build/tools/test-management/registerTestPlanTool.js +55 -7
- package/build/tools/trace/startTraceCollectionTool.js +3 -3
- package/build/types/FrontendIntegration.d.ts +3 -0
- package/build/types/FrontendIntegration.js +3 -0
- package/build/types/OneClickCommands.d.ts +1 -1
- package/build/types/Recommendation.d.ts +20 -0
- package/build/types/Recommendation.js +32 -6
- package/build/types/RepositoryAnalysis.d.ts +131 -14
- package/build/types/RepositoryAnalysis.js +16 -2
- package/build/types/ReuseOutcome.d.ts +63 -0
- package/build/types/ReuseOutcome.js +33 -0
- package/build/types/TestExecution.d.ts +1 -0
- package/build/types/TestTypes.d.ts +25 -7
- package/build/types/TestTypes.js +22 -6
- package/build/types/TestbotReport.d.ts +7 -0
- package/build/types/index.d.ts +2 -0
- package/build/types/index.js +1 -0
- package/build/utils/AnalysisStateManager.d.ts +26 -0
- package/build/utils/AnalysisStateManager.js +31 -1
- package/build/utils/analyze-openapi.js +18 -1
- package/build/utils/branchDiff.d.ts +17 -1
- package/build/utils/branchDiff.js +99 -14
- package/build/utils/featureFlags.d.ts +31 -0
- package/build/utils/featureFlags.js +37 -0
- package/build/utils/frontendIntegration.js +8 -1
- package/build/utils/grpcMockValidation.d.ts +1 -0
- package/build/utils/grpcMockValidation.js +49 -0
- package/build/utils/httpMethodValidation.d.ts +4 -0
- package/build/utils/httpMethodValidation.js +15 -0
- package/build/utils/logger.js +1 -1
- package/build/utils/mockCompatibility.d.ts +49 -0
- package/build/utils/mockCompatibility.js +82 -0
- package/build/utils/pom-scope/pom-files.js +7 -0
- package/build/utils/pom-verify/bindings.js +11 -1
- package/build/utils/pom-verify/re-exports.d.ts +10 -0
- package/build/utils/pom-verify/re-exports.js +61 -0
- package/build/utils/pom-verify/resolve.d.ts +4 -1
- package/build/utils/pom-verify/resolve.js +7 -4
- package/build/utils/pom-verify/verify.d.ts +5 -0
- package/build/utils/pom-verify/verify.js +25 -3
- package/build/utils/progress.js +10 -5
- package/build/utils/proxy-terminal.js +3 -3
- package/build/utils/routeParsers.d.ts +3 -9
- package/build/utils/routeParsers.js +79 -4
- package/build/utils/utils.js +2 -2
- package/build/utils/versions.d.ts +4 -3
- package/build/utils/versions.js +3 -1
- package/build/utils/workspaceAuth.d.ts +46 -0
- package/build/utils/workspaceAuth.js +156 -1
- package/build/workspace/testSuites.d.ts +2 -1
- package/build/workspace/testSuites.js +1 -1
- package/build/workspace/workspace.d.ts +108 -32
- package/build/workspace/workspace.js +32 -4
- package/package.json +5 -2
- package/build/adapters/jestAdapter.test.d.ts +0 -1
- package/build/adapters/jestAdapter.test.js +0 -93
- package/build/adapters/mochaAdapter.test.d.ts +0 -1
- package/build/adapters/mochaAdapter.test.js +0 -63
- package/build/adapters/playwrightAdapter.test.d.ts +0 -1
- package/build/adapters/playwrightAdapter.test.js +0 -169
- package/build/adapters/pytestAdapter.test.d.ts +0 -1
- package/build/adapters/pytestAdapter.test.js +0 -90
- package/build/prompts/code-reuse.test.d.ts +0 -1
- package/build/prompts/code-reuse.test.js +0 -62
- package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
- package/build/prompts/pom-aware-code-reuse.test.js +0 -11
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
- package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
- package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
- package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
- package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
- package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
- package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
- package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
- package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
- package/build/prompts/testbot/testbot-prompts.test.js +0 -451
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
- package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
- package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
- package/build/recommendation/discriminators.test.d.ts +0 -1
- package/build/recommendation/discriminators.test.js +0 -324
- package/build/recommendation/diversity.test.d.ts +0 -1
- package/build/recommendation/diversity.test.js +0 -77
- package/build/recommendation/planRanker.test.d.ts +0 -1
- package/build/recommendation/planRanker.test.js +0 -110
- package/build/resources/testbotResource.test.d.ts +0 -1
- package/build/resources/testbotResource.test.js +0 -44
- package/build/services/AnalyticsService.test.d.ts +0 -1
- package/build/services/AnalyticsService.test.js +0 -86
- package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.integration.test.js +0 -162
- package/build/services/ScenarioGenerationService.test.d.ts +0 -1
- package/build/services/ScenarioGenerationService.test.js +0 -414
- package/build/services/TestDiscoveryService.test.d.ts +0 -1
- package/build/services/TestDiscoveryService.test.js +0 -983
- package/build/services/TestExecutionService.test.d.ts +0 -1
- package/build/services/TestExecutionService.test.js +0 -1032
- package/build/services/TestGenerationService.test.d.ts +0 -1
- package/build/services/TestGenerationService.test.js +0 -578
- package/build/tool-phase-coverage.test.d.ts +0 -1
- package/build/tool-phase-coverage.test.js +0 -49
- package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
- package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
- package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
- package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
- package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
- package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
- package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
- package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
- package/build/tools/generate-tests/planGuard.test.js +0 -185
- package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
- package/build/tools/generate-tests/scenarioLint.test.js +0 -100
- package/build/tools/runExistingTestsTool.test.d.ts +0 -1
- package/build/tools/runExistingTestsTool.test.js +0 -379
- package/build/tools/submitReportTool.test.d.ts +0 -1
- package/build/tools/submitReportTool.test.js +0 -1428
- package/build/tools/test-management/actionsTool.test.d.ts +0 -1
- package/build/tools/test-management/actionsTool.test.js +0 -436
- package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
- package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
- package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
- package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
- package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
- package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
- package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
- package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
- package/build/tools/trace/resolveSessionPaths.test.js +0 -104
- package/build/tools/trace/sessionState.test.d.ts +0 -1
- package/build/tools/trace/sessionState.test.js +0 -17
- package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
- package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
- package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
- package/build/tools/workspace/serviceUpsert.test.js +0 -50
- package/build/utils/AnalysisStateManager.test.d.ts +0 -1
- package/build/utils/AnalysisStateManager.test.js +0 -134
- package/build/utils/dartRouteExtractor.test.d.ts +0 -1
- package/build/utils/dartRouteExtractor.test.js +0 -307
- package/build/utils/docker.test.d.ts +0 -1
- package/build/utils/docker.test.js +0 -114
- package/build/utils/featureFlags.test.d.ts +0 -1
- package/build/utils/featureFlags.test.js +0 -81
- package/build/utils/fileWalk.test.d.ts +0 -1
- package/build/utils/fileWalk.test.js +0 -252
- package/build/utils/frontendIntegration.test.d.ts +0 -1
- package/build/utils/frontendIntegration.test.js +0 -229
- package/build/utils/frontendSelectors.test.d.ts +0 -1
- package/build/utils/frontendSelectors.test.js +0 -118
- package/build/utils/gitStaging.test.d.ts +0 -1
- package/build/utils/gitStaging.test.js +0 -111
- package/build/utils/httpDefaults.test.d.ts +0 -1
- package/build/utils/httpDefaults.test.js +0 -21
- package/build/utils/importerHop.test.d.ts +0 -1
- package/build/utils/importerHop.test.js +0 -469
- package/build/utils/pathAffinityClassification.test.d.ts +0 -1
- package/build/utils/pathAffinityClassification.test.js +0 -208
- package/build/utils/planMatchKeys.test.d.ts +0 -1
- package/build/utils/planMatchKeys.test.js +0 -123
- package/build/utils/pom-scope/index.test.d.ts +0 -1
- package/build/utils/pom-scope/index.test.js +0 -278
- package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
- package/build/utils/pom-scope/pom-files.test.js +0 -29
- package/build/utils/pom-scope/scoring.test.d.ts +0 -1
- package/build/utils/pom-scope/scoring.test.js +0 -39
- package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
- package/build/utils/pom-scope/selector-extractor.test.js +0 -67
- package/build/utils/pom-verify/bindings.test.d.ts +0 -1
- package/build/utils/pom-verify/bindings.test.js +0 -164
- package/build/utils/pom-verify/calls.test.d.ts +0 -1
- package/build/utils/pom-verify/calls.test.js +0 -61
- package/build/utils/pom-verify/resolve.test.d.ts +0 -1
- package/build/utils/pom-verify/resolve.test.js +0 -114
- package/build/utils/pom-verify/verify.test.d.ts +0 -1
- package/build/utils/pom-verify/verify.test.js +0 -374
- package/build/utils/pr-comment-parser.test.d.ts +0 -1
- package/build/utils/pr-comment-parser.test.js +0 -428
- package/build/utils/progress.test.d.ts +0 -1
- package/build/utils/progress.test.js +0 -37
- package/build/utils/projectMetadata.test.d.ts +0 -1
- package/build/utils/projectMetadata.test.js +0 -172
- package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
- package/build/utils/pythonMountPrefixes.test.js +0 -113
- package/build/utils/repoScanner.test.d.ts +0 -1
- package/build/utils/repoScanner.test.js +0 -190
- package/build/utils/reportVerification.test.d.ts +0 -1
- package/build/utils/reportVerification.test.js +0 -185
- package/build/utils/routeParsers.test.d.ts +0 -1
- package/build/utils/routeParsers.test.js +0 -1011
- package/build/utils/scenarioDrafting.test.d.ts +0 -1
- package/build/utils/scenarioDrafting.test.js +0 -876
- package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
- package/build/utils/sourceRouteExtractor.test.js +0 -738
- package/build/utils/telemetry.test.d.ts +0 -1
- package/build/utils/telemetry.test.js +0 -70
- package/build/utils/trace-parser.test.d.ts +0 -6
- package/build/utils/trace-parser.test.js +0 -140
- package/build/utils/uiPageEnumerator.test.d.ts +0 -1
- package/build/utils/uiPageEnumerator.test.js +0 -824
- package/build/utils/utils.test.d.ts +0 -1
- package/build/utils/utils.test.js +0 -103
- package/build/utils/walkerCharacterization.test.d.ts +0 -1
- package/build/utils/walkerCharacterization.test.js +0 -233
- package/build/utils/workspaceAuth.test.d.ts +0 -1
- package/build/utils/workspaceAuth.test.js +0 -260
- package/build/workspace/testSuites.test.d.ts +0 -1
- package/build/workspace/testSuites.test.js +0 -23
- package/build/workspace/workspace.test.d.ts +0 -1
- package/build/workspace/workspace.test.js +0 -264
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { SkyrampClient } from "@skyramp/skyramp";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
import { RuntimeEnvironment, runtimeEnvironmentInputSchema } from "../types/TestTypes.js";
|
|
5
|
+
import { injectMockImports, isSupportedMockEnrichmentLanguage } from "./enrichTestWithMocksTool.js";
|
|
6
|
+
import { isAuthorizationHeaderName } from "../utils/workspaceAuth.js";
|
|
7
|
+
import { WORKER_CONTROL_PORT } from "../utils/versions.js";
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
const TOOL_NAME = "skyramp_generate_enriched_integration_test";
|
|
11
|
+
const enrichedIntegrationTestSchema = {
|
|
12
|
+
scenarioFile: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Absolute path to the scenario JSON file (from skyramp_batch_scenario_test_generation). Used as trace input for integration test generation."),
|
|
15
|
+
mockFiles: z
|
|
16
|
+
.array(z.string())
|
|
17
|
+
.describe("Absolute paths to the generated mock files (from skyramp_mock_generation or skyramp_batch_mock_generation) that this test needs."),
|
|
18
|
+
scenarioName: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Human-readable scenario name (e.g., order-happy-path). Used as the SCENARIO_NAME constant in the enriched test."),
|
|
21
|
+
outputDir: z
|
|
22
|
+
.string()
|
|
23
|
+
.describe("Absolute path to the directory where the test file will be written."),
|
|
24
|
+
output: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("Output test file name (e.g., order_happy_path_integration_test.py). Derived from scenario if omitted."),
|
|
28
|
+
runtime: runtimeEnvironmentInputSchema
|
|
29
|
+
.optional()
|
|
30
|
+
.default(RuntimeEnvironment.DOCKER)
|
|
31
|
+
.describe("Runtime environment: 'docker' or 'k8s' (also accepts 'kubernetes'). Defaults to docker."),
|
|
32
|
+
dockerNetwork: z
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Docker network name for the test runtime."),
|
|
36
|
+
dockerWorkerPort: z
|
|
37
|
+
.number()
|
|
38
|
+
.int()
|
|
39
|
+
.min(0)
|
|
40
|
+
.max(65535)
|
|
41
|
+
.optional()
|
|
42
|
+
.describe("Skyramp worker control port the generated client connects to. Defaults to 35142 (the local-dev compose worker's published port)."),
|
|
43
|
+
authHeader: z
|
|
44
|
+
.string()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("HTTP header that carries the auth credential (e.g., Authorization, X-Api-Key)."),
|
|
47
|
+
authScheme: z
|
|
48
|
+
.string()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Auth scheme prefix (e.g., Bearer). Mapped to authType for the backend."),
|
|
51
|
+
language: z
|
|
52
|
+
.string()
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Programming language for the generated test. Automatic mock enrichment supports Python, TypeScript, JavaScript, and Java."),
|
|
55
|
+
framework: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("Test framework (e.g., pytest, playwright)."),
|
|
59
|
+
traceComments: z
|
|
60
|
+
.array(z.string())
|
|
61
|
+
.optional()
|
|
62
|
+
.describe("Optional trace comments showing how mock values flow to assertions."),
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* skyramp_generate_enriched_integration_test
|
|
66
|
+
*
|
|
67
|
+
* Combines integration test generation (from a scenario file) and mock enrichment
|
|
68
|
+
* into a single atomic operation. Eliminates the need to call
|
|
69
|
+
* skyramp_integration_test_generation and skyramp_enrich_test_with_mocks separately.
|
|
70
|
+
*/
|
|
71
|
+
export function registerGenerateEnrichedIntegrationTestTool(server) {
|
|
72
|
+
server.registerTool(TOOL_NAME, {
|
|
73
|
+
description: "Generate an integration test from a scenario file AND enrich it with mock imports in one step. " +
|
|
74
|
+
"Combines skyramp_integration_test_generation + mock enrichment into a single call. " +
|
|
75
|
+
"Use this after skyramp_batch_scenario_test_generation and skyramp_batch_mock_generation when the target test language is Python, TypeScript, JavaScript, or Java.",
|
|
76
|
+
inputSchema: enrichedIntegrationTestSchema,
|
|
77
|
+
}, async (params) => {
|
|
78
|
+
return executeGenerateEnrichedIntegrationTest(params);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export async function executeGenerateEnrichedIntegrationTest(params) {
|
|
82
|
+
const { scenarioFile, mockFiles, scenarioName, outputDir, output, runtime, dockerNetwork, dockerWorkerPort, authHeader, authScheme, language, framework, traceComments, } = params;
|
|
83
|
+
try {
|
|
84
|
+
const resolvedLanguage = (language ?? "python").toLowerCase();
|
|
85
|
+
if (!isSupportedMockEnrichmentLanguage(resolvedLanguage)) {
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
text: `**Error:** Mock enrichment for ${resolvedLanguage} tests is not supported by this combined tool. ` +
|
|
91
|
+
"Supported languages: python, typescript, javascript, java. " +
|
|
92
|
+
"Use `skyramp_integration_test_generation` + `skyramp_enrich_test_with_mocks` separately if your language is listed but enrichment fails.",
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
isError: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Step 1b: Validate scenarioFile exists
|
|
99
|
+
if (!fs.existsSync(scenarioFile)) {
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: "text",
|
|
104
|
+
text: `**Error:** Scenario file not found: ${scenarioFile}`,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
isError: true,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Step 1b: Validate mock files exist
|
|
111
|
+
const missingFiles = mockFiles.filter((f) => !fs.existsSync(f));
|
|
112
|
+
if (missingFiles.length > 0) {
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: `**Error:** Mock files not found:\n` +
|
|
118
|
+
missingFiles.map((f) => ` - ${f}`).join("\n") +
|
|
119
|
+
`\n\nGenerate them first with \`skyramp_batch_mock_generation\`.`,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
isError: true,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Step 2: Generate the integration test
|
|
126
|
+
// Normalize auth params: the Go CLI treats --auth-type and --auth-header as
|
|
127
|
+
// mutually exclusive when authHeader is the standard Authorization header.
|
|
128
|
+
// Mirror TestGenerationService.executeGeneration() normalization:
|
|
129
|
+
// if authScheme is set and authHeader is Authorization, use authType only.
|
|
130
|
+
let resolvedAuthHeader = authHeader;
|
|
131
|
+
const resolvedAuthType = authScheme;
|
|
132
|
+
if (resolvedAuthType !== undefined && isAuthorizationHeaderName(resolvedAuthHeader || "")) {
|
|
133
|
+
resolvedAuthHeader = undefined;
|
|
134
|
+
}
|
|
135
|
+
const client = new SkyrampClient();
|
|
136
|
+
const result = await client.generateRestTest({
|
|
137
|
+
traceFilePath: scenarioFile,
|
|
138
|
+
outputDir,
|
|
139
|
+
output,
|
|
140
|
+
runtime: runtime ?? RuntimeEnvironment.DOCKER,
|
|
141
|
+
force: true,
|
|
142
|
+
dockerNetwork,
|
|
143
|
+
dockerWorkerPort: (dockerWorkerPort ?? WORKER_CONTROL_PORT).toString(),
|
|
144
|
+
authHeader: resolvedAuthHeader,
|
|
145
|
+
authType: resolvedAuthType,
|
|
146
|
+
language: resolvedLanguage,
|
|
147
|
+
framework,
|
|
148
|
+
testType: "integration",
|
|
149
|
+
});
|
|
150
|
+
// Check if generation succeeded
|
|
151
|
+
if (!result || !result.toLowerCase().includes("success")) {
|
|
152
|
+
return {
|
|
153
|
+
content: [
|
|
154
|
+
{
|
|
155
|
+
type: "text",
|
|
156
|
+
text: `**Error:** Integration test generation failed: ${result || "no output from backend"}`,
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
isError: true,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Step 3: Determine the test file path and read it
|
|
163
|
+
const testFileName = output || deriveTestFileName(scenarioFile, resolvedLanguage);
|
|
164
|
+
const testFilePath = path.join(outputDir, testFileName);
|
|
165
|
+
if (!fs.existsSync(testFilePath)) {
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
{
|
|
169
|
+
type: "text",
|
|
170
|
+
text: `**Error:** Generated test file not found at expected path: ${testFilePath}\n` +
|
|
171
|
+
`Backend output: ${result}`,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
isError: true,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const testContent = fs.readFileSync(testFilePath, "utf-8");
|
|
178
|
+
// Step 4: Enrich with mock imports
|
|
179
|
+
const enrichedContent = injectMockImports(testContent, testFilePath, scenarioName, mockFiles, traceComments, resolvedLanguage);
|
|
180
|
+
// Step 5: Write the enriched content back
|
|
181
|
+
fs.writeFileSync(testFilePath, enrichedContent);
|
|
182
|
+
logger.info(`Generated and enriched integration test: ${testFilePath}`, {
|
|
183
|
+
scenarioName,
|
|
184
|
+
mockFileCount: mockFiles.length,
|
|
185
|
+
});
|
|
186
|
+
return {
|
|
187
|
+
content: [
|
|
188
|
+
{
|
|
189
|
+
type: "text",
|
|
190
|
+
text: [
|
|
191
|
+
`**Integration test generated and enriched with mocks for scenario "${scenarioName}".**\n`,
|
|
192
|
+
`**Test file:** ${testFilePath}`,
|
|
193
|
+
`**Mock files imported:** ${mockFiles.length}`,
|
|
194
|
+
...mockFiles.map((f) => ` - ${path.basename(f)}`),
|
|
195
|
+
`\nThe test is ready for execution with: \`skyramp_execute_test({testFile: "${testFilePath}", ...})\``,
|
|
196
|
+
].join("\n"),
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
logger.error(`Failed to generate enriched integration test: ${error.message}`);
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: `**Failed to generate enriched integration test:** ${error.message}`,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
isError: true,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function deriveTestFileName(scenarioFile, language) {
|
|
215
|
+
const base = path.basename(scenarioFile, ".json");
|
|
216
|
+
const name = base.replace(/^scenario_/, "").replace(/[^a-zA-Z0-9]/g, "_");
|
|
217
|
+
const normalizedLanguage = language?.toLowerCase();
|
|
218
|
+
if (normalizedLanguage === "typescript") {
|
|
219
|
+
return `${name}_integration_test.spec.ts`;
|
|
220
|
+
}
|
|
221
|
+
if (normalizedLanguage === "javascript") {
|
|
222
|
+
return `${name}_integration_test.spec.js`;
|
|
223
|
+
}
|
|
224
|
+
if (normalizedLanguage === "java") {
|
|
225
|
+
return `${toPascalCase(name)}IntegrationTest.java`;
|
|
226
|
+
}
|
|
227
|
+
return `${name}_integration_test.py`;
|
|
228
|
+
}
|
|
229
|
+
function toPascalCase(value) {
|
|
230
|
+
return value
|
|
231
|
+
.split(/[^a-zA-Z0-9]+/)
|
|
232
|
+
.filter(Boolean)
|
|
233
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
234
|
+
.join("");
|
|
235
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export interface WorkerComposeResult {
|
|
3
|
+
baseComposeFile: string;
|
|
4
|
+
overrideFile: string;
|
|
5
|
+
dockerNetwork: string;
|
|
6
|
+
workerPort: number;
|
|
7
|
+
composeFilePrefix: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate the worker compose override and return the resolved network name and
|
|
11
|
+
* the `-f` prefix for `docker compose` commands. Throws on a missing compose file
|
|
12
|
+
* or if Docker is not running.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setupLocalDevWorker(repositoryPath: string, composeFile?: string, thirdPartyHosts?: string[]): WorkerComposeResult;
|
|
15
|
+
/**
|
|
16
|
+
* Deterministically set up the Skyramp worker as a Docker Compose service for
|
|
17
|
+
* the local-dev workflow.
|
|
18
|
+
*
|
|
19
|
+
* This replaces the SDK's imperative worker spawn (which raced onto the wrong
|
|
20
|
+
* Docker network and leaked on teardown — Local-Dev Skill Findings #1, #9, #10).
|
|
21
|
+
* The worker becomes a compose service via a generated override file, so it joins
|
|
22
|
+
* the SUT's network declaratively and is removed by `docker compose down`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function registerLocalDevWorkerComposeTool(server: McpServer): void;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import yaml from "js-yaml";
|
|
6
|
+
import { AnalyticsService } from "../services/AnalyticsService.js";
|
|
7
|
+
import { WORKER_DOCKER_IMAGE, WORKER_CONTROL_PORT } from "../utils/versions.js";
|
|
8
|
+
import { logger } from "../utils/logger.js";
|
|
9
|
+
const TOOL_NAME = "skyramp_setup_local_dev_worker";
|
|
10
|
+
// Relative path (under the repo) where the generated worker override is written.
|
|
11
|
+
const OVERRIDE_REL_PATH = ".skyramp/skyramp.worker.compose.yml";
|
|
12
|
+
/**
|
|
13
|
+
* Normalize and validate third-party host entries.
|
|
14
|
+
* - Trims whitespace from each entry
|
|
15
|
+
* - Filters out empty strings
|
|
16
|
+
* - Deduplicates
|
|
17
|
+
* - Rejects entries containing `://`, `/`, or `:` (scheme, path, or port)
|
|
18
|
+
*
|
|
19
|
+
* Returns the cleaned array, or throws on invalid entries.
|
|
20
|
+
*/
|
|
21
|
+
function normalizeThirdPartyHosts(hosts) {
|
|
22
|
+
const trimmed = hosts.map((h) => h.trim()).filter(Boolean);
|
|
23
|
+
const unique = [...new Set(trimmed)];
|
|
24
|
+
const invalid = unique.filter((h) => h.includes("://") || h.includes("/") || h.includes(":"));
|
|
25
|
+
if (invalid.length > 0) {
|
|
26
|
+
throw new Error(`Invalid thirdPartyHosts — entries must be bare hostnames without scheme, path, or port. ` +
|
|
27
|
+
`Got: ${invalid.join(", ")}`);
|
|
28
|
+
}
|
|
29
|
+
return unique;
|
|
30
|
+
}
|
|
31
|
+
const BASE_COMPOSE_CANDIDATES = [
|
|
32
|
+
"docker-compose.yml",
|
|
33
|
+
"docker-compose.yaml",
|
|
34
|
+
"compose.yml",
|
|
35
|
+
"compose.yaml",
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Docker Compose project name derivation: lowercase the directory basename and
|
|
39
|
+
* strip characters outside [a-z0-9_-] (Compose's normalization). COMPOSE_PROJECT_NAME
|
|
40
|
+
* overrides it when set. The default network is then `<project>_<networkKey>`, or
|
|
41
|
+
* `<project>_default` when the compose file declares no named networks.
|
|
42
|
+
*/
|
|
43
|
+
function deriveProjectName(composeDir, env = process.env) {
|
|
44
|
+
const override = env.COMPOSE_PROJECT_NAME?.trim();
|
|
45
|
+
if (override)
|
|
46
|
+
return override;
|
|
47
|
+
return path
|
|
48
|
+
.basename(composeDir)
|
|
49
|
+
.toLowerCase()
|
|
50
|
+
.replace(/[^a-z0-9_-]/g, "");
|
|
51
|
+
}
|
|
52
|
+
/** Resolve the base compose file: explicit path wins, else discover at repo root. */
|
|
53
|
+
function resolveBaseCompose(repositoryPath, composeFile) {
|
|
54
|
+
if (composeFile) {
|
|
55
|
+
const abs = path.isAbsolute(composeFile)
|
|
56
|
+
? composeFile
|
|
57
|
+
: path.join(repositoryPath, composeFile);
|
|
58
|
+
return fs.existsSync(abs) ? abs : undefined;
|
|
59
|
+
}
|
|
60
|
+
for (const candidate of BASE_COMPOSE_CANDIDATES) {
|
|
61
|
+
const abs = path.join(repositoryPath, candidate);
|
|
62
|
+
if (fs.existsSync(abs))
|
|
63
|
+
return abs;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build the worker override compose document. The worker joins the same named
|
|
69
|
+
* network(s) the base declares (so it shares the SUT's network for DNS-alias
|
|
70
|
+
* hijacking at mock-apply time); when the base declares none, the worker joins
|
|
71
|
+
* the implicit `default` network like every other service. Only the control
|
|
72
|
+
* port (35142) is published to the host — mock ports stay internal to the
|
|
73
|
+
* docker network.
|
|
74
|
+
*/
|
|
75
|
+
function buildOverrideDoc(networkKeys, thirdPartyHosts) {
|
|
76
|
+
const workerService = {
|
|
77
|
+
image: WORKER_DOCKER_IMAGE,
|
|
78
|
+
volumes: [
|
|
79
|
+
"skyramp:/etc/skyramp",
|
|
80
|
+
"/var/run/docker.sock:/var/run/docker.sock",
|
|
81
|
+
],
|
|
82
|
+
ports: [`127.0.0.1:${WORKER_CONTROL_PORT}:${WORKER_CONTROL_PORT}`],
|
|
83
|
+
restart: "always",
|
|
84
|
+
};
|
|
85
|
+
const doc = {
|
|
86
|
+
services: { skyramp: workerService },
|
|
87
|
+
volumes: { skyramp: null },
|
|
88
|
+
};
|
|
89
|
+
if (networkKeys.length > 0 || thirdPartyHosts?.length) {
|
|
90
|
+
// When third-party hosts are provided, the worker needs network aliases
|
|
91
|
+
// so Docker DNS resolves the FQDN to the worker container. This is how
|
|
92
|
+
// mocks intercept traffic to external services (e.g., www.google.com).
|
|
93
|
+
const nets = networkKeys.length > 0 ? networkKeys : ["default"];
|
|
94
|
+
const networkConfig = {};
|
|
95
|
+
for (const key of nets) {
|
|
96
|
+
if (thirdPartyHosts?.length) {
|
|
97
|
+
networkConfig[key] = { aliases: [...thirdPartyHosts] };
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
networkConfig[key] = {};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
workerService.networks = networkConfig;
|
|
104
|
+
doc.networks = Object.fromEntries(nets.map((k) => [k, {}]));
|
|
105
|
+
}
|
|
106
|
+
return doc;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resolve the actual Docker network name Compose uses for `key`:
|
|
110
|
+
* - an explicit `name:` is used verbatim (NOT project-scoped),
|
|
111
|
+
* - `external: true` networks are pre-existing and not project-scoped
|
|
112
|
+
* (use `external.name` for the legacy form, else the key),
|
|
113
|
+
* - otherwise Compose prefixes the project: `<project>_<key>`.
|
|
114
|
+
*/
|
|
115
|
+
function resolveNetworkName(project, key, def) {
|
|
116
|
+
const d = def ?? {};
|
|
117
|
+
if (typeof d.name === "string" && d.name.length > 0)
|
|
118
|
+
return d.name;
|
|
119
|
+
if (d.external) {
|
|
120
|
+
if (typeof d.external === "object" && d.external.name) {
|
|
121
|
+
return d.external.name;
|
|
122
|
+
}
|
|
123
|
+
return key;
|
|
124
|
+
}
|
|
125
|
+
return `${project}_${key}`;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Verify that the Docker daemon is reachable.
|
|
129
|
+
* Throws with a clear, actionable message so the agent stops immediately
|
|
130
|
+
* instead of spending turns manually debugging Docker connectivity.
|
|
131
|
+
*
|
|
132
|
+
* Does NOT switch Docker contexts — that can break a working setup when the
|
|
133
|
+
* active context differs from `default` but Docker is accessible via symlink.
|
|
134
|
+
*/
|
|
135
|
+
function checkDockerReady() {
|
|
136
|
+
try {
|
|
137
|
+
execSync("docker info", { stdio: "pipe", timeout: 15_000 });
|
|
138
|
+
return; // Docker is reachable.
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Docker not reachable on current context/config.
|
|
142
|
+
}
|
|
143
|
+
throw new Error("Docker daemon is not running or not reachable. " +
|
|
144
|
+
"Start Docker Desktop and retry. " +
|
|
145
|
+
"Do NOT attempt to debug Docker connectivity, try alternative socket paths, " +
|
|
146
|
+
"switch Docker contexts, or run `open -a Docker` — " +
|
|
147
|
+
"report this as a blocking environment error and stop.");
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Generate the worker compose override and return the resolved network name and
|
|
151
|
+
* the `-f` prefix for `docker compose` commands. Throws on a missing compose file
|
|
152
|
+
* or if Docker is not running.
|
|
153
|
+
*/
|
|
154
|
+
export function setupLocalDevWorker(repositoryPath, composeFile, thirdPartyHosts) {
|
|
155
|
+
// Fail fast if Docker is not available — prevents the agent from proceeding
|
|
156
|
+
// with false confidence and then spending turns debugging Docker manually.
|
|
157
|
+
// Skipped when SKIP_DOCKER_CHECK=1 (unit tests that only validate YAML generation).
|
|
158
|
+
if (process.env.SKIP_DOCKER_CHECK !== "1") {
|
|
159
|
+
checkDockerReady();
|
|
160
|
+
}
|
|
161
|
+
const baseComposeFile = resolveBaseCompose(repositoryPath, composeFile);
|
|
162
|
+
if (!baseComposeFile) {
|
|
163
|
+
throw new Error(composeFile
|
|
164
|
+
? `Compose file not found: ${composeFile}`
|
|
165
|
+
: `No docker-compose file found at ${repositoryPath} (looked for: ${BASE_COMPOSE_CANDIDATES.join(", ")}). Pass composeFile for a non-default location.`);
|
|
166
|
+
}
|
|
167
|
+
const parsed = yaml.load(fs.readFileSync(baseComposeFile, "utf-8"), {
|
|
168
|
+
schema: yaml.JSON_SCHEMA,
|
|
169
|
+
});
|
|
170
|
+
const networksObj = parsed?.networks ?? {};
|
|
171
|
+
const networkKeys = Object.keys(networksObj);
|
|
172
|
+
// Compose derives project name from the working directory (typically repo root),
|
|
173
|
+
// not from the compose file's directory. The plan instructs agents to run
|
|
174
|
+
// `docker compose` from repositoryPath.
|
|
175
|
+
const project = deriveProjectName(repositoryPath);
|
|
176
|
+
// The network the SDK client + executor target. First declared named network,
|
|
177
|
+
// else the implicit default network. Honor explicit `name:`/`external:` so the
|
|
178
|
+
// returned name matches the network Compose actually creates/uses.
|
|
179
|
+
const primaryKey = networkKeys[0] ?? "default";
|
|
180
|
+
const dockerNetwork = resolveNetworkName(project, primaryKey, networksObj[primaryKey]);
|
|
181
|
+
const overrideFile = path.join(repositoryPath, OVERRIDE_REL_PATH);
|
|
182
|
+
fs.mkdirSync(path.dirname(overrideFile), { recursive: true });
|
|
183
|
+
const overrideDoc = buildOverrideDoc(networkKeys, thirdPartyHosts);
|
|
184
|
+
const header = "# Generated by skyramp_setup_local_dev_worker — runs the Skyramp mock worker\n" +
|
|
185
|
+
"# as a compose service so it shares the SUT's network and is torn down with\n" +
|
|
186
|
+
"# the project. Layer it: docker compose -f <base> -f this up. Safe to delete.\n";
|
|
187
|
+
fs.writeFileSync(overrideFile, header + yaml.dump(overrideDoc, { lineWidth: -1 }), "utf-8");
|
|
188
|
+
return {
|
|
189
|
+
baseComposeFile,
|
|
190
|
+
overrideFile,
|
|
191
|
+
dockerNetwork,
|
|
192
|
+
workerPort: WORKER_CONTROL_PORT,
|
|
193
|
+
composeFilePrefix: `-f ${baseComposeFile} -f ${overrideFile}`,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Deterministically set up the Skyramp worker as a Docker Compose service for
|
|
198
|
+
* the local-dev workflow.
|
|
199
|
+
*
|
|
200
|
+
* This replaces the SDK's imperative worker spawn (which raced onto the wrong
|
|
201
|
+
* Docker network and leaked on teardown — Local-Dev Skill Findings #1, #9, #10).
|
|
202
|
+
* The worker becomes a compose service via a generated override file, so it joins
|
|
203
|
+
* the SUT's network declaratively and is removed by `docker compose down`.
|
|
204
|
+
*/
|
|
205
|
+
export function registerLocalDevWorkerComposeTool(server) {
|
|
206
|
+
server.registerTool(TOOL_NAME, {
|
|
207
|
+
description: `Set up the Skyramp mock worker as a Docker Compose service for the local-dev workflow (run this in the Deploy phase, before bringing the stack up).
|
|
208
|
+
|
|
209
|
+
Writes a compose override file (.skyramp/skyramp.worker.compose.yml) that declares the worker as a service on the SUT's docker network, then returns the docker-compose \`-f\` prefix and the resolved docker network name.
|
|
210
|
+
|
|
211
|
+
Why: running the worker as a compose service makes it join the SUT's network declaratively (so the app can reach its mocks) and tears it down with \`docker compose down\` — replacing the fragile runtime worker spawn that landed on the wrong network and leaked on teardown.
|
|
212
|
+
|
|
213
|
+
Use the returned values like this:
|
|
214
|
+
- Bring up: \`docker compose <composeFilePrefix> up -d --build <sut-service> <real-deps...> skyramp\` (stop mocked-service containers first).
|
|
215
|
+
- Tear down: \`docker compose <composeFilePrefix> down -v\`.
|
|
216
|
+
- Pass \`dockerNetwork\` (and \`dockerWorkerPort\`=workerPort) to every test generation call so the generated client — emitted with runtime="docker", docker_network, docker_skyramp_port — connects to this worker.`,
|
|
217
|
+
inputSchema: {
|
|
218
|
+
repositoryPath: z
|
|
219
|
+
.string()
|
|
220
|
+
.refine((value) => path.isAbsolute(value), {
|
|
221
|
+
message: "repositoryPath must be an absolute path",
|
|
222
|
+
})
|
|
223
|
+
.describe("Absolute path to the repository (where docker-compose runs)."),
|
|
224
|
+
composeFile: z
|
|
225
|
+
.string()
|
|
226
|
+
.optional()
|
|
227
|
+
.describe("Path to the base docker-compose file (absolute, or relative to repositoryPath). Omit to auto-discover docker-compose.yml/.yaml or compose.yml/.yaml at the repo root. Provide this when the compose file lives in a subdirectory or has a non-default name."),
|
|
228
|
+
thirdPartyHosts: z
|
|
229
|
+
.array(z.string().min(1, "Host entries must be non-empty strings"))
|
|
230
|
+
.optional()
|
|
231
|
+
.describe("Third-party FQDNs to intercept on the Docker network (e.g., ['www.google.com', 'api.stripe.com']). " +
|
|
232
|
+
"The worker is given Docker network aliases for these hostnames so DNS resolves them to the worker container, " +
|
|
233
|
+
"allowing mocks to intercept traffic to external services that are not part of the compose stack."),
|
|
234
|
+
},
|
|
235
|
+
}, async (args) => {
|
|
236
|
+
try {
|
|
237
|
+
const normalizedHosts = args.thirdPartyHosts
|
|
238
|
+
? normalizeThirdPartyHosts(args.thirdPartyHosts)
|
|
239
|
+
: undefined;
|
|
240
|
+
const result = setupLocalDevWorker(args.repositoryPath, args.composeFile, normalizedHosts);
|
|
241
|
+
AnalyticsService.pushMCPToolEvent(TOOL_NAME, undefined, {}).catch(() => { });
|
|
242
|
+
logger.info("Generated local-dev worker compose override", {
|
|
243
|
+
overrideFile: result.overrideFile,
|
|
244
|
+
dockerNetwork: result.dockerNetwork,
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
content: [
|
|
248
|
+
{
|
|
249
|
+
type: "text",
|
|
250
|
+
text: JSON.stringify(result, null, 2),
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
structuredContent: { ...result },
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
258
|
+
return {
|
|
259
|
+
isError: true,
|
|
260
|
+
content: [{ type: "text", text: message }],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
export declare enum CallingAgentIde {
|
|
3
|
+
Cursor = "cursor",
|
|
4
|
+
Claude = "claude"
|
|
5
|
+
}
|
|
2
6
|
/** User params passed to workflow builder (optional fields may be undefined) */
|
|
3
7
|
export type OneClickParams = {
|
|
4
8
|
workflow: string;
|
|
@@ -7,5 +11,14 @@ export type OneClickParams = {
|
|
|
7
11
|
apiSchema?: string;
|
|
8
12
|
topN?: number;
|
|
9
13
|
token?: string;
|
|
14
|
+
baseBranch?: string;
|
|
15
|
+
servicesToMock?: string;
|
|
16
|
+
realServices?: string;
|
|
17
|
+
mockProtocols?: string;
|
|
18
|
+
proxyUrl?: string;
|
|
19
|
+
proxyKubeconfig?: string;
|
|
20
|
+
proxyNamespace?: string;
|
|
21
|
+
callingAgent?: CallingAgentIde;
|
|
22
|
+
rawCallingAgent?: string;
|
|
10
23
|
};
|
|
11
24
|
export declare function registerOneClickTool(server: McpServer): void;
|