imperium-crawl 1.5.3 → 2.0.0

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 (81) hide show
  1. package/README.md +40 -32
  2. package/dist/constants.d.ts +2 -1
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +3 -1
  5. package/dist/constants.js.map +1 -1
  6. package/dist/network/interceptor.d.ts +19 -0
  7. package/dist/network/interceptor.d.ts.map +1 -0
  8. package/dist/network/interceptor.js +82 -0
  9. package/dist/network/interceptor.js.map +1 -0
  10. package/dist/network/types.d.ts +27 -0
  11. package/dist/network/types.d.ts.map +1 -0
  12. package/dist/network/types.js +2 -0
  13. package/dist/network/types.js.map +1 -0
  14. package/dist/security/action-policy.d.ts +26 -0
  15. package/dist/security/action-policy.d.ts.map +1 -0
  16. package/dist/security/action-policy.js +136 -0
  17. package/dist/security/action-policy.js.map +1 -0
  18. package/dist/security/auth-vault.d.ts +49 -0
  19. package/dist/security/auth-vault.d.ts.map +1 -0
  20. package/dist/security/auth-vault.js +133 -0
  21. package/dist/security/auth-vault.js.map +1 -0
  22. package/dist/security/domain-filter.d.ts +19 -0
  23. package/dist/security/domain-filter.d.ts.map +1 -0
  24. package/dist/security/domain-filter.js +114 -0
  25. package/dist/security/domain-filter.js.map +1 -0
  26. package/dist/security/types.d.ts +19 -0
  27. package/dist/security/types.d.ts.map +1 -0
  28. package/dist/security/types.js +2 -0
  29. package/dist/security/types.js.map +1 -0
  30. package/dist/sessions/encryption.d.ts +37 -0
  31. package/dist/sessions/encryption.d.ts.map +1 -0
  32. package/dist/sessions/encryption.js +108 -0
  33. package/dist/sessions/encryption.js.map +1 -0
  34. package/dist/sessions/index.d.ts +1 -0
  35. package/dist/sessions/index.d.ts.map +1 -1
  36. package/dist/sessions/index.js +1 -0
  37. package/dist/sessions/index.js.map +1 -1
  38. package/dist/sessions/manager.d.ts +3 -0
  39. package/dist/sessions/manager.d.ts.map +1 -1
  40. package/dist/sessions/manager.js +28 -2
  41. package/dist/sessions/manager.js.map +1 -1
  42. package/dist/snapshot/annotator.d.ts +21 -0
  43. package/dist/snapshot/annotator.d.ts.map +1 -0
  44. package/dist/snapshot/annotator.js +152 -0
  45. package/dist/snapshot/annotator.js.map +1 -0
  46. package/dist/snapshot/boundary.d.ts +7 -0
  47. package/dist/snapshot/boundary.d.ts.map +1 -0
  48. package/dist/snapshot/boundary.js +12 -0
  49. package/dist/snapshot/boundary.js.map +1 -0
  50. package/dist/snapshot/differ.d.ts +40 -0
  51. package/dist/snapshot/differ.d.ts.map +1 -0
  52. package/dist/snapshot/differ.js +194 -0
  53. package/dist/snapshot/differ.js.map +1 -0
  54. package/dist/snapshot/extractor.d.ts +27 -0
  55. package/dist/snapshot/extractor.d.ts.map +1 -0
  56. package/dist/snapshot/extractor.js +265 -0
  57. package/dist/snapshot/extractor.js.map +1 -0
  58. package/dist/snapshot/index.d.ts +8 -0
  59. package/dist/snapshot/index.d.ts.map +1 -0
  60. package/dist/snapshot/index.js +6 -0
  61. package/dist/snapshot/index.js.map +1 -0
  62. package/dist/snapshot/store.d.ts +28 -0
  63. package/dist/snapshot/store.d.ts.map +1 -0
  64. package/dist/snapshot/store.js +65 -0
  65. package/dist/snapshot/store.js.map +1 -0
  66. package/dist/snapshot/types.d.ts +42 -0
  67. package/dist/snapshot/types.d.ts.map +1 -0
  68. package/dist/snapshot/types.js +2 -0
  69. package/dist/snapshot/types.js.map +1 -0
  70. package/dist/tools/index.d.ts.map +1 -1
  71. package/dist/tools/index.js +2 -0
  72. package/dist/tools/index.js.map +1 -1
  73. package/dist/tools/interact.d.ts +194 -5
  74. package/dist/tools/interact.d.ts.map +1 -1
  75. package/dist/tools/interact.js +355 -20
  76. package/dist/tools/interact.js.map +1 -1
  77. package/dist/tools/snapshot.d.ts +53 -0
  78. package/dist/tools/snapshot.d.ts.map +1 -0
  79. package/dist/tools/snapshot.js +160 -0
  80. package/dist/tools/snapshot.js.map +1 -0
  81. package/package.json +1 -1
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Annotated Screenshots — Inject visual overlay badges on interactive elements.
3
+ *
4
+ * Zero external deps — uses DOM injection via page.evaluate(),
5
+ * takes screenshot, then cleans up injected elements.
6
+ *
7
+ * Color coding:
8
+ * - Red (#e53e3e) = button, switch
9
+ * - Blue (#3182ce) = link, tab
10
+ * - Green (#38a169) = textbox, searchbox, combobox, listbox
11
+ * - Orange (#dd6b20) = other interactive (checkbox, radio, slider, etc.)
12
+ */
13
+ const ROLE_COLORS = {
14
+ button: "#e53e3e",
15
+ switch: "#e53e3e",
16
+ link: "#3182ce",
17
+ tab: "#3182ce",
18
+ textbox: "#38a169",
19
+ searchbox: "#38a169",
20
+ combobox: "#38a169",
21
+ listbox: "#38a169",
22
+ };
23
+ const DEFAULT_COLOR = "#dd6b20";
24
+ const ANNOTATION_ATTR = "data-imperium-annotation";
25
+ /**
26
+ * Inject annotation overlays on interactive elements, take screenshot, cleanup.
27
+ * Returns PNG buffer.
28
+ */
29
+ export async function annotateScreenshot(page, refs) {
30
+ // Build annotation data for injection
31
+ const annotations = Object.entries(refs).map(([ref, entry]) => ({
32
+ ref,
33
+ role: entry.role,
34
+ name: entry.name,
35
+ nth: entry.nth,
36
+ color: ROLE_COLORS[entry.role] ?? DEFAULT_COLOR,
37
+ }));
38
+ // Inject overlays via page.evaluate
39
+ await page.evaluate((data) => {
40
+ const ATTR = "data-imperium-annotation";
41
+ for (const { ref, role, name, nth, color } of data) {
42
+ // Find the element using ARIA queries
43
+ let elements;
44
+ try {
45
+ // Try aria role query
46
+ const selector = name
47
+ ? `[role="${role}"]`
48
+ : `[role="${role}"]`;
49
+ elements = Array.from(document.querySelectorAll(selector));
50
+ // Filter by accessible name if provided
51
+ if (name) {
52
+ elements = elements.filter((el) => {
53
+ const accName = el.getAttribute("aria-label") ||
54
+ el.getAttribute("title") ||
55
+ (el.textContent ?? "").trim();
56
+ return accName.includes(name) || name.includes(accName.slice(0, 80));
57
+ });
58
+ }
59
+ // Handle nth
60
+ if (nth !== undefined && elements[nth]) {
61
+ elements = [elements[nth]];
62
+ }
63
+ else if (elements.length > 0) {
64
+ elements = [elements[0]];
65
+ }
66
+ // Fallback: try matching by tag for common roles
67
+ if (elements.length === 0) {
68
+ const tagMap = {
69
+ button: "button",
70
+ link: "a",
71
+ textbox: "input,textarea",
72
+ searchbox: "input[type=search]",
73
+ checkbox: "input[type=checkbox]",
74
+ radio: "input[type=radio]",
75
+ };
76
+ if (tagMap[role]) {
77
+ const tagEls = document.querySelectorAll(tagMap[role]);
78
+ for (const el of tagEls) {
79
+ const accName = el.getAttribute("aria-label") ||
80
+ el.getAttribute("title") ||
81
+ (el.textContent ?? "").trim();
82
+ if (!name || accName.includes(name) || name.includes(accName.slice(0, 80))) {
83
+ elements = [el];
84
+ break;
85
+ }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ catch {
91
+ elements = [];
92
+ }
93
+ if (elements.length === 0)
94
+ continue;
95
+ const el = elements[0];
96
+ const rect = el.getBoundingClientRect();
97
+ if (rect.width === 0 || rect.height === 0)
98
+ continue;
99
+ // Create border overlay
100
+ const border = document.createElement("div");
101
+ border.setAttribute(ATTR, ref);
102
+ Object.assign(border.style, {
103
+ position: "absolute",
104
+ top: `${rect.top + window.scrollY}px`,
105
+ left: `${rect.left + window.scrollX}px`,
106
+ width: `${rect.width}px`,
107
+ height: `${rect.height}px`,
108
+ border: `2px solid ${color}`,
109
+ borderRadius: "3px",
110
+ pointerEvents: "none",
111
+ zIndex: "2147483647",
112
+ boxSizing: "border-box",
113
+ });
114
+ // Create badge
115
+ const badge = document.createElement("div");
116
+ badge.setAttribute(ATTR, `${ref}-badge`);
117
+ const refNum = ref.replace("e", "");
118
+ badge.textContent = refNum;
119
+ Object.assign(badge.style, {
120
+ position: "absolute",
121
+ top: `${rect.top + window.scrollY - 10}px`,
122
+ left: `${rect.left + window.scrollX - 10}px`,
123
+ width: "20px",
124
+ height: "20px",
125
+ borderRadius: "50%",
126
+ backgroundColor: color,
127
+ color: "white",
128
+ fontSize: "11px",
129
+ fontWeight: "bold",
130
+ fontFamily: "Arial, sans-serif",
131
+ display: "flex",
132
+ alignItems: "center",
133
+ justifyContent: "center",
134
+ pointerEvents: "none",
135
+ zIndex: "2147483647",
136
+ lineHeight: "1",
137
+ });
138
+ document.body.appendChild(border);
139
+ document.body.appendChild(badge);
140
+ }
141
+ }, annotations);
142
+ // Take screenshot with annotations
143
+ const screenshot = await page.screenshot({ fullPage: false });
144
+ // Cleanup injected elements
145
+ await page.evaluate((attr) => {
146
+ const els = document.querySelectorAll(`[${attr}]`);
147
+ for (const el of els)
148
+ el.remove();
149
+ }, ANNOTATION_ATTR);
150
+ return screenshot;
151
+ }
152
+ //# sourceMappingURL=annotator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotator.js","sourceRoot":"","sources":["../../src/snapshot/annotator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,MAAM,WAAW,GAA2B;IAC1C,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,SAAS;IACd,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,SAAS;IACnB,OAAO,EAAE,SAAS;CACnB,CAAC;AAEF,MAAM,aAAa,GAAG,SAAS,CAAC;AAEhC,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAEnD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAU,EAAE,IAAY;IAC/D,sCAAsC;IACtC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,GAAG;QACH,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,aAAa;KAChD,CAAC,CAAC,CAAC;IAEJ,oCAAoC;IACpC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAwB,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,0BAA0B,CAAC;QAExC,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;YACnD,sCAAsC;YACtC,IAAI,QAAmB,CAAC;YACxB,IAAI,CAAC;gBACH,sBAAsB;gBACtB,MAAM,QAAQ,GAAG,IAAI;oBACnB,CAAC,CAAC,UAAU,IAAI,IAAI;oBACpB,CAAC,CAAC,UAAU,IAAI,IAAI,CAAC;gBACvB,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAE3D,wCAAwC;gBACxC,IAAI,IAAI,EAAE,CAAC;oBACT,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;wBAChC,MAAM,OAAO,GACX,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC;4BAC7B,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;4BACxB,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;wBAChC,OAAO,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;oBACvE,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,aAAa;gBACb,IAAI,GAAG,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvC,QAAQ,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7B,CAAC;qBAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC/B,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3B,CAAC;gBAED,iDAAiD;gBACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,MAAM,MAAM,GAA2B;wBACrC,MAAM,EAAE,QAAQ;wBAChB,IAAI,EAAE,GAAG;wBACT,OAAO,EAAE,gBAAgB;wBACzB,SAAS,EAAE,oBAAoB;wBAC/B,QAAQ,EAAE,sBAAsB;wBAChC,KAAK,EAAE,mBAAmB;qBAC3B,CAAC;oBACF,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;wBACjB,MAAM,MAAM,GAAG,QAAQ,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;wBACvD,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;4BACxB,MAAM,OAAO,GACX,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC;gCAC7B,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;gCACxB,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;4BAChC,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;gCAC3E,QAAQ,GAAG,CAAC,EAAE,CAAC,CAAC;gCAChB,MAAM;4BACR,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,GAAG,EAAE,CAAC;YAChB,CAAC;YAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEpC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACvB,MAAM,IAAI,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEpD,wBAAwB;YACxB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;gBAC1B,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI;gBACrC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,IAAI;gBACvC,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI;gBACxB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI;gBAC1B,MAAM,EAAE,aAAa,KAAK,EAAE;gBAC5B,YAAY,EAAE,KAAK;gBACnB,aAAa,EAAE,MAAM;gBACrB,MAAM,EAAE,YAAY;gBACpB,SAAS,EAAE,YAAY;aACxB,CAAC,CAAC;YAEH,eAAe;YACf,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC5C,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,QAAQ,CAAC,CAAC;YACzC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACpC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;YAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE;gBACzB,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,GAAG,EAAE,IAAI;gBAC1C,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,OAAO,GAAG,EAAE,IAAI;gBAC5C,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,MAAM;gBACd,YAAY,EAAE,KAAK;gBACnB,eAAe,EAAE,KAAK;gBACtB,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,MAAM;gBAClB,UAAU,EAAE,mBAAmB;gBAC/B,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,QAAQ;gBACpB,cAAc,EAAE,QAAQ;gBACxB,aAAa,EAAE,MAAM;gBACrB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,GAAG;aAChB,CAAC,CAAC;YAEH,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC,EAAE,WAAW,CAAC,CAAC;IAEhB,mCAAmC;IACnC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAE9D,4BAA4B;IAC5B,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAY,EAAE,EAAE;QACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,gBAAgB,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;QACnD,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,EAAE,CAAC,MAAM,EAAE,CAAC;IACpC,CAAC,EAAE,eAAe,CAAC,CAAC;IAEpB,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Content boundaries — unique markers to wrap content sections.
3
+ * Prevents LLM confusion about where content starts/ends.
4
+ */
5
+ export declare function generateBoundary(): string;
6
+ export declare function wrapContent(content: string, boundary: string): string;
7
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../src/snapshot/boundary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErE"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Content boundaries — unique markers to wrap content sections.
3
+ * Prevents LLM confusion about where content starts/ends.
4
+ */
5
+ import { randomBytes } from "node:crypto";
6
+ export function generateBoundary() {
7
+ return randomBytes(8).toString("hex");
8
+ }
9
+ export function wrapContent(content, boundary) {
10
+ return `<imperium-boundary:${boundary}>\n${content}\n</imperium-boundary:${boundary}>`;
11
+ }
12
+ //# sourceMappingURL=boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../../src/snapshot/boundary.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,gBAAgB;IAC9B,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,QAAgB;IAC3D,OAAO,sBAAsB,QAAQ,MAAM,OAAO,yBAAyB,QAAQ,GAAG,CAAC;AACzF,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Dual diff system — text (Myers) + image (pixel comparison).
3
+ *
4
+ * Text diff: Line-level Myers algorithm on snapshot strings.
5
+ * Image diff: Canvas-based pixel comparison in an isolated browser page.
6
+ */
7
+ type BrowserContext = import("rebrowser-playwright").BrowserContext;
8
+ export interface TextDiffResult {
9
+ diff: string;
10
+ additions: number;
11
+ removals: number;
12
+ unchanged: number;
13
+ changed: boolean;
14
+ }
15
+ /**
16
+ * Myers diff algorithm (line-level).
17
+ * Returns unified diff format with +/- prefixes.
18
+ */
19
+ export declare function diffSnapshots(before: string, after: string): TextDiffResult;
20
+ export interface ImageDiffResult {
21
+ mismatchPercentage: number;
22
+ match: boolean;
23
+ diffImage: Buffer;
24
+ totalPixels: number;
25
+ changedPixels: number;
26
+ }
27
+ export interface ImageDiffOptions {
28
+ /** Color distance threshold (0-255). Default: 30 */
29
+ threshold?: number;
30
+ /** Match if mismatch is below this % (default: 1.0) */
31
+ matchThreshold?: number;
32
+ }
33
+ /**
34
+ * Pixel-level comparison of two screenshots.
35
+ * Opens an isolated page, loads images via intercepted routes,
36
+ * computes per-pixel color distance, generates diff PNG.
37
+ */
38
+ export declare function diffScreenshots(context: BrowserContext, baseline: Buffer, current: Buffer, options?: ImageDiffOptions): Promise<ImageDiffResult>;
39
+ export {};
40
+ //# sourceMappingURL=differ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../../src/snapshot/differ.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,KAAK,cAAc,GAAG,OAAO,sBAAsB,EAAE,cAAc,CAAC;AAIpE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAOD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAwF3E;AAID,MAAM,WAAW,eAAe;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAkH1B"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Dual diff system — text (Myers) + image (pixel comparison).
3
+ *
4
+ * Text diff: Line-level Myers algorithm on snapshot strings.
5
+ * Image diff: Canvas-based pixel comparison in an isolated browser page.
6
+ */
7
+ /**
8
+ * Myers diff algorithm (line-level).
9
+ * Returns unified diff format with +/- prefixes.
10
+ */
11
+ export function diffSnapshots(before, after) {
12
+ const beforeLines = before.split("\n");
13
+ const afterLines = after.split("\n");
14
+ const n = beforeLines.length;
15
+ const m = afterLines.length;
16
+ const max = n + m;
17
+ // Shortcut: identical
18
+ if (before === after) {
19
+ return {
20
+ diff: beforeLines.map((l) => ` ${l}`).join("\n"),
21
+ additions: 0,
22
+ removals: 0,
23
+ unchanged: n,
24
+ changed: false,
25
+ };
26
+ }
27
+ // Myers shortest edit script
28
+ const v = { 1: { x: 0, history: [] } };
29
+ for (let d = 0; d <= max; d++) {
30
+ for (let k = -d; k <= d; k += 2) {
31
+ let path;
32
+ // Choose path: go down (insert) or go right (delete)
33
+ if (k === -d || (k !== d && v[k - 1].x < v[k + 1].x)) {
34
+ // Move down: insert from after
35
+ const prev = v[k + 1];
36
+ path = {
37
+ x: prev.x,
38
+ history: [...prev.history, { type: "add", line: afterLines[prev.x - k - 1] ?? "" }],
39
+ };
40
+ }
41
+ else {
42
+ // Move right: delete from before
43
+ const prev = v[k - 1];
44
+ path = {
45
+ x: prev.x + 1,
46
+ history: [...prev.history, { type: "remove", line: beforeLines[prev.x] ?? "" }],
47
+ };
48
+ }
49
+ // Follow diagonal (equal lines)
50
+ while (path.x < n && path.x - k < m && beforeLines[path.x] === afterLines[path.x - k]) {
51
+ path.history = [...path.history, { type: "equal", line: beforeLines[path.x] }];
52
+ path.x++;
53
+ }
54
+ // Check if we reached the end
55
+ if (path.x >= n && path.x - k >= m) {
56
+ let additions = 0;
57
+ let removals = 0;
58
+ let unchanged = 0;
59
+ const lines = [];
60
+ for (const entry of path.history) {
61
+ switch (entry.type) {
62
+ case "equal":
63
+ lines.push(` ${entry.line}`);
64
+ unchanged++;
65
+ break;
66
+ case "add":
67
+ lines.push(`+ ${entry.line}`);
68
+ additions++;
69
+ break;
70
+ case "remove":
71
+ lines.push(`- ${entry.line}`);
72
+ removals++;
73
+ break;
74
+ }
75
+ }
76
+ return {
77
+ diff: lines.join("\n"),
78
+ additions,
79
+ removals,
80
+ unchanged,
81
+ changed: additions > 0 || removals > 0,
82
+ };
83
+ }
84
+ v[k] = path;
85
+ }
86
+ }
87
+ // Should never reach here for valid inputs
88
+ return { diff: "", additions: 0, removals: 0, unchanged: 0, changed: false };
89
+ }
90
+ /**
91
+ * Pixel-level comparison of two screenshots.
92
+ * Opens an isolated page, loads images via intercepted routes,
93
+ * computes per-pixel color distance, generates diff PNG.
94
+ */
95
+ export async function diffScreenshots(context, baseline, current, options = {}) {
96
+ const { threshold = 30, matchThreshold = 1.0 } = options;
97
+ const page = await context.newPage();
98
+ try {
99
+ // Intercept image routes to serve our buffers
100
+ await page.route("**/baseline.png", (route) => {
101
+ route.fulfill({
102
+ status: 200,
103
+ contentType: "image/png",
104
+ body: baseline,
105
+ });
106
+ });
107
+ await page.route("**/current.png", (route) => {
108
+ route.fulfill({
109
+ status: 200,
110
+ contentType: "image/png",
111
+ body: current,
112
+ });
113
+ });
114
+ // Canvas-based pixel diff in browser context
115
+ const result = await page.evaluate(async (thresh) => {
116
+ // Load images
117
+ const loadImage = (src) => new Promise((resolve, reject) => {
118
+ const img = new Image();
119
+ img.onload = () => resolve(img);
120
+ img.onerror = reject;
121
+ img.src = src;
122
+ });
123
+ const [img1, img2] = await Promise.all([
124
+ loadImage("/baseline.png"),
125
+ loadImage("/current.png"),
126
+ ]);
127
+ const width = Math.max(img1.width, img2.width);
128
+ const height = Math.max(img1.height, img2.height);
129
+ // Draw images to canvases
130
+ const canvas1 = document.createElement("canvas");
131
+ canvas1.width = width;
132
+ canvas1.height = height;
133
+ canvas1.getContext("2d").drawImage(img1, 0, 0);
134
+ const canvas2 = document.createElement("canvas");
135
+ canvas2.width = width;
136
+ canvas2.height = height;
137
+ canvas2.getContext("2d").drawImage(img2, 0, 0);
138
+ // Diff canvas
139
+ const diffCanvas = document.createElement("canvas");
140
+ diffCanvas.width = width;
141
+ diffCanvas.height = height;
142
+ const diffCtx = diffCanvas.getContext("2d");
143
+ const data1 = canvas1.getContext("2d").getImageData(0, 0, width, height).data;
144
+ const data2 = canvas2.getContext("2d").getImageData(0, 0, width, height).data;
145
+ const diffData = diffCtx.createImageData(width, height);
146
+ let changed = 0;
147
+ const totalPixels = width * height;
148
+ for (let i = 0; i < data1.length; i += 4) {
149
+ const dr = Math.abs(data1[i] - data2[i]);
150
+ const dg = Math.abs(data1[i + 1] - data2[i + 1]);
151
+ const db = Math.abs(data1[i + 2] - data2[i + 2]);
152
+ const dist = Math.sqrt(dr * dr + dg * dg + db * db);
153
+ if (dist > thresh) {
154
+ // Highlight difference in red
155
+ diffData.data[i] = 255;
156
+ diffData.data[i + 1] = 0;
157
+ diffData.data[i + 2] = 0;
158
+ diffData.data[i + 3] = 200;
159
+ changed++;
160
+ }
161
+ else {
162
+ // Darken unchanged pixels
163
+ diffData.data[i] = Math.floor(data2[i] * 0.3);
164
+ diffData.data[i + 1] = Math.floor(data2[i + 1] * 0.3);
165
+ diffData.data[i + 2] = Math.floor(data2[i + 2] * 0.3);
166
+ diffData.data[i + 3] = 255;
167
+ }
168
+ }
169
+ diffCtx.putImageData(diffData, 0, 0);
170
+ // Export as data URL
171
+ const dataUrl = diffCanvas.toDataURL("image/png");
172
+ return {
173
+ totalPixels,
174
+ changedPixels: changed,
175
+ mismatchPercentage: (changed / totalPixels) * 100,
176
+ dataUrl,
177
+ };
178
+ }, threshold);
179
+ // Convert data URL to buffer
180
+ const base64Data = result.dataUrl.split(",")[1];
181
+ const diffImage = Buffer.from(base64Data, "base64");
182
+ return {
183
+ mismatchPercentage: result.mismatchPercentage,
184
+ match: result.mismatchPercentage <= matchThreshold,
185
+ diffImage,
186
+ totalPixels: result.totalPixels,
187
+ changedPixels: result.changedPixels,
188
+ };
189
+ }
190
+ finally {
191
+ await page.close();
192
+ }
193
+ }
194
+ //# sourceMappingURL=differ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.js","sourceRoot":"","sources":["../../src/snapshot/differ.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Snapshot Extractor — Core engine for ARIA-based page snapshots.
3
+ *
4
+ * Uses Playwright's locator.ariaSnapshot() for the ARIA tree,
5
+ * then post-processes to add [ref=eN] tags for interactive elements.
6
+ * Optionally detects cursor-interactive elements without ARIA roles.
7
+ *
8
+ * Inspired by agent-browser's approach but with:
9
+ * - Per-snapshot ref counter (thread-safe, no global state)
10
+ * - Hybrid cursor detection
11
+ * - Semantic locators (getByRole) for robust element targeting
12
+ */
13
+ import type { EnhancedSnapshot, SnapshotOptions } from "./types.js";
14
+ type Page = import("rebrowser-playwright").Page;
15
+ /**
16
+ * Generate an enhanced ARIA snapshot with ref annotations.
17
+ *
18
+ * Flow:
19
+ * 1. Get ARIA tree from Playwright's ariaSnapshot()
20
+ * 2. Parse each line, identify roles
21
+ * 3. Two-pass ref assignment (count first for dedup, then assign)
22
+ * 4. Optionally detect cursor-interactive elements
23
+ * 5. Build RefMap and annotated tree string
24
+ */
25
+ export declare function getEnhancedSnapshot(page: Page, options?: SnapshotOptions): Promise<EnhancedSnapshot>;
26
+ export {};
27
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/snapshot/extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAU,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE5E,KAAK,IAAI,GAAG,OAAO,sBAAsB,EAAE,IAAI,CAAC;AAkLhD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CAyH3B"}