playwriter 0.0.62 → 0.0.80

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 (216) hide show
  1. package/dist/aria-snapshot.d.ts +41 -3
  2. package/dist/aria-snapshot.d.ts.map +1 -1
  3. package/dist/aria-snapshot.js +131 -54
  4. package/dist/aria-snapshot.js.map +1 -1
  5. package/dist/aria-snapshot.test.js +5 -2
  6. package/dist/aria-snapshot.test.js.map +1 -1
  7. package/dist/aria-snapshot.unit.test.js +83 -41
  8. package/dist/aria-snapshot.unit.test.js.map +1 -1
  9. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +5 -0
  10. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +1 -0
  11. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +5 -0
  12. package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +1 -0
  13. package/dist/bippy.js +1 -1
  14. package/dist/cdp-log.d.ts +1 -1
  15. package/dist/cdp-log.d.ts.map +1 -1
  16. package/dist/cdp-log.js +1 -1
  17. package/dist/cdp-log.js.map +1 -1
  18. package/dist/cdp-relay.d.ts.map +1 -1
  19. package/dist/cdp-relay.js +465 -297
  20. package/dist/cdp-relay.js.map +1 -1
  21. package/dist/cdp-session.d.ts.map +1 -1
  22. package/dist/cdp-session.js.map +1 -1
  23. package/dist/cdp-types.d.ts.map +1 -1
  24. package/dist/cdp-types.js +7 -7
  25. package/dist/cdp-types.js.map +1 -1
  26. package/dist/clean-html.d.ts.map +1 -1
  27. package/dist/clean-html.js +4 -5
  28. package/dist/clean-html.js.map +1 -1
  29. package/dist/cli.js +70 -32
  30. package/dist/cli.js.map +1 -1
  31. package/dist/create-logger.d.ts.map +1 -1
  32. package/dist/create-logger.js +3 -1
  33. package/dist/create-logger.js.map +1 -1
  34. package/dist/debugger-examples-types.d.ts.map +1 -1
  35. package/dist/debugger.d.ts.map +1 -1
  36. package/dist/debugger.js +1 -3
  37. package/dist/debugger.js.map +1 -1
  38. package/dist/diff-utils.d.ts.map +1 -1
  39. package/dist/diff-utils.js +1 -4
  40. package/dist/diff-utils.js.map +1 -1
  41. package/dist/editor-api.md +12 -2
  42. package/dist/editor-examples.d.ts +1 -1
  43. package/dist/editor-examples.d.ts.map +1 -1
  44. package/dist/editor-examples.js +1 -1
  45. package/dist/editor-examples.js.map +1 -1
  46. package/dist/editor.d.ts +1 -1
  47. package/dist/editor.d.ts.map +1 -1
  48. package/dist/editor.js +1 -1
  49. package/dist/editor.js.map +1 -1
  50. package/dist/executor.d.ts +28 -3
  51. package/dist/executor.d.ts.map +1 -1
  52. package/dist/executor.js +314 -68
  53. package/dist/executor.js.map +1 -1
  54. package/dist/executor.unit.test.js +38 -1
  55. package/dist/executor.unit.test.js.map +1 -1
  56. package/dist/extension-connection.test.js +139 -36
  57. package/dist/extension-connection.test.js.map +1 -1
  58. package/dist/ffmpeg.d.ts +148 -0
  59. package/dist/ffmpeg.d.ts.map +1 -0
  60. package/dist/ffmpeg.js +523 -0
  61. package/dist/ffmpeg.js.map +1 -0
  62. package/dist/ghost-browser.d.ts.map +1 -1
  63. package/dist/ghost-browser.js.map +1 -1
  64. package/dist/ghost-cursor-client.js +281 -0
  65. package/dist/ghost-cursor.d.ts +27 -0
  66. package/dist/ghost-cursor.d.ts.map +1 -0
  67. package/dist/ghost-cursor.js +63 -0
  68. package/dist/ghost-cursor.js.map +1 -0
  69. package/dist/htmlrewrite.d.ts.map +1 -1
  70. package/dist/htmlrewrite.js +17 -55
  71. package/dist/htmlrewrite.js.map +1 -1
  72. package/dist/htmlrewrite.test.js.map +1 -1
  73. package/dist/kill-port.d.ts.map +1 -1
  74. package/dist/kill-port.js +1 -3
  75. package/dist/kill-port.js.map +1 -1
  76. package/dist/locator-selector.test.d.ts +2 -0
  77. package/dist/locator-selector.test.d.ts.map +1 -0
  78. package/dist/locator-selector.test.js +96 -0
  79. package/dist/locator-selector.test.js.map +1 -0
  80. package/dist/mcp-client.js.map +1 -1
  81. package/dist/mcp.d.ts.map +1 -1
  82. package/dist/mcp.js +14 -3
  83. package/dist/mcp.js.map +1 -1
  84. package/dist/on-mouse-action.test.d.ts +2 -0
  85. package/dist/on-mouse-action.test.d.ts.map +1 -0
  86. package/dist/on-mouse-action.test.js +155 -0
  87. package/dist/on-mouse-action.test.js.map +1 -0
  88. package/dist/page-markdown.js +4 -4
  89. package/dist/page-markdown.js.map +1 -1
  90. package/dist/prompt.md +725 -190
  91. package/dist/protocol.d.ts +4 -0
  92. package/dist/protocol.d.ts.map +1 -1
  93. package/dist/readability.js +1 -1
  94. package/dist/recording-ghost-cursor.d.ts +41 -0
  95. package/dist/recording-ghost-cursor.d.ts.map +1 -0
  96. package/dist/recording-ghost-cursor.js +79 -0
  97. package/dist/recording-ghost-cursor.js.map +1 -0
  98. package/dist/recording-relay.d.ts.map +1 -1
  99. package/dist/recording-relay.js +8 -8
  100. package/dist/recording-relay.js.map +1 -1
  101. package/dist/relay-client.d.ts +32 -4
  102. package/dist/relay-client.d.ts.map +1 -1
  103. package/dist/relay-client.js +60 -11
  104. package/dist/relay-client.js.map +1 -1
  105. package/dist/relay-core.test.d.ts.map +1 -1
  106. package/dist/relay-core.test.js +187 -26
  107. package/dist/relay-core.test.js.map +1 -1
  108. package/dist/relay-navigation.test.d.ts.map +1 -1
  109. package/dist/relay-navigation.test.js +54 -31
  110. package/dist/relay-navigation.test.js.map +1 -1
  111. package/dist/relay-session.test.d.ts.map +1 -1
  112. package/dist/relay-session.test.js +113 -65
  113. package/dist/relay-session.test.js.map +1 -1
  114. package/dist/relay-state.d.ts +158 -0
  115. package/dist/relay-state.d.ts.map +1 -0
  116. package/dist/relay-state.js +306 -0
  117. package/dist/relay-state.js.map +1 -0
  118. package/dist/relay-state.test.d.ts +2 -0
  119. package/dist/relay-state.test.d.ts.map +1 -0
  120. package/dist/relay-state.test.js +472 -0
  121. package/dist/relay-state.test.js.map +1 -0
  122. package/dist/scoped-fs.d.ts.map +1 -1
  123. package/dist/scoped-fs.js.map +1 -1
  124. package/dist/screen-recording.d.ts +42 -4
  125. package/dist/screen-recording.d.ts.map +1 -1
  126. package/dist/screen-recording.js +88 -13
  127. package/dist/screen-recording.js.map +1 -1
  128. package/dist/selector-generator.js +1 -1
  129. package/dist/snapshot-tools.test.js +71 -28
  130. package/dist/snapshot-tools.test.js.map +1 -1
  131. package/dist/start-relay-server.d.ts +1 -1
  132. package/dist/start-relay-server.d.ts.map +1 -1
  133. package/dist/start-relay-server.js +1 -1
  134. package/dist/start-relay-server.js.map +1 -1
  135. package/dist/styles-api.md +8 -1
  136. package/dist/styles-examples.d.ts +1 -1
  137. package/dist/styles-examples.d.ts.map +1 -1
  138. package/dist/styles-examples.js +1 -1
  139. package/dist/styles-examples.js.map +1 -1
  140. package/dist/styles.d.ts.map +1 -1
  141. package/dist/styles.js +1 -3
  142. package/dist/styles.js.map +1 -1
  143. package/dist/test-declarations.d.ts.map +1 -1
  144. package/dist/test-utils.d.ts +1 -1
  145. package/dist/test-utils.d.ts.map +1 -1
  146. package/dist/test-utils.js +7 -5
  147. package/dist/test-utils.js.map +1 -1
  148. package/dist/utils.d.ts.map +1 -1
  149. package/dist/utils.js.map +1 -1
  150. package/dist/wait-for-page-load.d.ts.map +1 -1
  151. package/dist/wait-for-page-load.js +1 -1
  152. package/dist/wait-for-page-load.js.map +1 -1
  153. package/package.json +4 -3
  154. package/src/a11y-client.ts +5 -4
  155. package/src/aria-snapshot.test.ts +5 -2
  156. package/src/aria-snapshot.ts +303 -116
  157. package/src/aria-snapshot.unit.test.ts +199 -141
  158. package/src/aria-snapshots/github-raw.txt +1 -1
  159. package/src/aria-snapshots/hackernews-interactive.txt +241 -237
  160. package/src/aria-snapshots/hackernews-raw.txt +266 -261
  161. package/src/assets/aria-labels-example.png +0 -0
  162. package/src/assets/aria-labels-github.png +0 -0
  163. package/src/assets/aria-labels-hacker-news.png +0 -0
  164. package/src/assets/aria-labels-old-reddit.png +0 -0
  165. package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +5 -0
  166. package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +18 -0
  167. package/src/cdp-log.ts +4 -1
  168. package/src/cdp-relay.ts +1012 -733
  169. package/src/cdp-session.ts +12 -3
  170. package/src/cdp-types.ts +51 -51
  171. package/src/clean-html.ts +4 -5
  172. package/src/cli.ts +107 -55
  173. package/src/create-logger.ts +5 -3
  174. package/src/debugger-examples-types.ts +4 -1
  175. package/src/debugger.ts +1 -5
  176. package/src/diff-utils.ts +2 -5
  177. package/src/editor-examples.ts +11 -1
  178. package/src/editor.ts +10 -2
  179. package/src/executor.ts +393 -78
  180. package/src/executor.unit.test.ts +48 -1
  181. package/src/extension-connection.test.ts +612 -488
  182. package/src/ffmpeg.ts +769 -0
  183. package/src/ghost-browser.ts +4 -6
  184. package/src/ghost-cursor-client.ts +368 -0
  185. package/src/ghost-cursor.ts +110 -0
  186. package/src/htmlrewrite.test.ts +6 -2
  187. package/src/htmlrewrite.ts +348 -386
  188. package/src/kill-port.ts +1 -3
  189. package/src/locator-selector.test.ts +115 -0
  190. package/src/mcp-client.ts +1 -1
  191. package/src/mcp.ts +29 -15
  192. package/src/on-mouse-action.test.ts +196 -0
  193. package/src/page-markdown.ts +7 -7
  194. package/src/protocol.ts +73 -57
  195. package/src/recording-ghost-cursor.ts +107 -0
  196. package/src/recording-relay.ts +20 -12
  197. package/src/relay-client.ts +101 -18
  198. package/src/relay-core.test.ts +761 -583
  199. package/src/relay-navigation.test.ts +517 -484
  200. package/src/relay-session.test.ts +984 -929
  201. package/src/relay-state.test.ts +570 -0
  202. package/src/relay-state.ts +497 -0
  203. package/src/resource.md +21 -49
  204. package/src/scoped-fs.ts +9 -3
  205. package/src/screen-recording.ts +175 -31
  206. package/src/skill.md +750 -206
  207. package/src/snapshot-tools.test.ts +580 -528
  208. package/src/snapshots/shadcn-ui-accessibility-full.md +181 -183
  209. package/src/snapshots/shadcn-ui-accessibility-interactive.md +119 -121
  210. package/src/start-relay-server.ts +14 -11
  211. package/src/styles-examples.ts +8 -1
  212. package/src/styles.ts +20 -21
  213. package/src/test-declarations.ts +6 -6
  214. package/src/test-utils.ts +104 -91
  215. package/src/utils.ts +2 -1
  216. package/src/wait-for-page-load.ts +6 -1
