@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.
Files changed (248) hide show
  1. package/build/commands/commandLibrary.d.ts +12 -0
  2. package/build/commands/recommendTestsAndExecuteCommand.d.ts +2 -0
  3. package/build/commands/testThisEndpointCommand.d.ts +2 -0
  4. package/build/index.d.ts +2 -0
  5. package/build/index.js +6 -4
  6. package/build/playwright/PlaywrightTraceService.d.ts +32 -0
  7. package/build/playwright/index.d.ts +3 -0
  8. package/build/playwright/registerPlaywrightTools.d.ts +8 -0
  9. package/build/playwright/registerPlaywrightTools.js +12 -11
  10. package/build/playwright/traceRecordingPrompt.d.ts +13 -0
  11. package/build/playwright/traceRecordingPrompt.js +3 -11
  12. package/build/prompts/code-reuse.d.ts +1 -0
  13. package/build/prompts/enhance-assertions/contractProviderAssertionsPrompt.d.ts +2 -0
  14. package/build/prompts/enhance-assertions/integrationAssertionsPrompt.d.ts +2 -0
  15. package/build/prompts/enhance-assertions/sharedAssertionRules.d.ts +15 -0
  16. package/build/prompts/enhance-assertions/uiAssertionsPrompt.d.ts +2 -0
  17. package/build/prompts/enhance-assertions/uiAssertionsPrompt.js +24 -5
  18. package/build/prompts/fix-error-prompt.d.ts +1 -0
  19. package/build/prompts/initialize-workspace/initializeWorkspacePrompt.d.ts +1 -0
  20. package/build/prompts/modularization/integration-test-modularization.d.ts +1 -0
  21. package/build/prompts/modularization/ui-test-modularization.d.ts +1 -0
  22. package/build/prompts/personas.d.ts +21 -0
  23. package/build/prompts/pom-aware-code-reuse.d.ts +1 -0
  24. package/build/prompts/startTraceCollectionPrompts.d.ts +2 -0
  25. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.d.ts +2 -0
  26. package/build/prompts/sut-setup/modes/adaptWorkflowPrompt.js +114 -0
  27. package/build/prompts/sut-setup/modes/dockerComposePrompt.d.ts +2 -0
  28. package/build/prompts/sut-setup/modes/dockerComposePrompt.js +292 -0
  29. package/build/prompts/sut-setup/shared.d.ts +39 -0
  30. package/build/prompts/sut-setup/shared.js +132 -0
  31. package/build/prompts/test-maintenance/actionsInstructions.d.ts +35 -0
  32. package/build/prompts/test-maintenance/drift-analysis-prompt.d.ts +4 -0
  33. package/build/prompts/test-maintenance/driftAnalysisSections.d.ts +13 -0
  34. package/build/prompts/test-maintenance/driftAnalysisSections.js +9 -3
  35. package/build/prompts/test-recommendation/analysisOutputPrompt.d.ts +84 -0
  36. package/build/prompts/test-recommendation/analysisOutputPrompt.js +1 -1
  37. package/build/prompts/test-recommendation/analysisOutputPrompt.test.d.ts +1 -0
  38. package/build/prompts/test-recommendation/analysisOutputPrompt.test.js +1 -0
  39. package/build/prompts/test-recommendation/diffExecutionPlan.d.ts +17 -0
  40. package/build/prompts/test-recommendation/diffExecutionPlan.js +83 -18
  41. package/build/prompts/test-recommendation/fullRepoCatalog.d.ts +7 -0
  42. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.d.ts +1 -0
  43. package/build/prompts/test-recommendation/mergeEnrichedScenarios.test.js +1 -0
  44. package/build/prompts/test-recommendation/promptPlan.d.ts +203 -0
  45. package/build/prompts/test-recommendation/promptPlan.test.d.ts +1 -0
  46. package/build/prompts/test-recommendation/recommendationSections.d.ts +35 -0
  47. package/build/prompts/test-recommendation/recommendationShared.d.ts +31 -0
  48. package/build/prompts/test-recommendation/registerRecommendTestsPrompt.d.ts +7 -0
  49. package/build/prompts/test-recommendation/scopeAssessment.d.ts +55 -0
  50. package/build/prompts/test-recommendation/scopeAssessment.js +2 -2
  51. package/build/prompts/test-recommendation/scopeAssessment.test.d.ts +1 -0
  52. package/build/prompts/test-recommendation/scopeAssessment.test.js +1 -0
  53. package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +6 -0
  54. package/build/prompts/test-recommendation/test-recommendation-prompt.js +4 -4
  55. package/build/prompts/test-recommendation/test-recommendation-prompt.test.d.ts +1 -0
  56. package/build/prompts/test-recommendation/test-recommendation-prompt.test.js +97 -99
  57. package/build/prompts/testbot/testbot-prompts.d.ts +26 -0
  58. package/build/prompts/testbot/testbot-prompts.js +301 -46
  59. package/build/prompts/testbot/testbot-prompts.test.d.ts +1 -0
  60. package/build/prompts/testbot/testbot-prompts.test.js +109 -117
  61. package/build/resources/analysisResources.d.ts +17 -0
  62. package/build/resources/progressResource.d.ts +2 -0
  63. package/build/resources/sutSetupResource.d.ts +2 -0
  64. package/build/resources/sutSetupResource.js +45 -0
  65. package/build/resources/testbotResource.d.ts +2 -0
  66. package/build/resources/testbotResource.js +2 -2
  67. package/build/services/AnalyticsService.d.ts +13 -0
  68. package/build/services/AnalyticsService.test.d.ts +1 -0
  69. package/build/services/AnalyticsService.test.js +86 -0
  70. package/build/services/ModularizationService.d.ts +11 -0
  71. package/build/services/ScenarioGenerationService.d.ts +37 -0
  72. package/build/services/ScenarioGenerationService.integration.test.d.ts +1 -0
  73. package/build/services/ScenarioGenerationService.integration.test.js +4 -0
  74. package/build/services/ScenarioGenerationService.test.d.ts +1 -0
  75. package/build/services/TestDiscoveryService.d.ts +128 -0
  76. package/build/services/TestDiscoveryService.js +22 -12
  77. package/build/services/TestDiscoveryService.test.d.ts +1 -0
  78. package/build/services/TestDiscoveryService.test.js +4 -3
  79. package/build/services/TestExecutionService.d.ts +55 -0
  80. package/build/services/TestExecutionService.js +158 -26
  81. package/build/services/TestExecutionService.test.d.ts +1 -0
  82. package/build/services/TestExecutionService.test.js +339 -25
  83. package/build/services/TestGenerationService.d.ts +56 -0
  84. package/build/services/TestGenerationService.test.d.ts +1 -0
  85. package/build/services/TestGenerationService.test.js +10 -8
  86. package/build/services/containerEnv.d.ts +14 -0
  87. package/build/tool-phase-coverage.test.d.ts +1 -0
  88. package/build/tool-phase-coverage.test.js +2 -0
  89. package/build/tool-phases.d.ts +38 -0
  90. package/build/tools/auth/loginTool.d.ts +2 -0
  91. package/build/tools/auth/logoutTool.d.ts +2 -0
  92. package/build/tools/code-refactor/codeReuseTool.d.ts +2 -0
  93. package/build/tools/code-refactor/enhanceAssertionsTool.d.ts +2 -0
  94. package/build/tools/code-refactor/modularizationTool.d.ts +2 -0
  95. package/build/tools/executeSkyrampTestTool.d.ts +2 -0
  96. package/build/tools/executeSkyrampTestTool.js +26 -7
  97. package/build/tools/fixErrorTool.d.ts +2 -0
  98. package/build/tools/generate-tests/generateBatchScenarioRestTool.d.ts +45 -0
  99. package/build/tools/generate-tests/generateBatchScenarioRestTool.js +1 -1
  100. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.d.ts +1 -0
  101. package/build/tools/generate-tests/generateBatchScenarioRestTool.test.js +11 -9
  102. package/build/tools/generate-tests/generateContractRestTool.d.ts +31 -0
  103. package/build/tools/generate-tests/generateE2ERestTool.d.ts +13 -0
  104. package/build/tools/generate-tests/generateFuzzRestTool.d.ts +10 -0
  105. package/build/tools/generate-tests/generateIntegrationRestTool.d.ts +16 -0
  106. package/build/tools/generate-tests/generateLoadRestTool.d.ts +18 -0
  107. package/build/tools/generate-tests/generateLoadRestTool.test.d.ts +1 -0
  108. package/build/tools/generate-tests/generateMockRestTool.d.ts +64 -0
  109. package/build/tools/generate-tests/generateSmokeRestTool.d.ts +8 -0
  110. package/build/tools/generate-tests/generateUIRestTool.d.ts +14 -0
  111. package/build/tools/generate-tests/generateUIRestTool.js +1 -1
  112. package/build/tools/generate-tests/loadTestSchema.d.ts +39 -0
  113. package/build/tools/one-click/oneClickTool.d.ts +11 -0
  114. package/build/tools/submitReportTool.d.ts +394 -0
  115. package/build/tools/submitReportTool.js +250 -41
  116. package/build/tools/submitReportTool.test.d.ts +1 -0
  117. package/build/tools/submitReportTool.test.js +511 -55
  118. package/build/tools/test-management/actionsTool.d.ts +10 -0
  119. package/build/tools/test-management/actionsTool.js +21 -7
  120. package/build/tools/test-management/analyzeChangesTool.d.ts +27 -0
  121. package/build/tools/test-management/analyzeChangesTool.js +150 -48
  122. package/build/tools/test-management/analyzeChangesTool.test.d.ts +1 -0
  123. package/build/tools/test-management/analyzeChangesTool.test.js +95 -78
  124. package/build/tools/test-management/analyzeTestHealthTool.d.ts +2 -0
  125. package/build/tools/test-management/analyzeTestHealthTool.js +16 -9
  126. package/build/tools/test-management/index.d.ts +3 -0
  127. package/build/tools/test-management/index.js +0 -1
  128. package/build/tools/trace/resolveSaveStoragePath.d.ts +7 -0
  129. package/build/tools/trace/resolveSaveStoragePath.test.d.ts +1 -0
  130. package/build/tools/trace/resolveSessionPaths.d.ts +40 -0
  131. package/build/tools/trace/resolveSessionPaths.test.d.ts +1 -0
  132. package/build/tools/trace/sessionState.d.ts +2 -0
  133. package/build/tools/trace/sessionState.test.d.ts +1 -0
  134. package/build/tools/trace/startTraceCollectionTool.d.ts +2 -0
  135. package/build/tools/trace/stopTraceCollectionTool.d.ts +2 -0
  136. package/build/tools/workspace/initScanWorkspaceTool.d.ts +4 -0
  137. package/build/tools/workspace/initializeWorkspaceTool.d.ts +2 -0
  138. package/build/tools/workspace/initializeWorkspaceTool.js +39 -22
  139. package/build/tools/workspace/initializeWorkspaceTool.test.d.ts +1 -0
  140. package/build/tools/workspace/initializeWorkspaceTool.test.js +134 -0
  141. package/build/tools/workspace/serviceUpsert.d.ts +12 -0
  142. package/build/tools/workspace/serviceUpsert.js +23 -0
  143. package/build/tools/workspace/serviceUpsert.test.d.ts +1 -0
  144. package/build/tools/workspace/serviceUpsert.test.js +50 -0
  145. package/build/types/OneClickCommands.d.ts +68 -0
  146. package/build/types/RepositoryAnalysis.d.ts +3004 -0
  147. package/build/types/TestAnalysis.d.ts +97 -0
  148. package/build/types/TestExecution.d.ts +63 -0
  149. package/build/types/TestExecution.js +11 -1
  150. package/build/types/TestRecommendation.d.ts +12 -0
  151. package/build/types/TestTypes.d.ts +234 -0
  152. package/build/types/TestbotReport.d.ts +68 -0
  153. package/build/types/TestbotReport.js +1 -0
  154. package/build/types/index.d.ts +4 -0
  155. package/build/types/index.js +3 -0
  156. package/build/utils/AnalysisStateManager.d.ts +242 -0
  157. package/build/utils/AnalysisStateManager.js +144 -3
  158. package/build/utils/AnalysisStateManager.test.d.ts +1 -0
  159. package/build/utils/AnalysisStateManager.test.js +98 -0
  160. package/build/utils/analyze-openapi.d.ts +1 -0
  161. package/build/utils/branchDiff.d.ts +18 -0
  162. package/build/utils/dartRouteExtractor.d.ts +45 -0
  163. package/build/utils/dartRouteExtractor.test.d.ts +1 -0
  164. package/build/utils/docker.d.ts +19 -0
  165. package/build/utils/docker.test.d.ts +1 -0
  166. package/build/utils/docker.test.js +10 -9
  167. package/build/utils/featureFlags.d.ts +37 -0
  168. package/build/utils/featureFlags.test.d.ts +1 -0
  169. package/build/utils/gitStaging.d.ts +24 -0
  170. package/build/utils/gitStaging.test.d.ts +1 -0
  171. package/build/utils/gitStaging.test.js +13 -7
  172. package/build/utils/httpDefaults.d.ts +10 -0
  173. package/build/utils/httpDefaults.test.d.ts +1 -0
  174. package/build/utils/initAgent.d.ts +36 -0
  175. package/build/utils/language-helper.d.ts +6 -0
  176. package/build/utils/logger.d.ts +11 -0
  177. package/build/utils/normalizeParams.d.ts +14 -0
  178. package/build/utils/normalizeSkyrampImports.d.ts +13 -0
  179. package/build/utils/pr-comment-parser.d.ts +31 -0
  180. package/build/utils/pr-comment-parser.test.d.ts +1 -0
  181. package/build/utils/pr-comment-parser.test.js +6 -5
  182. package/build/utils/projectMetadata.d.ts +15 -0
  183. package/build/utils/projectMetadata.test.d.ts +1 -0
  184. package/build/utils/proxy-terminal.d.ts +2 -0
  185. package/build/utils/repoScanner.d.ts +27 -0
  186. package/build/utils/repoScanner.test.d.ts +1 -0
  187. package/build/utils/routeParsers.d.ts +53 -0
  188. package/build/utils/routeParsers.js +31 -38
  189. package/build/utils/routeParsers.test.d.ts +1 -0
  190. package/build/utils/scenarioDrafting.d.ts +71 -0
  191. package/build/utils/scenarioDrafting.js +23 -1
  192. package/build/utils/scenarioDrafting.test.d.ts +1 -0
  193. package/build/utils/skyrampMdContent.d.ts +5 -0
  194. package/build/utils/sourceRouteExtractor.d.ts +48 -0
  195. package/build/utils/sourceRouteExtractor.test.d.ts +1 -0
  196. package/build/utils/telemetry.d.ts +32 -0
  197. package/build/utils/telemetry.test.d.ts +1 -0
  198. package/build/utils/trace-parser.d.ts +32 -0
  199. package/build/utils/trace-parser.test.d.ts +6 -0
  200. package/build/utils/uiPageEnumerator.d.ts +146 -0
  201. package/build/utils/uiPageEnumerator.js +58 -14
  202. package/build/utils/uiPageEnumerator.test.d.ts +1 -0
  203. package/build/utils/uiPageEnumerator.test.js +223 -43
  204. package/build/utils/utils.d.ts +45 -0
  205. package/build/utils/utils.js +10 -0
  206. package/build/utils/utils.test.d.ts +1 -0
  207. package/build/utils/versions.d.ts +3 -0
  208. package/build/utils/versions.js +1 -1
  209. package/build/utils/workspaceAuth.d.ts +127 -0
  210. package/build/utils/workspaceAuth.test.d.ts +1 -0
  211. package/build/utils/workspaceAuth.test.js +25 -25
  212. package/build/workspace/index.d.ts +1 -0
  213. package/build/workspace/workspace.d.ts +390 -0
  214. package/build/workspace/workspace.js +7 -7
  215. package/build/workspace/workspace.test.d.ts +1 -0
  216. package/build/workspace/workspace.test.js +6 -6
  217. package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +31 -13
  218. package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +88 -15
  219. package/node_modules/playwright/lib/mcp/test/skyRampExport.js +4 -3
  220. package/node_modules/playwright/node_modules/playwright-core/ThirdPartyNotices.txt +23 -126
  221. package/node_modules/playwright/node_modules/playwright-core/lib/generated/injectedScriptSource.js +1 -1
  222. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/recorderApp.js +79 -19
  223. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/aliasRemapper.js +84 -0
  224. package/node_modules/playwright/node_modules/playwright-core/lib/server/recorder/skyramp/replayEngine.js +15 -4
  225. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-CPZKmjFR.js → codeMirrorModule-D0BjbCb7.js} +1 -1
  226. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-lvTRGFx-.js +193 -0
  227. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
  228. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-B0JOjboO.js → codeMirrorModule-Cqp3cwEJ.js} +1 -1
  229. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{defaultSettingsView-1anWeyDf.js → defaultSettingsView-CYf9adZh.js} +79 -79
  230. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{index.Cc5029a3.js → index.B_7ywgmr.js} +1 -1
  231. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
  232. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
  233. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/{uiMode.Wo5yvvVh.js → uiMode.u4_8VnCV.js} +1 -1
  234. package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
  235. package/node_modules/playwright/node_modules/playwright-core/src/generated/injectedScriptSource.ts +1 -1
  236. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/recorderApp.ts +129 -43
  237. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/aliasRemapper.ts +119 -0
  238. package/node_modules/playwright/node_modules/playwright-core/src/server/recorder/skyramp/replayEngine.ts +33 -10
  239. package/node_modules/playwright/package.json +1 -1
  240. package/package.json +16 -4
  241. package/build/tools/test-management/uiAnalyzeChangesTool.js +0 -155
  242. package/build/tools/test-management/uiAnalyzeChangesTool.test.js +0 -147
  243. package/node_modules/playwright/node_modules/playwright-core/bundles/mcp/node_modules/.bin/node-which +0 -52
  244. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/is-docker +0 -5
  245. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/mime +0 -46
  246. package/node_modules/playwright/node_modules/playwright-core/bundles/utils/node_modules/.bin/yaml +0 -11
  247. package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-CsgPR2wy.js +0 -193
  248. package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.CP3Y8Zsb.js +0 -2
