@cmmd-center/forge 0.13.29 → 0.13.31

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 (44) hide show
  1. package/dist/{BunHttpServer-C0oPP_3A.cjs → BunHttpServer-CXndtc1j.cjs} +2 -2
  2. package/dist/{BunHttpServer-FbbQmsl_.mjs → BunHttpServer-DjilmGOM.mjs} +2 -2
  3. package/dist/{BunPTY-uyreNRGp.cjs → BunPTY-BiTlUj63.cjs} +1 -1
  4. package/dist/{BunPTY-DkAIzLIx.mjs → BunPTY-Csgwhbi5.mjs} +1 -1
  5. package/dist/{BunServices-DC7nhA3w.mjs → BunServices-BZKzHdrG.mjs} +1 -1
  6. package/dist/{BunServices-DkenwD7S.cjs → BunServices-DsWG7VM1.cjs} +1 -1
  7. package/dist/{NodeHttpServer-Cjd3bFrD.cjs → NodeHttpServer-B4dCKqYY.cjs} +1 -1
  8. package/dist/{NodeHttpServer-BJ4l15f-.mjs → NodeHttpServer-Ds3Gp1Gp.mjs} +1 -1
  9. package/dist/{NodePTY-BehazUMi.cjs → NodePTY-BJ7874MO.cjs} +1 -1
  10. package/dist/{NodePTY-BhezYy9H.mjs → NodePTY-DgXWLtWp.mjs} +1 -1
  11. package/dist/{NodeSqliteClient-CfsdC3AB.cjs → NodeSqliteClient-CPsJxxdD.cjs} +1 -1
  12. package/dist/{NodeSqliteClient-md8xd9hY.mjs → NodeSqliteClient-D29w60zZ.mjs} +1 -1
  13. package/dist/{SqliteClient-BKB695RF.mjs → SqliteClient-Bgo_s5sA.mjs} +1 -1
  14. package/dist/{SqliteClient-O1ABIngw.cjs → SqliteClient-k0pbfeIC.cjs} +1 -1
  15. package/dist/bin.cjs +1879 -2378
  16. package/dist/bin.mjs +1876 -2375
  17. package/dist/client/assets/{DiffPanel-CsYeFcEd.js → DiffPanel-rxdARnAn.js} +2 -2
  18. package/dist/client/assets/{DiffPanel.logic-BhrQueD8.js → DiffPanel.logic-pioWZtAT.js} +2 -2
  19. package/dist/client/assets/{DiffPanelShell-CssAtWUC.js → DiffPanelShell-CJre8MyV.js} +3 -3
  20. package/dist/client/assets/{DiffWorkerPoolProvider-C0iUCn9m.js → DiffWorkerPoolProvider-BoinSMK1.js} +2 -2
  21. package/dist/client/assets/{PullRequestCodePanel-O-XZJVnK.js → PullRequestCodePanel-BR0xA-je.js} +2 -2
  22. package/dist/client/assets/{Virtualizer-Z2t67-w7.js → Virtualizer-H0mi-vRc.js} +2 -2
  23. package/dist/client/assets/{index-AMVPSS6N.js → index-DQtjHxYt.js} +6 -6
  24. package/dist/client/index.html +4 -4
  25. package/dist/{execAsync-BUcaFQ1D.cjs → execAsync--H9ZZOiC.cjs} +1 -1
  26. package/dist/{execAsync-BNNdR88o.mjs → execAsync-BJ4g1UuR.mjs} +1 -1
  27. package/dist/forge-build.json +1 -1
  28. package/dist/{getMachineId-bsd-3FzKrfVS.cjs → getMachineId-bsd-CJJWgsvW.cjs} +2 -2
  29. package/dist/{getMachineId-bsd-BuYwT36r.mjs → getMachineId-bsd-CvzjzhCJ.mjs} +2 -2
  30. package/dist/{getMachineId-darwin-RZKhGQ6C.mjs → getMachineId-darwin-BkjZ6NK7.mjs} +2 -2
  31. package/dist/{getMachineId-darwin-J2wNbebX.cjs → getMachineId-darwin-hZeIAq-t.cjs} +2 -2
  32. package/dist/{getMachineId-linux-BDLTrARB.cjs → getMachineId-linux-B4Pn5gp9.cjs} +1 -1
  33. package/dist/{getMachineId-linux-D5HSP0rH.mjs → getMachineId-linux-BaBxzaf3.mjs} +1 -1
  34. package/dist/{getMachineId-unsupported-DRh5MFwr.cjs → getMachineId-unsupported-B3jtoOL0.cjs} +1 -1
  35. package/dist/{getMachineId-unsupported-IaplPZnC.mjs → getMachineId-unsupported-EhCzrOph.mjs} +1 -1
  36. package/dist/{getMachineId-win-D220ursp.mjs → getMachineId-win-BFwtIsaZ.mjs} +2 -2
  37. package/dist/{getMachineId-win-BA8dHcjg.cjs → getMachineId-win-Bb4lJE8e.cjs} +2 -2
  38. package/dist/{open-D8mGyWmt.mjs → open-2-reBrpv.mjs} +1 -1
  39. package/dist/{open-BAsPVCWX.cjs → open-CghsF25U.cjs} +1 -1
  40. package/dist/playwright-backend-BONxTCSA.cjs +643 -0
  41. package/dist/playwright-backend-DVQOhqRO.mjs +642 -0
  42. package/dist/settle-B6Rn65UV.cjs +28 -0
  43. package/dist/settle-BJcmpbvq.mjs +23 -0
  44. package/package.json +1 -1
