aws-runtime-bridge 1.9.96 → 1.9.100

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 (123) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +7 -1
  2. package/dist/adapter/AcodeSdkAdapter.js +5 -5
  3. package/dist/adapter/ClaudeSdkAdapter.d.ts +4 -0
  4. package/dist/adapter/ClaudeSdkAdapter.js +2 -2
  5. package/dist/adapter/CodexSdkAdapter.d.ts +2 -0
  6. package/dist/adapter/CodexSdkAdapter.js +3 -3
  7. package/dist/adapter/OpencodeSdkAdapter.d.ts +2 -0
  8. package/dist/adapter/OpencodeSdkAdapter.js +2 -2
  9. package/dist/adapter/idle-poll-loop.d.ts +4 -1
  10. package/dist/adapter/idle-poll-loop.js +1 -1
  11. package/dist/adapter/types.d.ts +4 -2
  12. package/dist/browser/browser-pool.d.ts +73 -0
  13. package/dist/browser/browser-pool.js +2 -0
  14. package/dist/browser/browser-profile-store.d.ts +28 -0
  15. package/dist/browser/browser-profile-store.js +2 -0
  16. package/dist/browser/built-in-browser-tools.d.ts +27 -0
  17. package/dist/browser/built-in-browser-tools.js +2 -0
  18. package/dist/browser/element-locator.d.ts +24 -0
  19. package/dist/browser/element-locator.js +2 -0
  20. package/dist/browser/element-picker.d.ts +17 -0
  21. package/dist/browser/element-picker.js +2 -0
  22. package/dist/browser/input-dispatcher.d.ts +34 -0
  23. package/dist/browser/input-dispatcher.js +2 -0
  24. package/dist/browser/listener-store.d.ts +32 -0
  25. package/dist/browser/listener-store.js +2 -0
  26. package/dist/browser/page-listener-manager.d.ts +106 -0
  27. package/dist/browser/page-listener-manager.js +307 -0
  28. package/dist/browser/page-listener-types.d.ts +90 -0
  29. package/dist/browser/page-listener-types.js +1 -0
  30. package/dist/browser/screencast-manager.d.ts +42 -0
  31. package/dist/browser/screencast-manager.js +2 -0
  32. package/dist/browser/snapshot-serializer.d.ts +15 -0
  33. package/dist/browser/snapshot-serializer.js +5 -0
  34. package/dist/browser/ssrf-guard.d.ts +15 -0
  35. package/dist/browser/ssrf-guard.js +2 -0
  36. package/dist/browser/stealth.d.ts +7 -0
  37. package/dist/browser/stealth.js +173 -0
  38. package/dist/browser/step-archive.d.ts +52 -0
  39. package/dist/browser/step-archive.js +2 -0
  40. package/dist/browser/types.d.ts +192 -0
  41. package/dist/browser/types.js +2 -0
  42. package/dist/browser/ws-server.d.ts +67 -0
  43. package/dist/browser/ws-server.js +2 -0
  44. package/dist/config.d.ts +1 -1
  45. package/dist/index.js +1 -1
  46. package/dist/middleware/auth.d.ts +2 -0
  47. package/dist/middleware/auth.js +1 -1
  48. package/dist/remote-desktop/computer-control.d.ts +30 -0
  49. package/dist/remote-desktop/computer-control.js +2 -0
  50. package/dist/remote-desktop/coords.d.ts +13 -0
  51. package/dist/remote-desktop/coords.js +2 -0
  52. package/dist/remote-desktop/frame-backpressure.d.ts +7 -0
  53. package/dist/remote-desktop/frame-backpressure.js +2 -0
  54. package/dist/remote-desktop/index.d.ts +7 -0
  55. package/dist/remote-desktop/index.js +4 -0
  56. package/dist/remote-desktop/input-backends/interface.d.ts +17 -0
  57. package/dist/remote-desktop/input-backends/interface.js +1 -0
  58. package/dist/remote-desktop/input-backends/key-map.d.ts +2 -0
  59. package/dist/remote-desktop/input-backends/key-map.js +2 -0
  60. package/dist/remote-desktop/input-dispatcher.d.ts +11 -0
  61. package/dist/remote-desktop/input-dispatcher.js +2 -0
  62. package/dist/remote-desktop/permission-manager.d.ts +7 -0
  63. package/dist/remote-desktop/permission-manager.js +2 -0
  64. package/dist/remote-desktop/screen-capture.d.ts +27 -0
  65. package/dist/remote-desktop/screen-capture.js +2 -0
  66. package/dist/remote-desktop/session-manager.d.ts +59 -0
  67. package/dist/remote-desktop/session-manager.js +2 -0
  68. package/dist/remote-desktop/system-backend.d.ts +65 -0
  69. package/dist/remote-desktop/system-backend.js +5 -0
  70. package/dist/remote-desktop/types.d.ts +68 -0
  71. package/dist/remote-desktop/types.js +1 -0
  72. package/dist/remote-desktop/ui-automation.d.ts +48 -0
  73. package/dist/remote-desktop/ui-automation.js +31 -0
  74. package/dist/remote-desktop/win32-api.d.ts +29 -0
  75. package/dist/remote-desktop/win32-api.js +2 -0
  76. package/dist/routes/background-tasks.d.ts +2 -0
  77. package/dist/routes/background-tasks.js +2 -0
  78. package/dist/routes/browser-listeners.d.ts +2 -0
  79. package/dist/routes/browser-listeners.js +2 -0
  80. package/dist/routes/browser-sessions.d.ts +2 -0
  81. package/dist/routes/browser-sessions.js +2 -0
  82. package/dist/routes/instance.js +2 -2
  83. package/dist/routes/pty.js +3 -3
  84. package/dist/routes/terminal.js +30 -30
  85. package/dist/services/agent-pty-manager.d.ts +22 -0
  86. package/dist/services/agent-pty-manager.js +5 -0
  87. package/dist/services/browser-session-manager.d.ts +55 -0
  88. package/dist/services/browser-session-manager.js +12 -0
  89. package/dist/services/cli-commands.d.ts +4 -0
  90. package/dist/services/cli-commands.js +5 -5
  91. package/dist/services/workspace-files.js +1 -1
  92. package/package/acode/dist/await-complete-tool.d.ts +17 -0
  93. package/package/acode/dist/await-complete-tool.js +21 -0
  94. package/package/acode/dist/background-command-manager.d.ts +148 -0
  95. package/package/acode/dist/background-command-manager.js +8 -0
  96. package/package/acode/dist/background-command-store.d.ts +46 -0
  97. package/package/acode/dist/background-command-store.js +2 -0
  98. package/package/acode/dist/background-command-tools.d.ts +5 -0
  99. package/package/acode/dist/background-command-tools.js +18 -0
  100. package/package/acode/dist/background-output-ringbuffer.d.ts +23 -0
  101. package/package/acode/dist/background-output-ringbuffer.js +3 -0
  102. package/package/acode/dist/built-in-file-tools.d.ts +8 -1
  103. package/package/acode/dist/built-in-file-tools.js +2 -2
  104. package/package/acode/dist/compaction.js +6 -6
  105. package/package/acode/dist/index.d.ts +1 -0
  106. package/package/acode/dist/index.js +1 -1
  107. package/package/acode/dist/runtime.d.ts +6 -0
  108. package/package/acode/dist/runtime.js +27 -27
  109. package/package/acode/dist/sub-agent-tools.d.ts +0 -1
  110. package/package/acode/dist/sub-agent-tools.js +11 -28
  111. package/package/acode/dist/terminal-tool.d.ts +7 -0
  112. package/package/acode/dist/terminal-tool.js +2 -0
  113. package/package/acode/dist/terminal-types.d.ts +38 -0
  114. package/package/acode/dist/terminal-types.js +1 -0
  115. package/package/acode/dist/types.d.ts +10 -1
  116. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +3 -1
  117. package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
  118. package/package/aws-client-agent-mcp/dist/logger.d.ts +2 -0
  119. package/package/aws-client-agent-mcp/dist/logger.js +1 -1
  120. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +8 -0
  121. package/package/aws-client-agent-mcp/dist/mcp-server.js +30 -19
  122. package/package/aws-client-agent-mcp/dist/types.d.ts +25 -0
  123. package/package.json +6 -2
