@kkeve/suite 0.0.13 → 0.0.17

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 (117) hide show
  1. package/dist/bin/keve.js +2 -1
  2. package/dist/commands/clean.js +2 -2
  3. package/dist/commands/config.js +7 -7
  4. package/dist/commands/init.js +2 -2
  5. package/dist/commands/report.js +7 -7
  6. package/dist/commands/run.js +16 -12
  7. package/dist/commands/test.js +7 -7
  8. package/dist/config.js +7 -7
  9. package/dist/core/action-log-writer.js +4 -1
  10. package/dist/core/decorator/keve-decorators.d.ts +128 -0
  11. package/dist/core/decorator/keve-decorators.js +254 -0
  12. package/dist/core/decorator/keve-host.d.ts +40 -0
  13. package/dist/core/decorator/keve-host.js +33 -0
  14. package/dist/core/{keve-registry.d.ts → decorator/keve-registry.d.ts} +19 -0
  15. package/dist/core/{keve-registry.js → decorator/keve-registry.js} +13 -1
  16. package/dist/core/generateReport/report.d.ts +1 -1
  17. package/dist/core/generateReport/report.js +2 -2
  18. package/dist/core/generateReport/reportData.d.ts +3 -0
  19. package/dist/core/generateReport/reportData.js +55 -18
  20. package/dist/core/judge/confidence.d.ts +119 -0
  21. package/dist/core/judge/confidence.js +295 -0
  22. package/dist/core/judge/goal-heuristics.d.ts +32 -0
  23. package/dist/core/judge/goal-heuristics.js +128 -0
  24. package/dist/core/judge/pngCodec.d.ts +23 -0
  25. package/dist/core/judge/pngCodec.js +215 -0
  26. package/dist/core/judge/screenshotDiff.d.ts +112 -0
  27. package/dist/core/judge/screenshotDiff.js +420 -0
  28. package/dist/core/page-object/definePage.d.ts +95 -0
  29. package/dist/core/page-object/definePage.js +62 -0
  30. package/dist/core/page-object/elementResolver.d.ts +32 -0
  31. package/dist/core/page-object/elementResolver.js +236 -0
  32. package/dist/core/page-object/engine-types.d.ts +140 -0
  33. package/dist/core/page-object/engine-types.js +34 -0
  34. package/dist/core/sso-cookie.d.ts +18 -0
  35. package/dist/core/sso-cookie.js +10 -0
  36. package/dist/dsl/index.d.ts +15 -0
  37. package/dist/dsl/index.js +29 -0
  38. package/dist/dsl/locatorSource.d.ts +25 -0
  39. package/dist/dsl/locatorSource.js +323 -0
  40. package/dist/dsl/ops.d.ts +46 -0
  41. package/dist/dsl/ops.js +95 -0
  42. package/dist/dsl/toDecorator.d.ts +98 -0
  43. package/dist/dsl/toDecorator.js +747 -0
  44. package/dist/engine-cypress/adapter.d.ts +108 -0
  45. package/dist/engine-cypress/adapter.js +514 -0
  46. package/dist/engine-cypress/agent-page.d.ts +159 -0
  47. package/dist/engine-cypress/agent-page.js +566 -0
  48. package/dist/engine-cypress/agentDom.d.ts +22 -0
  49. package/dist/engine-cypress/agentDom.js +590 -0
  50. package/dist/engine-cypress/bridge.d.ts +39 -0
  51. package/dist/engine-cypress/bridge.js +598 -0
  52. package/dist/engine-cypress/cdp.d.ts +78 -0
  53. package/dist/engine-cypress/cdp.js +339 -0
  54. package/dist/engine-cypress/host.d.ts +22 -0
  55. package/dist/engine-cypress/host.js +480 -0
  56. package/dist/engine-cypress/index.d.ts +26 -0
  57. package/dist/engine-cypress/index.js +58 -0
  58. package/dist/engine-cypress/keveGoal.d.ts +43 -0
  59. package/dist/engine-cypress/keveGoal.js +265 -0
  60. package/dist/engine-cypress/pageOps.d.ts +41 -0
  61. package/dist/engine-cypress/pageOps.js +439 -0
  62. package/dist/engine-cypress/reporter.d.ts +20 -0
  63. package/dist/engine-cypress/reporter.js +128 -0
  64. package/dist/engine-cypress/setup.d.ts +21 -0
  65. package/dist/engine-cypress/setup.js +27 -0
  66. package/dist/engine-cypress/shotBuffer.d.ts +40 -0
  67. package/dist/engine-cypress/shotBuffer.js +41 -0
  68. package/dist/engine-cypress/state.d.ts +56 -0
  69. package/dist/engine-cypress/state.js +81 -0
  70. package/dist/engine-playwright/engineAdapter.d.ts +78 -0
  71. package/dist/engine-playwright/engineAdapter.js +371 -0
  72. package/dist/engine-playwright/global-setup.d.ts +28 -0
  73. package/dist/engine-playwright/global-setup.js +142 -0
  74. package/dist/{core → engine-playwright}/keve-report.d.ts +0 -1
  75. package/dist/engine-playwright/keve-report.js +137 -0
  76. package/dist/{core → engine-playwright}/keve-test.d.ts +10 -8
  77. package/dist/{core → engine-playwright}/keve-test.js +257 -207
  78. package/dist/{core → engine-playwright}/pw-config.js +8 -7
  79. package/dist/index.d.ts +13 -8
  80. package/dist/index.js +43 -28
  81. package/dist/page-agent/agent.d.ts +98 -7
  82. package/dist/page-agent/agent.js +338 -84
  83. package/dist/page-agent/diagnostics.d.ts +184 -0
  84. package/dist/page-agent/diagnostics.js +377 -0
  85. package/dist/page-agent/hooks.d.ts +3 -2
  86. package/dist/page-agent/hooks.js +4 -3
  87. package/dist/page-agent/page-like.d.ts +116 -0
  88. package/dist/page-agent/page-like.js +14 -0
  89. package/dist/page-agent/playwright-page.d.ts +20 -0
  90. package/dist/page-agent/playwright-page.js +98 -0
  91. package/dist/page-agent/system-prompt.d.ts +7 -0
  92. package/dist/page-agent/system-prompt.js +10 -0
  93. package/dist/page-agent/system_prompt.md +1 -1
  94. package/dist/page-agent/tools.d.ts +1 -1
  95. package/dist/page-agent/tools.js +441 -9
  96. package/doc/skills/keve-e2e-gen/references/script-generation-guide.md +11 -0
  97. package/package.json +24 -11
  98. package/scripts/gen-system-prompt.mjs +36 -0
  99. package/scripts/run-dsl-task.mjs +619 -0
  100. package/scripts/runtime/cypress-preprocessor.mjs +44 -0
  101. package/scripts/runtime/cypress.config.mjs +35 -0
  102. package/scripts/runtime/playwright.config.mjs +41 -0
  103. package/scripts/verify-shot-diff.mjs +243 -0
  104. package/dist/commands/auth-update.d.ts +0 -16
  105. package/dist/commands/auth-update.js +0 -88
  106. package/dist/core/auth.d.ts +0 -17
  107. package/dist/core/auth.js +0 -224
  108. package/dist/core/cdp-resolver.d.ts +0 -5
  109. package/dist/core/cdp-resolver.js +0 -93
  110. package/dist/core/global-setup.d.ts +0 -6
  111. package/dist/core/global-setup.js +0 -113
  112. package/dist/core/keve-decorators.d.ts +0 -51
  113. package/dist/core/keve-decorators.js +0 -95
  114. package/dist/core/keve-report.js +0 -376
  115. /package/dist/core/{keve-aspect.d.ts → decorator/keve-aspect.d.ts} +0 -0
  116. /package/dist/core/{keve-aspect.js → decorator/keve-aspect.js} +0 -0
  117. /package/dist/{core → engine-playwright}/pw-config.d.ts +0 -0