@@ -26,6 +26,44 @@ export interface ScreenshotResult {
26
26
  snapshot: string;
27
27
  labelCount: number;
28
28
  }
29
+ /**
30
+ * LLM-optimal max dimension. Claude auto-resizes images larger than 1568px
31
+ * on any edge, adding latency. Token cost: (width * height) / 750.
32
+ */
33
+ export declare const LLM_MAX_DIMENSION = 1568;
34
+ export interface ResizeImageOptions {
35
+ /** Input: file path or Buffer */
36
+ input: string | Buffer;
37
+ /** Max pixels on longest edge. Default 1568 (Claude-optimal).
38
+ * Ignored if explicit width/height provided. */
39
+ maxDimension?: number;
40
+ /** Explicit target width in px (aspect ratio preserved unless both width+height set) */
41
+ width?: number;
42
+ /** Explicit target height in px */
43
+ height?: number;
44
+ /** How to fit when both width+height specified. Default 'inside' (preserve aspect ratio, no crop) */
45
+ fit?: 'inside' | 'cover' | 'contain' | 'fill';
46
+ /** JPEG quality 1-100. Default 80 */
47
+ quality?: number;
48
+ /** Output file path. Defaults to overwriting the input file (when input is a path) */
49
+ output?: string;
50
+ }
51
+ export interface ResizeImageResult {
52
+ buffer: Buffer;
53
+ mimeType: 'image/jpeg';
54
+ /** Only set if output path was provided */
55
+ path?: string;
56
+ }
57
+ /**
58
+ * Resize an image using sharp. Useful for shrinking screenshots before reading
59
+ * them back into context so they consume fewer tokens.
60
+ *
61
+ * Default behavior (no width/height): fits within 1568×1568px, preserving
62
+ * aspect ratio, never upscales. This is optimal for Claude vision.
63
+ *
64
+ * Explicit width/height: resizes to those dimensions using the fit strategy.
65
+ */
66
+ export declare function resizeImage(options: ResizeImageOptions): Promise<ResizeImageResult>;
29
67
  export interface AriaSnapshotResult {
30
68
  snapshot: string;
31
69
  tree: AriaSnapshotNode[];
@@ -140,7 +178,7 @@ export declare function finalizeSnapshotOutput(lines: SnapshotLine[], nodes: Sna
140
178
  * await page.locator(selector).click()
141
179
  * ```
142
180
  */
143
- export declare function getAriaSnapshot({ page, frame, locator, refFilter, interactiveOnly, cdp }: {
181
+ export declare function getAriaSnapshot({ page, frame, locator, refFilter, interactiveOnly, cdp, }: {
144
182
  page: Page;
145
183
  frame?: Frame | FrameLocator;
146
184
  locator?: Locator;
@@ -171,7 +209,7 @@ export declare function getAriaSnapshot({ page, frame, locator, refFilter, inter
171
209
  * await page.locator('[data-testid="submit-btn"]').click()
172
210
  * ```
173
211
  */
174
- export declare function showAriaRefLabels({ page, locator, interactiveOnly, logger }: {
212
+ export declare function showAriaRefLabels({ page, locator, interactiveOnly, logger, }: {
175
213
  page: Page;
176
214
  locator?: Locator;
177
215
  interactiveOnly?: boolean;
@@ -206,7 +244,7 @@ export declare function hideAriaRefLabels({ page }: {
206
244
  * await page.locator('[data-testid="submit-btn"]').click()
207
245
  * ```
208
246
  */
209
- export declare function screenshotWithAccessibilityLabels({ page, locator, interactiveOnly, collector, logger }: {
247
+ export declare function screenshotWithAccessibilityLabels({ page, locator, interactiveOnly, collector, logger, }: {
210
248
  page: Page;
211
249
  locator?: Locator;
212
250
  interactiveOnly?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"aria-snapshot.d.ts","sourceRoot":"","sources":["../src/aria-snapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAKhG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAanD,MAAM,MAAM,cAAc,GAAG,KAAK,CAAA;AAElC,eAAO,MAAM,uBAAuB,EAAE,cAAsB,CAAA;AA8B5D,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAA;CAC3C;AAID,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAA;IAC1C,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B,CAAA;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,YAAY,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,gBAAgB,EAAE,CAAA;IACxB,IAAI,EAAE,OAAO,EAAE,CAAA;IACf,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3E,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC;;;;OAIG;IACH,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;IACjD,kBAAkB,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,GAAG,aAAa,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAA;IAChG,gBAAgB,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAC/E,sBAAsB,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CACrF;AAeD,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAMhG;AAkED,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAA;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAA;IAC9B,aAAa,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAA;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,CAAA;AA0ED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAA;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB,CAAA;AAwBD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,MAAM,SAAI,GAAG,YAAY,EAAE,CAcpF;AAQD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAA;IACvC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAC3E,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,KAAK,OAAO,CAAA;CAChE,GAAG,YAAY,GAAG,IAAI,CA4BtB;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE;IACrD,IAAI,EAAE,YAAY,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAA;IAC9D,cAAc,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IAC5D,gBAAgB,EAAE,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,GAAG,IAAI,CAAA;CACzH,GAAG;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAqGhD;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,IAAI,EAAE,YAAY,CAAA;IAClB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAA;IAC9D,cAAc,EAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IAC5D,gBAAgB,EAAE,CAAC,OAAO,EAAE;QAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,GAAG,IAAI,CAAA;CACzH,GAAG;IAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAAE,CAsFhD;AAuBD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,EAAE,YAAY,EAAE,EACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAsDhD;AA2HD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,eAAe,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,eAAuB,EAAE,GAAG,EAAE,EAAE;IACvG,IAAI,EAAE,IAAI,CAAA;IACV,KAAK,CAAC,EAAE,KAAK,GAAG,YAAY,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAA;IAC7D,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,GAAG,CAAC,EAAE,WAAW,CAAA;CAClB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAqT9B;AA+FD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAsB,EAAE,MAAM,EAAE,EAAE;IACzF,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAA;CACvF,GAAG,OAAO,CAAC;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB,CAAC,CA0DD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB/E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iCAAiC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAsB,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE;IACpH,IAAI,EAAE,IAAI,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,SAAS,EAAE,gBAAgB,EAAE,CAAA;IAC7B,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAA;CACvF,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFhB;AAGD,OAAO,EAAE,eAAe,IAAI,uBAAuB,EAAE,CAAA"}
1
+ {"version":3,"file":"aria-snapshot.d.ts","sourceRoot":"","sources":["../src/aria-snapshot.ts"],"names":[],"mappings":"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"}
@@ -6,8 +6,12 @@ import { Sema } from 'async-sema';
6
6
  import { getCDPSessionForPage } from './cdp-session.js';
7
7
  // Import sharp at module level - resolves to null if not available
8
8
  const sharpPromise = import('sharp')
9
- .then((m) => { return m.default; })
10
- .catch(() => { return null; });
9
+ .then((m) => {
10
+ return m.default;
11
+ })
12
+ .catch(() => {
13
+ return null;
14
+ });
11
15
  export const DEFAULT_SNAPSHOT_FORMAT = 'raw';
12
16
  // ============================================================================
13
17
  // A11y Client Code Loading
@@ -29,6 +33,78 @@ async function ensureA11yClient(page) {
29
33
  await page.evaluate(code);
30
34
  }
31
35
  }
36
+ // ============================================================================
37
+ // Image Resize Utility
38
+ // ============================================================================
39
+ /**
40
+ * LLM-optimal max dimension. Claude auto-resizes images larger than 1568px
41
+ * on any edge, adding latency. Token cost: (width * height) / 750.
42
+ */
43
+ export const LLM_MAX_DIMENSION = 1568;
44
+ /**
45
+ * Resize an image using sharp. Useful for shrinking screenshots before reading
46
+ * them back into context so they consume fewer tokens.
47
+ *
48
+ * Default behavior (no width/height): fits within 1568×1568px, preserving
49
+ * aspect ratio, never upscales. This is optimal for Claude vision.
50
+ *
51
+ * Explicit width/height: resizes to those dimensions using the fit strategy.
52
+ */
53
+ export async function resizeImage(options) {
54
+ const sharp = await sharpPromise;
55
+ if (!sharp) {
56
+ throw new Error('sharp is not installed — install it with: pnpm add sharp');
57
+ }
58
+ const inputBuffer = (() => {
59
+ if (Buffer.isBuffer(options.input)) {
60
+ return options.input;
61
+ }
62
+ return fs.readFileSync(options.input);
63
+ })();
64
+ const quality = options.quality ?? 80;
65
+ const hasExplicitDimensions = options.width !== undefined || options.height !== undefined;
66
+ const fit = options.fit ?? 'inside';
67
+ const resizeOpts = (() => {
68
+ if (hasExplicitDimensions) {
69
+ return {
70
+ width: options.width,
71
+ height: options.height,
72
+ fit,
73
+ withoutEnlargement: false,
74
+ };
75
+ }
76
+ const max = options.maxDimension ?? LLM_MAX_DIMENSION;
77
+ return {
78
+ width: max,
79
+ height: max,
80
+ fit,
81
+ withoutEnlargement: true,
82
+ };
83
+ })();
84
+ const buffer = await sharp(inputBuffer)
85
+ .resize(resizeOpts)
86
+ .jpeg({ quality })
87
+ .toBuffer();
88
+ // Default: overwrite input file. When input is a Buffer, no file is written
89
+ // unless output is explicitly set.
90
+ const outputPath = (() => {
91
+ if (options.output) {
92
+ return options.output;
93
+ }
94
+ if (typeof options.input === 'string') {
95
+ return options.input;
96
+ }
97
+ return undefined;
98
+ })();
99
+ if (outputPath) {
100
+ fs.writeFileSync(outputPath, buffer);
101
+ }
102
+ return {
103
+ buffer,
104
+ mimeType: 'image/jpeg',
105
+ ...(outputPath ? { path: outputPath } : {}),
106
+ };
107
+ }
32
108
  export function buildShortRefMap({ refs }) {
33
109
  const map = new Map();
34
110
  refs.forEach((entry, index) => {
@@ -58,9 +134,7 @@ const INTERACTIVE_ROLES = new Set([
58
134
  'video',
59
135
  'audio',
60
136
  ]);
61
- const LABEL_ROLES = new Set([
62
- 'labeltext',
63
- ]);
137
+ const LABEL_ROLES = new Set(['labeltext']);
64
138
  const MAX_LABEL_POSITION_CONCURRENCY = 24;
65
139
  const BOX_MODEL_TIMEOUT_MS = 5000;
66
140
  const CONTEXT_ROLES = new Set([
@@ -78,12 +152,7 @@ const CONTEXT_ROLES = new Set([
78
152
  'row',
79
153
  'cell',
80
154
  ]);
81
- const SKIP_WRAPPER_ROLES = new Set([
82
- 'generic',
83
- 'group',
84
- 'none',
85
- 'presentation',
86
- ]);
155
+ const SKIP_WRAPPER_ROLES = new Set(['generic', 'group', 'none', 'presentation']);
87
156
  const TEST_ID_ATTRS = [
88
157
  'data-testid',
89
158
  'data-test-id',
@@ -130,7 +199,7 @@ function buildLocatorFromStable(stable) {
130
199
  const escaped = escapeLocatorValue(stable.value);
131
200
  return `[${stable.attr}="${escaped}"]`;
132
201
  }
133
- function buildBaseLocator({ role, name, stable }) {
202
+ function buildBaseLocator({ role, name, stable, }) {
134
203
  if (stable) {
135
204
  return buildLocatorFromStable(stable);
136
205
  }
@@ -158,7 +227,7 @@ function getAxRole(node) {
158
227
  const role = getAxValueString(node.role);
159
228
  return role.toLowerCase();
160
229
  }
161
- function buildSnapshotLine({ role, name, baseLocator, indent, hasChildren }) {
230
+ function buildSnapshotLine({ role, name, baseLocator, indent, hasChildren, }) {
162
231
  const prefix = ' '.repeat(indent);
163
232
  let text = `${prefix}- ${role}`;
164
233
  if (name) {
@@ -199,13 +268,15 @@ export function buildRawSnapshotTree(options) {
199
268
  }
200
269
  const role = getAxRole(node);
201
270
  const name = getAxValueString(node.name).trim();
202
- const children = (node.childIds ?? []).map((childId) => {
271
+ const children = (node.childIds ?? [])
272
+ .map((childId) => {
203
273
  return buildRawSnapshotTree({
204
274
  nodeId: childId,
205
275
  axById: options.axById,
206
276
  isNodeInScope: options.isNodeInScope,
207
277
  });
208
- }).filter(isTruthy);
278
+ })
279
+ .filter(isTruthy);
209
280
  const inScope = options.isNodeInScope(node) || children.length > 0;
210
281
  if (!inScope) {
211
282
  return null;
@@ -429,7 +500,8 @@ export function finalizeSnapshotOutput(lines, nodes, shortRefMap) {
429
500
  return acc;
430
501
  }, []);
431
502
  let lineLocatorIndex = 0;
432
- const snapshot = lines.map((line) => {
503
+ const snapshot = lines
504
+ .map((line) => {
433
505
  let text = line.text;
434
506
  if (line.baseLocator) {
435
507
  const locator = locatorSequence[lineLocatorIndex];
@@ -440,7 +512,8 @@ export function finalizeSnapshotOutput(lines, nodes, shortRefMap) {
440
512
  text += ':';
441
513
  }
442
514
  return text;
443
- }).join('\n');
515
+ })
516
+ .join('\n');
444
517
  let nodeLocatorIndex = 0;
445
518
  const applyLocators = (items) => {
446
519
  return items.map((item) => {
@@ -585,8 +658,8 @@ async function resolveFrame({ frame, page }) {
585
658
  * await page.locator(selector).click()
586
659
  * ```
587
660
  */
588
- export async function getAriaSnapshot({ page, frame, locator, refFilter, interactiveOnly = false, cdp }) {
589
- const session = cdp || await getCDPSessionForPage({ page });
661
+ export async function getAriaSnapshot({ page, frame, locator, refFilter, interactiveOnly = false, cdp, }) {
662
+ const session = cdp || (await getCDPSessionForPage({ page }));
590
663
  // Resolve FrameLocator to an actual Frame. FrameLocator (from locator.contentFrame())
591
664
  // is a scoping helper without CDP access. We need the real Frame from page.frames()
592
665
  // which has frameId() for OOPIF session attachment.
@@ -596,16 +669,16 @@ export async function getAriaSnapshot({ page, frame, locator, refFilter, interac
596
669
  let oopifSessionId = null;
597
670
  const frameId = resolvedFrame?.frameId() ?? null;
598
671
  if (frameId) {
599
- const { targetInfos } = await session.send('Target.getTargets');
672
+ const { targetInfos } = (await session.send('Target.getTargets'));
600
673
  const frameUrl = resolvedFrame.url();
601
674
  const iframeTarget = targetInfos.find((t) => {
602
675
  return t.type === 'iframe' && t.url === frameUrl;
603
676
  });
604
677
  if (iframeTarget) {
605
- const { sessionId } = await session.send('Target.attachToTarget', {
678
+ const { sessionId } = (await session.send('Target.attachToTarget', {
606
679
  targetId: iframeTarget.targetId,
607
680
  flatten: true,
608
- });
681
+ }));
609
682
  oopifSessionId = sessionId;
610
683
  await session.send('Runtime.runIfWaitingForDebugger', undefined, oopifSessionId);
611
684
  }
@@ -623,7 +696,7 @@ export async function getAriaSnapshot({ page, frame, locator, refFilter, interac
623
696
  }, { attr: scopeAttr, value: scopeValue });
624
697
  scopeApplied = true;
625
698
  }
626
- const { nodes: domNodes } = await session.send('DOM.getFlattenedDocument', { depth: -1, pierce: true }, oopifSessionId);
699
+ const { nodes: domNodes } = (await session.send('DOM.getFlattenedDocument', { depth: -1, pierce: true }, oopifSessionId));
627
700
  const { domById, domByBackendId, childrenByParent } = buildDomIndex(domNodes);
628
701
  let scopeRootNodeId = null;
629
702
  let scopeRootBackendId = null;
@@ -636,11 +709,9 @@ export async function getAriaSnapshot({ page, frame, locator, refFilter, interac
636
709
  }
637
710
  }
638
711
  }
639
- const allowedBackendIds = scopeRootNodeId
640
- ? buildBackendIdSet(scopeRootNodeId, childrenByParent, domById)
641
- : null;
712
+ const allowedBackendIds = scopeRootNodeId ? buildBackendIdSet(scopeRootNodeId, childrenByParent, domById) : null;
642
713
  const axParams = !oopifSessionId && frameId ? { frameId } : undefined;
643
- const { nodes: axNodes } = await session.send('Accessibility.getFullAXTree', axParams, oopifSessionId);
714
+ const { nodes: axNodes } = (await session.send('Accessibility.getFullAXTree', axParams, oopifSessionId));
644
715
  const axById = new Map();
645
716
  for (const node of axNodes) {
646
717
  axById.set(node.nodeId, node);
@@ -710,9 +781,11 @@ export async function getAriaSnapshot({ page, frame, locator, refFilter, interac
710
781
  const rootNode = axById.get(rootAxNodeId);
711
782
  const rootRole = rootNode ? getAxRole(rootNode) : '';
712
783
  const rawRoots = rootNode && (rootRole === 'rootwebarea' || rootRole === 'webarea') && rootNode.childIds
713
- ? rootNode.childIds.map((childId) => {
784
+ ? rootNode.childIds
785
+ .map((childId) => {
714
786
  return buildRawSnapshotTree({ nodeId: childId, axById, isNodeInScope });
715
- }).filter(isTruthy)
787
+ })
788
+ .filter(isTruthy)
716
789
  : [buildRawSnapshotTree({ nodeId: rootAxNodeId, axById, isNodeInScope })].filter(isTruthy);
717
790
  const filtered = rawRoots.flatMap((rawNode) => {
718
791
  if (interactiveOnly) {
@@ -791,7 +864,16 @@ export async function getAriaSnapshot({ page, frame, locator, refFilter, interac
791
864
  if (!target) {
792
865
  return null;
793
866
  }
794
- const testIdAttrs = ['data-testid', 'data-test-id', 'data-test', 'data-cy', 'data-pw', 'data-qa', 'data-e2e', 'data-automation-id'];
867
+ const testIdAttrs = [
868
+ 'data-testid',
869
+ 'data-test-id',
870
+ 'data-test',
871
+ 'data-cy',
872
+ 'data-pw',
873
+ 'data-qa',
874
+ 'data-e2e',
875
+ 'data-automation-id',
876
+ ];
795
877
  for (const attr of testIdAttrs) {
796
878
  const value = target.getAttribute(attr);
797
879
  if (value) {
@@ -874,7 +956,7 @@ function isTruthy(value) {
874
956
  }
875
957
  async function getLabelBoxesForRefs({ page, refs, maxConcurrency = MAX_LABEL_POSITION_CONCURRENCY, logger, cdp, }) {
876
958
  const log = logger?.info ?? logger?.error ?? console.error;
877
- const session = cdp || await getCDPSessionForPage({ page });
959
+ const session = cdp || (await getCDPSessionForPage({ page }));
878
960
  const sema = new Sema(maxConcurrency);
879
961
  const labelRefs = refs.filter((ref) => {
880
962
  return Boolean(ref.backendNodeId) && INTERACTIVE_ROLES.has(ref.role);
@@ -892,9 +974,13 @@ async function getLabelBoxesForRefs({ page, refs, maxConcurrency = MAX_LABEL_POS
892
974
  await sema.acquire();
893
975
  try {
894
976
  const response = await Promise.race([
895
- session.send('DOM.getBoxModel', { backendNodeId: ref.backendNodeId }),
977
+ session.send('DOM.getBoxModel', {
978
+ backendNodeId: ref.backendNodeId,
979
+ }),
896
980
  new Promise((resolve) => {
897
- setTimeout(() => { resolve(null); }, BOX_MODEL_TIMEOUT_MS);
981
+ setTimeout(() => {
982
+ resolve(null);
983
+ }, BOX_MODEL_TIMEOUT_MS);
898
984
  }),
899
985
  ]);
900
986
  completed++;
@@ -949,7 +1035,7 @@ async function getLabelBoxesForRefs({ page, refs, maxConcurrency = MAX_LABEL_POS
949
1035
  * await page.locator('[data-testid="submit-btn"]').click()
950
1036
  * ```
951
1037
  */
952
- export async function showAriaRefLabels({ page, locator, interactiveOnly = true, logger }) {
1038
+ export async function showAriaRefLabels({ page, locator, interactiveOnly = true, logger, }) {
953
1039
  const startTime = Date.now();
954
1040
  const log = logger?.info ?? logger?.error ?? console.error;
955
1041
  log(`[showAriaRefLabels] starting...`);
@@ -984,7 +1070,8 @@ export async function showAriaRefLabels({ page, locator, interactiveOnly = true,
984
1070
  }
985
1071
  if (a11y?.computeA11ySnapshot) {
986
1072
  const rootElement = root || document.body;
987
- return a11y.computeA11ySnapshot({ root: rootElement, interactiveOnly: intOnly, renderLabels: true }).labelCount;
1073
+ return a11y.computeA11ySnapshot({ root: rootElement, interactiveOnly: intOnly, renderLabels: true })
1074
+ .labelCount;
988
1075
  }
989
1076
  throw new Error('a11y client not loaded');
990
1077
  }, { entries: shortLabels, root: rootHandle, interactiveOnly });
@@ -1035,7 +1122,7 @@ export async function hideAriaRefLabels({ page }) {
1035
1122
  * await page.locator('[data-testid="submit-btn"]').click()
1036
1123
  * ```
1037
1124
  */
1038
- export async function screenshotWithAccessibilityLabels({ page, locator, interactiveOnly = true, collector, logger }) {
1125
+ export async function screenshotWithAccessibilityLabels({ page, locator, interactiveOnly = true, collector, logger, }) {
1039
1126
  const log = logger?.info ?? logger?.error;
1040
1127
  const showLabelsStart = Date.now();
1041
1128
  const { snapshot, labelCount } = await showAriaRefLabels({ page, locator, interactiveOnly, logger });
@@ -1053,15 +1140,12 @@ export async function screenshotWithAccessibilityLabels({ page, locator, interac
1053
1140
  }
1054
1141
  const screenshotPath = path.join(tmpDir, filename);
1055
1142
  // Get viewport size to clip screenshot to visible area
1056
- const viewport = await page.evaluate('({ width: window.innerWidth, height: window.innerHeight })');
1057
- // Max 1568px on any edge (larger gets auto-resized by Claude, adding latency)
1058
- // Token formula: tokens = (width * height) / 750
1059
- const MAX_DIMENSION = 1568;
1143
+ const viewport = (await page.evaluate('({ width: window.innerWidth, height: window.innerHeight })'));
1060
1144
  // Check if sharp is available for resizing
1061
1145
  const sharp = await sharpPromise;
1062
- // Clip dimensions: if sharp unavailable, limit capture area to MAX_DIMENSION
1063
- const clipWidth = sharp ? viewport.width : Math.min(viewport.width, MAX_DIMENSION);
1064
- const clipHeight = sharp ? viewport.height : Math.min(viewport.height, MAX_DIMENSION);
1146
+ // Clip dimensions: if sharp unavailable, limit capture area to LLM_MAX_DIMENSION
1147
+ const clipWidth = sharp ? viewport.width : Math.min(viewport.width, LLM_MAX_DIMENSION);
1148
+ const clipHeight = sharp ? viewport.height : Math.min(viewport.height, LLM_MAX_DIMENSION);
1065
1149
  // Take viewport screenshot with scale: 'css' to ignore device pixel ratio
1066
1150
  const screenshotStart = Date.now();
1067
1151
  const rawBuffer = await page.screenshot({
@@ -1073,23 +1157,16 @@ export async function screenshotWithAccessibilityLabels({ page, locator, interac
1073
1157
  if (log) {
1074
1158
  log(`page.screenshot: ${Date.now() - screenshotStart}ms`);
1075
1159
  }
1076
- // Resize with sharp if available, otherwise use clipped raw buffer
1160
+ // Resize with resizeImage if sharp available, otherwise use clipped raw buffer
1077
1161
  const resizeStart = Date.now();
1078
1162
  const buffer = await (async () => {
1079
1163
  if (!sharp) {
1080
- logger?.error?.('[playwriter] sharp not available, using clipped screenshot (max', MAX_DIMENSION, 'px)');
1164
+ logger?.error?.('[playwriter] sharp not available, using clipped screenshot (max', LLM_MAX_DIMENSION, 'px)');
1081
1165
  return rawBuffer;
1082
1166
  }
1083
1167
  try {
1084
- return await sharp(rawBuffer)
1085
- .resize({
1086
- width: MAX_DIMENSION,
1087
- height: MAX_DIMENSION,
1088
- fit: 'inside', // Scale down to fit, preserving aspect ratio
1089
- withoutEnlargement: true, // Don't upscale small images
1090
- })
1091
- .jpeg({ quality: 80 })
1092
- .toBuffer();
1168
+ const result = await resizeImage({ input: rawBuffer });
1169
+ return result.buffer;
1093
1170
  }
1094
1171
  catch (err) {
1095
1172
  logger?.error?.('[playwriter] sharp resize failed, using raw buffer:', err);