@@ -0,0 +1,134 @@
1
+ // @ts-nocheck - Jest ESM type inference issues
2
+ import { jest } from "@jest/globals";
3
+ import { z } from "zod";
4
+ import * as fs from "fs/promises";
5
+ import * as path from "path";
6
+ import * as os from "os";
7
+ // WorkspaceConfigManager + serviceSchema now live in the local workspace module
8
+ // (SKYR-3794 moved them out of @skyramp/skyramp). serviceSchema must be a real
9
+ // zod schema because `z.array(serviceSchema)` runs at module import time.
10
+ jest.unstable_mockModule("../../workspace/workspace.js", () => ({
11
+ WorkspaceConfigManager: jest.fn(),
12
+ serviceSchema: z.any(),
13
+ }));
14
+ jest.unstable_mockModule("js-yaml", () => ({
15
+ default: { dump: jest.fn() },
16
+ }));
17
+ jest.unstable_mockModule("../../utils/logger.js", () => ({
18
+ logger: { info: jest.fn(), error: jest.fn() },
19
+ }));
20
+ jest.unstable_mockModule("../../services/AnalyticsService.js", () => ({
21
+ AnalyticsService: { pushMCPToolEvent: jest.fn() },
22
+ }));
23
+ jest.unstable_mockModule("./initScanWorkspaceTool.js", () => ({
24
+ validateAndConsumeScanToken: jest.fn(),
25
+ }));
26
+ const { registerInitializeWorkspaceTool } = await import("./initializeWorkspaceTool.js");
27
+ const { validateAndConsumeScanToken } = await import("./initScanWorkspaceTool.js");
28
+ const { WorkspaceConfigManager } = await import("../../workspace/workspace.js");
29
+ const yaml = (await import("js-yaml")).default;
30
+ describe("initializeWorkspaceTool", () => {
31
+ let tmpDir;
32
+ let handler;
33
+ let mockManager;
34
+ beforeEach(async () => {
35
+ tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "init-workspace-test-"));
36
+ // Build a mock WorkspaceConfigManager
37
+ mockManager = {
38
+ exists: jest.fn().mockResolvedValue(false),
39
+ getConfigPath: jest.fn().mockReturnValue(path.join(tmpDir, ".skyramp/workspace.yml")),
40
+ initialize: jest.fn().mockResolvedValue({ workspace: {}, services: [] }),
41
+ updateMetadata: jest.fn().mockImplementation(async (data) => ({
42
+ workspace: {},
43
+ services: [],
44
+ metadata: { ...data, updatedAt: "2024-01-01T00:00:00.000Z" },
45
+ })),
46
+ };
47
+ WorkspaceConfigManager.mockImplementation(() => mockManager);
48
+ // Mock validateAndConsumeScanToken to accept any token
49
+ validateAndConsumeScanToken.mockReturnValue(true);
50
+ // Mock yaml.dump to return a simple string
51
+ yaml.dump.mockReturnValue("services: []\n");
52
+ // Register the tool and capture the handler
53
+ const mockServer = {
54
+ registerTool: jest.fn((_name, _opts, fn) => {
55
+ handler = fn;
56
+ }),
57
+ };
58
+ registerInitializeWorkspaceTool(mockServer);
59
+ });
60
+ afterEach(async () => {
61
+ await fs.rm(tmpDir, { recursive: true, force: true });
62
+ jest.clearAllMocks();
63
+ });
64
+ it("registers the tool with the expected schema shape", () => {
65
+ const mockServer = {
66
+ registerTool: jest.fn(),
67
+ };
68
+ registerInitializeWorkspaceTool(mockServer);
69
+ expect(mockServer.registerTool).toHaveBeenCalledWith("skyramp_init_workspace", expect.objectContaining({
70
+ description: expect.stringContaining("PREREQUISITE"),
71
+ inputSchema: expect.objectContaining({
72
+ workspacePath: expect.any(Object),
73
+ services: expect.any(Object),
74
+ scanToken: expect.any(Object),
75
+ force: expect.any(Object),
76
+ }),
77
+ }), expect.any(Function));
78
+ });
79
+ it("successfully initializes workspace with valid input in merge mode", async () => {
80
+ // Create the parent directory
81
+ await fs.mkdir(path.join(tmpDir, ".skyramp"), { recursive: true });
82
+ const result = await handler({
83
+ workspacePath: tmpDir,
84
+ services: [
85
+ {
86
+ serviceName: "test-service",
87
+ language: "python",
88
+ testDirectory: "tests",
89
+ },
90
+ ],
91
+ scanToken: "valid-token",
92
+ force: false,
93
+ });
94
+ expect(result.isError).toBeFalsy();
95
+ expect(result.content[0].text).toContain("Workspace initialized");
96
+ expect(mockManager.initialize).toHaveBeenCalled();
97
+ expect(mockManager.updateMetadata).toHaveBeenCalledWith(expect.objectContaining({
98
+ mcpVersion: expect.any(String),
99
+ executorVersion: expect.any(String),
100
+ }));
101
+ });
102
+ it("returns error when workspace already exists without force flag", async () => {
103
+ mockManager.exists.mockResolvedValue(true);
104
+ const result = await handler({
105
+ workspacePath: tmpDir,
106
+ services: [{ serviceName: "svc", language: "python", testDirectory: "tests" }],
107
+ scanToken: "valid-token",
108
+ force: false,
109
+ });
110
+ expect(result.isError).toBe(false);
111
+ expect(result.content[0].text).toContain("already initialized");
112
+ });
113
+ it("returns error when scanToken is invalid", async () => {
114
+ validateAndConsumeScanToken.mockReturnValue(false);
115
+ const result = await handler({
116
+ workspacePath: tmpDir,
117
+ services: [{ serviceName: "svc", language: "python", testDirectory: "tests" }],
118
+ scanToken: "bad-token",
119
+ force: false,
120
+ });
121
+ expect(result.isError).toBe(true);
122
+ expect(result.content[0].text).toContain("Invalid or expired scanToken");
123
+ });
124
+ it("returns error when no services provided", async () => {
125
+ const result = await handler({
126
+ workspacePath: tmpDir,
127
+ services: [],
128
+ scanToken: "valid-token",
129
+ force: false,
130
+ });
131
+ expect(result.isError).toBe(true);
132
+ expect(result.content[0].text).toContain("No services provided");
133
+ });
134
+ });
@@ -0,0 +1,12 @@
1
+ import type { Service } from "../../workspace/workspace.js";
2
+ /**
3
+ * Upsert `incoming` services into `existing`, keyed on the composite
4
+ * (repository, serviceName). A service's `repository` (absent → primary,
5
+ * normalized to "") is part of its identity, so a same-named service from a
6
+ * different repo is a distinct entry rather than an overwrite. Mutates and
7
+ * returns `existing`.
8
+ *
9
+ * Lives in its own module (no `import.meta`) so it can be unit-tested under
10
+ * ts-jest's CommonJS transform without loading the tool's ESM-only deps.
11
+ */
12
+ export declare function upsertServicesByRepo(existing: Service[], incoming: Service[]): Service[];
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Upsert `incoming` services into `existing`, keyed on the composite
3
+ * (repository, serviceName). A service's `repository` (absent → primary,
4
+ * normalized to "") is part of its identity, so a same-named service from a
5
+ * different repo is a distinct entry rather than an overwrite. Mutates and
6
+ * returns `existing`.
7
+ *
8
+ * Lives in its own module (no `import.meta`) so it can be unit-tested under
9
+ * ts-jest's CommonJS transform without loading the tool's ESM-only deps.
10
+ */
11
+ export function upsertServicesByRepo(existing, incoming) {
12
+ for (const svc of incoming) {
13
+ const repoKey = svc.repository || "";
14
+ const idx = existing.findIndex((s) => (s.repository || "") === repoKey && s.serviceName === svc.serviceName);
15
+ if (idx >= 0) {
16
+ existing[idx] = svc;
17
+ }
18
+ else {
19
+ existing.push(svc);
20
+ }
21
+ }
22
+ return existing;
23
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
1
+ import { upsertServicesByRepo } from "./serviceUpsert.js";
2
+ // upsertServicesByRepo is the merge=true core: it upserts incoming services into
3
+ // the existing list keyed on the composite (repository, serviceName), so a
4
+ // same-named service from a different repo is a distinct entry rather than an
5
+ // overwrite. This is what makes the unified multi-repo workspace.yml correct.
6
+ describe("upsertServicesByRepo", () => {
7
+ const svc = (serviceName, repository, testDirectory) => ({ serviceName, repository, testDirectory });
8
+ it("keeps same-named services from different repos as distinct entries", () => {
9
+ const existing = [svc("api", undefined, "tests/primary")];
10
+ const result = upsertServicesByRepo(existing, [
11
+ svc("api", "letsramp/api-insight", "tests/py"),
12
+ ]);
13
+ expect(result).toHaveLength(2);
14
+ expect(result.find((s) => !s.repository)?.testDirectory).toBe("tests/primary");
15
+ expect(result.find((s) => s.repository === "letsramp/api-insight")?.testDirectory).toBe("tests/py");
16
+ });
17
+ it("updates only the matching (repository, serviceName) entry in place", () => {
18
+ const existing = [
19
+ svc("api", undefined, "tests/primary"),
20
+ svc("api", "letsramp/api-insight", "tests/py"),
21
+ ];
22
+ // Re-register the related repo's service with a new testDirectory.
23
+ const result = upsertServicesByRepo(existing, [
24
+ svc("api", "letsramp/api-insight", "tests/py-v2"),
25
+ ]);
26
+ expect(result).toHaveLength(2);
27
+ // Primary untouched.
28
+ expect(result.find((s) => !s.repository)?.testDirectory).toBe("tests/primary");
29
+ // Related repo's entry updated in place (not duplicated).
30
+ const related = result.filter((s) => s.repository === "letsramp/api-insight");
31
+ expect(related).toHaveLength(1);
32
+ expect(related[0].testDirectory).toBe("tests/py-v2");
33
+ });
34
+ it("treats an absent repository as the primary (normalized to '')", () => {
35
+ const existing = [svc("api", undefined, "tests/primary")];
36
+ // A second primary write (no repository) upserts the SAME entry.
37
+ const result = upsertServicesByRepo(existing, [svc("api", undefined, "tests/primary-v2")]);
38
+ expect(result).toHaveLength(1);
39
+ expect(result[0].testDirectory).toBe("tests/primary-v2");
40
+ });
41
+ it("appends brand-new services from multiple repos", () => {
42
+ const result = upsertServicesByRepo([], [
43
+ svc("web", "letsramp/frontend", "tests/web"),
44
+ svc("api", "letsramp/backend", "tests/api"),
45
+ svc("api", undefined, "tests/primary"),
46
+ ]);
47
+ expect(result).toHaveLength(3);
48
+ expect(new Set(result.map((s) => `${s.repository ?? ""}|${s.serviceName}`))).toEqual(new Set(["letsramp/frontend|web", "letsramp/backend|api", "|api"]));
49
+ });
50
+ });
@@ -0,0 +1,68 @@
1
+ /**
2
+ * One-Click Commands: declarative workflow specifications for orchestrated
3
+ * multi-step testing workflows. Commands are stored in a predefined library
4
+ * and executed by the coding assistant following the workflow instructions.
5
+ */
6
+ /** Unique identifier for a one-click command */
7
+ export type OneClickCommandId = "test_given_endpoint_comprehensively" | "full_repo_scan_recommend_generate_and_execute_top_n_tests";
8
+ /** Metadata for intent recognition by coding assistants */
9
+ export interface CommandIntentMetadata {
10
+ /** Context indicators describing when to use and when NOT to use this workflow */
11
+ contextIndicators: string[];
12
+ /** Short purpose summary for discoverability */
13
+ purpose: string;
14
+ /** One-line workflow summary */
15
+ workflowSummary: string;
16
+ /** Few-shot examples to guide LLM intent matching */
17
+ examples?: {
18
+ /** User messages that SHOULD trigger this workflow */
19
+ use: string[];
20
+ /** User messages that should NOT trigger this workflow */
21
+ doNotUse: string[];
22
+ };
23
+ }
24
+ /** Reference to an MCP tool and how to obtain its inputs */
25
+ export interface WorkflowStepToolCall {
26
+ /** MCP tool name to invoke (e.g. skyramp_analyze_repository) */
27
+ toolName: string;
28
+ /** Human-readable step description */
29
+ description: string;
30
+ /** Input parameter names and source: "user" | "step:<n>" | "literal" */
31
+ inputs: Record<string, {
32
+ source: "user";
33
+ paramKey: string;
34
+ } | {
35
+ source: "step";
36
+ stepIndex: number;
37
+ outputKey: string;
38
+ } | {
39
+ source: "literal";
40
+ value: string | number | boolean;
41
+ }>;
42
+ /** Output keys this step produces (e.g. stateFile) for later steps */
43
+ outputs?: string[];
44
+ }
45
+ /** Single step in a workflow */
46
+ export interface WorkflowStep {
47
+ stepIndex: number;
48
+ title: string;
49
+ description: string;
50
+ /** Optional: explicit tool call spec for this step */
51
+ toolCall?: WorkflowStepToolCall;
52
+ /** Optional: guidance when step is conditional (e.g. "for each recommended type") */
53
+ conditionalGuidance?: string;
54
+ }
55
+ /** Full definition of a one-click command */
56
+ export interface OneClickCommandDef {
57
+ id: OneClickCommandId;
58
+ name: string;
59
+ description: string;
60
+ intent: CommandIntentMetadata;
61
+ /** Ordered sequence of workflow steps */
62
+ steps: WorkflowStep[];
63
+ /** Input parameters this command accepts from the user */
64
+ inputParams: {
65
+ required: string[];
66
+ optional?: string[];
67
+ };
68
+ }