@particle-academy/agent-integrations 0.45.0 → 0.47.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 (110) hide show
  1. package/CHANGELOG.md +835 -0
  2. package/LICENSE +21 -0
  3. package/README.md +54 -6
  4. package/dist/bridges/artboard.d.cts +3 -3
  5. package/dist/bridges/artboard.d.ts +3 -3
  6. package/dist/bridges/catalog.d.cts +3 -3
  7. package/dist/bridges/catalog.d.ts +3 -3
  8. package/dist/bridges/charts.d.cts +3 -3
  9. package/dist/bridges/charts.d.ts +3 -3
  10. package/dist/bridges/cms.d.cts +3 -3
  11. package/dist/bridges/cms.d.ts +3 -3
  12. package/dist/bridges/code.d.cts +3 -3
  13. package/dist/bridges/code.d.ts +3 -3
  14. package/dist/bridges/doc.d.cts +3 -3
  15. package/dist/bridges/doc.d.ts +3 -3
  16. package/dist/bridges/features.d.cts +3 -3
  17. package/dist/bridges/features.d.ts +3 -3
  18. package/dist/bridges/files.d.cts +3 -3
  19. package/dist/bridges/files.d.ts +3 -3
  20. package/dist/bridges/flow.d.cts +3 -3
  21. package/dist/bridges/flow.d.ts +3 -3
  22. package/dist/bridges/forms.d.cts +3 -3
  23. package/dist/bridges/forms.d.ts +3 -3
  24. package/dist/bridges/git.d.cts +3 -3
  25. package/dist/bridges/git.d.ts +3 -3
  26. package/dist/bridges/grid.d.cts +3 -3
  27. package/dist/bridges/grid.d.ts +3 -3
  28. package/dist/bridges/map.d.cts +3 -3
  29. package/dist/bridges/map.d.ts +3 -3
  30. package/dist/bridges/navigation.d.cts +127 -0
  31. package/dist/bridges/navigation.d.ts +127 -0
  32. package/dist/bridges/passkeys.d.cts +4 -4
  33. package/dist/bridges/passkeys.d.ts +4 -4
  34. package/dist/bridges/scene.d.cts +3 -3
  35. package/dist/bridges/scene.d.ts +3 -3
  36. package/dist/bridges/screens.d.cts +3 -3
  37. package/dist/bridges/screens.d.ts +3 -3
  38. package/dist/bridges/sheets.d.cts +3 -3
  39. package/dist/bridges/sheets.d.ts +3 -3
  40. package/dist/bridges/slides.d.cts +3 -3
  41. package/dist/bridges/slides.d.ts +3 -3
  42. package/dist/bridges/terminal.d.cts +3 -3
  43. package/dist/bridges/terminal.d.ts +3 -3
  44. package/dist/bridges/tui.d.cts +2 -2
  45. package/dist/bridges/tui.d.ts +2 -2
  46. package/dist/bridges/whiteboard.d.cts +3 -3
  47. package/dist/bridges/whiteboard.d.ts +3 -3
  48. package/dist/bridges-navigation.cjs +391 -0
  49. package/dist/bridges-navigation.cjs.map +1 -0
  50. package/dist/bridges-navigation.js +7 -0
  51. package/dist/bridges-navigation.js.map +1 -0
  52. package/dist/bridges-passkeys.cjs.map +1 -1
  53. package/dist/bridges-passkeys.js +1 -1
  54. package/dist/{chunk-OZBUPO4K.js → chunk-5W34X4EY.js} +263 -58
  55. package/dist/chunk-5W34X4EY.js.map +1 -0
  56. package/dist/{chunk-PWYEW6NL.js → chunk-G6CRHFWU.js} +2 -2
  57. package/dist/{chunk-PWYEW6NL.js.map → chunk-G6CRHFWU.js.map} +1 -1
  58. package/dist/chunk-JGJHPH65.js +271 -0
  59. package/dist/chunk-JGJHPH65.js.map +1 -0
  60. package/dist/dom-navigation/index.d.cts +164 -0
  61. package/dist/dom-navigation/index.d.ts +164 -0
  62. package/dist/dom-navigation/script.d.cts +3 -0
  63. package/dist/dom-navigation/script.d.ts +3 -0
  64. package/dist/dom-navigation-script.cjs +11 -0
  65. package/dist/dom-navigation-script.cjs.map +1 -0
  66. package/dist/dom-navigation-script.js +9 -0
  67. package/dist/dom-navigation-script.js.map +1 -0
  68. package/dist/dom-navigation.cjs +387 -0
  69. package/dist/dom-navigation.cjs.map +1 -0
  70. package/dist/dom-navigation.js +370 -0
  71. package/dist/dom-navigation.js.map +1 -0
  72. package/dist/index.cjs +31 -31
  73. package/dist/index.cjs.map +1 -1
  74. package/dist/index.d.cts +10 -125
  75. package/dist/index.d.ts +10 -125
  76. package/dist/index.js +12 -275
  77. package/dist/index.js.map +1 -1
  78. package/dist/mcp/index.d.cts +5 -5
  79. package/dist/mcp/index.d.ts +5 -5
  80. package/dist/mcp/stdio.d.cts +3 -3
  81. package/dist/mcp/stdio.d.ts +3 -3
  82. package/dist/presence/index.d.cts +1 -1
  83. package/dist/presence/index.d.ts +1 -1
  84. package/dist/relay-server/index.d.cts +110 -26
  85. package/dist/relay-server/index.d.ts +110 -26
  86. package/dist/relay-server-cli.cjs +374 -89
  87. package/dist/relay-server-cli.cjs.map +1 -1
  88. package/dist/relay-server-cli.js +120 -38
  89. package/dist/relay-server-cli.js.map +1 -1
  90. package/dist/relay-server.cjs +255 -51
  91. package/dist/relay-server.cjs.map +1 -1
  92. package/dist/relay-server.js +1 -1
  93. package/dist/{server-BIcA3ZtK.d.cts → server-1y0n61R5.d.cts} +2 -2
  94. package/dist/{server-DnUyeavY.d.ts → server-vq6qVl3T.d.ts} +2 -2
  95. package/dist/sharing/index.d.cts +3 -3
  96. package/dist/sharing/index.d.ts +3 -3
  97. package/dist/sheets-adapter.d.cts +3 -3
  98. package/dist/sheets-adapter.d.ts +3 -3
  99. package/dist/{tool-host-LVBgCN5m.d.cts → tool-host-D67N2a2h.d.cts} +1 -1
  100. package/dist/{tool-host-Wo0pkY83.d.ts → tool-host-LYfdPE8u.d.ts} +1 -1
  101. package/dist/{types-EcElKOlk.d.cts → types-DP5yQZQU.d.cts} +1 -1
  102. package/dist/{types-BxNRKSVd.d.ts → types-VX_9je7w.d.ts} +1 -1
  103. package/dist/{types-C2DtnHIn.d.cts → types-gzIpsUDE.d.cts} +1 -1
  104. package/dist/{types-C2DtnHIn.d.ts → types-gzIpsUDE.d.ts} +1 -1
  105. package/dist/undo/index.d.cts +2 -2
  106. package/dist/undo/index.d.ts +2 -2
  107. package/docs/relay-protocol.md +41 -5
  108. package/docs/relay-server.md +102 -15
  109. package/package.json +41 -3
  110. package/dist/chunk-OZBUPO4K.js.map +0 -1