@@ -0,0 +1,643 @@
1
+ #!/usr/bin/env node
2
+
3
+ require("./chunk-BhaIgcZK.cjs");
4
+ const require_settle = require("./settle-B6Rn65UV.cjs");
5
+ let node_crypto = require("node:crypto");
6
+ let playwright = require("playwright");
7
+ //#region ../../node_modules/.bun/@cmmd-center+agent-browser@0.6.2+69e331b0475d65dc/node_modules/@cmmd-center/agent-browser/dist/backends/playwright-locators.js
8
+ function locatorForAction(page, action) {
9
+ return action.query ? locatorFromQuery(page, action.query) : page.locator(action.selector ?? "");
10
+ }
11
+ function locatorFromQuery(page, query) {
12
+ switch (query.kind) {
13
+ case "and": return locatorFromQuery(page, query.left).and(locatorFromQuery(page, query.right));
14
+ case "css": return page.locator(query.selector);
15
+ case "filter": return locatorFromQuery(page, query.base).filter(filterOptions(page, query.options));
16
+ case "first": return locatorFromQuery(page, query.base).first();
17
+ case "frame": return locatorInFrame(page, page.frameLocator(query.selector), query.child);
18
+ case "label": return page.getByLabel(query.text, query.options);
19
+ case "last": return locatorFromQuery(page, query.base).last();
20
+ case "locator": return locatorFromQuery(page, query.base).locator(query.selector, filterOptions(page, query.options));
21
+ case "nth": return locatorFromQuery(page, query.base).nth(query.index);
22
+ case "or": return locatorFromQuery(page, query.left).or(locatorFromQuery(page, query.right));
23
+ case "placeholder": return page.getByPlaceholder(query.text, query.options);
24
+ case "role": return page.getByRole(query.role, query.options);
25
+ case "testId": return page.getByTestId(query.testId);
26
+ case "text": return page.getByText(query.text, query.options);
27
+ }
28
+ }
29
+ function locatorInFrame(page, frame, query) {
30
+ switch (query.kind) {
31
+ case "css": return frame.locator(query.selector);
32
+ case "filter": return locatorInFrame(page, frame, query.base).filter(filterOptions(page, query.options));
33
+ case "first": return locatorInFrame(page, frame, query.base).first();
34
+ case "label": return frame.getByLabel(query.text, query.options);
35
+ case "last": return locatorInFrame(page, frame, query.base).last();
36
+ case "locator": return locatorInFrame(page, frame, query.base).locator(query.selector, filterOptions(page, query.options));
37
+ case "nth": return locatorInFrame(page, frame, query.base).nth(query.index);
38
+ case "placeholder": return frame.getByPlaceholder(query.text, query.options);
39
+ case "role": return frame.getByRole(query.role, query.options);
40
+ case "testId": return frame.getByTestId(query.testId);
41
+ case "text": return frame.getByText(query.text, query.options);
42
+ case "and":
43
+ case "frame":
44
+ case "or": throw new Error(`Unsupported frame locator query kind: ${query.kind}`);
45
+ }
46
+ }
47
+ function filterOptions(page, options) {
48
+ if (!options) return void 0;
49
+ return {
50
+ ...options.has === void 0 ? {} : { has: locatorFromQuery(page, options.has) },
51
+ ...options.hasNot === void 0 ? {} : { hasNot: locatorFromQuery(page, options.hasNot) },
52
+ ...options.hasNotText === void 0 ? {} : { hasNotText: options.hasNotText },
53
+ ...options.hasText === void 0 ? {} : { hasText: options.hasText }
54
+ };
55
+ }
56
+ //#endregion
57
+ //#region ../../node_modules/.bun/@cmmd-center+agent-browser@0.6.2+69e331b0475d65dc/node_modules/@cmmd-center/agent-browser/dist/backends/playwright-backend.js
58
+ const TAB_METADATA_TIMEOUT_MS = 250;
59
+ const TAB_CONTROL_TIMEOUT_MS = 500;
60
+ var PlaywrightBackend = class {
61
+ options;
62
+ browser;
63
+ context;
64
+ pageIds = /* @__PURE__ */ new WeakMap();
65
+ logs = /* @__PURE__ */ new WeakMap();
66
+ registeredPages = /* @__PURE__ */ new WeakSet();
67
+ constructor(options = {}) {
68
+ this.options = options;
69
+ }
70
+ info() {
71
+ return {
72
+ id: "playwright",
73
+ kind: "playwright",
74
+ name: this.options.name ?? "Playwright Chromium"
75
+ };
76
+ }
77
+ async close() {
78
+ /* v8 ignore next -- defensive cleanup for already-closed Playwright contexts. */
79
+ await this.context?.close().catch(() => void 0);
80
+ await this.browser?.close();
81
+ this.browser = void 0;
82
+ this.context = void 0;
83
+ }
84
+ async listTabs() {
85
+ const context = await this.getContext();
86
+ return Promise.all(context.pages().map((page) => this.toTab(page).info()));
87
+ }
88
+ async selectedTab() {
89
+ const page = (await this.getContext()).pages().at(-1);
90
+ if (page) await require_settle.settleValueWithin(page.bringToFront(), TAB_CONTROL_TIMEOUT_MS);
91
+ return page ? this.toTab(page) : void 0;
92
+ }
93
+ async newTab() {
94
+ const page = await (await this.getContext()).newPage();
95
+ await this.preparePage(page);
96
+ await require_settle.settleValueWithin(page.bringToFront(), TAB_CONTROL_TIMEOUT_MS);
97
+ return this.toTab(page);
98
+ }
99
+ async getTab(id) {
100
+ const page = (await this.getContext()).pages().find((candidate) => this.idFor(candidate) === id);
101
+ if (!page) throw new Error(`Tab not found: ${id}`);
102
+ await require_settle.settleValueWithin(page.bringToFront(), TAB_CONTROL_TIMEOUT_MS);
103
+ return this.toTab(page);
104
+ }
105
+ async getContext() {
106
+ /* v8 ignore next -- persistent headed/default launch combinations are covered by smoke, not unit coverage. */
107
+ if (this.options.userDataDir && !this.context) {
108
+ this.context = await playwright.chromium.launchPersistentContext(this.options.userDataDir, {
109
+ ...this.options.launchOptions,
110
+ ...this.options.contextOptions,
111
+ headless: this.options.headless ?? false
112
+ });
113
+ this.browser = this.context.browser() ?? void 0;
114
+ return this.context;
115
+ }
116
+ /* v8 ignore next -- requires a live externally managed Chrome CDP endpoint */
117
+ if (!this.browser && this.options.cdpEndpoint) {
118
+ /* v8 ignore start -- requires a live externally managed Chrome CDP endpoint */
119
+ this.browser = await playwright.chromium.connectOverCDP(this.options.cdpEndpoint);
120
+ this.context = this.browser.contexts()[0] ?? await this.browser.newContext(this.options.contextOptions);
121
+ return this.context;
122
+ }
123
+ /* v8 ignore next -- headed/default launch is covered by browser parity smoke. */
124
+ if (!this.browser) this.browser = await playwright.chromium.launch({
125
+ ...this.options.launchOptions,
126
+ headless: this.options.headless ?? false
127
+ });
128
+ if (!this.context) this.context = await this.browser.newContext(this.options.contextOptions);
129
+ return this.context;
130
+ }
131
+ toTab(page) {
132
+ this.registerPage(page);
133
+ return new PlaywrightTabHandle(page, this.idFor(page), this.logsFor(page));
134
+ }
135
+ async preparePage(page) {
136
+ this.registerPage(page);
137
+ const bounds = this.options.windowBounds;
138
+ if (!bounds) return;
139
+ await require_settle.settleValueWithin(page.setViewportSize({
140
+ width: bounds.width,
141
+ height: bounds.height
142
+ }), TAB_CONTROL_TIMEOUT_MS);
143
+ const sessionResult = await require_settle.settleValueWithin(page.context().newCDPSession(page), TAB_CONTROL_TIMEOUT_MS);
144
+ /* v8 ignore next -- Playwright CDP attachment failures are bounded and covered by the shared timeout primitive. */
145
+ if (sessionResult.status !== "fulfilled") return;
146
+ const session = sessionResult.value;
147
+ try {
148
+ const windowResult = await require_settle.settleValueWithin(session.send("Browser.getWindowForTarget"), TAB_CONTROL_TIMEOUT_MS);
149
+ /* v8 ignore next -- Chromium may decline window control in unsupported headless/CDP environments. */
150
+ if (windowResult.status !== "fulfilled" || typeof windowResult.value.windowId !== "number") return;
151
+ await require_settle.settleValueWithin(session.send("Browser.setWindowBounds", {
152
+ bounds: {
153
+ height: bounds.height,
154
+ left: bounds.left ?? 0,
155
+ top: bounds.top ?? 0,
156
+ width: bounds.width,
157
+ windowState: "normal"
158
+ },
159
+ windowId: windowResult.value.windowId
160
+ }), TAB_CONTROL_TIMEOUT_MS);
161
+ } finally {
162
+ await require_settle.settleValueWithin(session.detach(), TAB_CONTROL_TIMEOUT_MS);
163
+ }
164
+ }
165
+ registerPage(page) {
166
+ this.idFor(page);
167
+ this.logsFor(page);
168
+ if (this.registeredPages.has(page)) return;
169
+ this.registeredPages.add(page);
170
+ page.on("console", (message) => {
171
+ this.logsFor(page).push(toConsoleLog(message, page.url()));
172
+ });
173
+ }
174
+ idFor(page) {
175
+ let id = this.pageIds.get(page);
176
+ if (!id) {
177
+ id = `tab_${(0, node_crypto.randomUUID)()}`;
178
+ this.pageIds.set(page, id);
179
+ }
180
+ return id;
181
+ }
182
+ logsFor(page) {
183
+ let entries = this.logs.get(page);
184
+ if (!entries) {
185
+ entries = [];
186
+ this.logs.set(page, entries);
187
+ }
188
+ return entries;
189
+ }
190
+ };
191
+ var PlaywrightTabHandle = class {
192
+ page;
193
+ id;
194
+ logEntries;
195
+ constructor(page, id, logEntries) {
196
+ this.page = page;
197
+ this.id = id;
198
+ this.logEntries = logEntries;
199
+ }
200
+ async info() {
201
+ const [title, history] = await Promise.all([require_settle.settleValueWithin(this.page.title(), TAB_METADATA_TIMEOUT_MS), require_settle.settleValueWithin(this.historyState(), TAB_METADATA_TIMEOUT_MS)]);
202
+ const base = title.status !== "fulfilled" ? {
203
+ id: this.id,
204
+ url: this.page.url()
205
+ } : {
206
+ id: this.id,
207
+ title: title.value,
208
+ url: this.page.url()
209
+ };
210
+ /* v8 ignore next -- metadata timeout fallback is covered through AgentBrowser's bounded observation contract. */
211
+ return history.status === "fulfilled" ? {
212
+ ...base,
213
+ ...history.value
214
+ } : base;
215
+ }
216
+ async historyState() {
217
+ const sessionResult = await require_settle.settleValueWithin(this.page.context().newCDPSession(this.page), TAB_METADATA_TIMEOUT_MS);
218
+ /* v8 ignore next -- Playwright CDP attachment failures are bounded and covered by the shared timeout primitive. */
219
+ if (sessionResult.status !== "fulfilled") return {};
220
+ const session = sessionResult.value;
221
+ try {
222
+ const historyResult = await require_settle.settleValueWithin(session.send("Page.getNavigationHistory"), TAB_METADATA_TIMEOUT_MS);
223
+ /* v8 ignore next -- Chromium navigation-history failures are bounded external CDP behavior. */
224
+ if (historyResult.status !== "fulfilled") return {};
225
+ const history = historyResult.value;
226
+ return {
227
+ canGoBack: history.currentIndex > 0,
228
+ canGoForward: history.currentIndex < history.entries.length - 1
229
+ };
230
+ } finally {
231
+ await require_settle.settleValueWithin(session.detach(), TAB_METADATA_TIMEOUT_MS);
232
+ }
233
+ }
234
+ async goto(url) {
235
+ await this.page.goto(url, { waitUntil: "domcontentloaded" });
236
+ }
237
+ async reload() {
238
+ await this.page.reload({ waitUntil: "domcontentloaded" });
239
+ }
240
+ async forceReload() {
241
+ const client = await this.page.context().newCDPSession(this.page);
242
+ try {
243
+ await client.send("Page.reload", { ignoreCache: true });
244
+ /* v8 ignore next -- defensive fallback for navigations that do not settle after CDP reload. */
245
+ await this.page.waitForLoadState("domcontentloaded", { timeout: 3e4 }).catch(() => void 0);
246
+ } finally {
247
+ await client.detach();
248
+ }
249
+ }
250
+ async back() {
251
+ await this.page.goBack({ waitUntil: "domcontentloaded" });
252
+ }
253
+ async forward() {
254
+ await this.page.goForward({ waitUntil: "domcontentloaded" });
255
+ }
256
+ async close() {
257
+ await this.page.close();
258
+ }
259
+ async screenshot(options = {}) {
260
+ const bytes = await this.page.screenshot({
261
+ ...options.fullPage === void 0 ? {} : { fullPage: options.fullPage },
262
+ ...options.clip === void 0 ? {} : { clip: options.clip },
263
+ ...options.mimeType === void 0 ? {} : { type: options.mimeType === "image/jpeg" ? "jpeg" : "png" },
264
+ ...options.quality === void 0 ? {} : { quality: options.quality }
265
+ });
266
+ if (options.maxBytes !== void 0 && bytes.byteLength > options.maxBytes) throw new Error(`Browser screenshot exceeded maxBytes=${options.maxBytes}. size=${bytes.byteLength}`);
267
+ return bytes;
268
+ }
269
+ async setViewport(size) {
270
+ await this.page.setViewportSize({
271
+ width: Math.round(size.width),
272
+ height: Math.round(size.height)
273
+ });
274
+ }
275
+ async setZoom(zoom) {
276
+ /* v8 ignore next 3 -- browser-executed callback runs outside Node coverage */
277
+ await this.page.evaluate((level) => {
278
+ document.documentElement.style.zoom = String(level);
279
+ }, zoom.level);
280
+ }
281
+ async clearCookies() {
282
+ await this.page.context().clearCookies();
283
+ }
284
+ async clearCache() {
285
+ const client = await this.page.context().newCDPSession(this.page);
286
+ try {
287
+ await client.send("Network.clearBrowserCache");
288
+ } finally {
289
+ await client.detach();
290
+ }
291
+ }
292
+ async domSnapshot() {
293
+ return this.page.locator("body").ariaSnapshot({ timeout: 5e3 });
294
+ }
295
+ async evaluate(expression, arg) {
296
+ /* v8 ignore next 4 -- browser-executed callback runs outside Node coverage */
297
+ return this.page.evaluate((input) => {
298
+ return new Function("arg", `return (${input.expression})(arg);`)(input.arg);
299
+ }, {
300
+ arg,
301
+ expression
302
+ });
303
+ }
304
+ async waitForLoadState(state = "load", timeoutMs) {
305
+ await this.page.waitForLoadState(state, timeoutOptions(timeoutMs));
306
+ }
307
+ async waitForURL(url, timeoutMs) {
308
+ await this.page.waitForURL(url, timeoutOptions(timeoutMs));
309
+ }
310
+ async waitForDownload(timeoutMs) {
311
+ return toBrowserDownload(await this.page.waitForEvent("download", timeoutOptions(timeoutMs)));
312
+ }
313
+ async elementInfo(options) {
314
+ /* v8 ignore start -- browser-executed DOM inspection runs outside Node coverage */
315
+ return this.page.evaluate(({ x, y, includeNonInteractable }) => {
316
+ const element = document.elementFromPoint(x, y);
317
+ if (!element || element === document.documentElement || element === document.body) return;
318
+ const rect = element.getBoundingClientRect();
319
+ if (rect.width <= 0 || rect.height <= 0) return;
320
+ const style = window.getComputedStyle(element);
321
+ if (!includeNonInteractable && (style.visibility === "hidden" || style.display === "none" || style.pointerEvents === "none")) return;
322
+ const tagName = element.tagName.toLowerCase();
323
+ const visibleText = visibleElementText(element);
324
+ const ariaName = element.getAttribute("aria-label") ?? element.getAttribute("alt") ?? void 0;
325
+ const role = element.getAttribute("role") ?? inferRole(element);
326
+ const candidates = selectorCandidates(element);
327
+ const testId = element.getAttribute("data-testid") ?? element.getAttribute("data-test-id") ?? void 0;
328
+ const nodeId = ensureNodeId(element);
329
+ const preview = compactText(`${tagName}${role ? ` role=${role}` : ""}${ariaName ? ` aria="${ariaName}"` : ""}${visibleText ? ` text="${visibleText}"` : ""}`);
330
+ return {
331
+ ...ariaName ? { ariaName } : {},
332
+ boundingBox: {
333
+ x: rect.x,
334
+ y: rect.y,
335
+ width: rect.width,
336
+ height: rect.height
337
+ },
338
+ nodeId,
339
+ preview,
340
+ ...role ? { role } : {},
341
+ selector: {
342
+ candidates,
343
+ primary: candidates[0] ?? null
344
+ },
345
+ tagName,
346
+ ...testId ? { testId } : {},
347
+ ...visibleText ? { visibleText } : {}
348
+ };
349
+ function compactText(value) {
350
+ return value.replace(/\s+/g, " ").trim().slice(0, 180);
351
+ }
352
+ function visibleElementText(node) {
353
+ if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) return compactText(node.value || node.placeholder || "");
354
+ if (node instanceof HTMLSelectElement) return compactText(node.selectedOptions[0]?.textContent ?? node.value);
355
+ return compactText(node.textContent ?? "") || void 0;
356
+ }
357
+ function inferRole(node) {
358
+ if (node instanceof HTMLAnchorElement && node.href) return "link";
359
+ if (node instanceof HTMLButtonElement) return "button";
360
+ if (node instanceof HTMLInputElement) return node.type || "textbox";
361
+ if (node instanceof HTMLSelectElement) return "combobox";
362
+ if (node instanceof HTMLTextAreaElement) return "textbox";
363
+ if (/^h[1-6]$/i.test(node.tagName)) return "heading";
364
+ }
365
+ function ensureNodeId(node) {
366
+ const existing = node.getAttribute("data-agent-browser-node-id");
367
+ if (existing) return Number(existing);
368
+ const next = Number(document.documentElement.getAttribute("data-agent-browser-next-node-id") ?? "1");
369
+ document.documentElement.setAttribute("data-agent-browser-next-node-id", String(next + 1));
370
+ node.setAttribute("data-agent-browser-node-id", String(next));
371
+ return next;
372
+ }
373
+ function selectorCandidates(node) {
374
+ const candidates = [];
375
+ if (node.id) candidates.push(`#${cssEscape(node.id)}`);
376
+ const testId = node.getAttribute("data-testid") ?? node.getAttribute("data-test-id");
377
+ if (testId) candidates.push(`[data-testid="${cssString(testId)}"]`);
378
+ const href = node.getAttribute("href");
379
+ if (href) candidates.push(`${node.tagName.toLowerCase()}[href="${cssString(href)}"]`);
380
+ const aria = node.getAttribute("aria-label");
381
+ if (aria) candidates.push(`${node.tagName.toLowerCase()}[aria-label="${cssString(aria)}"]`);
382
+ const name = node.getAttribute("name");
383
+ if (name) candidates.push(`${node.tagName.toLowerCase()}[name="${cssString(name)}"]`);
384
+ const parts = [];
385
+ let current = node;
386
+ while (current && current !== document.body && current !== document.documentElement && parts.length < 5) {
387
+ let part = current.tagName.toLowerCase();
388
+ const name = current.getAttribute("name");
389
+ if (name) part += `[name="${cssString(name)}"]`;
390
+ else {
391
+ const className = Array.from(current.classList).find(Boolean);
392
+ if (className) part += `.${cssEscape(className)}`;
393
+ }
394
+ const parent = current.parentElement;
395
+ if (parent) {
396
+ const siblings = Array.from(parent.children).filter((sibling) => sibling.tagName === current?.tagName);
397
+ if (siblings.length > 1) part += `:nth-of-type(${siblings.indexOf(current) + 1})`;
398
+ }
399
+ parts.unshift(part);
400
+ const candidate = parts.join(" > ");
401
+ if (document.querySelectorAll(candidate).length === 1) {
402
+ candidates.push(candidate);
403
+ break;
404
+ }
405
+ current = parent;
406
+ }
407
+ const fallback = parts.join(" > ") || node.tagName.toLowerCase();
408
+ candidates.push(fallback);
409
+ return Array.from(new Set(candidates));
410
+ }
411
+ function cssEscape(value) {
412
+ return CSS.escape(value);
413
+ }
414
+ function cssString(value) {
415
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
416
+ }
417
+ }, options);
418
+ /* v8 ignore stop */
419
+ }
420
+ async elementScreenshot(options) {
421
+ const element = await this.elementInfo(options);
422
+ if (!element?.boundingBox) return void 0;
423
+ return this.screenshot({ clip: element.boundingBox });
424
+ }
425
+ async click(action) {
426
+ const locator = this.locatorFor(action);
427
+ await assertSingle(locator.count(), locatorActionLabel(action));
428
+ await locator.click(timeoutOptions(action.timeoutMs));
429
+ }
430
+ async doubleClick(action) {
431
+ const locator = this.locatorFor(action);
432
+ await assertSingle(locator.count(), locatorActionLabel(action));
433
+ await locator.dblclick(timeoutOptions(action.timeoutMs));
434
+ }
435
+ async fill(action, value) {
436
+ const locator = this.locatorFor(action);
437
+ await assertSingle(locator.count(), locatorActionLabel(action));
438
+ await locator.fill(value, timeoutOptions(action.timeoutMs));
439
+ }
440
+ async type(action, value) {
441
+ const locator = this.locatorFor(action);
442
+ await assertSingle(locator.count(), locatorActionLabel(action));
443
+ await locator.pressSequentially(value, timeoutOptions(action.timeoutMs));
444
+ }
445
+ async press(action, key) {
446
+ const locator = this.locatorFor(action);
447
+ await assertSingle(locator.count(), locatorActionLabel(action));
448
+ await locator.press(key, timeoutOptions(action.timeoutMs));
449
+ }
450
+ async select(action, value) {
451
+ const locator = this.locatorFor(action);
452
+ await assertSingle(locator.count(), locatorActionLabel(action));
453
+ await locator.selectOption(value, timeoutOptions(action.timeoutMs));
454
+ }
455
+ async check(action, checked) {
456
+ const locator = this.locatorFor(action);
457
+ await assertSingle(locator.count(), locatorActionLabel(action));
458
+ await locator.setChecked(checked, timeoutOptions(action.timeoutMs));
459
+ }
460
+ async text(action) {
461
+ const locator = this.locatorFor(action);
462
+ await assertSingle(locator.count(), locatorActionLabel(action));
463
+ return locator.textContent(timeoutOptions(action.timeoutMs));
464
+ }
465
+ async innerText(action) {
466
+ const locator = this.locatorFor(action);
467
+ await assertSingle(locator.count(), locatorActionLabel(action));
468
+ return locator.innerText(timeoutOptions(action.timeoutMs));
469
+ }
470
+ async allTextContents(action) {
471
+ return this.locatorFor(action).allTextContents();
472
+ }
473
+ async attribute(action, name) {
474
+ const locator = this.locatorFor(action);
475
+ await assertSingle(locator.count(), locatorActionLabel(action));
476
+ return locator.getAttribute(name, timeoutOptions(action.timeoutMs));
477
+ }
478
+ async isVisible(action) {
479
+ const locator = this.locatorFor(action);
480
+ await assertSingle(locator.count(), locatorActionLabel(action));
481
+ return locator.isVisible(timeoutOptions(action.timeoutMs));
482
+ }
483
+ async isEnabled(action) {
484
+ const locator = this.locatorFor(action);
485
+ await assertSingle(locator.count(), locatorActionLabel(action));
486
+ return locator.isEnabled(timeoutOptions(action.timeoutMs));
487
+ }
488
+ async locatorCount(action) {
489
+ return this.locatorFor(action).count();
490
+ }
491
+ async waitForLocator(action, state) {
492
+ await this.locatorFor(action).waitFor({
493
+ ...state === void 0 ? {} : { state },
494
+ ...timeoutOptions(action.timeoutMs)
495
+ });
496
+ }
497
+ async cuaMove(point) {
498
+ await this.page.mouse.move(point.x, point.y);
499
+ }
500
+ async cuaClick(point) {
501
+ await this.page.mouse.click(point.x, point.y, { button: mouseButton(point.button) });
502
+ }
503
+ async cuaDoubleClick(point) {
504
+ await this.page.mouse.dblclick(point.x, point.y);
505
+ }
506
+ async cuaDrag(path) {
507
+ const [start, ...rest] = path;
508
+ if (!start) return;
509
+ await this.page.mouse.move(start.x, start.y);
510
+ await this.page.mouse.down();
511
+ for (const point of rest) await this.page.mouse.move(point.x, point.y);
512
+ await this.page.mouse.up();
513
+ }
514
+ async cuaScroll(input) {
515
+ await this.page.mouse.move(input.x, input.y);
516
+ await this.page.mouse.wheel(input.scrollX, input.scrollY);
517
+ }
518
+ async cuaType(text) {
519
+ await this.page.keyboard.type(text);
520
+ }
521
+ async cuaKeypress(keys) {
522
+ await this.page.keyboard.press(keys.join("+"));
523
+ }
524
+ async visibleDom() {
525
+ return this.page.evaluate(`(() => {
526
+ let nextId = Number(document.documentElement.getAttribute("data-agent-browser-next-node-id") || "1");
527
+ function walk(element) {
528
+ const rect = element.getBoundingClientRect();
529
+ const style = window.getComputedStyle(element);
530
+ if (rect.width <= 0 || rect.height <= 0 || style.display === "none" || style.visibility === "hidden") {
531
+ return undefined;
532
+ }
533
+ let nodeId = element.getAttribute("data-agent-browser-node-id");
534
+ if (!nodeId) {
535
+ nodeId = String(nextId++);
536
+ element.setAttribute("data-agent-browser-node-id", nodeId);
537
+ }
538
+ const tagName = element.tagName.toLowerCase();
539
+ const visibleText = (element.textContent ?? "").replace(/\s+/g, " ").trim().slice(0, 120) || undefined;
540
+ const role = element.getAttribute("role") ?? undefined;
541
+ const ariaName = element.getAttribute("aria-label") ?? undefined;
542
+ const children = Array.from(element.children).map(walk).filter(Boolean);
543
+ return {
544
+ ...(ariaName ? { ariaName } : {}),
545
+ boundingBox: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
546
+ ...(children.length ? { children } : {}),
547
+ nodeId,
548
+ preview: (tagName + (ariaName ? ' "' + ariaName + '"' : "") + (visibleText ? " " + visibleText : "")).slice(0, 180),
549
+ ...(role ? { role } : {}),
550
+ tagName,
551
+ ...(visibleText ? { visibleText } : {})
552
+ };
553
+ }
554
+ document.documentElement.setAttribute("data-agent-browser-next-node-id", String(nextId));
555
+ return walk(document.body) ?? { nodeId: "body", preview: "body", tagName: "body" };
556
+ })()`);
557
+ }
558
+ async domClick(nodeId) {
559
+ await this.byNodeId(nodeId).click();
560
+ }
561
+ async domDoubleClick(nodeId) {
562
+ await this.byNodeId(nodeId).dblclick();
563
+ }
564
+ async domScroll(input) {
565
+ if (input.nodeId) {
566
+ /* v8 ignore next -- browser-executed DOM callback runs outside Node coverage */
567
+ await this.byNodeId(input.nodeId).evaluate((element, delta) => element.scrollBy(delta.x, delta.y), {
568
+ x: input.x,
569
+ y: input.y
570
+ });
571
+ return;
572
+ }
573
+ await this.page.mouse.wheel(input.x, input.y);
574
+ }
575
+ async domType(text) {
576
+ await this.page.keyboard.type(text);
577
+ }
578
+ async domKeypress(keys) {
579
+ await this.page.keyboard.press(keys.join("+"));
580
+ }
581
+ async clipboardReadText() {
582
+ /* v8 ignore next -- browser-executed callback runs outside Node coverage */
583
+ return this.page.evaluate(() => navigator.clipboard.readText());
584
+ }
585
+ async clipboardWriteText(text) {
586
+ /* v8 ignore next -- browser-executed callback runs outside Node coverage */
587
+ await this.page.evaluate((value) => navigator.clipboard.writeText(value), text);
588
+ }
589
+ async logs(limit = 100) {
590
+ return this.logEntries.slice(-limit);
591
+ }
592
+ byNodeId(nodeId) {
593
+ return this.page.locator(`[data-agent-browser-node-id="${cssStringForSelector(nodeId)}"]`);
594
+ }
595
+ locatorFor(action) {
596
+ return locatorForAction(this.page, action);
597
+ }
598
+ };
599
+ function locatorActionLabel(action) {
600
+ /* v8 ignore next -- valid public calls always supply selector or query; malformed calls are rejected downstream. */
601
+ return action.selector ?? action.query?.kind ?? "locator";
602
+ }
603
+ function mouseButton(button) {
604
+ if (button === 2) return "middle";
605
+ if (button === 3) return "right";
606
+ return "left";
607
+ }
608
+ function cssStringForSelector(value) {
609
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
610
+ }
611
+ function timeoutOptions(timeoutMs) {
612
+ return timeoutMs === void 0 ? {} : { timeout: timeoutMs };
613
+ }
614
+ function toBrowserDownload(download) {
615
+ return {
616
+ failure: () => download.failure(),
617
+ path: () => download.path().catch(() => null),
618
+ saveAs: (path) => download.saveAs(path),
619
+ suggestedFilename: () => download.suggestedFilename(),
620
+ url: () => download.url()
621
+ };
622
+ }
623
+ async function assertSingle(countPromise, selector) {
624
+ const count = await countPromise;
625
+ if (count !== 1) throw new Error(`Selector must resolve to exactly one element. selector=${selector} count=${count}`);
626
+ }
627
+ function toConsoleLog(message, url) {
628
+ return {
629
+ level: normalizeLevel(message.type()),
630
+ message: message.text(),
631
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
632
+ url
633
+ };
634
+ }
635
+ function normalizeLevel(level) {
636
+ if (level === "debug" || level === "info" || level === "log" || level === "warn" || level === "error") return level;
637
+ /* v8 ignore next -- Playwright currently normalizes known console message types */
638
+ return "log";
639
+ }
640
+ //#endregion
641
+ exports.PlaywrightBackend = PlaywrightBackend;
642
+
643
+ //# sourceMappingURL=playwright-backend-BONxTCSA.cjs.map