@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.
Files changed (289) hide show
  1. package/build/commands/commandLibrary.d.ts +1 -0
  2. package/build/commands/commandLibrary.js +19 -13
  3. package/build/commands/localDevTestChangesCommand.d.ts +15 -0
  4. package/build/commands/localDevTestChangesCommand.js +201 -0
  5. package/build/index.js +80 -6
  6. package/build/prompts/code-reuse.js +3 -0
  7. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +1 -0
  8. package/build/prompts/enhance-assertions/sharedAssertionRules.js +17 -0
  9. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.js +11 -9
  10. package/build/prompts/local-dev/local-dev-plan.d.ts +35 -0
  11. package/build/prompts/local-dev/local-dev-plan.js +429 -0
  12. package/build/prompts/local-dev/local-dev-prompts.d.ts +4 -0
  13. package/build/prompts/local-dev/local-dev-prompts.js +190 -0
  14. package/build/prompts/pom-aware-code-reuse.js +12 -0
  15. package/build/prompts/prompt-utils.d.ts +8 -0
  16. package/build/prompts/prompt-utils.js +33 -0
  17. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +37 -14
  18. package/build/prompts/sut-setup/shared.js +16 -12
  19. package/build/prompts/test-recommendation/analysisOutputPrompt.js +21 -29
  20. package/build/prompts/test-recommendation/scopeAssessment.d.ts +24 -7
  21. package/build/prompts/test-recommendation/scopeAssessment.js +111 -12
  22. package/build/prompts/test-recommendation/test-recommendation-prompt.js +41 -4
  23. package/build/prompts/testbot/testbot-prompts.d.ts +0 -5
  24. package/build/prompts/testbot/testbot-prompts.js +32 -52
  25. package/build/recommendation/planRanker.d.ts +15 -2
  26. package/build/recommendation/planRanker.js +76 -5
  27. package/build/resources/testbotResource.js +2 -1
  28. package/build/services/AnalyticsService.d.ts +1 -1
  29. package/build/services/TestExecutionService.d.ts +2 -1
  30. package/build/services/TestExecutionService.js +8 -3
  31. package/build/services/TestGenerationService.d.ts +2 -2
  32. package/build/services/TestGenerationService.js +39 -21
  33. package/build/services/containerEnv.js +3 -1
  34. package/build/tool-phases.js +6 -0
  35. package/build/tools/code-refactor/codeReuseTool.js +43 -4
  36. package/build/tools/code-refactor/enhanceAssertionsTool.js +68 -18
  37. package/build/tools/code-refactor/reuse-outcome.d.ts +109 -0
  38. package/build/tools/code-refactor/reuse-outcome.js +158 -0
  39. package/build/tools/code-refactor/reuse-state.d.ts +45 -0
  40. package/build/tools/code-refactor/reuse-state.js +140 -0
  41. package/build/tools/enrichTestWithMocksTool.d.ts +28 -0
  42. package/build/tools/enrichTestWithMocksTool.js +726 -0
  43. package/build/tools/executeSkyrampTestTool.d.ts +11 -0
  44. package/build/tools/executeSkyrampTestTool.js +62 -21
  45. package/build/tools/generate-tests/batchMockGenerationTool.d.ts +106 -0
  46. package/build/tools/generate-tests/batchMockGenerationTool.js +545 -0
  47. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +25 -23
  48. package/build/tools/generate-tests/generateContractRestTool.js +2 -2
  49. package/build/tools/generate-tests/generateE2ERestTool.d.ts +1 -1
  50. package/build/tools/generate-tests/generateE2ERestTool.js +1 -1
  51. package/build/tools/generate-tests/generateLoadRestTool.d.ts +1 -1
  52. package/build/tools/generate-tests/generateLoadRestTool.js +1 -1
  53. package/build/tools/generate-tests/generateMockRestTool.d.ts +179 -6
  54. package/build/tools/generate-tests/generateMockRestTool.js +391 -22
  55. package/build/tools/generate-tests/loadTestSchema.d.ts +1 -1
  56. package/build/tools/generate-tests/planGuard.js +2 -22
  57. package/build/tools/generateEnrichedIntegrationTestTool.d.ts +25 -0
  58. package/build/tools/generateEnrichedIntegrationTestTool.js +235 -0
  59. package/build/tools/localDevWorkerComposeTool.d.ts +24 -0
  60. package/build/tools/localDevWorkerComposeTool.js +264 -0
  61. package/build/tools/one-click/oneClickTool.d.ts +13 -0
  62. package/build/tools/one-click/oneClickTool.js +195 -24
  63. package/build/tools/preflightMockCheckTool.d.ts +2 -0
  64. package/build/tools/preflightMockCheckTool.js +96 -0
  65. package/build/tools/queryProxyMocksTool.d.ts +70 -0
  66. package/build/tools/queryProxyMocksTool.js +522 -0
  67. package/build/tools/runExistingTestsTool.d.ts +31 -0
  68. package/build/tools/runExistingTestsTool.js +214 -13
  69. package/build/tools/submitReportTool.js +38 -3
  70. package/build/tools/test-management/analyzeChangesTool.d.ts +2 -1
  71. package/build/tools/test-management/analyzeChangesTool.js +63 -40
  72. package/build/tools/test-management/registerTestPlanTool.js +55 -7
  73. package/build/tools/trace/startTraceCollectionTool.js +3 -3
  74. package/build/types/FrontendIntegration.d.ts +3 -0
  75. package/build/types/FrontendIntegration.js +3 -0
  76. package/build/types/OneClickCommands.d.ts +1 -1
  77. package/build/types/Recommendation.d.ts +20 -0
  78. package/build/types/Recommendation.js +32 -6
  79. package/build/types/RepositoryAnalysis.d.ts +131 -14
  80. package/build/types/RepositoryAnalysis.js +16 -2
  81. package/build/types/ReuseOutcome.d.ts +63 -0
  82. package/build/types/ReuseOutcome.js +33 -0
  83. package/build/types/TestExecution.d.ts +1 -0
  84. package/build/types/TestTypes.d.ts +25 -7
  85. package/build/types/TestTypes.js +22 -6
  86. package/build/types/TestbotReport.d.ts +7 -0
  87. package/build/types/index.d.ts +2 -0
  88. package/build/types/index.js +1 -0
  89. package/build/utils/AnalysisStateManager.d.ts +26 -0
  90. package/build/utils/AnalysisStateManager.js +31 -1
  91. package/build/utils/analyze-openapi.js +18 -1
  92. package/build/utils/branchDiff.d.ts +17 -1
  93. package/build/utils/branchDiff.js +99 -14
  94. package/build/utils/featureFlags.d.ts +31 -0
  95. package/build/utils/featureFlags.js +37 -0
  96. package/build/utils/frontendIntegration.js +8 -1
  97. package/build/utils/grpcMockValidation.d.ts +1 -0
  98. package/build/utils/grpcMockValidation.js +49 -0
  99. package/build/utils/httpMethodValidation.d.ts +4 -0
  100. package/build/utils/httpMethodValidation.js +15 -0
  101. package/build/utils/logger.js +1 -1
  102. package/build/utils/mockCompatibility.d.ts +49 -0
  103. package/build/utils/mockCompatibility.js +82 -0
  104. package/build/utils/pom-scope/pom-files.js +7 -0
  105. package/build/utils/pom-verify/bindings.js +11 -1
  106. package/build/utils/pom-verify/re-exports.d.ts +10 -0
  107. package/build/utils/pom-verify/re-exports.js +61 -0
  108. package/build/utils/pom-verify/resolve.d.ts +4 -1
  109. package/build/utils/pom-verify/resolve.js +7 -4
  110. package/build/utils/pom-verify/verify.d.ts +5 -0
  111. package/build/utils/pom-verify/verify.js +25 -3
  112. package/build/utils/progress.js +10 -5
  113. package/build/utils/proxy-terminal.js +3 -3
  114. package/build/utils/routeParsers.d.ts +3 -9
  115. package/build/utils/routeParsers.js +79 -4
  116. package/build/utils/utils.js +2 -2
  117. package/build/utils/versions.d.ts +4 -3
  118. package/build/utils/versions.js +3 -1
  119. package/build/utils/workspaceAuth.d.ts +46 -0
  120. package/build/utils/workspaceAuth.js +156 -1
  121. package/build/workspace/testSuites.d.ts +2 -1
  122. package/build/workspace/testSuites.js +1 -1
  123. package/build/workspace/workspace.d.ts +108 -32
  124. package/build/workspace/workspace.js +32 -4
  125. package/package.json +5 -2
  126. package/build/adapters/jestAdapter.test.d.ts +0 -1
  127. package/build/adapters/jestAdapter.test.js +0 -93
  128. package/build/adapters/mochaAdapter.test.d.ts +0 -1
  129. package/build/adapters/mochaAdapter.test.js +0 -63
  130. package/build/adapters/playwrightAdapter.test.d.ts +0 -1
  131. package/build/adapters/playwrightAdapter.test.js +0 -169
  132. package/build/adapters/pytestAdapter.test.d.ts +0 -1
  133. package/build/adapters/pytestAdapter.test.js +0 -90
  134. package/build/prompts/code-reuse.test.d.ts +0 -1
  135. package/build/prompts/code-reuse.test.js +0 -62
  136. package/build/prompts/pom-aware-code-reuse.test.d.ts +0 -1
  137. package/build/prompts/pom-aware-code-reuse.test.js +0 -11
  138. package/build/prompts/test-maintenance/drift-analysis-prompt.test.d.ts +0 -1
  139. package/build/prompts/test-maintenance/drift-analysis-prompt.test.js +0 -51
  140. package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +0 -1
  141. package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +0 -264
  142. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +0 -1
  143. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +0 -126
  144. package/build/prompts/test-recommendation/promptPlan.test.d.ts +0 -1
  145. package/build/prompts/test-recommendation/promptPlan.test.js +0 -336
  146. package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +0 -1
  147. package/build/prompts/test-recommendation/scopeAssessment.test.js +0 -371
  148. package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +0 -1
  149. package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +0 -1925
  150. package/build/prompts/testbot/testbot-prompts.test.d.ts +0 -1
  151. package/build/prompts/testbot/testbot-prompts.test.js +0 -451
  152. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.d.ts +0 -1
  153. package/build/recommendation/budgeters/diversityBalancedBudgeter.test.js +0 -138
  154. package/build/recommendation/budgeters/fixedNBudgeter.test.d.ts +0 -1
  155. package/build/recommendation/budgeters/fixedNBudgeter.test.js +0 -66
  156. package/build/recommendation/discriminators.test.d.ts +0 -1
  157. package/build/recommendation/discriminators.test.js +0 -324
  158. package/build/recommendation/diversity.test.d.ts +0 -1
  159. package/build/recommendation/diversity.test.js +0 -77
  160. package/build/recommendation/planRanker.test.d.ts +0 -1
  161. package/build/recommendation/planRanker.test.js +0 -110
  162. package/build/resources/testbotResource.test.d.ts +0 -1
  163. package/build/resources/testbotResource.test.js +0 -44
  164. package/build/services/AnalyticsService.test.d.ts +0 -1
  165. package/build/services/AnalyticsService.test.js +0 -86
  166. package/build/services/ScenarioGenerationService.integration.test.d.ts +0 -1
  167. package/build/services/ScenarioGenerationService.integration.test.js +0 -162
  168. package/build/services/ScenarioGenerationService.test.d.ts +0 -1
  169. package/build/services/ScenarioGenerationService.test.js +0 -414
  170. package/build/services/TestDiscoveryService.test.d.ts +0 -1
  171. package/build/services/TestDiscoveryService.test.js +0 -983
  172. package/build/services/TestExecutionService.test.d.ts +0 -1
  173. package/build/services/TestExecutionService.test.js +0 -1032
  174. package/build/services/TestGenerationService.test.d.ts +0 -1
  175. package/build/services/TestGenerationService.test.js +0 -578
  176. package/build/tool-phase-coverage.test.d.ts +0 -1
  177. package/build/tool-phase-coverage.test.js +0 -49
  178. package/build/tools/code-refactor/codeReuseTool.test.d.ts +0 -1
  179. package/build/tools/code-refactor/codeReuseTool.test.js +0 -572
  180. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +0 -1
  181. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +0 -433
  182. package/build/tools/generate-tests/generateContractRestTool.test.d.ts +0 -1
  183. package/build/tools/generate-tests/generateContractRestTool.test.js +0 -142
  184. package/build/tools/generate-tests/generateIntegrationRestTool.test.d.ts +0 -1
  185. package/build/tools/generate-tests/generateIntegrationRestTool.test.js +0 -159
  186. package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +0 -1
  187. package/build/tools/generate-tests/generateLoadRestTool.test.js +0 -169
  188. package/build/tools/generate-tests/generateUIRestTool.test.d.ts +0 -1
  189. package/build/tools/generate-tests/generateUIRestTool.test.js +0 -32
  190. package/build/tools/generate-tests/planGuard.test.d.ts +0 -1
  191. package/build/tools/generate-tests/planGuard.test.js +0 -185
  192. package/build/tools/generate-tests/scenarioLint.test.d.ts +0 -1
  193. package/build/tools/generate-tests/scenarioLint.test.js +0 -100
  194. package/build/tools/runExistingTestsTool.test.d.ts +0 -1
  195. package/build/tools/runExistingTestsTool.test.js +0 -379
  196. package/build/tools/submitReportTool.test.d.ts +0 -1
  197. package/build/tools/submitReportTool.test.js +0 -1428
  198. package/build/tools/test-management/actionsTool.test.d.ts +0 -1
  199. package/build/tools/test-management/actionsTool.test.js +0 -436
  200. package/build/tools/test-management/analyzeChangesTool.test.d.ts +0 -1
  201. package/build/tools/test-management/analyzeChangesTool.test.js +0 -522
  202. package/build/tools/test-management/analyzeTestHealthTool.test.d.ts +0 -1
  203. package/build/tools/test-management/analyzeTestHealthTool.test.js +0 -385
  204. package/build/tools/test-management/registerTestPlanTool.test.d.ts +0 -1
  205. package/build/tools/test-management/registerTestPlanTool.test.js +0 -296
  206. package/build/tools/trace/resolveSaveStoragePath.test.d.ts +0 -1
  207. package/build/tools/trace/resolveSaveStoragePath.test.js +0 -17
  208. package/build/tools/trace/resolveSessionPaths.test.d.ts +0 -1
  209. package/build/tools/trace/resolveSessionPaths.test.js +0 -104
  210. package/build/tools/trace/sessionState.test.d.ts +0 -1
  211. package/build/tools/trace/sessionState.test.js +0 -17
  212. package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +0 -1
  213. package/build/tools/workspace/initializeWorkspaceTool.test.js +0 -139
  214. package/build/tools/workspace/serviceUpsert.test.d.ts +0 -1
  215. package/build/tools/workspace/serviceUpsert.test.js +0 -50
  216. package/build/utils/AnalysisStateManager.test.d.ts +0 -1
  217. package/build/utils/AnalysisStateManager.test.js +0 -134
  218. package/build/utils/dartRouteExtractor.test.d.ts +0 -1
  219. package/build/utils/dartRouteExtractor.test.js +0 -307
  220. package/build/utils/docker.test.d.ts +0 -1
  221. package/build/utils/docker.test.js +0 -114
  222. package/build/utils/featureFlags.test.d.ts +0 -1
  223. package/build/utils/featureFlags.test.js +0 -81
  224. package/build/utils/fileWalk.test.d.ts +0 -1
  225. package/build/utils/fileWalk.test.js +0 -252
  226. package/build/utils/frontendIntegration.test.d.ts +0 -1
  227. package/build/utils/frontendIntegration.test.js +0 -229
  228. package/build/utils/frontendSelectors.test.d.ts +0 -1
  229. package/build/utils/frontendSelectors.test.js +0 -118
  230. package/build/utils/gitStaging.test.d.ts +0 -1
  231. package/build/utils/gitStaging.test.js +0 -111
  232. package/build/utils/httpDefaults.test.d.ts +0 -1
  233. package/build/utils/httpDefaults.test.js +0 -21
  234. package/build/utils/importerHop.test.d.ts +0 -1
  235. package/build/utils/importerHop.test.js +0 -469
  236. package/build/utils/pathAffinityClassification.test.d.ts +0 -1
  237. package/build/utils/pathAffinityClassification.test.js +0 -208
  238. package/build/utils/planMatchKeys.test.d.ts +0 -1
  239. package/build/utils/planMatchKeys.test.js +0 -123
  240. package/build/utils/pom-scope/index.test.d.ts +0 -1
  241. package/build/utils/pom-scope/index.test.js +0 -278
  242. package/build/utils/pom-scope/pom-files.test.d.ts +0 -1
  243. package/build/utils/pom-scope/pom-files.test.js +0 -29
  244. package/build/utils/pom-scope/scoring.test.d.ts +0 -1
  245. package/build/utils/pom-scope/scoring.test.js +0 -39
  246. package/build/utils/pom-scope/selector-extractor.test.d.ts +0 -1
  247. package/build/utils/pom-scope/selector-extractor.test.js +0 -67
  248. package/build/utils/pom-verify/bindings.test.d.ts +0 -1
  249. package/build/utils/pom-verify/bindings.test.js +0 -164
  250. package/build/utils/pom-verify/calls.test.d.ts +0 -1
  251. package/build/utils/pom-verify/calls.test.js +0 -61
  252. package/build/utils/pom-verify/resolve.test.d.ts +0 -1
  253. package/build/utils/pom-verify/resolve.test.js +0 -114
  254. package/build/utils/pom-verify/verify.test.d.ts +0 -1
  255. package/build/utils/pom-verify/verify.test.js +0 -374
  256. package/build/utils/pr-comment-parser.test.d.ts +0 -1
  257. package/build/utils/pr-comment-parser.test.js +0 -428
  258. package/build/utils/progress.test.d.ts +0 -1
  259. package/build/utils/progress.test.js +0 -37
  260. package/build/utils/projectMetadata.test.d.ts +0 -1
  261. package/build/utils/projectMetadata.test.js +0 -172
  262. package/build/utils/pythonMountPrefixes.test.d.ts +0 -1
  263. package/build/utils/pythonMountPrefixes.test.js +0 -113
  264. package/build/utils/repoScanner.test.d.ts +0 -1
  265. package/build/utils/repoScanner.test.js +0 -190
  266. package/build/utils/reportVerification.test.d.ts +0 -1
  267. package/build/utils/reportVerification.test.js +0 -185
  268. package/build/utils/routeParsers.test.d.ts +0 -1
  269. package/build/utils/routeParsers.test.js +0 -1011
  270. package/build/utils/scenarioDrafting.test.d.ts +0 -1
  271. package/build/utils/scenarioDrafting.test.js +0 -876
  272. package/build/utils/sourceRouteExtractor.test.d.ts +0 -1
  273. package/build/utils/sourceRouteExtractor.test.js +0 -738
  274. package/build/utils/telemetry.test.d.ts +0 -1
  275. package/build/utils/telemetry.test.js +0 -70
  276. package/build/utils/trace-parser.test.d.ts +0 -6
  277. package/build/utils/trace-parser.test.js +0 -140
  278. package/build/utils/uiPageEnumerator.test.d.ts +0 -1
  279. package/build/utils/uiPageEnumerator.test.js +0 -824
  280. package/build/utils/utils.test.d.ts +0 -1
  281. package/build/utils/utils.test.js +0 -103
  282. package/build/utils/walkerCharacterization.test.d.ts +0 -1
  283. package/build/utils/walkerCharacterization.test.js +0 -233
  284. package/build/utils/workspaceAuth.test.d.ts +0 -1
  285. package/build/utils/workspaceAuth.test.js +0 -260
  286. package/build/workspace/testSuites.test.d.ts +0 -1
  287. package/build/workspace/testSuites.test.js +0 -23
  288. package/build/workspace/workspace.test.d.ts +0 -1
  289. 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;