@@ -0,0 +1,370 @@
1
+ // src/dom-navigation/agent.ts
2
+ var INTERACTIVE = "a[href], button, input, select, textarea, [role=button], [role=link], [role=checkbox], [role=tab], [data-co-handle]";
3
+ var DOM_NAVIGATION_METHODS = [
4
+ "getLocation",
5
+ "describe",
6
+ "read",
7
+ "visit",
8
+ "back",
9
+ "forward",
10
+ "scrollTo",
11
+ "scrollBy",
12
+ "setField",
13
+ "click",
14
+ "submit",
15
+ "rectFor"
16
+ ];
17
+ var tag = (el) => el.tagName.toUpperCase();
18
+ function isVisible(el) {
19
+ const he = el;
20
+ if (el.type === "hidden") return false;
21
+ if (he.hidden || he.getAttribute("aria-hidden") === "true") return false;
22
+ return he.offsetParent !== null || he.getClientRects().length > 0;
23
+ }
24
+ function isSensitive(el) {
25
+ const input = el;
26
+ const ac = (el.getAttribute("autocomplete") ?? "").toLowerCase();
27
+ return input.type === "password" || ac.startsWith("cc-") || ac === "one-time-code" || el.hasAttribute("data-private");
28
+ }
29
+ function insideSensitive(node) {
30
+ for (let el = node.parentElement; el; el = el.parentElement) {
31
+ if (isSensitive(el)) return true;
32
+ }
33
+ return false;
34
+ }
35
+ function safeText(root) {
36
+ const doc = root.ownerDocument ?? root;
37
+ const walker = doc.createTreeWalker(root, 4);
38
+ let out = "";
39
+ for (let n = walker.nextNode(); n; n = walker.nextNode()) {
40
+ if (!insideSensitive(n)) out += n.nodeValue ?? "";
41
+ }
42
+ return out;
43
+ }
44
+ function roleOf(el) {
45
+ const explicit = el.getAttribute("role");
46
+ if (explicit) return explicit;
47
+ const t = tag(el);
48
+ if (t === "A") return "link";
49
+ if (t === "BUTTON") return "button";
50
+ if (t === "SELECT") return "select";
51
+ if (t === "TEXTAREA") return "textbox";
52
+ if (t === "INPUT") {
53
+ const type = el.type;
54
+ if (type === "checkbox") return "checkbox";
55
+ if (type === "radio") return "radio";
56
+ if (type === "submit" || type === "button") return "button";
57
+ return "textbox";
58
+ }
59
+ return "generic";
60
+ }
61
+ function labelFor(doc, id) {
62
+ for (const lbl of Array.from(doc.querySelectorAll("label[for]"))) {
63
+ if (lbl.getAttribute("for") === id) return lbl;
64
+ }
65
+ return null;
66
+ }
67
+ function accessibleName(el) {
68
+ const doc = el.ownerDocument;
69
+ const aria = el.getAttribute("aria-label");
70
+ if (aria) return aria.trim();
71
+ const labelledby = el.getAttribute("aria-labelledby");
72
+ if (labelledby) {
73
+ const txt = labelledby.split(/\s+/).map((id2) => doc.getElementById(id2)?.textContent ?? "").join(" ").trim();
74
+ if (txt) return txt;
75
+ }
76
+ const id = el.getAttribute("id");
77
+ if (id) {
78
+ const lbl = labelFor(doc, id);
79
+ if (lbl?.textContent?.trim()) return lbl.textContent.trim();
80
+ }
81
+ const wrapping = el.closest("label");
82
+ if (wrapping) {
83
+ const txt = safeText(wrapping).trim();
84
+ if (txt) return txt;
85
+ }
86
+ const placeholder = el.getAttribute("placeholder");
87
+ if (placeholder) return placeholder.trim();
88
+ const text = isSensitive(el) ? "" : el.textContent?.trim();
89
+ if (text) return text.replace(/\s+/g, " ").slice(0, 80);
90
+ return el.getAttribute("name") ?? el.getAttribute("id") ?? roleOf(el);
91
+ }
92
+ function isDestructive(el, label) {
93
+ if (el.hasAttribute("data-co-confirm")) return true;
94
+ if (el.type === "submit") return true;
95
+ if (tag(el) === "BUTTON" && el.type === "submit") return true;
96
+ return /\b(delete|remove|destroy|sign out|log ?out|cancel subscription|deactivate)\b/i.test(label);
97
+ }
98
+ function attributeHandle(el) {
99
+ return el.getAttribute("data-co-handle") || el.getAttribute("name") || el.getAttribute("id") || "";
100
+ }
101
+ function walk(doc = document) {
102
+ const registry = /* @__PURE__ */ new Map();
103
+ const actions = [];
104
+ const seen = /* @__PURE__ */ new Set();
105
+ let synthetic = 0;
106
+ for (const el of Array.from(doc.querySelectorAll(INTERACTIVE))) {
107
+ if (seen.has(el) || !isVisible(el)) continue;
108
+ seen.add(el);
109
+ const label = accessibleName(el);
110
+ const role = roleOf(el);
111
+ let handle = attributeHandle(el);
112
+ if (!handle || registry.has(handle)) handle = `${role}#${synthetic++}`;
113
+ registry.set(handle, el);
114
+ let value;
115
+ if (role === "textbox" || role === "select") {
116
+ value = isSensitive(el) ? void 0 : el.value;
117
+ } else if (role === "checkbox" || role === "radio") {
118
+ value = el.checked;
119
+ }
120
+ const action = { handle, role, label, destructive: isDestructive(el, label) };
121
+ if (value !== void 0) action.value = value;
122
+ actions.push(action);
123
+ }
124
+ const loc = doc.defaultView?.location;
125
+ return {
126
+ snapshot: { url: loc ? loc.pathname + loc.search : "", title: doc.title, actions },
127
+ registry
128
+ };
129
+ }
130
+ function isField(el) {
131
+ const t = tag(el);
132
+ return t === "INPUT" || t === "TEXTAREA" || t === "SELECT";
133
+ }
134
+ function setNativeValue(el, value) {
135
+ const view = el.ownerDocument.defaultView ?? globalThis;
136
+ const fire = () => {
137
+ el.dispatchEvent(new view.Event("input", { bubbles: true }));
138
+ el.dispatchEvent(new view.Event("change", { bubbles: true }));
139
+ };
140
+ const t = tag(el);
141
+ if (t === "INPUT" && (el.type === "checkbox" || el.type === "radio")) {
142
+ const setter2 = Object.getOwnPropertyDescriptor(view.HTMLInputElement.prototype, "checked")?.set;
143
+ setter2?.call(el, Boolean(value));
144
+ fire();
145
+ return;
146
+ }
147
+ const proto = t === "TEXTAREA" ? view.HTMLTextAreaElement.prototype : t === "SELECT" ? view.HTMLSelectElement.prototype : view.HTMLInputElement.prototype;
148
+ const setter = Object.getOwnPropertyDescriptor(proto, "value")?.set;
149
+ setter?.call(el, String(value));
150
+ fire();
151
+ }
152
+ function readPage(doc = document) {
153
+ const main = doc.querySelector("main") ?? doc.body;
154
+ if (!main) return doc.title;
155
+ const heads = Array.from(main.querySelectorAll("h1, h2, h3")).map((h) => `${h.tagName}: ${safeText(h).trim()}`).filter(Boolean);
156
+ const text = safeText(main).replace(/\s+/g, " ").trim().slice(0, 4e3);
157
+ return [doc.title, ...heads, "", text].join("\n");
158
+ }
159
+ function findByAttribute(doc, attr, value) {
160
+ for (const el of Array.from(doc.querySelectorAll(`[${attr}]`))) {
161
+ if (el.getAttribute(attr) === value) return el;
162
+ }
163
+ return null;
164
+ }
165
+ var num = (v) => typeof v === "number" ? v : void 0;
166
+ function createDomNavigationAgent(options = {}) {
167
+ let registry = /* @__PURE__ */ new Map();
168
+ const doc = () => options.document ?? document;
169
+ const win = () => doc().defaultView ?? window;
170
+ const before = (action) => options.beforeAction?.(action);
171
+ const resolve = (handle) => {
172
+ const hit = registry.get(handle);
173
+ if (hit && hit.isConnected) return hit;
174
+ const d = doc();
175
+ return findByAttribute(d, "data-co-handle", handle) ?? findByAttribute(d, "name", handle) ?? d.getElementById(handle);
176
+ };
177
+ const agent = {
178
+ getLocation: () => {
179
+ const loc = win().location;
180
+ return { url: loc.pathname + loc.search, title: doc().title };
181
+ },
182
+ describe: () => {
183
+ const res = walk(doc());
184
+ registry = res.registry;
185
+ return res.snapshot;
186
+ },
187
+ read: () => readPage(doc()),
188
+ visit: (url) => {
189
+ const w = win();
190
+ const target = new URL(String(url), w.location.href);
191
+ if (target.protocol !== "http:" && target.protocol !== "https:") {
192
+ throw new Error(`Refusing to navigate to a '${target.protocol}' URL.`);
193
+ }
194
+ w.setTimeout(() => w.location.assign(target.href), 0);
195
+ },
196
+ back: () => win().history.back(),
197
+ forward: () => win().history.forward(),
198
+ scrollTo: ({ x, y, handle }) => {
199
+ const w = win();
200
+ if (handle) {
201
+ resolve(handle)?.scrollIntoView({ behavior: "smooth", block: "center" });
202
+ return;
203
+ }
204
+ w.scrollTo({ left: x ?? w.scrollX, top: y ?? w.scrollY, behavior: "smooth" });
205
+ },
206
+ scrollBy: (dy) => win().scrollBy({ top: dy, behavior: "smooth" }),
207
+ setField: (handle, value) => {
208
+ before("setField");
209
+ const el = resolve(handle);
210
+ if (!el) return { ok: false, error: `No element for handle "${handle}"` };
211
+ if (isField(el)) {
212
+ setNativeValue(el, value);
213
+ return { ok: true };
214
+ }
215
+ return { ok: false, error: `Handle "${handle}" is not a form field` };
216
+ },
217
+ click: (handle) => {
218
+ const el = resolve(handle);
219
+ if (!el) return { ok: false, error: `No element for handle "${handle}"` };
220
+ before("click");
221
+ el.click();
222
+ return { ok: true };
223
+ },
224
+ submit: (handle) => {
225
+ const el = resolve(handle);
226
+ if (!el) return { ok: false, error: `No element for handle "${handle}"` };
227
+ const form = tag(el) === "FORM" ? el : el.closest("form");
228
+ if (!form) return { ok: false, error: `Handle "${handle}" is not inside a form` };
229
+ before("submit");
230
+ if (typeof form.requestSubmit === "function") form.requestSubmit();
231
+ else form.submit();
232
+ return { ok: true };
233
+ },
234
+ rectFor: (handle) => {
235
+ const el = resolve(handle);
236
+ if (!el) return null;
237
+ const r = el.getBoundingClientRect();
238
+ return { x: r.left, y: r.top, width: r.width, height: r.height };
239
+ },
240
+ resolve,
241
+ call: (method, args = []) => {
242
+ const a = Array.isArray(args) ? args : [];
243
+ const handle = String(a[0] ?? "");
244
+ switch (method) {
245
+ case "getLocation":
246
+ return agent.getLocation();
247
+ case "describe":
248
+ return agent.describe();
249
+ case "read":
250
+ return agent.read();
251
+ case "visit":
252
+ agent.visit(String(a[0] ?? ""));
253
+ return void 0;
254
+ case "back":
255
+ agent.back();
256
+ return void 0;
257
+ case "forward":
258
+ agent.forward();
259
+ return void 0;
260
+ case "scrollTo": {
261
+ const o = a[0] && typeof a[0] === "object" ? a[0] : {};
262
+ agent.scrollTo({
263
+ x: num(o.x),
264
+ y: num(o.y),
265
+ handle: typeof o.handle === "string" ? o.handle : void 0
266
+ });
267
+ return void 0;
268
+ }
269
+ case "scrollBy":
270
+ agent.scrollBy(Number(a[0] ?? 0));
271
+ return void 0;
272
+ case "setField":
273
+ return agent.setField(handle, a[1]);
274
+ case "click":
275
+ return agent.click(handle);
276
+ case "submit":
277
+ return agent.submit(handle);
278
+ case "rectFor":
279
+ return agent.rectFor(handle);
280
+ default:
281
+ throw new Error(`Unknown dom-navigation method: ${String(method)}`);
282
+ }
283
+ }
284
+ };
285
+ return agent;
286
+ }
287
+
288
+ // src/dom-navigation/remote.ts
289
+ var DOM_NAVIGATION_GLOBAL = "__fancyDomNavigation";
290
+ var DOM_NAVIGATION_PROTOCOL = 1;
291
+ var METHODS = new Set(DOM_NAVIGATION_METHODS);
292
+ function assertMethod(method) {
293
+ if (!METHODS.has(method)) throw new Error(`Unknown dom-navigation method: ${method}`);
294
+ }
295
+ function domNavigationCallScript(method, args = []) {
296
+ assertMethod(method);
297
+ const g = JSON.stringify(DOM_NAVIGATION_GLOBAL);
298
+ return `(function(){var n=globalThis[${g}];if(!n||typeof n.call!=="function")throw new Error("fancy dom-navigation is not injected in this world");return n.call(${JSON.stringify(method)},${JSON.stringify(args)});})()`;
299
+ }
300
+ var str = (v, fallback = "") => typeof v === "string" ? v : fallback;
301
+ var isObj = (v) => typeof v === "object" && v !== null;
302
+ function coerceAction(v) {
303
+ if (!isObj(v) || typeof v.handle !== "string" || v.handle === "") return null;
304
+ const action = {
305
+ handle: v.handle,
306
+ role: str(v.role, "generic"),
307
+ label: str(v.label),
308
+ destructive: v.destructive === true
309
+ };
310
+ const value = v.value;
311
+ if (typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value)) {
312
+ action.value = value;
313
+ }
314
+ return action;
315
+ }
316
+ function coerceSnapshot(v) {
317
+ const o = isObj(v) ? v : {};
318
+ const actions = Array.isArray(o.actions) ? o.actions.map(coerceAction).filter((a) => a !== null) : [];
319
+ return { url: str(o.url), title: str(o.title), actions };
320
+ }
321
+ function coerceResult(v) {
322
+ const o = isObj(v) ? v : {};
323
+ return { ok: o.ok === true, error: typeof o.error === "string" ? o.error : void 0 };
324
+ }
325
+ function coerceRect(v) {
326
+ if (!isObj(v)) return null;
327
+ const { x, y, width, height } = v;
328
+ const finite = (n) => typeof n === "number" && Number.isFinite(n);
329
+ return finite(x) && finite(y) && finite(width) && finite(height) ? { x, y, width, height } : null;
330
+ }
331
+ function createRemoteNavigationAdapter(options) {
332
+ const { transport } = options;
333
+ const call = (method, ...args) => transport.call(method, args);
334
+ const fail = (e) => ({ ok: false, error: e instanceof Error ? e.message : String(e) });
335
+ return {
336
+ screenId: options.screenId,
337
+ getRevision: options.getRevision,
338
+ confirm: options.confirm,
339
+ getLocation: async () => {
340
+ const o = await call("getLocation");
341
+ const loc = isObj(o) ? o : {};
342
+ return { url: str(loc.url), title: str(loc.title) };
343
+ },
344
+ describe: async () => coerceSnapshot(await call("describe")),
345
+ read: async () => str(await call("read")),
346
+ visit: async (url) => {
347
+ await call("visit", url);
348
+ },
349
+ back: async () => {
350
+ await call("back");
351
+ },
352
+ forward: async () => {
353
+ await call("forward");
354
+ },
355
+ scrollTo: async (opts) => {
356
+ await call("scrollTo", { x: opts.x, y: opts.y, handle: opts.handle });
357
+ },
358
+ scrollBy: async (dy) => {
359
+ await call("scrollBy", dy);
360
+ },
361
+ setField: async (handle, value) => coerceResult(await call("setField", handle, value).catch(fail)),
362
+ click: async (handle) => coerceResult(await call("click", handle).catch(fail)),
363
+ submit: async (handle) => coerceResult(await call("submit", handle).catch(fail)),
364
+ rectFor: async (handle) => coerceRect(await call("rectFor", handle).catch(() => null))
365
+ };
366
+ }
367
+
368
+ export { DOM_NAVIGATION_GLOBAL, DOM_NAVIGATION_METHODS, DOM_NAVIGATION_PROTOCOL, INTERACTIVE, accessibleName, attributeHandle, createDomNavigationAgent, createRemoteNavigationAdapter, domNavigationCallScript, isDestructive, isSensitive, isVisible, readPage, roleOf, setNativeValue, walk };
369
+ //# sourceMappingURL=dom-navigation.js.map
370
+ //# sourceMappingURL=dom-navigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dom-navigation/agent.ts","../src/dom-navigation/remote.ts"],"names":["id","setter"],"mappings":"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","file":"dom-navigation.js","sourcesContent":["/**\n * The in-page half of DOM co-browsing: a framework-free walker that turns a\n * live document into a {@link PageSnapshot} of stable handles, and acts on\n * those handles.\n *\n * Extracted from px-ui-sandbox's CoBrowseProvider so a host that does NOT own\n * the page (Genie's browser, showing sites through an Electron\n * WebContentsView) can run the same walker, injected into an isolated world.\n *\n * Constraints this file holds, because the injected IIFE is built from it:\n *\n * - NO runtime imports. Type-only imports are erased; anything else would be\n * bundled into a script that must run with no module loader.\n * - Nothing touches `document` / `window` until a method is called, so the\n * script can be evaluated in a context with no DOM at all.\n * - Every result is plain, structured-cloneable data.\n *\n * Trust boundary: the page is hostile input. It controls every attribute,\n * label and text node read here. Two consequences:\n * - Sensitive values (passwords, card fields, one-time codes, anything marked\n * `data-private`) are masked HERE, before anything leaves the page — the host\n * cannot mask what it has already received.\n * - Handles are compared as plain strings, never spliced into a CSS selector,\n * so a crafted handle cannot change what a lookup matches.\n */\nimport type { PageAction, PageSnapshot } from \"../bridges/navigation\";\n\n/** Elements the walker considers actionable. */\nexport const INTERACTIVE =\n \"a[href], button, input, select, textarea, [role=button], [role=link], [role=checkbox], [role=tab], [data-co-handle]\";\n\n/** Every method the in-page agent answers. The wire protocol is exactly this list. */\nexport const DOM_NAVIGATION_METHODS = [\n \"getLocation\",\n \"describe\",\n \"read\",\n \"visit\",\n \"back\",\n \"forward\",\n \"scrollTo\",\n \"scrollBy\",\n \"setField\",\n \"click\",\n \"submit\",\n \"rectFor\",\n] as const;\n\nexport type DomNavigationMethod = (typeof DOM_NAVIGATION_METHODS)[number];\n\nexport type ActionResult = { ok: boolean; error?: string };\nexport type HandleRect = { x: number; y: number; width: number; height: number };\n\ntype FieldElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;\n\nconst tag = (el: Element) => el.tagName.toUpperCase();\n\nexport function isVisible(el: Element): boolean {\n const he = el as HTMLElement;\n if ((el as HTMLInputElement).type === \"hidden\") return false;\n if (he.hidden || he.getAttribute(\"aria-hidden\") === \"true\") return false;\n return he.offsetParent !== null || he.getClientRects().length > 0;\n}\n\n/** Sensitive fields whose value is never read into the snapshot. */\nexport function isSensitive(el: Element): boolean {\n const input = el as HTMLInputElement;\n const ac = (el.getAttribute(\"autocomplete\") ?? \"\").toLowerCase();\n return (\n input.type === \"password\" ||\n ac.startsWith(\"cc-\") ||\n ac === \"one-time-code\" ||\n el.hasAttribute(\"data-private\")\n );\n}\n\n/** True when this node, or any element containing it, is sensitive. */\nfunction insideSensitive(node: Node): boolean {\n for (let el = node.parentElement; el; el = el.parentElement) {\n if (isSensitive(el)) return true;\n }\n return false;\n}\n\n/** textContent, minus any text that sits inside a sensitive element. */\nfunction safeText(root: Node): string {\n const doc = root.ownerDocument ?? (root as Document);\n // NodeFilter.SHOW_TEXT === 4; the literal avoids depending on a NodeFilter global.\n const walker = doc.createTreeWalker(root, 4);\n let out = \"\";\n for (let n = walker.nextNode(); n; n = walker.nextNode()) {\n if (!insideSensitive(n)) out += n.nodeValue ?? \"\";\n }\n return out;\n}\n\nexport function roleOf(el: Element): string {\n const explicit = el.getAttribute(\"role\");\n if (explicit) return explicit;\n const t = tag(el);\n if (t === \"A\") return \"link\";\n if (t === \"BUTTON\") return \"button\";\n if (t === \"SELECT\") return \"select\";\n if (t === \"TEXTAREA\") return \"textbox\";\n if (t === \"INPUT\") {\n const type = (el as HTMLInputElement).type;\n if (type === \"checkbox\") return \"checkbox\";\n if (type === \"radio\") return \"radio\";\n if (type === \"submit\" || type === \"button\") return \"button\";\n return \"textbox\";\n }\n return \"generic\";\n}\n\nfunction labelFor(doc: Document, id: string): Element | null {\n // Equivalent to querySelector(`label[for=\"${CSS.escape(id)}\"]`) — first match\n // in document order — without building a selector from page-controlled text.\n for (const lbl of Array.from(doc.querySelectorAll(\"label[for]\"))) {\n if (lbl.getAttribute(\"for\") === id) return lbl;\n }\n return null;\n}\n\nexport function accessibleName(el: Element): string {\n const doc = el.ownerDocument;\n const aria = el.getAttribute(\"aria-label\");\n if (aria) return aria.trim();\n const labelledby = el.getAttribute(\"aria-labelledby\");\n if (labelledby) {\n const txt = labelledby\n .split(/\\s+/)\n .map((id) => doc.getElementById(id)?.textContent ?? \"\")\n .join(\" \")\n .trim();\n if (txt) return txt;\n }\n const id = el.getAttribute(\"id\");\n if (id) {\n const lbl = labelFor(doc, id);\n if (lbl?.textContent?.trim()) return lbl.textContent.trim();\n }\n const wrapping = el.closest(\"label\");\n if (wrapping) {\n const txt = safeText(wrapping).trim();\n if (txt) return txt;\n }\n const placeholder = el.getAttribute(\"placeholder\");\n if (placeholder) return placeholder.trim();\n // A sensitive field's own text is its value (a textarea's content), so it is\n // never used as its name.\n const text = isSensitive(el) ? \"\" : (el as HTMLElement).textContent?.trim();\n if (text) return text.replace(/\\s+/g, \" \").slice(0, 80);\n return el.getAttribute(\"name\") ?? el.getAttribute(\"id\") ?? roleOf(el);\n}\n\nexport function isDestructive(el: Element, label: string): boolean {\n if (el.hasAttribute(\"data-co-confirm\")) return true;\n if ((el as HTMLInputElement).type === \"submit\") return true;\n if (tag(el) === \"BUTTON\" && (el as HTMLButtonElement).type === \"submit\") return true;\n return /\\b(delete|remove|destroy|sign out|log ?out|cancel subscription|deactivate)\\b/i.test(label);\n}\n\n/**\n * The element's own stable handle: data-co-handle → name → id, or \"\" when it\n * has none. An EMPTY attribute counts as absent — `button.name` is `\"\"`, not\n * null, on every button, anchor and input without one, so a plain `??` chain\n * never reaches the id.\n */\nexport function attributeHandle(el: Element): string {\n return (\n el.getAttribute(\"data-co-handle\") ||\n el.getAttribute(\"name\") ||\n el.getAttribute(\"id\") ||\n \"\"\n );\n}\n\n/**\n * Build a fresh snapshot + a handle→element registry. Handle preference:\n * data-co-handle → name → id → `role#index` (stable within a snapshot).\n */\nexport function walk(doc: Document = document): { snapshot: PageSnapshot; registry: Map<string, Element> } {\n const registry = new Map<string, Element>();\n const actions: PageAction[] = [];\n const seen = new Set<Element>();\n let synthetic = 0;\n\n for (const el of Array.from(doc.querySelectorAll(INTERACTIVE))) {\n if (seen.has(el) || !isVisible(el)) continue;\n seen.add(el);\n const label = accessibleName(el);\n const role = roleOf(el);\n let handle = attributeHandle(el);\n if (!handle || registry.has(handle)) handle = `${role}#${synthetic++}`;\n registry.set(handle, el);\n\n let value: unknown;\n if (role === \"textbox\" || role === \"select\") {\n value = isSensitive(el) ? undefined : (el as HTMLInputElement).value;\n } else if (role === \"checkbox\" || role === \"radio\") {\n value = (el as HTMLInputElement).checked;\n }\n\n const action: PageAction = { handle, role, label, destructive: isDestructive(el, label) };\n if (value !== undefined) action.value = value;\n actions.push(action);\n }\n\n const loc = doc.defaultView?.location;\n return {\n snapshot: { url: loc ? loc.pathname + loc.search : \"\", title: doc.title, actions },\n registry,\n };\n}\n\nfunction isField(el: Element): el is FieldElement {\n const t = tag(el);\n return t === \"INPUT\" || t === \"TEXTAREA\" || t === \"SELECT\";\n}\n\n/**\n * Set a field's value so a React-controlled input sees the change: call the\n * PROTOTYPE setter (React shadows `value` on the instance with its value\n * tracker), then dispatch bubbling `input` + `change`.\n */\nexport function setNativeValue(el: FieldElement, value: unknown): void {\n const view = (el.ownerDocument.defaultView ?? globalThis) as typeof globalThis;\n const fire = () => {\n el.dispatchEvent(new view.Event(\"input\", { bubbles: true }));\n el.dispatchEvent(new view.Event(\"change\", { bubbles: true }));\n };\n const t = tag(el);\n if (t === \"INPUT\" && ((el as HTMLInputElement).type === \"checkbox\" || (el as HTMLInputElement).type === \"radio\")) {\n const setter = Object.getOwnPropertyDescriptor(view.HTMLInputElement.prototype, \"checked\")?.set;\n setter?.call(el, Boolean(value));\n fire();\n return;\n }\n const proto =\n t === \"TEXTAREA\"\n ? view.HTMLTextAreaElement.prototype\n : t === \"SELECT\"\n ? view.HTMLSelectElement.prototype\n : view.HTMLInputElement.prototype;\n const setter = Object.getOwnPropertyDescriptor(proto, \"value\")?.set;\n setter?.call(el, String(value));\n fire();\n}\n\n/** Visible text / heading outline, with sensitive text removed. */\nexport function readPage(doc: Document = document): string {\n const main = doc.querySelector(\"main\") ?? doc.body;\n if (!main) return doc.title;\n const heads = Array.from(main.querySelectorAll(\"h1, h2, h3\"))\n .map((h) => `${h.tagName}: ${safeText(h).trim()}`)\n .filter(Boolean);\n const text = safeText(main).replace(/\\s+/g, \" \").trim().slice(0, 4000);\n return [doc.title, ...heads, \"\", text].join(\"\\n\");\n}\n\nexport type DomNavigationAgentOptions = {\n /** Document to drive. Default: the global `document`, read lazily. */\n document?: Document;\n /**\n * Called just before the agent acts on the page — before resolving a field\n * for `setField`, and after resolving (only when the element exists) for\n * `click` / `submit`. The sandbox uses it to attribute the request an action\n * causes to the agent.\n */\n beforeAction?: (action: \"setField\" | \"click\" | \"submit\") => void;\n};\n\nexport type DomNavigationAgent = {\n getLocation(): { url: string; title: string };\n describe(): PageSnapshot;\n read(): string;\n /** Navigate. Only http(s) or same-site paths; deferred a tick so a remote call returns first. */\n visit(url: string): void;\n back(): void;\n forward(): void;\n scrollTo(opts: { x?: number; y?: number; handle?: string }): void;\n scrollBy(dy: number): void;\n setField(handle: string, value: unknown): ActionResult;\n click(handle: string): ActionResult;\n submit(handle: string): ActionResult;\n rectFor(handle: string): HandleRect | null;\n /** Element for a handle: this snapshot's registry, then a live attribute lookup. */\n resolve(handle: string): Element | null;\n /** Serialisable dispatch — what the injected script exposes to a host. */\n call(method: DomNavigationMethod, args?: unknown[]): unknown;\n};\n\nfunction findByAttribute(doc: Document, attr: string, value: string): Element | null {\n for (const el of Array.from(doc.querySelectorAll(`[${attr}]`))) {\n if (el.getAttribute(attr) === value) return el;\n }\n return null;\n}\n\nconst num = (v: unknown) => (typeof v === \"number\" ? v : undefined);\n\nexport function createDomNavigationAgent(options: DomNavigationAgentOptions = {}): DomNavigationAgent {\n let registry = new Map<string, Element>();\n const doc = () => options.document ?? document;\n const win = () => (doc().defaultView ?? window) as Window;\n const before = (action: \"setField\" | \"click\" | \"submit\") => options.beforeAction?.(action);\n\n const resolve = (handle: string): Element | null => {\n const hit = registry.get(handle);\n if (hit && hit.isConnected) return hit;\n // Fallback: a real attribute handle the agent may use before describe().\n const d = doc();\n return (\n findByAttribute(d, \"data-co-handle\", handle) ??\n findByAttribute(d, \"name\", handle) ??\n d.getElementById(handle)\n );\n };\n\n const agent: DomNavigationAgent = {\n getLocation: () => {\n const loc = win().location;\n return { url: loc.pathname + loc.search, title: doc().title };\n },\n describe: () => {\n const res = walk(doc());\n registry = res.registry;\n return res.snapshot;\n },\n read: () => readPage(doc()),\n visit: (url) => {\n const w = win();\n const target = new URL(String(url), w.location.href);\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") {\n throw new Error(`Refusing to navigate to a '${target.protocol}' URL.`);\n }\n w.setTimeout(() => w.location.assign(target.href), 0);\n },\n back: () => win().history.back(),\n forward: () => win().history.forward(),\n scrollTo: ({ x, y, handle }) => {\n const w = win();\n if (handle) {\n resolve(handle)?.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n return;\n }\n w.scrollTo({ left: x ?? w.scrollX, top: y ?? w.scrollY, behavior: \"smooth\" });\n },\n scrollBy: (dy) => win().scrollBy({ top: dy, behavior: \"smooth\" }),\n setField: (handle, value) => {\n before(\"setField\");\n const el = resolve(handle);\n if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n if (isField(el)) {\n setNativeValue(el, value);\n return { ok: true };\n }\n return { ok: false, error: `Handle \"${handle}\" is not a form field` };\n },\n click: (handle) => {\n const el = resolve(handle);\n if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n // Before the click: an Inertia link fires its visit synchronously inside click().\n before(\"click\");\n (el as HTMLElement).click();\n return { ok: true };\n },\n submit: (handle) => {\n const el = resolve(handle);\n if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n const form = (tag(el) === \"FORM\" ? el : el.closest(\"form\")) as HTMLFormElement | null;\n if (!form) return { ok: false, error: `Handle \"${handle}\" is not inside a form` };\n before(\"submit\");\n if (typeof form.requestSubmit === \"function\") form.requestSubmit();\n else form.submit();\n return { ok: true };\n },\n rectFor: (handle) => {\n const el = resolve(handle);\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left, y: r.top, width: r.width, height: r.height };\n },\n resolve,\n call: (method, args = []) => {\n const a = Array.isArray(args) ? args : [];\n const handle = String(a[0] ?? \"\");\n switch (method) {\n case \"getLocation\":\n return agent.getLocation();\n case \"describe\":\n return agent.describe();\n case \"read\":\n return agent.read();\n case \"visit\":\n agent.visit(String(a[0] ?? \"\"));\n return undefined;\n case \"back\":\n agent.back();\n return undefined;\n case \"forward\":\n agent.forward();\n return undefined;\n case \"scrollTo\": {\n const o = (a[0] && typeof a[0] === \"object\" ? a[0] : {}) as Record<string, unknown>;\n agent.scrollTo({\n x: num(o.x),\n y: num(o.y),\n handle: typeof o.handle === \"string\" ? o.handle : undefined,\n });\n return undefined;\n }\n case \"scrollBy\":\n agent.scrollBy(Number(a[0] ?? 0));\n return undefined;\n case \"setField\":\n return agent.setField(handle, a[1]);\n case \"click\":\n return agent.click(handle);\n case \"submit\":\n return agent.submit(handle);\n case \"rectFor\":\n return agent.rectFor(handle);\n default:\n throw new Error(`Unknown dom-navigation method: ${String(method)}`);\n }\n },\n };\n return agent;\n}\n","/**\n * The host half: a {@link NavigationBridgeAdapter} that drives a page it does\n * not run in, through any transport that can carry a method name and plain\n * arguments into the page and a plain result back — Electron's\n * `executeJavaScript` / `executeJavaScriptInIsolatedWorld`, a MessagePort, a\n * WebSocket to a remote browser.\n *\n * Every result is treated as hostile: the page owns the DOM the in-page walker\n * reads, and if the script was injected into the MAIN world the page can\n * replace the walker outright. So results are coerced to the declared shapes\n * here, and anything malformed is dropped rather than passed on to the agent.\n */\nimport type {\n NavigationBridgeAdapter,\n NavigationConfirmRequest,\n PageAction,\n PageSnapshot,\n} from \"../bridges/navigation\";\nimport { DOM_NAVIGATION_METHODS, type ActionResult, type DomNavigationMethod, type HandleRect } from \"./agent\";\n\n/** The global the injected script installs in the world it runs in. */\nexport const DOM_NAVIGATION_GLOBAL = \"__fancyDomNavigation\";\n\n/** Bumped only if the wire protocol changes incompatibly. */\nexport const DOM_NAVIGATION_PROTOCOL = 1;\n\n/**\n * Carries one call into the page. `args` and the resolved value are plain,\n * structured-cloneable data. Reject (or throw) when the call could not be\n * delivered — e.g. the page navigated and the script must be re-injected.\n */\nexport type DomNavigationTransport = {\n call(method: DomNavigationMethod, args: unknown[]): Promise<unknown>;\n};\n\nexport type RemoteNavigationAdapterOptions = {\n transport: DomNavigationTransport;\n /** Optional fancy-screens screen id for presence targeting. */\n screenId?: string;\n /** Human-control revision, if the host tracks one. Omit to disable stale-intent protection. */\n getRevision?: () => number | Promise<number>;\n /**\n * Trust-but-verify. Without it, `page_submit` and destructive `page_click`\n * are NOT staged — they run as soon as the agent asks. A host showing pages\n * it does not own should always supply one.\n */\n confirm?: (req: NavigationConfirmRequest) => Promise<boolean>;\n};\n\nconst METHODS = new Set<string>(DOM_NAVIGATION_METHODS);\n\nfunction assertMethod(method: string): asserts method is DomNavigationMethod {\n if (!METHODS.has(method)) throw new Error(`Unknown dom-navigation method: ${method}`);\n}\n\n/**\n * A JavaScript expression that performs one call against the injected global —\n * what a host passes to `executeJavaScript`. Arguments are embedded as JSON,\n * which is a valid JS expression, so no argument can break out of its literal.\n */\nexport function domNavigationCallScript(method: DomNavigationMethod, args: unknown[] = []): string {\n assertMethod(method);\n const g = JSON.stringify(DOM_NAVIGATION_GLOBAL);\n return (\n `(function(){var n=globalThis[${g}];` +\n `if(!n||typeof n.call!==\"function\")throw new Error(\"fancy dom-navigation is not injected in this world\");` +\n `return n.call(${JSON.stringify(method)},${JSON.stringify(args)});})()`\n );\n}\n\nconst str = (v: unknown, fallback = \"\") => (typeof v === \"string\" ? v : fallback);\nconst isObj = (v: unknown): v is Record<string, unknown> => typeof v === \"object\" && v !== null;\n\nfunction coerceAction(v: unknown): PageAction | null {\n if (!isObj(v) || typeof v.handle !== \"string\" || v.handle === \"\") return null;\n const action: PageAction = {\n handle: v.handle,\n role: str(v.role, \"generic\"),\n label: str(v.label),\n destructive: v.destructive === true,\n };\n const value = v.value;\n if (typeof value === \"string\" || typeof value === \"boolean\" || (typeof value === \"number\" && Number.isFinite(value))) {\n action.value = value;\n }\n return action;\n}\n\nfunction coerceSnapshot(v: unknown): PageSnapshot {\n const o = isObj(v) ? v : {};\n const actions = Array.isArray(o.actions)\n ? o.actions.map(coerceAction).filter((a): a is PageAction => a !== null)\n : [];\n return { url: str(o.url), title: str(o.title), actions };\n}\n\nfunction coerceResult(v: unknown): ActionResult {\n const o = isObj(v) ? v : {};\n return { ok: o.ok === true, error: typeof o.error === \"string\" ? o.error : undefined };\n}\n\nfunction coerceRect(v: unknown): HandleRect | null {\n if (!isObj(v)) return null;\n const { x, y, width, height } = v;\n const finite = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n);\n return finite(x) && finite(y) && finite(width) && finite(height) ? { x, y, width, height } : null;\n}\n\n/** Build a NavigationBridgeAdapter backed by a transport into the page. */\nexport function createRemoteNavigationAdapter(options: RemoteNavigationAdapterOptions): NavigationBridgeAdapter {\n const { transport } = options;\n const call = (method: DomNavigationMethod, ...args: unknown[]) => transport.call(method, args);\n const fail = (e: unknown): ActionResult => ({ ok: false, error: e instanceof Error ? e.message : String(e) });\n\n return {\n screenId: options.screenId,\n getRevision: options.getRevision,\n confirm: options.confirm,\n getLocation: async () => {\n const o = await call(\"getLocation\");\n const loc = isObj(o) ? o : {};\n return { url: str(loc.url), title: str(loc.title) };\n },\n describe: async () => coerceSnapshot(await call(\"describe\")),\n read: async () => str(await call(\"read\")),\n visit: async (url) => {\n await call(\"visit\", url);\n },\n back: async () => {\n await call(\"back\");\n },\n forward: async () => {\n await call(\"forward\");\n },\n scrollTo: async (opts) => {\n await call(\"scrollTo\", { x: opts.x, y: opts.y, handle: opts.handle });\n },\n scrollBy: async (dy) => {\n await call(\"scrollBy\", dy);\n },\n setField: async (handle, value) => coerceResult(await call(\"setField\", handle, value).catch(fail)),\n click: async (handle) => coerceResult(await call(\"click\", handle).catch(fail)),\n submit: async (handle) => coerceResult(await call(\"submit\", handle).catch(fail)),\n rectFor: async (handle) => coerceRect(await call(\"rectFor\", handle).catch(() => null)),\n };\n}\n"]}
package/dist/index.cjs CHANGED
@@ -3422,8 +3422,8 @@ function registerNavigationBridge(host, options) {
3422
3422
  const pendingMode = options.pendingMode ?? true;
3423
3423
  const disposers = [];
3424
3424
  let groundedRevision = null;
3425
- const staleIntent = () => {
3426
- const current = adapter.getRevision?.();
3425
+ const staleIntent = async () => {
3426
+ const current = await adapter.getRevision?.();
3427
3427
  if (current === void 0) return null;
3428
3428
  if (groundedRevision === null || groundedRevision !== current) {
3429
3429
  return errorResult(
@@ -3470,9 +3470,9 @@ function registerNavigationBridge(host, options) {
3470
3470
  "Describe the current page: its URL, title, and the interactive elements you can act on (each with a stable `handle`, role, and label). Call this first, and again after navigating.",
3471
3471
  {},
3472
3472
  [],
3473
- () => {
3474
- const snap = adapter.describe();
3475
- const revision = adapter.getRevision?.();
3473
+ async () => {
3474
+ const snap = await adapter.describe();
3475
+ const revision = await adapter.getRevision?.();
3476
3476
  if (revision !== void 0) {
3477
3477
  snap.revision = revision;
3478
3478
  groundedRevision = revision;
@@ -3492,7 +3492,7 @@ function registerNavigationBridge(host, options) {
3492
3492
  "Read the page's visible text / heading outline for grounding.",
3493
3493
  {},
3494
3494
  [],
3495
- () => textResult(adapter.read ? adapter.read() : "(host did not provide page text)"),
3495
+ async () => textResult(adapter.read ? await adapter.read() : "(host did not provide page text)"),
3496
3496
  () => target("Read page")
3497
3497
  );
3498
3498
  reg(
@@ -3500,15 +3500,15 @@ function registerNavigationBridge(host, options) {
3500
3500
  "Move the agent's visible focus to an interactive element by stable handle without activating it.",
3501
3501
  { handle: { type: "string" } },
3502
3502
  ["handle"],
3503
- (args) => {
3504
- const stale = staleIntent();
3503
+ async (args) => {
3504
+ const stale = await staleIntent();
3505
3505
  if (stale) return stale;
3506
3506
  const handle = String(args.handle ?? "");
3507
- const action = adapter.describe().actions.find((candidate) => candidate.handle === handle);
3507
+ const action = (await adapter.describe()).actions.find((candidate) => candidate.handle === handle);
3508
3508
  if (!action) return errorResult(`No element for handle "${handle}"`);
3509
3509
  return textResult(`Focused ${handle}`, {
3510
3510
  handle,
3511
- rect: adapter.rectFor?.(handle) ?? void 0
3511
+ rect: await adapter.rectFor?.(handle) ?? void 0
3512
3512
  });
3513
3513
  },
3514
3514
  (args) => target(`Focus ${String(args.handle ?? "")}`, String(args.handle ?? ""))
@@ -3519,7 +3519,7 @@ function registerNavigationBridge(host, options) {
3519
3519
  { url: { type: "string", description: "Path like /packages or an absolute URL." } },
3520
3520
  ["url"],
3521
3521
  async (args) => {
3522
- const stale = staleIntent();
3522
+ const stale = await staleIntent();
3523
3523
  if (stale) return stale;
3524
3524
  const url = String(args.url ?? "");
3525
3525
  if (!url) return errorResult("url is required");
@@ -3529,7 +3529,7 @@ function registerNavigationBridge(host, options) {
3529
3529
  `Refusing to navigate to a '${scheme}:' URL. Only http(s) URLs or same-site paths are allowed.`
3530
3530
  );
3531
3531
  }
3532
- const from = adapter.getLocation().url;
3532
+ const from = (await adapter.getLocation()).url;
3533
3533
  await adapter.visit(url);
3534
3534
  fancyAutoCommon.pushUndoEntry(agent.id, {
3535
3535
  timestamp: Date.now(),
@@ -3553,7 +3553,7 @@ function registerNavigationBridge(host, options) {
3553
3553
  {},
3554
3554
  [],
3555
3555
  async () => {
3556
- const stale = staleIntent();
3556
+ const stale = await staleIntent();
3557
3557
  if (stale) return stale;
3558
3558
  if (!adapter.back) return errorResult("Host did not provide back navigation.");
3559
3559
  await adapter.back();
@@ -3567,7 +3567,7 @@ function registerNavigationBridge(host, options) {
3567
3567
  {},
3568
3568
  [],
3569
3569
  async () => {
3570
- const stale = staleIntent();
3570
+ const stale = await staleIntent();
3571
3571
  if (stale) return stale;
3572
3572
  if (!adapter.forward) return errorResult("Host did not provide forward navigation.");
3573
3573
  await adapter.forward();
@@ -3584,16 +3584,16 @@ function registerNavigationBridge(host, options) {
3584
3584
  y: { type: "number" }
3585
3585
  },
3586
3586
  [],
3587
- (args) => {
3588
- const stale = staleIntent();
3587
+ async (args) => {
3588
+ const stale = await staleIntent();
3589
3589
  if (stale) return stale;
3590
3590
  const handle = typeof args.handle === "string" ? args.handle : void 0;
3591
- adapter.scrollTo({
3591
+ await adapter.scrollTo({
3592
3592
  handle,
3593
3593
  x: typeof args.x === "number" ? args.x : void 0,
3594
3594
  y: typeof args.y === "number" ? args.y : void 0
3595
3595
  });
3596
- return textResult("Scrolled", handle ? { handle, rect: adapter.rectFor?.(handle) ?? void 0 } : void 0);
3596
+ return textResult("Scrolled", handle ? { handle, rect: await adapter.rectFor?.(handle) ?? void 0 } : void 0);
3597
3597
  },
3598
3598
  () => target("Scroll")
3599
3599
  );
@@ -3602,10 +3602,10 @@ function registerNavigationBridge(host, options) {
3602
3602
  "Scroll the page by a vertical delta in pixels (negative scrolls up).",
3603
3603
  { dy: { type: "number" } },
3604
3604
  ["dy"],
3605
- (args) => {
3606
- const stale = staleIntent();
3605
+ async (args) => {
3606
+ const stale = await staleIntent();
3607
3607
  if (stale) return stale;
3608
- adapter.scrollBy(Number(args.dy ?? 0));
3608
+ await adapter.scrollBy(Number(args.dy ?? 0));
3609
3609
  return textResult(`Scrolled by ${Number(args.dy ?? 0)}px`);
3610
3610
  },
3611
3611
  () => target("Scroll")
@@ -3618,13 +3618,13 @@ function registerNavigationBridge(host, options) {
3618
3618
  value: { description: "Value to set; type matches the field." }
3619
3619
  },
3620
3620
  ["handle", "value"],
3621
- (args) => {
3622
- const stale = staleIntent();
3621
+ async (args) => {
3622
+ const stale = await staleIntent();
3623
3623
  if (stale) return stale;
3624
3624
  const handle = String(args.handle ?? "");
3625
- const res = adapter.setField(handle, args.value);
3625
+ const res = await adapter.setField(handle, args.value);
3626
3626
  if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);
3627
- return textResult(`${handle} \u2190 ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: adapter.rectFor?.(handle) ?? void 0 });
3627
+ return textResult(`${handle} \u2190 ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: await adapter.rectFor?.(handle) ?? void 0 });
3628
3628
  },
3629
3629
  (args) => target(`Set ${String(args.handle ?? "")}`, String(args.handle ?? ""))
3630
3630
  );
@@ -3634,16 +3634,16 @@ function registerNavigationBridge(host, options) {
3634
3634
  { handle: { type: "string" } },
3635
3635
  ["handle"],
3636
3636
  async (args) => {
3637
- const stale = staleIntent();
3637
+ const stale = await staleIntent();
3638
3638
  if (stale) return stale;
3639
3639
  const handle = String(args.handle ?? "");
3640
- const action = adapter.describe().actions.find((a) => a.handle === handle);
3641
- const rect = adapter.rectFor?.(handle) ?? void 0;
3640
+ const action = (await adapter.describe()).actions.find((a) => a.handle === handle);
3641
+ const rect = await adapter.rectFor?.(handle) ?? void 0;
3642
3642
  if (pendingMode && action?.destructive && adapter.confirm) {
3643
3643
  const ok = await adapter.confirm({ action: "click", handle, label: action.label });
3644
3644
  if (!ok) return errorResult("Declined by user");
3645
3645
  }
3646
- const res = adapter.click(handle);
3646
+ const res = await adapter.click(handle);
3647
3647
  if (!res.ok) return errorResult(res.error ?? `Could not click ${handle}`);
3648
3648
  return textResult(`Clicked ${handle}`, { handle, rect });
3649
3649
  },
@@ -3655,10 +3655,10 @@ function registerNavigationBridge(host, options) {
3655
3655
  { handle: { type: "string" } },
3656
3656
  ["handle"],
3657
3657
  async (args) => {
3658
- const stale = staleIntent();
3658
+ const stale = await staleIntent();
3659
3659
  if (stale) return stale;
3660
3660
  const handle = String(args.handle ?? "");
3661
- const rect = adapter.rectFor?.(handle) ?? void 0;
3661
+ const rect = await adapter.rectFor?.(handle) ?? void 0;
3662
3662
  if (pendingMode && adapter.confirm) {
3663
3663
  const ok = await adapter.confirm({ action: "submit", handle, label: handle });
3664
3664
  if (!ok) return errorResult("Declined by user");