@@ -0,0 +1,307 @@
1
+ import{randomUUID as T}from"node:crypto";const w=500,_=200,P=300,E="__bridgeNotifyDomChange";function u(n){if(!n)return"";try{const e=new URL(n);return e.origin+e.pathname}catch{return n}}function y(n,e){let t=n,r=e;e.includes("://")?(t=u(n),r=u(e)):t=L(n)||n;let i="^";for(let s=0;s<r.length;s++){const a=r[s];if(a===":")if(r[s+1]==="/")i+="\\:";else if(r[s+1]!==void 0&&/[0-9]/.test(r[s+1]))i+="\\:";else{for(;s+1<r.length&&/[a-zA-Z0-9_]/.test(r[s+1]);)s++;i+="[^/]+"}else a==="*"?r[s+1]==="*"?(i+=".*",s++):i+="[^/]*":a==="?"?i+=".":".+^${}()|[]\\".includes(a)?i+="\\"+a:i+=a}i+="$";try{return new RegExp(i).test(t)}catch{return!1}}function L(n){if(!n)return"";try{return new URL(n).pathname}catch{return""}}function S(n){if(!n)return"";try{return u(n.url())}catch{return""}}function b(n,e){const t=n.trim();if(!t)return S(e);if(t.includes("://"))return t;if(e)try{const r=new URL(e.url()).origin;if(r)return r+(t.startsWith("/")?"":"/")+t}catch{}return t}const v=["added","removed","changed"];function x(n){if(!Array.isArray(n)||n.length===0)return[...v];const e=new Set;for(const t of n)typeof t=="string"&&(t==="added"||t==="removed"||t==="changed"||t==="exists")&&e.add(t);return e.size>0?[...e]:[...v]}function f(n){if(!n||n.length===0)return!1;for(let e=0;e<n.length;e++){const t=n[e];if(t&&t.nodeType===1)return!0}return!1}function m(n){const e=new Set;if(!n)return e.add("changed"),["changed"];for(let r=0;r<n.length;r++){const i=n[r];if(i.type==="childList"){const s=f(i.addedNodes),a=f(i.removedNodes);s&&e.add("added"),a&&e.add("removed"),!s&&!a&&(i.addedNodes&&i.addedNodes.length>0||i.removedNodes&&i.removedNodes.length>0)&&e.add("changed")}else i.type==="characterData"&&e.add("changed")}if(e.size===0)return["changed"];const t=[];return e.has("added")&&t.push("added"),e.has("removed")&&t.push("removed"),e.has("changed")&&t.push("changed"),t}function I(n){return m(n)[0]??"changed"}function H(n,e,t){return`
2
+ (function() {
3
+ var w = window;
4
+ var DEBOUNCE_MS = ${n};
5
+ var MAX_TEXT = ${e};
6
+ var HIGHLIGHT_ENABLED = ${t?"true":"false"};
7
+ var POLL_INTERVAL = 500;
8
+ var POLL_TIMEOUT = 30000;
9
+ // \u6BCF\u6B21 navigation \u540E\u91CD\u7F6E\uFF08init script \u91CD\u65B0\u6267\u884C\uFF09
10
+ w.__bridgeListeners = {};
11
+ w.__bridgeHighlightEnabled = HIGHLIGHT_ENABLED;
12
+ w.__bridgeHighlightedEls = new Set();
13
+ var overlayLayer = null;
14
+ var boxMap = new Map();
15
+ var badgeRafId = null;
16
+ var highlightStyleReady = false;
17
+ function normalizeUrlForMatch(url) {
18
+ if (!url) return '';
19
+ try { var u = new URL(url); return u.origin + u.pathname; } catch (e) { return url; }
20
+ }
21
+ function matchPath(target, pattern) {
22
+ var targetStr = target;
23
+ var pat = pattern;
24
+ if (pattern.indexOf('://') >= 0) {
25
+ targetStr = normalizeUrlForMatch(target);
26
+ pat = normalizeUrlForMatch(pattern);
27
+ } else {
28
+ try { targetStr = new URL(target).pathname; } catch (e) { targetStr = target; }
29
+ }
30
+ var regexStr = '^';
31
+ for (var i = 0; i < pat.length; i++) {
32
+ var ch = pat[i];
33
+ if (ch === ':') {
34
+ if (pat[i+1] === '/') { regexStr += '\\:'; }
35
+ else if (pat[i+1] !== undefined && /[0-9]/.test(pat[i+1])) { regexStr += '\\:'; }
36
+ else { while (i+1 < pat.length && /[a-zA-Z0-9_]/.test(pat[i+1])) { i++; } regexStr += '[^/]+'; }
37
+ } else if (ch === '*') {
38
+ if (pat[i+1] === '*') { regexStr += '.*'; i++; } else { regexStr += '[^/]*'; }
39
+ } else if (ch === '?') {
40
+ regexStr += '.';
41
+ } else if ('.+^\${}()|[]\\\\'.indexOf(ch) >= 0) {
42
+ regexStr += '\\\\' + ch;
43
+ } else {
44
+ regexStr += ch;
45
+ }
46
+ }
47
+ regexStr += '$';
48
+ try { return new RegExp(regexStr).test(targetStr); } catch (e) { return false; }
49
+ }
50
+ // \u6CE8\u5165\uFF08\u590D\u7528\uFF09\u6A21\u5757\u7EA7\u7EAF\u51FD\u6570\uFF1A\u8282\u70B9/\u53D8\u5316\u7C7B\u578B\u68C0\u6D4B\uFF08\u4E0E Node \u4FA7\u5355\u6D4B\u540C\u4E00\u4EFD\u5B9E\u73B0\uFF0C\u4FDD\u8BC1\u6D4F\u89C8\u5668\u884C\u4E3A\u4E00\u81F4\uFF09\u3002
51
+ ${f.toString()}
52
+ ${m.toString()}
53
+ // \u5143\u7D20\u300C\u5B58\u5728\u300D\u76D1\u542C\uFF1A\u8FB9\u6CBF\u89E6\u53D1\uFF08\u4E0D\u5B58\u5728 \u2192 \u5B58\u5728 \u65F6\u901A\u77E5\u4E00\u6B21\uFF1B\u6D88\u5931\u540E\u518D\u6B21\u51FA\u73B0\u518D\u901A\u77E5\uFF09\u3002
54
+ // \u4E0E added/removed/changed \u4E0D\u540C\uFF0Cexists \u662F\u72B6\u6001\u578B\u76D1\u542C\uFF0C\u7531\u8F6E\u8BE2\u68C0\u6D4B\u800C\u975E MutationObserver\u3002
55
+ function checkPresenceFor(listenerId, entry) {
56
+ if (!entry || !entry.subscribedExists) return;
57
+ if (!matchPath(location.href, entry.pathPattern)) return;
58
+ var present;
59
+ try { present = !!document.querySelector(entry.selector); } catch (e) { present = false; }
60
+ if (present && !entry.lastPresence) {
61
+ // \u5143\u7D20\u4ECE\u4E0D\u5B58\u5728\u53D8\u4E3A\u5B58\u5728\uFF1A\u89E6\u53D1 exists \u4E8B\u4EF6\uFF08\u8FB9\u6CBF\u89E6\u53D1\uFF0C\u907F\u514D\u968F\u8F6E\u8BE2\u5237\u5C4F\uFF09
62
+ var text = '';
63
+ try {
64
+ var el = document.querySelector(entry.selector);
65
+ text = (el && el.textContent ? el.textContent : '').slice(0, MAX_TEXT);
66
+ } catch (e) {}
67
+ entry.lastPresence = true;
68
+ if (w.__bridgeNotifyDomChange) {
69
+ try { w.__bridgeNotifyDomChange(listenerId, text, 'exists'); } catch (e) {}
70
+ }
71
+ } else if (!present && entry.lastPresence) {
72
+ // \u5143\u7D20\u6D88\u5931\uFF1A\u590D\u4F4D\uFF0C\u7B49\u5F85\u4E0B\u6B21\u51FA\u73B0\u518D\u89E6\u53D1
73
+ entry.lastPresence = false;
74
+ }
75
+ }
76
+ // \u2500\u2500 \u9AD8\u4EAE\uFF08\u56DE\u663E\uFF09\uFF1A\u76D1\u542C\u5668\u751F\u6548\u65F6\u5728\u76EE\u6807\u5143\u7D20\u4E0A\u53E0\u52A0\u53EF\u89C6\u6807\u6CE8\uFF08\u9752\u8272\u63CF\u8FB9\u6846\uFF09 \u2500\u2500
77
+ // active \u76D1\u542C\u5668 \u2192 \u5728\u72EC\u7ACB overlay \u5C42\u4E3A\u8BE5\u5143\u7D20\u753B\u4E00\u4E2A\u9752\u8272\u63CF\u8FB9\u6846\uFF08position:fixed + getBoundingClientRect \u5B9A\u4F4D\uFF09\uFF0C
78
+ // \u4E0D\u53D7\u76EE\u6807\u5143\u7D20 z-index / \u540C\u7EA7\u906E\u6321\u5F71\u54CD\uFF0C\u59CB\u7EC8\u4F4D\u4E8E\u6700\u4E0A\u5C42\uFF1B\u4F46\u4F1A\u8DDF\u968F\u5143\u7D20\u5728 overflow:hidden \u7B49\u88C1\u526A\u7956\u5148\u4E2D\u7684\u53EF\u89C1\u533A\u57DF\uFF0C
79
+ // \u5143\u7D20\u88AB\u6EDA\u51FA\u88C1\u526A\u5BB9\u5668\u65F6\u9AD8\u4EAE\u540C\u6B65\u9690\u85CF\uFF08\u5C0A\u91CD overflow \u88C1\u526A\uFF0C\u65B9\u6848 1\uFF09\u3002
80
+ // \u6BCF\u79D2\u7531 presence \u5B9A\u65F6\u5668 reconcile \u4E00\u6B21\uFF0C\u5E76\u5728 install/uninstall \u65F6\u7ACB\u5373 reconcile\uFF0C\u4FDD\u8BC1\u72B6\u6001\u4E0E\u9AD8\u4EAE\u4E00\u81F4\u3002
81
+ var HIGHLIGHT_CSS = ""
82
+ + ".bridge-listener-box{position:fixed;left:0;top:0;box-sizing:border-box;border:2px solid #14b8a6;border-radius:4px;pointer-events:none;z-index:2147483646;}"
83
+ + ".bridge-listener-box--added{border-color:#22c55e;}"
84
+ + ".bridge-listener-box--removed{border-color:#ef4444;}"
85
+ + ".bridge-listener-box--changed{border-color:#facc15;}"
86
+ + ".bridge-listener-box--exists{border-color:#a855f7;}";
87
+ function ensureHighlightApi() {
88
+ if (highlightStyleReady) return;
89
+ var s = document.createElement('style');
90
+ s.id = 'bridge-listener-highlight-style';
91
+ s.textContent = HIGHLIGHT_CSS;
92
+ (document.head || document.documentElement).appendChild(s);
93
+ highlightStyleReady = true;
94
+ }
95
+ function ensureOverlayLayer() {
96
+ if (overlayLayer) return overlayLayer;
97
+ overlayLayer = document.createElement('div');
98
+ overlayLayer.id = 'bridge-listener-overlay';
99
+ overlayLayer.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:2147483647;';
100
+ (document.body || document.documentElement).appendChild(overlayLayer);
101
+ return overlayLayer;
102
+ }
103
+ // \u8BA1\u7B97\u5143\u7D20\u5728\u300C\u6240\u6709 overflow \u88C1\u526A\u7956\u5148\u300D\u9650\u5236\u4E0B\u7684\u53EF\u89C1\u77E9\u5F62\uFF1A
104
+ // \u8BA9\u9AD8\u4EAE\u6846\u53EA\u63CF\u51FA\u771F\u6B63\u53EF\u89C1\u7684\u90E8\u5206\uFF0C\u5143\u7D20\u88AB overflow:hidden \u6EDA\u51FA\u5BB9\u5668\u65F6\u9AD8\u4EAE\u968F\u4E4B\u6D88\u5931\uFF08\u5C0A\u91CD overflow \u88C1\u526A\uFF09\u3002
105
+ function computeVisibleRect(el) {
106
+ var r = el.getBoundingClientRect();
107
+ var left = r.left, top = r.top, right = r.right, bottom = r.bottom;
108
+ var parent = el.parentElement;
109
+ while (parent && parent.nodeType === 1) {
110
+ var cs = getComputedStyle(parent);
111
+ var ox = cs.overflowX, oy = cs.overflowY;
112
+ if ((ox && ox !== 'visible') || (oy && oy !== 'visible')) {
113
+ var pr = parent.getBoundingClientRect();
114
+ var bl = parseFloat(cs.borderLeftWidth) || 0;
115
+ var bt = parseFloat(cs.borderTopWidth) || 0;
116
+ var br = parseFloat(cs.borderRightWidth) || 0;
117
+ var bb = parseFloat(cs.borderBottomWidth) || 0;
118
+ var pl = pr.left + bl, pt = pr.top + bt, prr = pr.right - br, pbb = pr.bottom - bb;
119
+ if (ox && ox !== 'visible') { left = Math.max(left, pl); right = Math.min(right, prr); }
120
+ if (oy && oy !== 'visible') { top = Math.max(top, pt); bottom = Math.min(bottom, pbb); }
121
+ }
122
+ parent = parent.parentElement;
123
+ }
124
+ return { left: left, top: top, right: right, bottom: bottom, width: right - left, height: bottom - top };
125
+ }
126
+ function startBoxRaf() {
127
+ if (badgeRafId) return;
128
+ function loop() {
129
+ if (boxMap.size === 0) { badgeRafId = null; return; }
130
+ boxMap.forEach(function(box, el) {
131
+ try {
132
+ var vr = computeVisibleRect(el);
133
+ if (vr.width <= 0 || vr.height <= 0) {
134
+ box.style.display = 'none';
135
+ return;
136
+ }
137
+ box.style.display = '';
138
+ box.style.left = vr.left + 'px';
139
+ box.style.top = vr.top + 'px';
140
+ box.style.width = vr.width + 'px';
141
+ box.style.height = vr.height + 'px';
142
+ } catch (e) {}
143
+ });
144
+ badgeRafId = requestAnimationFrame(loop);
145
+ }
146
+ badgeRafId = requestAnimationFrame(loop);
147
+ }
148
+ function cleanupHighlight(el) {
149
+ var box = boxMap.get(el);
150
+ if (box) { if (box.parentNode) box.parentNode.removeChild(box); boxMap.delete(el); }
151
+ if (w.__bridgeHighlightedEls) w.__bridgeHighlightedEls.delete(el);
152
+ }
153
+ function applyHighlightClasses(el, ids) {
154
+ ensureHighlightApi();
155
+ var layer = ensureOverlayLayer();
156
+ // \u63CF\u8FB9\u6846\uFF1A\u72EC\u7ACB overlay \u5C42\uFF0C\u907F\u514D\u88AB\u76EE\u6807\u5143\u7D20 z-index / overflow:hidden / \u540C\u7EA7\u906E\u6321
157
+ var box = boxMap.get(el);
158
+ if (!box) {
159
+ box = document.createElement('div');
160
+ box.className = 'bridge-listener-box';
161
+ layer.appendChild(box);
162
+ boxMap.set(el, box);
163
+ }
164
+ // \u6309\u76D1\u542C\u7C7B\u578B\u4E0A\u8272\uFF1A\u547D\u4E2D\u8BE5\u5143\u7D20\u7684\u6240\u6709\u76D1\u542C\u5668\u8BA2\u9605\u7C7B\u578B\u5408\u5E76\u540E\u82E5\u4E3A\u5355\u4E00\u7C7B\u578B \u2192 \u5BF9\u5E94\u989C\u8272\uFF1B
165
+ // \u591A\u7C7B\u578B / \u6DF7\u5408 \u2192 \u4FDD\u6301\u9ED8\u8BA4\u9752\u8272\u3002\u6539\u53D8=\u9EC4 \u5220\u9664=\u7EA2 \u65B0\u589E=\u7EFF \u5B58\u5728=\u7D2B\u3002
166
+ var types = new Set();
167
+ ids.forEach(function(lid) {
168
+ var ent = w.__bridgeListeners[lid];
169
+ if (ent && ent.changeTypesList) {
170
+ for (var i = 0; i < ent.changeTypesList.length; i++) types.add(ent.changeTypesList[i]);
171
+ }
172
+ });
173
+ var typeClass = '';
174
+ if (types.size === 1) {
175
+ var only = types.values().next().value;
176
+ if (only === 'added' || only === 'removed' || only === 'changed' || only === 'exists') {
177
+ typeClass = 'bridge-listener-box--' + only;
178
+ }
179
+ }
180
+ box.className = 'bridge-listener-box' + (typeClass ? ' ' + typeClass : '');
181
+ w.__bridgeHighlightedEls.add(el);
182
+ startBoxRaf();
183
+ }
184
+ function clearAllHighlights() {
185
+ if (w.__bridgeHighlightedEls) {
186
+ var arr = Array.from(w.__bridgeHighlightedEls);
187
+ for (var i = 0; i < arr.length; i++) cleanupHighlight(arr[i]);
188
+ w.__bridgeHighlightedEls.clear();
189
+ }
190
+ boxMap.forEach(function(box) { if (box.parentNode) box.parentNode.removeChild(box); });
191
+ boxMap.clear();
192
+ }
193
+ function reconcileHighlights() {
194
+ if (w.__bridgeHighlightEnabled === false) return;
195
+ var activeEls = new Map();
196
+ for (var lid in w.__bridgeListeners) {
197
+ if (!w.__bridgeListeners.hasOwnProperty(lid)) continue;
198
+ var entry = w.__bridgeListeners[lid];
199
+ var el = null;
200
+ if (matchPath(location.href, entry.pathPattern)) {
201
+ try { el = document.querySelector(entry.selector); } catch (e) { el = null; }
202
+ }
203
+ if (el) {
204
+ if (!activeEls.has(el)) activeEls.set(el, new Set());
205
+ activeEls.get(el).add(lid);
206
+ }
207
+ }
208
+ if (w.__bridgeHighlightedEls) {
209
+ w.__bridgeHighlightedEls.forEach(function(el) { if (!activeEls.has(el)) cleanupHighlight(el); });
210
+ }
211
+ activeEls.forEach(function(ids, el) { applyHighlightClasses(el, ids); });
212
+ }
213
+ function installListener(listenerId, selector, pathPattern, changeTypes) {
214
+ var existing = w.__bridgeListeners[listenerId];
215
+ if (existing) {
216
+ try { if (existing.observer) existing.observer.disconnect(); } catch (e) {}
217
+ if (existing.pollTimer) clearInterval(existing.pollTimer);
218
+ if (existing.debounceTimer) clearTimeout(existing.debounceTimer);
219
+ }
220
+ // \u8BA2\u9605\u7684\u53D8\u5316\u7C7B\u578B\u96C6\u5408\uFF08\u7A7A\u6570\u7EC4\u89C6\u4E3A\u5168\u90E8\uFF0C\u4E0E\u540E\u7AEF normalizeChangeTypes \u4E00\u81F4\uFF09
221
+ var typeSet = {};
222
+ var allMode = true;
223
+ if (changeTypes && Object.prototype.toString.call(changeTypes) === '[object Array]' && changeTypes.length > 0) {
224
+ allMode = false;
225
+ for (var k = 0; k < changeTypes.length; k++) {
226
+ var t = changeTypes[k];
227
+ if (t === 'added' || t === 'removed' || t === 'changed' || t === 'exists') typeSet[t] = true;
228
+ }
229
+ // \u82E5\u6570\u7EC4\u91CC\u6CA1\u6709\u4EFB\u4F55\u5408\u6CD5\u503C\uFF0C\u56DE\u843D\u5168\u90E8\u6A21\u5F0F
230
+ var cnt = 0;
231
+ for (var key in typeSet) { if (typeSet.hasOwnProperty(key)) cnt++; }
232
+ if (cnt === 0) allMode = true;
233
+ }
234
+ function isSubscribed(ct) { return allMode || typeSet.hasOwnProperty(ct); }
235
+ // exists \u4E3A\u72EC\u7ACB\u7684\u72B6\u6001\u578B\u76D1\u542C\uFF08\u975E MutationObserver \u53D8\u5316\u7C7B\u578B\uFF09
236
+ var subscribedExists = allMode || (typeSet['exists'] === true);
237
+ // \u7528\u4E8E\u9AD8\u4EAE\u4E0A\u8272\uFF1A\u5408\u5E76\u8BE5\u76D1\u542C\u5668\u8BA2\u9605\u7684\u5168\u90E8\u53D8\u5316\u7C7B\u578B\uFF08allMode \u89C6\u4E3A added/removed/changed/exists \u5168\u8BA2\u9605\uFF09
238
+ var subscribedTypes = allMode ? ['added', 'removed', 'changed', 'exists'] : Object.keys(typeSet);
239
+ var entry = { selector: selector, pathPattern: pathPattern, observer: null, pollTimer: null, debounceTimer: null, pendingTypes: null, subscribedExists: subscribedExists, lastPresence: null, changeTypesList: subscribedTypes };
240
+ w.__bridgeListeners[listenerId] = entry;
241
+ // exists \u4E0D\u5728\u9875\u9762\u4FA7\u89E6\u53D1\uFF08\u8FB9\u6CBF\u89E6\u53D1\u5DF2\u79FB\u9664\uFF09\uFF1Aexists \u662F\u72B6\u6001\u578B\u76D1\u542C\uFF0C
242
+ // \u4EC5\u7531 Node \u4FA7 scanExistsAtPoll \u5728 poll_message \u65F6\u6309\u5F53\u524D\u771F\u5B9E DOM \u8865\u67E5\u3002
243
+ function tryAttach() {
244
+ if (!matchPath(location.href, pathPattern)) return false;
245
+ var el = null;
246
+ try { el = document.querySelector(selector); } catch (e) { return false; }
247
+ if (!el) return false;
248
+ var obs = new MutationObserver(function(mutations) {
249
+ if (entry.debounceTimer) clearTimeout(entry.debounceTimer);
250
+ // \u9632\u6296\u7A97\u53E3\u5185\u7D2F\u8BA1\u300C\u51FA\u73B0\u8FC7\u7684\u6240\u6709\u53D8\u5316\u7C7B\u578B\u300D\uFF08added/removed/changed \u5404\u81EA\u72EC\u7ACB\uFF0C\u4E92\u4E0D\u8986\u76D6\uFF09
251
+ var batchTypes = detectChangeTypes(mutations);
252
+ if (!entry.pendingTypes) entry.pendingTypes = {};
253
+ for (var bi = 0; bi < batchTypes.length; bi++) entry.pendingTypes[batchTypes[bi]] = true;
254
+ entry.debounceTimer = setTimeout(function() {
255
+ var pts = entry.pendingTypes || {};
256
+ entry.pendingTypes = null;
257
+ var text = (el.textContent || '').slice(0, MAX_TEXT);
258
+ // \u6BCF\u4E2A\u547D\u4E2D\u8BA2\u9605\u96C6\u5408\u7684\u53D8\u5316\u7C7B\u578B\u90FD\u89E6\u53D1\u4E00\u6B21\uFF1A\u65B0\u589E/\u5220\u9664/\u6539\u53D8\u53EF\u540C\u65F6\u53D1\u751F\uFF0C\u4E0D\u80FD\u4E92\u76F8\u541E\u6CA1
259
+ // \uFF08\u4FEE\u590D Issue A\uFF1A\u65E7\u903B\u8F91\u628A add+remove \u5408\u5E76\u6210\u5355\u4E00\u7C7B\u578B\uFF0C\u5BFC\u81F4 removed-only \u6F0F\u89E6\u53D1\uFF09
260
+ for (var t in pts) {
261
+ if (!pts.hasOwnProperty(t)) continue;
262
+ if (!isSubscribed(t)) continue;
263
+ if (w.__bridgeNotifyDomChange) {
264
+ try { w.__bridgeNotifyDomChange(listenerId, text, t); } catch (e) {}
265
+ }
266
+ }
267
+ }, DEBOUNCE_MS);
268
+ });
269
+ try {
270
+ obs.observe(el, { childList: true, characterData: true, subtree: true });
271
+ entry.observer = obs;
272
+ return true;
273
+ } catch (e) { return false; }
274
+ }
275
+ if (tryAttach()) { reconcileHighlights(); return; }
276
+ var startTime = Date.now();
277
+ entry.pollTimer = setInterval(function() {
278
+ if (tryAttach()) { clearInterval(entry.pollTimer); entry.pollTimer = null; reconcileHighlights(); }
279
+ else if (Date.now() - startTime > POLL_TIMEOUT) { clearInterval(entry.pollTimer); entry.pollTimer = null; }
280
+ }, POLL_INTERVAL);
281
+ }
282
+ function uninstallListener(listenerId) {
283
+ var entry = w.__bridgeListeners[listenerId];
284
+ if (entry) {
285
+ try { if (entry.observer) entry.observer.disconnect(); } catch (e) {}
286
+ if (entry.pollTimer) clearInterval(entry.pollTimer);
287
+ if (entry.debounceTimer) clearTimeout(entry.debounceTimer);
288
+ delete w.__bridgeListeners[listenerId];
289
+ }
290
+ reconcileHighlights();
291
+ }
292
+ // \u5168\u5C40\u5B9A\u65F6\u5668\uFF1A\u6BCF 1s \u4EC5\u505A\u9AD8\u4EAE reconcile\uFF08exists \u8FB9\u6CBF\u89E6\u53D1\u5DF2\u79FB\u9664\uFF0C
293
+ // exists \u7531 Node \u4FA7 scanExistsAtPoll \u5728 poll_message \u65F6\u6309\u5F53\u524D DOM \u8865\u67E5\uFF09
294
+ if (w.__bridgePresenceTimer) { try { clearInterval(w.__bridgePresenceTimer); } catch (e) {} }
295
+ w.__bridgePresenceTimer = setInterval(function() {
296
+ if (w.__bridgeHighlightEnabled !== false) reconcileHighlights();
297
+ }, 1000);
298
+ w.__bridgeInstallListener = installListener;
299
+ w.__bridgeUninstallListener = uninstallListener;
300
+ w.__bridgeSetHighlightEnabled = function(v) {
301
+ w.__bridgeHighlightEnabled = !!v;
302
+ if (!w.__bridgeHighlightEnabled) clearAllHighlights();
303
+ else reconcileHighlights();
304
+ };
305
+ })();
306
+ `}class C{constructor(e,t,r){this.listeners=new Map,this.eventQueue=[],this.triggerMeta=new Map,this.pendingChangeTypes=new Map,this.existsLatched=new Set,this.attachedPages=new WeakSet,this.navHandledPages=new WeakSet,this.currentPage=null,this.agentId=e,this.browserId=t,this.config={debounceMs:r?.debounceMs??w,maxTextLength:r?.maxTextLength??_,reattachDelayMs:r?.reattachDelayMs??P,onTrigger:r?.onTrigger,store:r?.store??null,scopeKey:r?.scopeKey??`agent:${e}`,highlight:r?.highlight??(typeof process>"u"||process.env?.AWSB_LISTENER_HIGHLIGHT!=="false")}}getCurrentPage(){return this.currentPage}async loadFromStore(){if(!this.config.store)return 0;try{const e=await this.config.store.load(this.config.scopeKey);let t=0;for(const r of e)this.listeners.has(r.id)||(this.listeners.set(r.id,{...r}),t++);return t>0&&this.currentPage&&await this.reattach(this.currentPage).catch(()=>{}),t}catch{return 0}}async attach(e){this.currentPage=e,await this.ensureExposed(e),this.config.store&&this.listeners.size===0&&await this.loadFromStore().catch(()=>{}),await this.reattach(e),this.attachNavigationHandler(e)}async reattach(e){this.currentPage=e,await this.ensureExposed(e);const t=[];for(const r of this.listeners.values())r.enabled&&t.push(this.installOnPage(e,r).catch(()=>{}));await Promise.all(t)}async addListener(e){if(!e.selector||!e.selector.trim())throw new Error("selector is required");if(!e.prompt||!e.prompt.trim())throw new Error("prompt is required");const t={id:T(),selector:e.selector.trim(),pathPattern:b(e.pathPattern??"",this.currentPage),prompt:e.prompt.trim(),enabled:e.enabled??!0,changeTypes:x(e.changeTypes),createdAt:Date.now()};if(this.listeners.set(t.id,t),t.enabled&&this.currentPage&&await this.installOnPage(this.currentPage,t).catch(()=>{}),this.config.store)try{await this.config.store.add(this.config.scopeKey,t)}catch{}return t}async updateListener(e){const t=this.listeners.get(e.listenerId);if(t){if(typeof e.selector=="string"&&e.selector.trim()&&(t.selector=e.selector.trim()),typeof e.prompt=="string"&&e.prompt.trim()&&(t.prompt=e.prompt.trim()),typeof e.pathPattern=="string"&&(t.pathPattern=b(e.pathPattern,this.currentPage)),Array.isArray(e.changeTypes)&&(t.changeTypes=x(e.changeTypes)),typeof e.enabled=="boolean"&&(t.enabled=e.enabled),this.currentPage&&(t.enabled?await this.installOnPage(this.currentPage,t).catch(()=>{}):await this.uninstallOnPage(this.currentPage,t.id).catch(()=>{})),this.config.store)try{await this.config.store.update(this.config.scopeKey,t)}catch{}return t}}async removeListener(e){if(!this.listeners.get(e))return!1;if(this.listeners.delete(e),this.triggerMeta.delete(e),this.pendingChangeTypes.delete(e),this.existsLatched.delete(e),this.currentPage&&await this.uninstallOnPage(this.currentPage,e).catch(()=>{}),this.config.store)try{await this.config.store.remove(this.config.scopeKey,e)}catch{}return!0}async toggleListener(e,t){const r=this.listeners.get(e);if(!r)return;const i=t??!r.enabled;if(i===r.enabled)return r;if(r.enabled=i,this.currentPage&&(i?await this.installOnPage(this.currentPage,r).catch(()=>{}):await this.uninstallOnPage(this.currentPage,r.id).catch(()=>{})),this.config.store)try{await this.config.store.update(this.config.scopeKey,r)}catch{}return r}async listListeners(){const e=this.currentPage?this.currentPage.url():"",t=[];for(const r of this.listeners.values()){const i={...r,status:"disabled"};r.enabled&&(y(e,r.pathPattern)?this.currentPage&&await this.elementExists(this.currentPage,r.selector)?i.status="active":i.status="inactive_element_missing":i.status="inactive_path_mismatch");const s=this.triggerMeta.get(r.id);s&&(i.lastTriggeredAt=s.at,i.currentUrl=s.url,i.currentText=s.text),t.push(i)}return t}hasPendingEvents(){return this.eventQueue.length>0}enqueueEvent(e){this.eventQueue.push(e)}dequeueEvent(){return this.eventQueue.shift()}collectEvents(){const e=[...this.eventQueue];this.eventQueue.length=0,e.sort((t,r)=>t.triggeredAt-r.triggeredAt);for(const t of e)t.changeType&&this.pendingChangeTypes.get(t.listenerId)?.delete(t.changeType);return this.existsLatched.clear(),e}async scanExistsAtPoll(){const e=this.currentPage;if(!e)return[];const t=e.url(),r=[];for(const l of this.listeners.values())l.enabled&&l.changeTypes.includes("exists")&&y(t,l.pathPattern)&&r.push({id:l.id,selector:l.selector});if(r.length===0)return[];let i=[];try{i=await e.evaluate(l=>l.map(o=>{let c=!1,h="";try{const d=globalThis.document?.querySelector(o.selector)??null;c=!!d,d&&(h=(d.textContent||"").slice(0,4096))}catch{c=!1}return{id:o.id,present:c,text:h}}),r)}catch{return[]}const s=[],a=Date.now();for(const l of i){const o=l.id;if(!l.present){this.existsLatched.delete(o);continue}if(this.existsLatched.has(o))continue;const c=this.listeners.get(o);if(!c||this.eventQueue.some(p=>p.listenerId===l.id&&p.changeType==="exists"))continue;const g=l.text.slice(0,this.config.maxTextLength);this.triggerMeta.set(o,{at:a,url:t,text:g});const d={listenerId:o,prompt:c.prompt,triggeredAt:a,url:t,browserId:this.browserId,text:g,selector:c.selector,changeType:"exists"};this.eventQueue.push(d),this.existsLatched.add(o),s.push(d)}return s}async dispose(){if(this.currentPage)for(const e of this.listeners.values())await this.uninstallOnPage(this.currentPage,e.id).catch(()=>{});this.listeners.clear(),this.triggerMeta.clear(),this.pendingChangeTypes.clear(),this.existsLatched.clear(),this.eventQueue.length=0}async setHighlightEnabled(e){this.currentPage&&await this.currentPage.evaluate(t=>{const r=globalThis;typeof r.__bridgeSetHighlightEnabled=="function"&&r.__bridgeSetHighlightEnabled(t)},e).catch(()=>{})}async ensureExposed(e){if(!this.attachedPages.has(e)){try{await e.exposeFunction(E,(t,r,i)=>{this.handleDomChange(t,r,i)})}catch{}try{await e.addInitScript({content:H(this.config.debounceMs,this.config.maxTextLength,this.config.highlight)})}catch{}this.attachedPages.add(e)}}attachNavigationHandler(e){if(this.navHandledPages.has(e))return;const t=e.on;if(typeof t!="function")return;this.navHandledPages.add(e);let r;t.call(e,"framenavigated",i=>{(typeof i?.isMainFrame!="function"||i.isMainFrame())&&(r&&clearTimeout(r),r=setTimeout(()=>{r=void 0,!(this.currentPage!==e||e.isClosed?.())&&this.reattach(e).catch(()=>{})},this.config.reattachDelayMs))})}handleDomChange(e,t,r){const i=this.listeners.get(e);if(!i||!i.enabled)return;const s=this.currentPage?this.currentPage.url():"",a=Date.now(),l=t?.slice(0,this.config.maxTextLength)??"",o=r??"changed";if(this.triggerMeta.set(e,{at:a,url:s,text:l}),o!=="exists"){let h=this.pendingChangeTypes.get(e);if(h||(h=new Set,this.pendingChangeTypes.set(e,h)),h.has(o))return;h.add(o)}else this.existsLatched.add(e);const c={listenerId:e,prompt:i.prompt,triggeredAt:a,url:s,browserId:this.browserId,text:l,selector:i.selector,changeType:o};this.eventQueue.push(c);try{this.config.onTrigger?.(c,i)}catch{}}async installOnPage(e,t){await e.evaluate(r=>{const i=globalThis;typeof i.__bridgeInstallListener=="function"&&i.__bridgeInstallListener(r.listenerId,r.selector,r.pathPattern,r.changeTypes)},{listenerId:t.id,selector:t.selector,pathPattern:t.pathPattern,changeTypes:t.changeTypes})}async uninstallOnPage(e,t){await e.evaluate(r=>{const i=globalThis;typeof i.__bridgeUninstallListener=="function"&&i.__bridgeUninstallListener(r)},t)}async elementExists(e,t){try{return await e.evaluate(r=>{try{return!!globalThis.document?.querySelector(r)}catch{return!1}},t)}catch{return!1}}}export{C as PageListenerManager,S as derivePathPatternFromUrl,I as detectChangeType,m as detectChangeTypes,L as extractPathname,y as matchPath,f as nodesContainElement};
307
+
@@ -0,0 +1,90 @@
1
+
2
+
3
+ export type ListenerId = string;
4
+
5
+ export type ListenerChangeType = "added" | "removed" | "changed" | "exists";
6
+
7
+ export type ListenerStatus = "active" | "inactive_element_missing" | "inactive_path_mismatch" | "disabled";
8
+
9
+ export interface PageListener {
10
+
11
+ readonly id: ListenerId;
12
+
13
+ selector: string;
14
+
15
+ pathPattern: string;
16
+
17
+ prompt: string;
18
+
19
+ enabled: boolean;
20
+
21
+ changeTypes: ListenerChangeType[];
22
+
23
+ readonly createdAt: number;
24
+ }
25
+
26
+ export interface PageListenerInfo extends PageListener {
27
+
28
+ status: ListenerStatus;
29
+
30
+ currentUrl?: string;
31
+
32
+ lastTriggeredAt?: number;
33
+
34
+ currentText?: string;
35
+ }
36
+
37
+ export interface ListenerTriggerEvent {
38
+
39
+ readonly listenerId: ListenerId;
40
+
41
+ readonly prompt: string;
42
+
43
+ readonly triggeredAt: number;
44
+
45
+ readonly url: string;
46
+
47
+ readonly browserId: string;
48
+
49
+ readonly text?: string;
50
+
51
+ readonly selector?: string;
52
+
53
+ readonly changeType?: ListenerChangeType;
54
+ }
55
+
56
+ export interface ListenerEventQueue {
57
+
58
+ enqueue(event: ListenerTriggerEvent): void;
59
+
60
+ dequeue(): ListenerTriggerEvent | undefined;
61
+
62
+ peek(): ListenerTriggerEvent | undefined;
63
+
64
+ length(): number;
65
+
66
+ clear(): void;
67
+ }
68
+
69
+ export interface PageListenerManagerConfig {
70
+
71
+ debounceMs?: number;
72
+
73
+ maxTextLength?: number;
74
+
75
+ reattachDelayMs?: number;
76
+
77
+ onTrigger?: (event: ListenerTriggerEvent, listener: PageListener) => void;
78
+
79
+ store?: import("./listener-store.js").ListenerStore | null;
80
+
81
+ scopeKey?: string;
82
+
83
+ highlight?: boolean;
84
+ }
85
+
86
+ export interface PathMatchResult {
87
+ matched: boolean;
88
+
89
+ reason?: string;
90
+ }
@@ -0,0 +1,42 @@
1
+
2
+ import type { CDPSession, Page } from "playwright";
3
+ import { type FrameSubscriber, type QualityPresetConfig, type ScreencastConfig, type ScreencastFrame } from "./types.js";
4
+
5
+ export declare class ScreencastManager {
6
+ private config;
7
+
8
+ private currentPage;
9
+
10
+ private currentSession;
11
+
12
+ private isRunning;
13
+
14
+ private readonly subscribers;
15
+
16
+ private lastFrame;
17
+ constructor(config?: ScreencastConfig);
18
+
19
+ subscribe(fn: FrameSubscriber): () => void;
20
+
21
+ start(page: Page): Promise<void>;
22
+
23
+ private handleScreencastFrame;
24
+
25
+ stop(page: Page): Promise<void>;
26
+
27
+ stopAll(): Promise<void>;
28
+
29
+ capture(page: Page): Promise<ScreencastFrame | undefined>;
30
+
31
+ getLastFrame(): ScreencastFrame | undefined;
32
+
33
+ getCurrentCdpSession(): CDPSession | undefined;
34
+
35
+ restartAfterNavigation(page: Page): Promise<void>;
36
+
37
+ updateQuality(preset: QualityPresetConfig): Promise<boolean>;
38
+
39
+ forceCaptureAndPush(page: Page): Promise<void>;
40
+
41
+ dispose(): Promise<void>;
42
+ }
@@ -0,0 +1,2 @@
1
+ import{QUALITY_PRESETS as o}from"./types.js";const h=o.original,u=1,f="jpeg",g=30;class d{constructor(t){this.currentPage=null,this.currentSession=null,this.isRunning=!1,this.subscribers=new Set,this.config={quality:t?.quality??h.quality,maxWidth:t?.maxWidth??h.maxWidth,maxHeight:t?.maxHeight??h.maxHeight,everyNthFrame:t?.everyNthFrame??u,maxFramesPerSecond:t?.maxFramesPerSecond??g,format:t?.format??f}}subscribe(t){if(this.subscribers.add(t),this.subscribers.size===1&&this.currentPage&&!this.isRunning&&this.start(this.currentPage).catch(()=>{}),this.lastFrame){const s=this.lastFrame;setImmediate(()=>{if(this.subscribers.has(t))try{t(s)}catch{}})}return()=>{this.subscribers.delete(t)}}async start(t){if(this.currentPage===t&&this.isRunning)return;this.currentPage&&this.currentPage!==t&&await this.stop(this.currentPage),this.currentPage=t;let s;try{s=await t.context().newCDPSession(t)}catch(e){throw this.isRunning=!1,new Error(`Failed to create CDPSession for screencast: ${e instanceof Error?e.message:String(e)}`)}this.currentSession=s,s.on("Page.screencastFrame",e=>{this.handleScreencastFrame(e,t)});try{await s.send("Page.startScreencast",{format:this.config.format,quality:this.config.quality,maxWidth:this.config.maxWidth,maxHeight:this.config.maxHeight,everyNthFrame:this.config.everyNthFrame,...this.config.maxFramesPerSecond?{maxFramesPerSecond:this.config.maxFramesPerSecond}:{}}),this.isRunning=!0}catch(e){try{await s.detach()}catch{}throw this.currentSession=null,this.isRunning=!1,new Error(`Failed to start screencast: ${e instanceof Error?e.message:String(e)}`)}}handleScreencastFrame(t,s){this.currentSession&&t.sessionId&&this.currentSession.send("Page.screencastFrameAck",{sessionId:t.sessionId}).catch(()=>{});const e=t.data??"",i=t.metadata?.deviceWidth??0,r=t.metadata?.deviceHeight??0;let a="";try{a=s.url()}catch{}const n={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${e}`,base64:e,width:i,height:r,timestamp:Date.now(),url:a};this.lastFrame=n;for(const c of this.subscribers)try{c(n)}catch{}}async stop(t){if(this.currentPage!==t)return;const s=this.currentSession;if(s){try{await s.send("Page.stopScreencast")}catch{}try{await s.detach()}catch{}}this.currentSession=null,this.isRunning=!1,this.currentPage=null}async stopAll(){this.currentPage&&await this.stop(this.currentPage)}async capture(t){if(this.lastFrame&&this.currentPage===t)return this.lastFrame;try{const e=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64"),i=`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${e}`,r=t.viewportSize();return{dataUrl:i,base64:e,width:r?.width??0,height:r?.height??0,timestamp:Date.now(),url:t.url()}}catch{return}}getLastFrame(){return this.lastFrame}getCurrentCdpSession(){return this.currentSession??void 0}async restartAfterNavigation(t){if(this.currentPage===t)try{await this.stop(t)}catch{}let s=!1;for(let e=0;e<2;e++)try{await this.start(t),s=!0;break}catch{e===0&&await new Promise(i=>setTimeout(i,300))}s||(this.isRunning=!1,this.currentSession=null,this.currentPage=null),await this.forceCaptureAndPush(t).catch(()=>{})}async updateQuality(t){this.config={...this.config,quality:t.quality,maxWidth:t.maxWidth,maxHeight:t.maxHeight};const s=this.currentPage;if(!s||!this.isRunning)return!1;try{await this.stop(s)}catch{}try{await this.start(s)}catch{return!1}return this.forceCaptureAndPush(s).catch(()=>{}),!0}async forceCaptureAndPush(t){if(!t||t.isClosed())return;let s;const e=t.viewportSize(),i=e?.width??0,r=e?.height??0;if(this.currentSession)try{s=(await this.currentSession.send("Page.captureScreenshot",{format:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).data}catch{}if(!s)try{s=(await t.screenshot({type:this.config.format==="png"?"png":"jpeg",quality:this.config.format==="png"?void 0:this.config.quality})).toString("base64")}catch{return}let a="";try{a=t.url()}catch{}const n={dataUrl:`data:image/${this.config.format==="png"?"png":"jpeg"};base64,${s}`,base64:s,width:i,height:r,timestamp:Date.now(),url:a};this.lastFrame=n;for(const c of this.subscribers)try{c(n)}catch{}}async dispose(){await this.stopAll(),this.subscribers.clear(),this.lastFrame=void 0}}export{d as ScreencastManager};
2
+
@@ -0,0 +1,15 @@
1
+
2
+ import type { Locator, Page } from "playwright";
3
+
4
+ export declare function buildRefMap(snapshot: string): Map<string, {
5
+ role: string;
6
+ name: string;
7
+ }>;
8
+
9
+ export declare function serializeSnapshot(page: Page, options?: {
10
+ maxChars?: number;
11
+ }): Promise<string>;
12
+
13
+ export declare function locateByRoleName(page: Page, role: string, name?: string): Locator | null;
14
+
15
+ export declare function findElementByRef(page: Page, ref: string): Promise<Locator | null>;
@@ -0,0 +1,5 @@
1
+ const f=16e3,c="ref must be a non-empty string",l=/^\s*-\s+(?<role>[a-zA-Z][\w-]*)(?:\s+"(?<name>[^"]*)")?[^[]*(?:\[ref=(?<ref>e\d+)\])/;function a(t){const n=l.exec(t);if(!n||!n.groups)return null;const r=n.groups.role??"",e=n.groups.name??"",o=n.groups.ref??null;return!r||!o?null:{role:r,name:e,ref:o}}function p(t){const n=new Map;if(!t)return n;for(const r of t.split(`
2
+ `)){const e=a(r);e&&e.ref&&n.set(e.ref,{role:e.role,name:e.name})}return n}async function m(t,n){const r=n?.maxChars??16e3,e=await t.ariaSnapshot({mode:"ai"});return e?e.length<=r?e:`${e.slice(0,r)}
3
+ ... (truncated at ${r} chars)`:"(empty accessibility tree)"}function u(t,n,r){if(!n)return null;try{if(r){const e=r.replace(/\\/g,"\\\\").replace(/"/g,'\\"');return t.locator(`role=${n}[name="${e}"]`).first()}return t.locator(`role=${n}`).first()}catch{return null}}async function d(t,n){if(typeof n!="string"||!n.trim())throw new Error(c);const r=n.trim();if(!/^e\d+$/.test(r))return null;const e=await t.ariaSnapshot({mode:"ai"});if(!e)return null;const o=e.split(`
4
+ `);for(const i of o){const s=a(i);if(!(!s||s.ref!==r))return u(t,s.role,s.name)}return null}export{p as buildRefMap,d as findElementByRef,u as locateByRoleName,m as serializeSnapshot};
5
+
@@ -0,0 +1,15 @@
1
+
2
+ import type { SsrfConfig } from "./types.js";
3
+
4
+ export declare function validateUrl(url: string, config?: SsrfConfig): string;
5
+
6
+ export declare function validateUrlWithDns(url: string, config?: SsrfConfig): Promise<string>;
7
+
8
+ export declare class SsrfGuard {
9
+ private readonly config;
10
+ constructor(config?: SsrfConfig);
11
+
12
+ validate(url: string): string;
13
+
14
+ validateWithDns(url: string): Promise<string>;
15
+ }
@@ -0,0 +1,2 @@
1
+ import*as d from"node:dns/promises";function l(e){const t=e.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);if(!t)return!1;const r=Number(t[1]),o=Number(t[2]);return r===10||r===172&&o>=16&&o<=31||r===192&&o===168||r===127||r===169&&o===254||r===0}function f(e){const t=e.toLowerCase();if(t==="::1"||t.startsWith("fe80:")||t.startsWith("fc")||t.startsWith("fd")||t.startsWith("::")&&!t.startsWith("::ffff:"))return!0;const r=t.match(/::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);return r?l(r[1]):!1}function u(e){const t=e.replace(/^\[/,"").replace(/\]$/,"");return t.includes(":")&&!t.match(/^\d+\.\d+\.\d+\.\d+$/)?f(t):/^\d{1,3}(\.\d{1,3}){3}$/.test(t)?l(t):t.toLowerCase()==="localhost"}function c(e,t){const r=t??{};let o;try{o=new URL(e)}catch{throw new Error(`Invalid URL: ${e}`)}const a=o.protocol.toLowerCase();if(a!=="http:"&&a!=="https:")throw new Error(`Disallowed protocol '${a}' \u2014 only http/https are allowed`);const s=o.hostname;if(r.allowlist&&r.allowlist.length>0&&!r.allowlist.map(n=>n.toLowerCase()).includes(s.toLowerCase()))throw new Error(`Host '${s}' is not in the allowlist`);if(r.blocklist&&r.blocklist.length>0&&r.blocklist.map(n=>n.toLowerCase()).includes(s.toLowerCase()))throw new Error(`Host '${s}' is blocked by ssrf blocklist`);if(!r.allowPrivate&&u(s))throw new Error(`Refusing to navigate to private/loopback address: ${s} (set ssrfConfig.allowPrivate=true to override)`);return o.href}async function w(e,t){const r=c(e,t);if((t??{}).allowPrivate)return r;const s=new URL(r).hostname.replace(/^\[/,"").replace(/\]$/,"");try{const i=await d.lookup(s,{all:!0});for(const n of i)if(l(n.address)||f(n.address))throw new Error(`Refusing to navigate to '${s}' which resolves to private address ${n.address} (DNS rebinding protection; set ssrfConfig.allowPrivate=true to override)`)}catch(i){if(i instanceof Error&&i.message.includes("DNS rebinding protection"))throw i}return r}class h{constructor(t){this.config=t??{}}validate(t){return c(t,this.config)}validateWithDns(t){return w(t,this.config)}}export{h as SsrfGuard,c as validateUrl,w as validateUrlWithDns};
2
+
@@ -0,0 +1,7 @@
1
+
2
+
3
+ export declare const STEALTH_LAUNCH_ARGS: string[];
4
+
5
+ export declare const STEALTH_IGNORE_ARGS: string[];
6
+
7
+ export declare function buildStealthInitScript(chromeMajorVersion: string): string;