@skyramp/mcp 0.3.5 → 0.3.6-rc.2.ac20
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/adapters/jestAdapter.js +3 -0
- package/build/adapters/mochaAdapter.js +2 -0
- package/build/adapters/playwrightAdapter.js +3 -0
- package/build/adapters/pytestAdapter.js +12 -0
- package/build/playwright/registerPlaywrightTools.js +92 -30
- package/build/playwright/traceRecordingPrompt.d.ts +6 -0
- package/build/playwright/traceRecordingPrompt.js +6 -2
- package/build/prompts/code-reuse.d.ts +1 -2
- package/build/prompts/code-reuse.js +182 -77
- package/build/prompts/modularization/integration-test-modularization.d.ts +2 -0
- package/build/prompts/modularization/integration-test-modularization.js +83 -41
- package/build/prompts/modularization/render.d.ts +18 -0
- package/build/prompts/modularization/render.js +12 -0
- package/build/prompts/modularization/ui-test-modularization.d.ts +3 -1
- package/build/prompts/modularization/ui-test-modularization.js +89 -47
- package/build/prompts/pom-aware-code-reuse.js +3 -1
- package/build/prompts/shared-helper-policy.d.ts +57 -0
- package/build/prompts/shared-helper-policy.js +135 -0
- package/build/prompts/test-recommendation/diffExecutionPlan.js +62 -56
- package/build/prompts/test-recommendation/fullRepoCatalog.js +19 -8
- package/build/prompts/test-recommendation/recommendationShared.d.ts +28 -6
- package/build/prompts/test-recommendation/recommendationShared.js +90 -16
- package/build/prompts/test-recommendation/registerRecommendTestsPrompt.js +22 -0
- package/build/prompts/test-recommendation/test-recommendation-prompt.d.ts +2 -2
- package/build/prompts/test-recommendation/test-recommendation-prompt.js +3 -3
- package/build/prompts/testbot/testbot-prompts.js +81 -35
- package/build/recommendation/budgeters/shared.js +105 -27
- package/build/recommendation/discriminators.js +13 -2
- package/build/recommendation/planRanker.d.ts +6 -6
- package/build/recommendation/planRanker.js +6 -61
- package/build/services/AnalyticsService.d.ts +7 -0
- package/build/services/AnalyticsService.js +7 -1
- package/build/services/ModularizationService.js +1 -3
- package/build/services/TestDiscoveryService.d.ts +0 -2
- package/build/services/TestDiscoveryService.js +2 -37
- package/build/services/TestGenerationService.d.ts +16 -0
- package/build/services/TestGenerationService.js +86 -10
- package/build/services/containerEnv.js +13 -12
- package/build/tools/code-refactor/codeReuseTool.js +279 -93
- package/build/tools/code-refactor/enhance-state.d.ts +49 -0
- package/build/tools/code-refactor/enhance-state.js +109 -0
- package/build/tools/code-refactor/enhanceAssertionsTool.js +34 -1
- package/build/tools/code-refactor/modularizationTool.js +9 -2
- package/build/tools/code-refactor/reuse-outcome.d.ts +23 -1
- package/build/tools/code-refactor/reuse-outcome.js +14 -4
- package/build/tools/code-refactor/reuse-state.d.ts +127 -5
- package/build/tools/code-refactor/reuse-state.js +628 -16
- package/build/tools/code-refactor/utils-verify-gates.d.ts +26 -0
- package/build/tools/code-refactor/utils-verify-gates.js +100 -0
- package/build/tools/code-refactor/verify-gates.d.ts +2 -1
- package/build/tools/code-refactor/verify-gates.js +90 -25
- package/build/tools/executeSkyrampTestTool.d.ts +19 -0
- package/build/tools/executeSkyrampTestTool.js +158 -8
- package/build/tools/generate-tests/generateBatchScenarioRestTool.js +2 -2
- package/build/tools/generate-tests/generateE2ERestTool.js +16 -0
- package/build/tools/generate-tests/generateUIRestTool.d.ts +1 -0
- package/build/tools/generate-tests/generateUIRestTool.js +22 -0
- package/build/tools/generate-tests/scenarioLint.d.ts +2 -0
- package/build/tools/generate-tests/scenarioLint.js +127 -19
- package/build/tools/generate-tests/trace-reuse-guard.d.ts +20 -0
- package/build/tools/generate-tests/trace-reuse-guard.js +93 -0
- package/build/tools/runExistingTestsTool.d.ts +34 -2
- package/build/tools/runExistingTestsTool.js +104 -4
- package/build/tools/submitReportTool.d.ts +38 -38
- package/build/tools/submitReportTool.js +537 -120
- package/build/tools/test-management/analyzeChangesTool.d.ts +24 -1
- package/build/tools/test-management/analyzeChangesTool.js +71 -10
- package/build/tools/test-management/analyzeTestHealthTool.js +7 -7
- package/build/tools/test-management/registerTestPlanTool.d.ts +203 -0
- package/build/tools/test-management/registerTestPlanTool.js +70 -12
- package/build/types/ExternalTestExecution.d.ts +67 -1
- package/build/types/Recommendation.d.ts +34 -5
- package/build/types/RepositoryAnalysis.d.ts +133 -114
- package/build/types/RepositoryAnalysis.js +1 -1
- package/build/types/ReuseOutcome.d.ts +102 -6
- package/build/types/ReuseOutcome.js +16 -2
- package/build/types/TestRecommendation.js +21 -3
- package/build/types/TestTypes.js +14 -8
- package/build/types/TestbotReport.d.ts +10 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.js +1 -1
- package/build/utils/AnalysisStateManager.d.ts +57 -1
- package/build/utils/AnalysisStateManager.js +54 -5
- package/build/utils/branchDiff.d.ts +10 -0
- package/build/utils/branchDiff.js +28 -0
- package/build/utils/changedRoutes.d.ts +29 -0
- package/build/utils/changedRoutes.js +87 -0
- package/build/utils/featureFlags.d.ts +21 -0
- package/build/utils/featureFlags.js +23 -0
- package/build/utils/frontendIntegration.js +34 -4
- package/build/utils/importerHop.d.ts +2 -8
- package/build/utils/importerHop.js +15 -53
- package/build/utils/pathMatching.d.ts +38 -0
- package/build/utils/pathMatching.js +71 -0
- package/build/utils/pathSignatures.d.ts +22 -0
- package/build/utils/pathSignatures.js +57 -0
- package/build/utils/planMatchKeys.d.ts +16 -3
- package/build/utils/planMatchKeys.js +26 -10
- package/build/utils/pluralization.d.ts +10 -0
- package/build/utils/pluralization.js +18 -0
- package/build/utils/pom-catalog-parse.d.ts +52 -0
- package/build/utils/pom-catalog-parse.js +141 -0
- package/build/utils/pom-scope/selector-extractor.d.ts +12 -0
- package/build/utils/pom-scope/selector-extractor.js +34 -8
- package/build/utils/pom-verify/verify.d.ts +6 -5
- package/build/utils/pom-verify/verify.js +8 -6
- package/build/utils/reportVerification.d.ts +64 -4
- package/build/utils/reportVerification.js +228 -3
- package/build/utils/reuseRouting.d.ts +3 -0
- package/build/utils/reuseRouting.js +50 -0
- package/build/utils/routeParsers.d.ts +2 -0
- package/build/utils/routeParsers.js +65 -8
- package/build/utils/scenarioDrafting.d.ts +1 -1
- package/build/utils/scenarioDrafting.js +57 -45
- package/build/utils/subjectEndpoints.d.ts +19 -0
- package/build/utils/subjectEndpoints.js +98 -0
- package/build/utils/testFileClassification.d.ts +11 -0
- package/build/utils/testFileClassification.js +47 -0
- package/build/utils/uiPageEnumerator.d.ts +45 -19
- package/build/utils/uiPageEnumerator.js +95 -51
- package/build/utils/utils-verify/allow.d.ts +16 -0
- package/build/utils/utils-verify/allow.js +68 -0
- package/build/utils/utils-verify/call-sites.d.ts +34 -0
- package/build/utils/utils-verify/call-sites.js +154 -0
- package/build/utils/utils-verify/index.d.ts +7 -0
- package/build/utils/utils-verify/index.js +7 -0
- package/build/utils/utils-verify/language-spec.d.ts +91 -0
- package/build/utils/utils-verify/language-spec.js +210 -0
- package/build/utils/utils-verify/locate.d.ts +39 -0
- package/build/utils/utils-verify/locate.js +199 -0
- package/build/utils/utils-verify/parse.d.ts +34 -0
- package/build/utils/utils-verify/parse.js +177 -0
- package/build/utils/utils-verify/stage.d.ts +24 -0
- package/build/utils/utils-verify/stage.js +107 -0
- package/build/utils/utils-verify/verify.d.ts +63 -0
- package/build/utils/utils-verify/verify.js +168 -0
- package/build/utils/utils.d.ts +3 -1
- package/build/utils/utils.js +3 -1
- package/build/workspace/workspace.d.ts +32 -32
- package/node_modules/playwright/lib/mcp/skyramp/assertTool.js +9 -5
- package/node_modules/playwright/lib/mcp/skyramp/loadTraceTool.js +16 -0
- package/node_modules/playwright/lib/mcp/skyramp/skyRampImport.js +2 -0
- package/node_modules/playwright/lib/mcp/skyramp/traceRecordingBackend.js +115 -14
- package/node_modules/playwright/lib/mcp/test/skyRampExport.js +13 -1
- package/node_modules/playwright/node_modules/playwright-core/.DS_Store +0 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/server/codegen/skyramp/jsonlReader.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/htmlReport/index.html +27 -253
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/{codeMirrorModule-DtudTj_v.js → codeMirrorModule-DJMC4zNo.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BW82eAUI.js +196 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/index.html +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/{codeMirrorModule-FNMuBzX1.js → codeMirrorModule-CZfp96qZ.js} +1 -1
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-gpLo02E0.js +809 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.Bq1r1URj.js +2 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.VEfqi1qN.js +5 -0
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.html +2 -2
- package/node_modules/playwright/node_modules/playwright-core/package.json +1 -1
- package/node_modules/playwright/node_modules/playwright-core/src/server/codegen/skyramp/jsonlReader.ts +1 -1
- package/node_modules/playwright/package.json +1 -1
- package/package.json +2 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/recorder/assets/index-BpDwp16L.js +0 -422
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/assets/defaultSettingsView-Co9upU5h.js +0 -1035
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/index.DXNIQ_dx.js +0 -2
- package/node_modules/playwright/node_modules/playwright-core/lib/vite/traceViewer/uiMode.CIKB3XSv.js +0 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as path from "path";
|
|
1
2
|
/**
|
|
2
3
|
* Shared jest + vitest adapter for skyramp_run_existing_tests. vitest's json
|
|
3
4
|
* reporter is jest-compatible, so both use ONE parser; only the reporter flag
|
|
@@ -40,6 +41,7 @@ export function parseJestJson(report, opts) {
|
|
|
40
41
|
results.push({
|
|
41
42
|
testId: `${name} › (file failed to run)`,
|
|
42
43
|
file: name,
|
|
44
|
+
...(path.isAbsolute(name) ? { absoluteFile: name } : {}),
|
|
43
45
|
status: "error",
|
|
44
46
|
message: stripVTControlCharacters(raw).trim() || undefined,
|
|
45
47
|
durationMs: 0,
|
|
@@ -55,6 +57,7 @@ export function parseJestJson(report, opts) {
|
|
|
55
57
|
results.push({
|
|
56
58
|
testId: `${name} › ${titlePath}`,
|
|
57
59
|
file: name,
|
|
60
|
+
...(path.isAbsolute(name) ? { absoluteFile: name } : {}),
|
|
58
61
|
status,
|
|
59
62
|
message,
|
|
60
63
|
durationMs: Math.round(a.duration ?? 0),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as path from "path";
|
|
1
2
|
/**
|
|
2
3
|
* Mocha adapter for skyramp_run_existing_tests. Normalizes `mocha --reporter
|
|
3
4
|
* json` (emitted to stdout) into the neutral shape. Mocha does not tag
|
|
@@ -29,6 +30,7 @@ function toResult(t, status) {
|
|
|
29
30
|
return {
|
|
30
31
|
testId: `${file} › ${full}`,
|
|
31
32
|
file,
|
|
33
|
+
...(path.isAbsolute(file) ? { absoluteFile: file } : {}),
|
|
32
34
|
status,
|
|
33
35
|
message: status === "fail" || status === "error" ? messageOf(t) : undefined,
|
|
34
36
|
durationMs: Math.round(t.duration ?? 0),
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* builds the flags appended to the suite's `testRunCommand`. The IO shell that
|
|
13
13
|
* actually spawns the run lives in `runExistingTestsTool`.
|
|
14
14
|
*/
|
|
15
|
+
import * as path from "path";
|
|
15
16
|
import { stripVTControlCharacters } from "util";
|
|
16
17
|
/**
|
|
17
18
|
* A Playwright project (or spec file) is "infra" when it exists to bring up /
|
|
@@ -67,6 +68,7 @@ function messageOf(test) {
|
|
|
67
68
|
}
|
|
68
69
|
export function parsePlaywrightJson(report, opts) {
|
|
69
70
|
const rep = (report ?? {});
|
|
71
|
+
const rootDir = rep.config?.rootDir;
|
|
70
72
|
const collected = [];
|
|
71
73
|
for (const fileSuite of rep.suites ?? []) {
|
|
72
74
|
collectSpecs(fileSuite, fileSuite.file ?? "", [], collected);
|
|
@@ -118,6 +120,7 @@ export function parsePlaywrightJson(report, opts) {
|
|
|
118
120
|
results.push({
|
|
119
121
|
testId,
|
|
120
122
|
file,
|
|
123
|
+
...(rootDir ? { absoluteFile: path.resolve(rootDir, file) } : {}),
|
|
121
124
|
status,
|
|
122
125
|
message: status === "fail" || status === "error" ? messageOf(test) : undefined,
|
|
123
126
|
durationMs,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as path from "path";
|
|
1
2
|
/**
|
|
2
3
|
* pytest adapter for skyramp_run_existing_tests. Normalizes the
|
|
3
4
|
* `pytest-json-report` (`--json-report`) output into the neutral result shape.
|
|
@@ -39,6 +40,8 @@ function durationMsOf(test) {
|
|
|
39
40
|
export function parsePytestJson(report, opts) {
|
|
40
41
|
const rep = (report ?? {});
|
|
41
42
|
const tests = rep.tests ?? [];
|
|
43
|
+
const root = rep.root;
|
|
44
|
+
const abs = (f) => (root ? { absoluteFile: path.resolve(root, f) } : {});
|
|
42
45
|
// Real test outcomes.
|
|
43
46
|
const testResults = tests.map((t) => {
|
|
44
47
|
const status = mapOutcome(t.outcome);
|
|
@@ -46,6 +49,7 @@ export function parsePytestJson(report, opts) {
|
|
|
46
49
|
return {
|
|
47
50
|
testId: nodeid,
|
|
48
51
|
file: fileOf(nodeid),
|
|
52
|
+
...abs(fileOf(nodeid)),
|
|
49
53
|
status,
|
|
50
54
|
message: status === "fail" || status === "error" ? messageOf(t) : undefined,
|
|
51
55
|
durationMs: durationMsOf(t),
|
|
@@ -61,6 +65,7 @@ export function parsePytestJson(report, opts) {
|
|
|
61
65
|
return {
|
|
62
66
|
testId: `${nodeid} › (collection error)`,
|
|
63
67
|
file: fileOf(nodeid),
|
|
68
|
+
...abs(fileOf(nodeid)),
|
|
64
69
|
status: "error",
|
|
65
70
|
message: lastLine(c.longrepr),
|
|
66
71
|
durationMs: 0,
|
|
@@ -72,6 +77,13 @@ export function parsePytestJson(report, opts) {
|
|
|
72
77
|
// When collection failed AND no real test ran, the suite as a whole could not be
|
|
73
78
|
// collected — environmental (a wall of red), not PR signal. When some real tests
|
|
74
79
|
// DID run, the collection errors above stand as ordinary PR-signal error results.
|
|
80
|
+
// NOTE: a collection error names the file that failed to import, but says nothing
|
|
81
|
+
// about WHY. A missing settings module, a database that is down or any shared
|
|
82
|
+
// dependency failure surfaces per-module, landing on exactly the files the run
|
|
83
|
+
// selected — indistinguishable here from a file the PR itself broke. So a run that
|
|
84
|
+
// collected nothing stays unhealthy even when scoped, and the file keeps its
|
|
85
|
+
// Unknown baseline. Treating it as PR signal would let an environment outage be
|
|
86
|
+
// reported as a test the change broke, and then repaired.
|
|
75
87
|
if (collectionErrors.length > 0 && testResults.length === 0) {
|
|
76
88
|
environmentHealthy = false;
|
|
77
89
|
const first = collectionErrors[0];
|
|
@@ -4,36 +4,111 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { logger } from "../utils/logger.js";
|
|
7
|
-
import { dualChannelResult } from "../utils/utils.js";
|
|
8
7
|
import { PlaywrightTraceService, } from "./PlaywrightTraceService.js";
|
|
9
8
|
let _service = null;
|
|
10
9
|
export function getPlaywrightTraceService() {
|
|
11
10
|
return _service;
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
14
|
-
* The one browser tool whose
|
|
15
|
-
*
|
|
13
|
+
* The one browser tool whose text payload is shrunk on the way out — see
|
|
14
|
+
* shrinkBlueprintResult.
|
|
16
15
|
*/
|
|
17
16
|
const BLUEPRINT_TOOL = "browser_blueprint";
|
|
18
17
|
/**
|
|
19
|
-
*
|
|
18
|
+
* Shrink a browser_blueprint result on the text channel it already arrives on.
|
|
20
19
|
*
|
|
21
|
-
* SKYR-
|
|
22
|
-
*
|
|
23
|
-
* `
|
|
24
|
-
*
|
|
20
|
+
* SKYR-4267. SKYR-4194 (#752) also copied the capture into `structuredContent`
|
|
21
|
+
* as a JSON string. Claude Code measures that copy against its size cap and
|
|
22
|
+
* drops `content[]` when both channels are present, so the escape added to
|
|
23
|
+
* every quote and newline counted against the cap. On the largest real capture
|
|
24
|
+
* (`sb20-bucket-visibility`) the text is 26,542 bytes and the escaped string
|
|
25
|
+
* 29,411 — which BOTH channels carried, because `dualChannelResult` puts the
|
|
26
|
+
* JSON serialization of `structuredContent` into `content[]`, so 58,822 went on
|
|
27
|
+
* the wire.
|
|
25
28
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
29
|
+
* The escaping also collapsed the whole payload onto ONE line, so a spill file
|
|
30
|
+
* read at a line offset returned nothing at all
|
|
31
|
+
* (`repo14-U06-field-reorder-toast`). Dropping it does not give the capture its
|
|
32
|
+
* newlines back: the fork pretty-prints the JSON, but shrinkBlueprintText below
|
|
33
|
+
* re-serializes with no indent, so the body is still one line. What returns are
|
|
34
|
+
* the `### ` section headers around it, so an offset read now lands on a header
|
|
35
|
+
* instead of erroring — the failure is mitigated, not closed.
|
|
36
|
+
*
|
|
37
|
+
* The text channel is the one every agent CLI reads, and it is what the other
|
|
38
|
+
* browser tools already return, so the capture rides it alone.
|
|
39
|
+
*
|
|
40
|
+
* An error result is returned untouched.
|
|
28
41
|
*/
|
|
29
|
-
function
|
|
42
|
+
function shrinkBlueprintResult(result) {
|
|
30
43
|
if (result?.isError)
|
|
31
44
|
return result;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.map((block) => block
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
return {
|
|
46
|
+
...result,
|
|
47
|
+
content: (result?.content ?? []).map((block) => block?.type === "text"
|
|
48
|
+
? { ...block, text: shrinkBlueprintText(block.text) }
|
|
49
|
+
: block),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Drop every null-valued key, at any depth.
|
|
54
|
+
*
|
|
55
|
+
* SKYR-4208. Array entries are left alone — a null there holds a position, and
|
|
56
|
+
* removing it would renumber everything after it.
|
|
57
|
+
*/
|
|
58
|
+
function dropNulls(value) {
|
|
59
|
+
if (Array.isArray(value))
|
|
60
|
+
return value.map(dropNulls);
|
|
61
|
+
if (value === null || typeof value !== "object")
|
|
62
|
+
return value;
|
|
63
|
+
return Object.fromEntries(Object.entries(value)
|
|
64
|
+
.filter(([, v]) => v !== null)
|
|
65
|
+
.map(([k, v]) => [k, dropNulls(v)]));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Minify the JSON body of a browser_blueprint payload and drop its null keys.
|
|
69
|
+
*
|
|
70
|
+
* SKYR-4208. The fork pretty-prints the capture behind a `### Result` header.
|
|
71
|
+
* On eval run 32458076607 (962 payloads, 11,368 elements) the indentation is
|
|
72
|
+
* 35.4% of the payload's tokens, and the null keys a further 6.8% — `stableId`,
|
|
73
|
+
* `testId` and `fingerprint` are null on 72-94% of elements and cost their key
|
|
74
|
+
* name on every one.
|
|
75
|
+
*
|
|
76
|
+
* Both steps are lossless: the agent parses the same fields with the same
|
|
77
|
+
* values, and an absent key already says what a null key says. Keys that merely
|
|
78
|
+
* hold their DEFAULT (`framePath: []`, `shadowRoot: false`) are deliberately
|
|
79
|
+
* kept — dropping those makes the agent infer the default from an absence, and
|
|
80
|
+
* `framePath` stops being empty as soon as the page has an iframe.
|
|
81
|
+
*
|
|
82
|
+
* The header and anything else outside the JSON survive unchanged, and a body
|
|
83
|
+
* that does not parse is returned as it arrived.
|
|
84
|
+
*/
|
|
85
|
+
function shrinkBlueprintText(text) {
|
|
86
|
+
const start = text.indexOf("{");
|
|
87
|
+
if (start === -1)
|
|
88
|
+
return text;
|
|
89
|
+
// The fork can append more sections after `### Result` — `### Page` whenever
|
|
90
|
+
// the title or URL changed since the last call, and `### Modal state`,
|
|
91
|
+
// `### Snapshot` or `### Events` when the page produced them. Only the Result
|
|
92
|
+
// section holds JSON, so the body has to stop at the next header; reading to
|
|
93
|
+
// the end of the string makes the parse throw and costs the whole saving.
|
|
94
|
+
// A `### ` at the start of a line cannot sit inside the JSON, because JSON
|
|
95
|
+
// escapes the newline that would have to precede it.
|
|
96
|
+
const nextSection = text.slice(start).search(/\n### /);
|
|
97
|
+
const end = nextSection === -1 ? text.length : start + nextSection;
|
|
98
|
+
// The blank line the fork puts after a section belongs to the payload, not to
|
|
99
|
+
// the JSON, so it is put back byte-for-byte rather than parsed away.
|
|
100
|
+
const body = text.slice(start, end);
|
|
101
|
+
const json = body.trimEnd();
|
|
102
|
+
try {
|
|
103
|
+
return (text.slice(0, start) +
|
|
104
|
+
JSON.stringify(dropNulls(JSON.parse(json))) +
|
|
105
|
+
body.slice(json.length) +
|
|
106
|
+
text.slice(end));
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
logger.warning("browser_blueprint payload did not parse as JSON — delivering it unshrunk (SKYR-4208)");
|
|
110
|
+
return text;
|
|
111
|
+
}
|
|
37
112
|
}
|
|
38
113
|
export async function registerPlaywrightTools(server, options) {
|
|
39
114
|
_service = new PlaywrightTraceService(options);
|
|
@@ -98,19 +173,6 @@ export async function registerPlaywrightTools(server, options) {
|
|
|
98
173
|
server.registerTool(tool.name, {
|
|
99
174
|
description: tool.description || `Playwright tool: ${tool.name}`,
|
|
100
175
|
inputSchema: zodSchema,
|
|
101
|
-
// SKYR-4194: only browser_blueprint returns its payload via
|
|
102
|
-
// structuredContent, which requires a declared outputSchema. The other
|
|
103
|
-
// browser tools return small results, and some return images, which this
|
|
104
|
-
// text-only re-shaping would drop.
|
|
105
|
-
...(isBlueprint
|
|
106
|
-
? {
|
|
107
|
-
outputSchema: {
|
|
108
|
-
blueprint: z
|
|
109
|
-
.string()
|
|
110
|
-
.describe("The captured PageBlueprint — sections, elements, and their logical names. Read and follow this field."),
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
: {}),
|
|
114
176
|
}, async (params) => {
|
|
115
177
|
if (!_service?.isInitialized()) {
|
|
116
178
|
return {
|
|
@@ -124,7 +186,7 @@ export async function registerPlaywrightTools(server, options) {
|
|
|
124
186
|
};
|
|
125
187
|
}
|
|
126
188
|
const result = await _service.callTool(tool.name, params);
|
|
127
|
-
return isBlueprint ?
|
|
189
|
+
return isBlueprint ? shrinkBlueprintResult(result) : result;
|
|
128
190
|
});
|
|
129
191
|
}
|
|
130
192
|
logger.info(`Registered ${filteredTools.length} Playwright tools: ${filteredTools.map((t) => t.name).join(", ")}`);
|
|
@@ -8,6 +8,12 @@ export interface TraceRecordingPromptOpts {
|
|
|
8
8
|
outputDir?: string;
|
|
9
9
|
/** Whether to run skyramp_modularization after generation. Default: true. Set false in CI. */
|
|
10
10
|
modularize?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* With modularize=false: the generation result itself may still instruct a
|
|
13
|
+
* modularization pass (codeReuse flows that seed a shared utils file). When
|
|
14
|
+
* true, the note defers to that result instead of banning the tool outright.
|
|
15
|
+
*/
|
|
16
|
+
modularizeViaGenerationResult?: boolean;
|
|
11
17
|
}
|
|
12
18
|
export declare function getTraceRecordingPromptText(opts?: TraceRecordingPromptOpts): string;
|
|
13
19
|
export declare function registerTraceRecordingPrompt(server: McpServer): void;
|
|
@@ -13,10 +13,14 @@ export function getTraceRecordingPromptText(opts) {
|
|
|
13
13
|
: `Call \`skyramp_export_zip\` with \`outputPath\` set to the absolute zip path (same directory and base name as the test file, replacing \`.spec.ts\` with \`.zip\`).`;
|
|
14
14
|
const generateInstruction = modularize
|
|
15
15
|
? `Call \`skyramp_ui_test_generation\` with \`playwrightInput\` set to the absolute zip path from the Export step.`
|
|
16
|
-
:
|
|
16
|
+
: opts?.modularizeViaGenerationResult
|
|
17
|
+
? `Call \`skyramp_ui_test_generation\` with \`playwrightInput\` set to the absolute zip path from step 5, \`modularizeCode: false\`, and \`codeReuse: true\` — its result lists the post-generation steps (assertion enhancement, modularization, reuse) with their arguments.`
|
|
18
|
+
: `Call \`skyramp_ui_test_generation\` with \`playwrightInput\` set to the absolute zip path from step 5 and \`modularizeCode: false\`.`;
|
|
17
19
|
const modularizeNote = modularize
|
|
18
20
|
? `- **After generating the test**, run \`skyramp_modularization\` for code quality.`
|
|
19
|
-
:
|
|
21
|
+
: opts?.modularizeViaGenerationResult
|
|
22
|
+
? `- Run \`skyramp_modularization\` ONLY when the generation result's CRITICAL NEXT STEPS instruct it (with the arguments they give) — never on your own initiative.`
|
|
23
|
+
: `- Do NOT run \`skyramp_modularization\` — skip modularization in CI.`;
|
|
20
24
|
return `## Skyramp UI Test Recording
|
|
21
25
|
|
|
22
26
|
${getPersonaPrefix()} For UI recording, every action must be grounded in what \`browser_snapshot\` returns. If an element is not visible in the snapshot, do not interact with it.
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
import type { ScopedPomInput } from "../utils/pom-scope/index.js";
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function getCodeReusePrompt(testFile: string, language: string, framework?: string, scopedPoms?: ScopedPomInput): string;
|
|
2
|
+
export declare function getCodeReusePrompt(testFile: string, language: string, framework?: string, scopedPoms?: ScopedPomInput, testType?: string): string;
|