@@ -0,0 +1,339 @@
1
+ "use strict";
2
+ /**
3
+ * cdp — Cypress 下的 AUT(被测应用)驱动层
4
+ *
5
+ * 背景:Cypress 的命令队列无法承载 async 的 EngineAdapter(详见
6
+ * EVE/docs/cypress-engine-cdp-findings.md)。这里完全绕开命令队列,只用
7
+ * `Cypress.automation('remote:debugger:protocol')` 直连 CDP,得到与 Playwright
8
+ * 等价的「读 DOM / 交互 / 导航 / 截图」能力。
9
+ *
10
+ * 三条硬约束(探针实测,改动前先看 findings 文档):
11
+ * 1. 严禁对主会话发 Page.navigate / Page.reload —— 会导航 Cypress runner 顶层页,
12
+ * 摧毁 runner。导航/刷新一律在 AUT 的 isolated world 内改 location。
13
+ * 2. 所有 DOM 读写必须走 `Page.createIsolatedWorld` 得到的 executionContextId,
14
+ * 否则读到的是 Cypress runner 自己的 UI(cy.$$ / Cypress.$ 同理不可用)。
15
+ * 3. Page.captureScreenshot 不带 clip 会拍到 runner 界面;必须用
16
+ * `iframe.aut-iframe` 的 rect 裁剪,才能得到干净的 AUT 截图。
17
+ *
18
+ * 本模块零依赖,运行在 Cypress 的 spec 上下文(浏览器)。
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.isRunnerFrameUrl = isRunnerFrameUrl;
55
+ exports.pollUntil = pollUntil;
56
+ exports.createCdp = createCdp;
57
+ const RUNNER_FRAME_RE = /__cypress|__\//;
58
+ /** 判断 frame URL 是否属于 Cypress runner 自身(AUT 诊断采集应跳过) */
59
+ function isRunnerFrameUrl(url) {
60
+ return RUNNER_FRAME_RE.test(String(url || ''));
61
+ }
62
+ /** 轮询工具:`fn` 返回 undefined 表示「还没就绪」,继续轮询 */
63
+ async function pollUntil(fn, timeout, interval = 100) {
64
+ const deadline = Date.now() + timeout;
65
+ let last;
66
+ for (;;) {
67
+ try {
68
+ const out = await fn();
69
+ if (out !== undefined)
70
+ return out;
71
+ last = out;
72
+ }
73
+ catch {
74
+ /* 过渡期(frame 正在重建 / context 已销毁):继续轮询 */
75
+ }
76
+ if (Date.now() >= deadline)
77
+ return undefined;
78
+ await new Promise((r) => setTimeout(r, interval));
79
+ }
80
+ }
81
+ function createCdp(send) {
82
+ let cachedWorld = null;
83
+ async function frames() {
84
+ const tree = await send('Page.getFrameTree');
85
+ const all = [];
86
+ const walk = (node) => {
87
+ if (!node?.frame)
88
+ return;
89
+ all.push({ id: node.frame.id, url: String(node.frame.url || '') });
90
+ (node.childFrames || []).forEach(walk);
91
+ };
92
+ walk(tree?.frameTree);
93
+ return all;
94
+ }
95
+ /** AUT frame:过滤掉 Cypress runner 自身的 frame */
96
+ async function autFrame() {
97
+ const all = await frames();
98
+ const hit = all.find((f) => !RUNNER_FRAME_RE.test(f.url));
99
+ if (!hit) {
100
+ throw new Error(`[cypress-engine] 未找到 AUT frame,现有 frame: ${JSON.stringify(all.map((f) => f.url))}`);
101
+ }
102
+ return hit;
103
+ }
104
+ /**
105
+ * AUT 的 isolated world。
106
+ * 导航会销毁旧 contextId,因此每次调用先校验缓存是否仍指向同一 frame;
107
+ * 失效时重建(`Page.createIsolatedWorld` 对同 frame + 同 worldName 会复用)。
108
+ */
109
+ async function context(force = false) {
110
+ const frame = await autFrame();
111
+ if (!force && cachedWorld && cachedWorld.frameId === frame.id)
112
+ return cachedWorld.contextId;
113
+ const res = await send('Page.createIsolatedWorld', { frameId: frame.id, worldName: 'keve' });
114
+ cachedWorld = { frameId: frame.id, contextId: res.executionContextId };
115
+ return res.executionContextId;
116
+ }
117
+ /** 在 AUT 内求值;context 失效时自动重建并重试一次 */
118
+ async function evaluateInAut(expression, opts = {}) {
119
+ const run = async () => {
120
+ const ctx = await context();
121
+ const res = await send('Runtime.evaluate', {
122
+ expression,
123
+ contextId: ctx,
124
+ returnByValue: true,
125
+ awaitPromise: opts.awaitPromise !== false,
126
+ });
127
+ if (res?.exceptionDetails) {
128
+ const desc = res.exceptionDetails.exception?.description || res.exceptionDetails.text;
129
+ throw new Error(String(desc));
130
+ }
131
+ return res?.result?.value;
132
+ };
133
+ try {
134
+ return await run();
135
+ }
136
+ catch (err) {
137
+ const msg = String(err?.message || err);
138
+ if (!/context|Cannot find|Execution context/i.test(msg))
139
+ throw err;
140
+ cachedWorld = null;
141
+ return await run();
142
+ }
143
+ }
144
+ /**
145
+ * 在指定 frame 内求值(诊断遍历子 frame 用)。
146
+ *
147
+ * Cypress 的 AUT 与业务子 frame 可能是跨域 OOPIF,但它们仍在同一 CDP
148
+ * 页面目标内;`Page.createIsolatedWorld` + `Runtime.evaluate` 可以逐个 frame
149
+ * 读主世界快照。逐次创建 world 成本可接受,且对同 frame + 同 worldName
150
+ * 浏览器会复用已有执行上下文。
151
+ */
152
+ async function evaluateInFrame(frameId, expression, opts = {}) {
153
+ const run = async () => {
154
+ const res = await send('Page.createIsolatedWorld', { frameId, worldName: 'keve' });
155
+ const ctx = res?.executionContextId;
156
+ if (!ctx)
157
+ throw new Error(`[cypress-engine] frame ${frameId} 未返回 isolated world`);
158
+ const evaluated = await send('Runtime.evaluate', {
159
+ expression,
160
+ contextId: ctx,
161
+ returnByValue: true,
162
+ awaitPromise: opts.awaitPromise !== false,
163
+ });
164
+ if (evaluated?.exceptionDetails) {
165
+ const desc = evaluated.exceptionDetails.exception?.description || evaluated.exceptionDetails.text;
166
+ throw new Error(String(desc));
167
+ }
168
+ return evaluated?.result?.value;
169
+ };
170
+ try {
171
+ return await run();
172
+ }
173
+ catch (err) {
174
+ const msg = String(err?.message || err);
175
+ if (!/context|Cannot find|Execution context|frame/i.test(msg))
176
+ throw err;
177
+ return await run();
178
+ }
179
+ }
180
+ /** 在 runner 顶层页求值(仅用于取 AUT iframe 的 rect,不用于业务断言) */
181
+ async function evaluateInRunner(expression) {
182
+ const res = await send('Runtime.evaluate', { expression, returnByValue: true });
183
+ if (res?.exceptionDetails) {
184
+ throw new Error(String(res.exceptionDetails.exception?.description || res.exceptionDetails.text));
185
+ }
186
+ return res?.result?.value;
187
+ }
188
+ /** 读取 AUT 基础状态(frame URL / readyState / title) */
189
+ async function snapshot() {
190
+ const frame = await autFrame();
191
+ const probe = await evaluateInAut(`document.readyState + "\\u0000" + location.href + "\\u0000" + String(document.title || "")`);
192
+ const [readyState, url, title] = String(probe ?? '').split('\u0000');
193
+ return { frameId: frame.id, url: url || frame.url, readyState: readyState || '', title: title || '' };
194
+ }
195
+ /** 当前 AUT URL(context 失效时回退到 frame.url) */
196
+ async function currentUrl() {
197
+ try {
198
+ return await evaluateInAut('location.href');
199
+ }
200
+ catch {
201
+ return (await autFrame()).url;
202
+ }
203
+ }
204
+ /**
205
+ * 导航到目标 URL。
206
+ * 必须「先等 URL 变化、再等 readyState=complete」—— 探针里先把旧页面的
207
+ * readyState=complete 当成导航完成过,导致后续断言跑在旧页面上。
208
+ */
209
+ async function goto(url, timeout = 30000) {
210
+ const before = await currentUrl();
211
+ await evaluateInAut(`location.href = ${JSON.stringify(url)}`);
212
+ const landed = await pollUntil(async () => {
213
+ const snap = await snapshot();
214
+ if (snap.readyState !== 'complete')
215
+ return undefined;
216
+ if (snap.url === before && snap.url !== url)
217
+ return undefined;
218
+ // 同 URL 的显式 re-goto 场景:URL 不变时直接以 readyState 为准
219
+ return snap;
220
+ }, timeout);
221
+ if (!landed) {
222
+ throw new Error(`[cypress-engine] 导航超时(${timeout}ms):${url}`);
223
+ }
224
+ }
225
+ /** 刷新当前 AUT 页面(在 AUT context 内 reload,绝不碰 runner) */
226
+ async function reload(timeout = 30000) {
227
+ const before = await currentUrl();
228
+ await evaluateInAut('location.reload()').catch(() => { });
229
+ const landed = await pollUntil(async () => {
230
+ const snap = await snapshot();
231
+ if (snap.readyState !== 'complete')
232
+ return undefined;
233
+ // reload 后 URL 不变,只能等 frame 重建后的 complete
234
+ return snap.url === before ? snap : undefined;
235
+ }, timeout, 200);
236
+ if (!landed)
237
+ throw new Error(`[cypress-engine] 刷新超时(${timeout}ms)`);
238
+ }
239
+ /** AUT 截图(裁剪到 iframe 区域,得到不含 runner chrome 的图) */
240
+ async function autRect() {
241
+ return await evaluateInRunner(`(() => {
242
+ var f = document.querySelector('iframe.aut-iframe');
243
+ if (!f) return null;
244
+ var b = f.getBoundingClientRect();
245
+ return { x: Math.round(b.x), y: Math.round(b.y), w: Math.round(b.width), h: Math.round(b.height) };
246
+ })()`);
247
+ }
248
+ /** AUT 截图(裁剪到 iframe 区域,得到不含 runner chrome 的图) */
249
+ async function screenshot() {
250
+ const rect = await autRect();
251
+ const shot = rect
252
+ ? await send('Page.captureScreenshot', {
253
+ format: 'png',
254
+ clip: { x: rect.x, y: rect.y, width: rect.w, height: rect.h, scale: 1 },
255
+ })
256
+ : await send('Page.captureScreenshot', { format: 'png' });
257
+ return String(shot?.data || '');
258
+ }
259
+ /**
260
+ * 元素级截图:`clip` 是 AUT 视口坐标(getBoundingClientRect 的 x/y/width/height),
261
+ * 这里叠加 AUT iframe 在 runner 顶层页里的偏移与顶层滚动量,得到
262
+ * Page.captureScreenshot 需要的顶层页面坐标。
263
+ */
264
+ async function screenshotClip(clip) {
265
+ const rect = await autRect();
266
+ const scroll = await evaluateInRunner('({ x: window.scrollX || 0, y: window.scrollY || 0 })').catch(() => ({ x: 0, y: 0 }));
267
+ const shot = await send('Page.captureScreenshot', {
268
+ format: 'png',
269
+ clip: {
270
+ x: clip.x + (rect?.x || 0) + (scroll?.x || 0),
271
+ y: clip.y + (rect?.y || 0) + (scroll?.y || 0),
272
+ width: Math.max(1, clip.width),
273
+ height: Math.max(1, clip.height),
274
+ scale: 1,
275
+ },
276
+ });
277
+ return String(shot?.data || '');
278
+ }
279
+ /** 注入浏览器侧定位器源码(幂等) */
280
+ async function injectLocator(source) {
281
+ await evaluateInAut(source);
282
+ }
283
+ /**
284
+ * 注册新文档预加载脚本(主世界)。
285
+ *
286
+ * Cypress 的 isolated world 只能访问 AUT 的独立执行上下文,改不了主世界里应用
287
+ * 依赖的 `window.*`。要兜底像 `requestAnimationFrame` 这类 DOM 运行时 API,
288
+ * 必须在每次新文档创建前注册到主世界,确保应用脚本执行前已就位。
289
+ */
290
+ async function installPreloadScript(source) {
291
+ await send('Page.addScriptToEvaluateOnNewDocument', { source });
292
+ }
293
+ async function ensureLocator() {
294
+ const ok = await evaluateInAut('Boolean(window.__keveLocator && window.__keveLocatorSource === "v1")');
295
+ if (!ok) {
296
+ const { locatorSource } = await Promise.resolve().then(() => __importStar(require('../dsl/locatorSource.js')));
297
+ await injectLocator(locatorSource());
298
+ }
299
+ }
300
+ async function setCookie(cookie) {
301
+ await send('Network.setCookie', {
302
+ name: cookie.name,
303
+ value: cookie.value,
304
+ domain: cookie.domain,
305
+ path: cookie.path || '/',
306
+ secure: cookie.secure,
307
+ httpOnly: cookie.httpOnly,
308
+ expires: cookie.expires,
309
+ });
310
+ }
311
+ /** AUT 可访问性树(仅 AUT,主会话调用拿到的是 runner UI) */
312
+ async function axTree() {
313
+ const frame = await autFrame();
314
+ const res = await send('Accessibility.getFullAXTree', { frameId: frame.id });
315
+ return Array.isArray(res?.nodes) ? res.nodes : [];
316
+ }
317
+ return {
318
+ send,
319
+ frames,
320
+ autFrame,
321
+ context,
322
+ evaluateInAut,
323
+ evaluateInFrame,
324
+ evaluateInRunner,
325
+ snapshot,
326
+ currentUrl,
327
+ goto,
328
+ reload,
329
+ autRect,
330
+ screenshot,
331
+ screenshotClip,
332
+ injectLocator,
333
+ installPreloadScript,
334
+ ensureLocator,
335
+ setCookie,
336
+ axTree,
337
+ invalidateWorld: () => { cachedWorld = null; },
338
+ };
339
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * host — 把 Cypress 的 describe/it 适配成 KeveHost
3
+ *
4
+ * 关键约束(探针结论,见 EVE/docs/cypress-engine-cdp-findings.md):
5
+ * 1. 用例体整体跑在 `cy.then({ timeout }, async () => …)` 内,内部**零 cy 命令**,
6
+ * 全靠 CDP + 原生 DOM。默认 cy.then 超时只有 4000ms,必须显式放大。
7
+ * 2. 必须先 `cy.visit(base)` 把 AUT iframe 建起来,否则 CDP 找不到 frame。
8
+ * 3. `cy.task` 在 async cy.then 内不可 await —— Node 侧能力一律走 HTTP 桥。
9
+ *
10
+ * 这样同一份 @keveModel/@keveScene 脚本在 Playwright 与 Cypress 下注册出的
11
+ * 场景元数据完全一致,报告才能同构。
12
+ */
13
+ import type { KeveHost } from '../core/decorator/keve-host.js';
14
+ import { CypressEngine } from './adapter.js';
15
+ import type { KeveGoalCallOptions } from './keveGoal.js';
16
+ /** AUT 打底 URL:优先 cypress.config baseUrl,其次 KEVE_TARGET_URL */
17
+ export declare function resolveBaseUrl(): string;
18
+ export declare function createCypressEngine(bridge?: import("./adapter.js").Bridge): CypressEngine;
19
+ export declare function installCypressHost(): KeveHost;
20
+ /** 模块级前置校验的跳过原因(供 reporter 归因展示) */
21
+ export declare function getBlockedReason(suiteTitle: string): string | undefined;
22
+ export type { KeveGoalCallOptions };