@nexface/tools 0.1.15-alpha.1 → 0.1.15-alpha.11

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 (87) hide show
  1. package/dist/browser/actions.js +34 -10
  2. package/dist/browser/controller.js +91 -76
  3. package/dist/browser/diagnostics.js +8 -3
  4. package/dist/browser/dom.js +23 -30
  5. package/dist/browser/feedback.js +6 -5
  6. package/dist/browser/focus.d.ts +0 -1
  7. package/dist/browser/focus.js +1 -13
  8. package/dist/browser/locator.js +3 -9
  9. package/dist/browser/prompt.d.ts +1 -1
  10. package/dist/browser/prompt.generated.d.ts +1 -1
  11. package/dist/browser/prompt.generated.js +9 -4
  12. package/dist/browser/prompt.js +0 -1
  13. package/dist/browser/snapshot.js +199 -117
  14. package/dist/browser/toolset.js +42 -36
  15. package/dist/browser/types.d.ts +1 -1
  16. package/dist/browser/types.js +0 -1
  17. package/dist/browser/worker-runner.js +0 -1
  18. package/dist/definition.d.ts +1 -3
  19. package/dist/definition.js +2 -2
  20. package/dist/index.browser.js +0 -1
  21. package/dist/index.js +0 -1
  22. package/dist/internal-react.d.ts +1 -1
  23. package/dist/internal-react.js +3 -4
  24. package/dist/internal-types.js +0 -1
  25. package/dist/navigation.js +0 -1
  26. package/dist/operation-lock.d.ts +1 -1
  27. package/dist/operation-lock.js +36 -19
  28. package/dist/operation-runtime.js +41 -13
  29. package/dist/operation-surface.js +118 -41
  30. package/dist/operation-types.js +0 -1
  31. package/dist/operation-view.d.ts +1 -1
  32. package/dist/operation-view.js +232 -82
  33. package/dist/react.js +9 -14
  34. package/dist/registration.js +4 -3
  35. package/dist/runtime.d.ts +4 -2
  36. package/dist/runtime.js +114 -52
  37. package/dist/shared/definition.js +2 -3
  38. package/dist/shared/errors.d.ts +1 -1
  39. package/dist/shared/errors.js +0 -1
  40. package/dist/shared/page-protocol.js +0 -1
  41. package/dist/shared/page-tools.js +2 -3
  42. package/dist/shared/runtime-controller.d.ts +1 -0
  43. package/dist/shared/runtime-controller.js +0 -1
  44. package/dist/shared/runtime-execution.js +0 -1
  45. package/dist/shared/schema.js +45 -19
  46. package/dist/styles.css +882 -109
  47. package/dist/tool-search.d.ts +11 -0
  48. package/dist/tool-search.js +117 -0
  49. package/dist/types.js +0 -1
  50. package/dist/webmcp.js +39 -13
  51. package/package.json +8 -4
  52. package/dist/browser/actions.js.map +0 -1
  53. package/dist/browser/controller.js.map +0 -1
  54. package/dist/browser/diagnostics.js.map +0 -1
  55. package/dist/browser/dom.js.map +0 -1
  56. package/dist/browser/feedback.js.map +0 -1
  57. package/dist/browser/focus.js.map +0 -1
  58. package/dist/browser/locator.js.map +0 -1
  59. package/dist/browser/prompt.generated.js.map +0 -1
  60. package/dist/browser/prompt.js.map +0 -1
  61. package/dist/browser/snapshot.js.map +0 -1
  62. package/dist/browser/toolset.js.map +0 -1
  63. package/dist/browser/types.js.map +0 -1
  64. package/dist/browser/worker-runner.js.map +0 -1
  65. package/dist/definition.js.map +0 -1
  66. package/dist/index.browser.js.map +0 -1
  67. package/dist/index.js.map +0 -1
  68. package/dist/internal-react.js.map +0 -1
  69. package/dist/internal-types.js.map +0 -1
  70. package/dist/navigation.js.map +0 -1
  71. package/dist/operation-lock.js.map +0 -1
  72. package/dist/operation-runtime.js.map +0 -1
  73. package/dist/operation-surface.js.map +0 -1
  74. package/dist/operation-types.js.map +0 -1
  75. package/dist/operation-view.js.map +0 -1
  76. package/dist/react.js.map +0 -1
  77. package/dist/registration.js.map +0 -1
  78. package/dist/runtime.js.map +0 -1
  79. package/dist/shared/definition.js.map +0 -1
  80. package/dist/shared/errors.js.map +0 -1
  81. package/dist/shared/page-protocol.js.map +0 -1
  82. package/dist/shared/page-tools.js.map +0 -1
  83. package/dist/shared/runtime-controller.js.map +0 -1
  84. package/dist/shared/runtime-execution.js.map +0 -1
  85. package/dist/shared/schema.js.map +0 -1
  86. package/dist/types.js.map +0 -1
  87. package/dist/webmcp.js.map +0 -1
@@ -6,12 +6,22 @@ export function collectElementActions(actions, ref, element, role, label, state,
6
6
  return;
7
7
  const id = `a${actions.size + 1}`;
8
8
  actions.set(id, {
9
- candidate: { id, operation, ref, role, label: (optionElement ? `${label} / ${option}` : label).slice(0, 500), state, ...(option === undefined ? {} : { option: option.slice(0, 500) }) },
9
+ candidate: {
10
+ id,
11
+ operation,
12
+ ref,
13
+ role,
14
+ label: (optionElement ? `${label} / ${option}` : label).slice(0, 500),
15
+ state,
16
+ ...(option === undefined ? {} : { option: option.slice(0, 500) }),
17
+ },
10
18
  command: { target, method, args },
11
19
  ...(optionElement ? { optionElement } : {}),
12
20
  });
13
21
  };
14
- if (state.disabled || element.closest('[inert],[aria-disabled="true"]') || element.matches(":disabled"))
22
+ if (state.disabled ||
23
+ element.closest('[inert],[aria-disabled="true"]') ||
24
+ element.matches(":disabled"))
15
25
  return;
16
26
  if (scrollable) {
17
27
  if (element.scrollTop > 0)
@@ -30,18 +40,25 @@ export function collectElementActions(actions, ref, element, role, label, state,
30
40
  counts.set(option.value, (counts.get(option.value) ?? 0) + 1);
31
41
  for (const option of element.options) {
32
42
  if (element.multiple) {
33
- if (counts.get(option.value) === 1 && !option.disabled && !option.closest("optgroup[disabled]")) {
43
+ if (counts.get(option.value) === 1 &&
44
+ !option.disabled &&
45
+ !option.closest("optgroup[disabled]")) {
34
46
  add(option.selected ? "uncheck" : "check", "setOptionSelected", [option.value, !option.selected, option.label], option.label, option);
35
47
  }
36
48
  continue;
37
49
  }
38
- if (counts.get(option.value) === 1 && !(element.required && option.value === "") && !option.disabled && !option.selected && !option.closest("optgroup[disabled]"))
50
+ if (counts.get(option.value) === 1 &&
51
+ !(element.required && option.value === "") &&
52
+ !option.disabled &&
53
+ !option.selected &&
54
+ !option.closest("optgroup[disabled]"))
39
55
  add("select", "selectOption", [option.value], option.label);
40
56
  }
41
57
  return;
42
58
  }
43
- if (role === "option" && element.closest('[role="listbox"]')?.getAttribute("aria-multiselectable") === "true"
44
- && ["true", "false"].includes(element.getAttribute("aria-selected") ?? "")) {
59
+ if (role === "option" &&
60
+ element.closest('[role="listbox"]')?.getAttribute("aria-multiselectable") === "true" &&
61
+ ["true", "false"].includes(element.getAttribute("aria-selected") ?? "")) {
45
62
  const field = computeName(element.closest('[role="listbox"]'));
46
63
  label = field ? `${field} / ${label}` : label;
47
64
  add(state.selected ? "uncheck" : "check", state.selected ? "uncheck" : "check", []);
@@ -54,15 +71,23 @@ export function collectElementActions(actions, ref, element, role, label, state,
54
71
  add("uncheck", "uncheck", []);
55
72
  return;
56
73
  }
57
- const editable = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || (element instanceof HTMLElement && element.isContentEditable);
58
- if (editable && !("readOnly" in element && element.readOnly) && element.getAttribute("aria-readonly") !== "true" && ["textbox", "searchbox", "combobox", "spinbutton"].includes(role)) {
74
+ const editable = element instanceof HTMLInputElement ||
75
+ element instanceof HTMLTextAreaElement ||
76
+ (element instanceof HTMLElement && element.isContentEditable);
77
+ if (editable &&
78
+ !("readOnly" in element && element.readOnly) &&
79
+ element.getAttribute("aria-readonly") !== "true" &&
80
+ ["textbox", "searchbox", "combobox", "spinbutton"].includes(role)) {
59
81
  add("fill", "fill", []);
60
82
  }
61
83
  add("click", "click", []);
62
84
  }
63
85
  export function collectPageActions(actions) {
64
86
  const add = (id, operation, method, args) => {
65
- actions.set(id, { candidate: { id, operation, label: operation, role: "page", state: {} }, command: { target: { type: "page" }, method, args } });
87
+ actions.set(id, {
88
+ candidate: { id, operation, label: operation, role: "page", state: {} },
89
+ command: { target: { type: "page" }, method, args },
90
+ });
66
91
  };
67
92
  if (window.scrollY > 0)
68
93
  add("pageUp", "scrollUp", "scrollBy", [{ y: -560 }]);
@@ -70,4 +95,3 @@ export function collectPageActions(actions) {
70
95
  add("pageDown", "scrollDown", "scrollBy", [{ y: 560 }]);
71
96
  add("wait", "wait", "waitForTimeout", [100]);
72
97
  }
73
- //# sourceMappingURL=actions.js.map
@@ -20,11 +20,7 @@ const LOCATOR_METHODS = new Set([
20
20
  "text",
21
21
  "waitFor",
22
22
  ]);
23
- const PAGE_METHODS = new Set([
24
- "scrollBy",
25
- "waitForTimeout",
26
- "waitForURL",
27
- ]);
23
+ const PAGE_METHODS = new Set(["scrollBy", "waitForTimeout", "waitForURL"]);
28
24
  const WAIT_FOR_URL_TIMEOUT_MS = 3_000;
29
25
  const URL_POLL_INTERVAL_MS = 50;
30
26
  const ACTION_METHODS = new Set([
@@ -65,7 +61,7 @@ function dispatchClickSequence(element) {
65
61
  message: "Click target does not have an uncovered hit point.",
66
62
  });
67
63
  }
68
- const { element: hitTarget, clientX, clientY, } = hit;
64
+ const { element: hitTarget, clientX, clientY } = hit;
69
65
  const init = {
70
66
  bubbles: true,
71
67
  cancelable: true,
@@ -195,8 +191,7 @@ function validateArgs(command, maxChars) {
195
191
  }
196
192
  if (command.method === "selectOption") {
197
193
  if (command.args.length !== 1 ||
198
- (typeof command.args[0] !== "string" &&
199
- !Array.isArray(command.args[0]))) {
194
+ (typeof command.args[0] !== "string" && !Array.isArray(command.args[0]))) {
200
195
  throw invalidCommand("selectOption() requires a string or string array.");
201
196
  }
202
197
  if (Array.isArray(command.args[0]) &&
@@ -204,8 +199,11 @@ function validateArgs(command, maxChars) {
204
199
  throw invalidCommand("selectOption() array values must be strings.");
205
200
  }
206
201
  }
207
- if (command.method === "setOptionSelected" && (command.args.length !== 3
208
- || typeof command.args[0] !== "string" || typeof command.args[1] !== "boolean" || typeof command.args[2] !== "string")) {
202
+ if (command.method === "setOptionSelected" &&
203
+ (command.args.length !== 3 ||
204
+ typeof command.args[0] !== "string" ||
205
+ typeof command.args[1] !== "boolean" ||
206
+ typeof command.args[2] !== "string")) {
209
207
  throw invalidCommand("Invalid observed option selection.");
210
208
  }
211
209
  if (command.method === "waitFor") {
@@ -221,9 +219,7 @@ function validateArgs(command, maxChars) {
221
219
  throw invalidCommand("waitFor() state is invalid.");
222
220
  }
223
221
  if (value?.timeout !== undefined &&
224
- (typeof value.timeout !== "number" ||
225
- !Number.isFinite(value.timeout) ||
226
- value.timeout < 0)) {
222
+ (typeof value.timeout !== "number" || !Number.isFinite(value.timeout) || value.timeout < 0)) {
227
223
  throw invalidCommand("waitFor() timeout is invalid.");
228
224
  }
229
225
  }
@@ -264,10 +260,8 @@ function validateArgs(command, maxChars) {
264
260
  Array.isArray(value) ||
265
261
  Object.keys(value).length === 0 ||
266
262
  Object.keys(value).some((key) => !["x", "y"].includes(key)) ||
267
- (value.x !== undefined &&
268
- (typeof value.x !== "number" || !Number.isFinite(value.x))) ||
269
- (value.y !== undefined &&
270
- (typeof value.y !== "number" || !Number.isFinite(value.y)))) {
263
+ (value.x !== undefined && (typeof value.x !== "number" || !Number.isFinite(value.x))) ||
264
+ (value.y !== undefined && (typeof value.y !== "number" || !Number.isFinite(value.y)))) {
271
265
  throw invalidCommand("scrollBy() requires finite numeric x/y values.");
272
266
  }
273
267
  }
@@ -281,8 +275,7 @@ function validateArgs(command, maxChars) {
281
275
  Object.keys(value).some((key) => !["left", "top"].includes(key)) ||
282
276
  (value.left !== undefined &&
283
277
  (typeof value.left !== "number" || !Number.isFinite(value.left))) ||
284
- (value.top !== undefined &&
285
- (typeof value.top !== "number" || !Number.isFinite(value.top)))) {
278
+ (value.top !== undefined && (typeof value.top !== "number" || !Number.isFinite(value.top)))) {
286
279
  throw invalidCommand("scrollTo() requires finite numeric left/top values.");
287
280
  }
288
281
  }
@@ -340,9 +333,7 @@ export class PageController {
340
333
  throw invalidCommand("Command envelope is invalid.");
341
334
  }
342
335
  const record = this.executions.get(command.executionId);
343
- if (!record ||
344
- record.status !== "running" ||
345
- record.abortController.signal.aborted) {
336
+ if (!record || record.status !== "running" || record.abortController.signal.aborted) {
346
337
  throw new PageCommandError({
347
338
  code: "EXECUTION_CANCELLED",
348
339
  message: "The execution is no longer active.",
@@ -393,15 +384,16 @@ export class PageController {
393
384
  record = this.requireActive(command);
394
385
  const value = command.target.type === "page"
395
386
  ? await this.executePage(command, record)
396
- : await this.executeTarget(command, record, beforeAction && (async () => {
397
- try {
398
- await beforeAction();
399
- }
400
- catch (error) {
401
- presentationFailed = true;
402
- throw error;
403
- }
404
- }));
387
+ : await this.executeTarget(command, record, beforeAction &&
388
+ (async () => {
389
+ try {
390
+ await beforeAction();
391
+ }
392
+ catch (error) {
393
+ presentationFailed = true;
394
+ throw error;
395
+ }
396
+ }));
405
397
  if (ACTION_METHODS.has(command.method) &&
406
398
  !record.completedActions.some((action) => action.callIndex === command.commandSeq)) {
407
399
  this.recordCompletedAction(record, command);
@@ -521,9 +513,7 @@ export class PageController {
521
513
  return record.registry.refs.get(command.target.ref);
522
514
  }
523
515
  locator(command) {
524
- return command.target.type === "locator"
525
- ? command.target.locator
526
- : undefined;
516
+ return command.target.type === "locator" ? command.target.locator : undefined;
527
517
  }
528
518
  async executeTarget(command, record, beforeAction) {
529
519
  const signal = record.abortController.signal;
@@ -557,11 +547,7 @@ export class PageController {
557
547
  return null;
558
548
  }
559
549
  if (command.method === "text") {
560
- const element = ref
561
- ? requireValidRef(ref)
562
- : locator
563
- ? requireUnique(locator)
564
- : undefined;
550
+ const element = ref ? requireValidRef(ref) : locator ? requireUnique(locator) : undefined;
565
551
  if (!element)
566
552
  throw invalidCommand("Target is missing.");
567
553
  if (element instanceof HTMLInputElement ||
@@ -572,11 +558,7 @@ export class PageController {
572
558
  return normalizeText(element.textContent);
573
559
  }
574
560
  if (command.method === "scrollIntoView") {
575
- const element = ref
576
- ? requireValidRef(ref)
577
- : locator
578
- ? requireUnique(locator)
579
- : undefined;
561
+ const element = ref ? requireValidRef(ref) : locator ? requireUnique(locator) : undefined;
580
562
  if (!element)
581
563
  throw invalidCommand("Target is missing.");
582
564
  const beforeIdentity = createIdentity(element);
@@ -597,11 +579,7 @@ export class PageController {
597
579
  return null;
598
580
  }
599
581
  if (command.method === "scrollBy" || command.method === "scrollTo") {
600
- const element = ref
601
- ? ref.element
602
- : locator
603
- ? requireUnique(locator)
604
- : undefined;
582
+ const element = ref ? ref.element : locator ? requireUnique(locator) : undefined;
605
583
  if (!(element instanceof HTMLElement)) {
606
584
  throw new PageCommandError({
607
585
  code: "UNSUPPORTED_OPERATION",
@@ -648,12 +626,8 @@ export class PageController {
648
626
  }
649
627
  else {
650
628
  const value = command.args[0];
651
- if ((value.left !== undefined &&
652
- value.left !== element.scrollLeft &&
653
- !scrollability.x) ||
654
- (value.top !== undefined &&
655
- value.top !== element.scrollTop &&
656
- !scrollability.y)) {
629
+ if ((value.left !== undefined && value.left !== element.scrollLeft && !scrollability.x) ||
630
+ (value.top !== undefined && value.top !== element.scrollTop && !scrollability.y)) {
657
631
  throw new PageCommandError({
658
632
  code: "UNSUPPORTED_OPERATION",
659
633
  message: "Requested axis does not have a scroll range.",
@@ -682,7 +656,9 @@ export class PageController {
682
656
  this.requireStillActive(record);
683
657
  const element = ref
684
658
  ? await prepareRefForAction(ref, signal)
685
- : locator ? await prepareLocatorForAction(locator, signal) : undefined;
659
+ : locator
660
+ ? await prepareLocatorForAction(locator, signal)
661
+ : undefined;
686
662
  if (!element)
687
663
  throw invalidCommand("Target is missing.");
688
664
  this.requireStillActive(record);
@@ -692,9 +668,13 @@ export class PageController {
692
668
  await feedback;
693
669
  this.requireStillActive(record);
694
670
  await beforeAction?.();
695
- if (!element.isConnected || createIdentity(element) !== identity
696
- || (locator && requireUnique(locator) !== element)) {
697
- throw new PageCommandError({ code: "REF_ACTION_FAILED", message: "Target changed before the action." });
671
+ if (!element.isConnected ||
672
+ createIdentity(element) !== identity ||
673
+ (locator && requireUnique(locator) !== element)) {
674
+ throw new PageCommandError({
675
+ code: "REF_ACTION_FAILED",
676
+ message: "Target changed before the action.",
677
+ });
698
678
  }
699
679
  ensureActionable(element);
700
680
  this.requireStillActive(record);
@@ -714,8 +694,7 @@ export class PageController {
714
694
  });
715
695
  }
716
696
  requireStillActive(record) {
717
- if (record.status !== "running" ||
718
- record.abortController.signal.aborted) {
697
+ if (record.status !== "running" || record.abortController.signal.aborted) {
719
698
  throw new PageCommandError({
720
699
  code: "EXECUTION_CANCELLED",
721
700
  message: "Execution was cancelled before the DOM action.",
@@ -729,8 +708,7 @@ export class PageController {
729
708
  }
730
709
  if (command.method === "fill") {
731
710
  const value = String(command.args[0] ?? "");
732
- if ((element instanceof HTMLInputElement ||
733
- element instanceof HTMLTextAreaElement) &&
711
+ if ((element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) &&
734
712
  !element.readOnly) {
735
713
  focusForAgent(element);
736
714
  setNativeValue(element, value);
@@ -749,21 +727,56 @@ export class PageController {
749
727
  }
750
728
  if (command.method === "press") {
751
729
  const key = String(command.args[0] ?? "");
752
- element.dispatchEvent(new KeyboardEvent("keydown", { key, bubbles: true }));
753
- element.dispatchEvent(new KeyboardEvent("keyup", { key, bubbles: true }));
730
+ const keyCodes = {
731
+ Backspace: 8,
732
+ Tab: 9,
733
+ Enter: 13,
734
+ Shift: 16,
735
+ Control: 17,
736
+ Alt: 18,
737
+ Escape: 27,
738
+ " ": 32,
739
+ PageUp: 33,
740
+ PageDown: 34,
741
+ End: 35,
742
+ Home: 36,
743
+ ArrowLeft: 37,
744
+ ArrowUp: 38,
745
+ ArrowRight: 39,
746
+ ArrowDown: 40,
747
+ Delete: 46,
748
+ };
749
+ const keyCode = keyCodes[key] ?? (/^[a-z0-9]$/i.test(key) ? key.toUpperCase().charCodeAt(0) : 0);
750
+ const code = /^[a-z]$/i.test(key)
751
+ ? `Key${key.toUpperCase()}`
752
+ : /^[0-9]$/.test(key)
753
+ ? `Digit${key}`
754
+ : key === " "
755
+ ? "Space"
756
+ : key;
757
+ const init = {
758
+ key,
759
+ code,
760
+ keyCode,
761
+ which: keyCode,
762
+ bubbles: true,
763
+ cancelable: true,
764
+ composed: true,
765
+ };
766
+ element.dispatchEvent(new KeyboardEvent("keydown", init));
767
+ element.dispatchEvent(new KeyboardEvent("keyup", init));
754
768
  return null;
755
769
  }
756
770
  if (command.method === "check" || command.method === "uncheck") {
757
771
  const checked = command.method === "check";
758
- if (element.getAttribute("role") === "option"
759
- && element.closest('[role="listbox"]')?.getAttribute("aria-multiselectable") === "true"
760
- && ["true", "false"].includes(element.getAttribute("aria-selected") ?? "")) {
772
+ if (element.getAttribute("role") === "option" &&
773
+ element.closest('[role="listbox"]')?.getAttribute("aria-multiselectable") === "true" &&
774
+ ["true", "false"].includes(element.getAttribute("aria-selected") ?? "")) {
761
775
  if ((element.getAttribute("aria-selected") === "true") !== checked)
762
776
  dispatchClickSequence(element);
763
777
  return null;
764
778
  }
765
- if (element instanceof HTMLInputElement &&
766
- ["checkbox", "radio"].includes(element.type)) {
779
+ if (element instanceof HTMLInputElement && ["checkbox", "radio"].includes(element.type)) {
767
780
  if (element.type === "radio" && !checked) {
768
781
  throw new PageCommandError({
769
782
  code: "UNSUPPORTED_OPERATION",
@@ -789,9 +802,14 @@ export class PageController {
789
802
  if (command.method === "setOptionSelected") {
790
803
  const [value, selected, label] = command.args;
791
804
  const options = element instanceof HTMLSelectElement && element.multiple
792
- ? [...element.options].filter((option) => option.value === value) : [];
805
+ ? [...element.options].filter((option) => option.value === value)
806
+ : [];
793
807
  const option = options[0];
794
- if (options.length !== 1 || !option || option.label !== label || option.disabled || option.closest("optgroup[disabled]")) {
808
+ if (options.length !== 1 ||
809
+ !option ||
810
+ option.label !== label ||
811
+ option.disabled ||
812
+ option.closest("optgroup[disabled]")) {
795
813
  throw invalidCommand("The observed multiple-select option is no longer available.");
796
814
  }
797
815
  if (option.selected !== selected) {
@@ -808,9 +826,7 @@ export class PageController {
808
826
  });
809
827
  }
810
828
  const requested = command.args[0];
811
- const values = Array.isArray(requested)
812
- ? requested.map(String)
813
- : [String(requested ?? "")];
829
+ const values = Array.isArray(requested) ? requested.map(String) : [String(requested ?? "")];
814
830
  const availableValues = new Set(Array.from(element.options, (option) => option.value));
815
831
  const missing = values.filter((value) => !availableValues.has(value));
816
832
  if (missing.length > 0) {
@@ -841,4 +857,3 @@ export class PageController {
841
857
  throw invalidCommand(`Unsupported locator method: ${command.method}`);
842
858
  }
843
859
  }
844
- //# sourceMappingURL=controller.js.map
@@ -11,10 +11,15 @@ export async function measurePagePhase(phase, execute) {
11
11
  }
12
12
  finally {
13
13
  try {
14
- performance.measure("nexface.browser.phase", { start, end: performance.now(), detail: { phase, status } });
14
+ performance.measure("nexface.browser.phase", {
15
+ start,
16
+ end: performance.now(),
17
+ detail: { phase, status },
18
+ });
15
19
  performance.clearMeasures("nexface.browser.phase");
16
20
  }
17
- catch { /* Diagnostics must never interrupt execution. */ }
21
+ catch {
22
+ /* Diagnostics must never interrupt execution. */
23
+ }
18
24
  }
19
25
  }
20
- //# sourceMappingURL=diagnostics.js.map
@@ -108,9 +108,7 @@ export function* walkComposedElements(root = document) {
108
108
  function hasGenericInteractionEvidence(element) {
109
109
  if (!(element instanceof HTMLElement))
110
110
  return false;
111
- return (element.tabIndex >= 0 ||
112
- element.hasAttribute("onclick") ||
113
- element.isContentEditable);
111
+ return element.tabIndex >= 0 || element.hasAttribute("onclick") || element.isContentEditable;
114
112
  }
115
113
  export function computeRole(element) {
116
114
  const explicit = normalizeText(element.getAttribute("role"))
@@ -146,9 +144,7 @@ export function computeRole(element) {
146
144
  }
147
145
  function referencedText(element, attribute) {
148
146
  const root = element.getRootNode();
149
- const ids = normalizeText(element.getAttribute(attribute))
150
- .split(" ")
151
- .filter(Boolean);
147
+ const ids = normalizeText(element.getAttribute(attribute)).split(" ").filter(Boolean);
152
148
  return normalizeText(ids
153
149
  .map((id) => {
154
150
  if (root instanceof Document || root instanceof ShadowRoot) {
@@ -187,24 +183,14 @@ export function computeNameInfo(element) {
187
183
  if (caption)
188
184
  return { value: caption, source: "explicit" };
189
185
  }
190
- if (element instanceof HTMLInputElement &&
191
- ["button", "submit", "reset"].includes(element.type)) {
186
+ if (element instanceof HTMLInputElement && ["button", "submit", "reset"].includes(element.type)) {
192
187
  const value = normalizeText(element.value);
193
188
  if (value)
194
189
  return { value, source: "fallback" };
195
190
  }
196
191
  const role = computeRole(element);
197
192
  if (isActionableRole(role) ||
198
- [
199
- "cell",
200
- "columnheader",
201
- "heading",
202
- "listitem",
203
- "option",
204
- "row",
205
- "tab",
206
- "treeitem",
207
- ].includes(role)) {
193
+ ["cell", "columnheader", "heading", "listitem", "option", "row", "tab", "treeitem"].includes(role)) {
208
194
  const content = normalizeText(element.textContent);
209
195
  if (content)
210
196
  return { value: content, source: "content" };
@@ -212,8 +198,7 @@ export function computeNameInfo(element) {
212
198
  const title = normalizeText(element.getAttribute("title"));
213
199
  if (title)
214
200
  return { value: title, source: "fallback" };
215
- if (element instanceof HTMLInputElement ||
216
- element instanceof HTMLTextAreaElement) {
201
+ if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
217
202
  return {
218
203
  value: normalizeText(element.placeholder),
219
204
  source: "fallback",
@@ -228,10 +213,8 @@ const SCROLLABLE_OVERFLOW = new Set(["auto", "scroll", "overlay", "hidden"]);
228
213
  export function getElementScrollability(element, style = getComputedStyle(element)) {
229
214
  if (!(element instanceof HTMLElement))
230
215
  return undefined;
231
- const x = SCROLLABLE_OVERFLOW.has(style.overflowX) &&
232
- element.scrollWidth > element.clientWidth + 2;
233
- const y = SCROLLABLE_OVERFLOW.has(style.overflowY) &&
234
- element.scrollHeight > element.clientHeight + 2;
216
+ const x = SCROLLABLE_OVERFLOW.has(style.overflowX) && element.scrollWidth > element.clientWidth + 2;
217
+ const y = SCROLLABLE_OVERFLOW.has(style.overflowY) && element.scrollHeight > element.clientHeight + 2;
235
218
  if (!x && !y)
236
219
  return undefined;
237
220
  return {
@@ -329,7 +312,10 @@ export function computeState(element) {
329
312
  if (element instanceof HTMLSelectElement) {
330
313
  if (element.multiple) {
331
314
  state.multiple = true;
332
- state.selectedOptions = [...element.selectedOptions].map((option) => ({ value: option.value, label: normalizeText(option.label) }));
315
+ state.selectedOptions = [...element.selectedOptions].map((option) => ({
316
+ value: option.value,
317
+ label: normalizeText(option.label),
318
+ }));
333
319
  }
334
320
  if (element.value)
335
321
  state.value = element.value;
@@ -367,11 +353,20 @@ export function findSemanticContext(element) {
367
353
  }
368
354
  return {};
369
355
  }
356
+ function composedTextContent(node) {
357
+ if (node instanceof Text)
358
+ return node.data;
359
+ if (!(node instanceof Element))
360
+ return "";
361
+ return composedChildren(node).map(composedTextContent).join("");
362
+ }
370
363
  export function createIdentity(element) {
371
364
  const context = findSemanticContext(element);
365
+ const role = computeRole(element);
366
+ const name = computeName(element) || (!role ? composedTextContent(element) : "");
372
367
  return JSON.stringify([
373
- computeRole(element),
374
- normalizeText(computeName(element)),
368
+ role,
369
+ normalizeText(name),
375
370
  context.role ?? "",
376
371
  normalizeText(context.text),
377
372
  ]);
@@ -382,8 +377,7 @@ export function isElementRendered(element, style = getComputedStyle(element)) {
382
377
  }
383
378
  if (isAgentIgnored(element))
384
379
  return false;
385
- if (element.hasAttribute("hidden") ||
386
- element.getAttribute("aria-hidden") === "true") {
380
+ if (element.hasAttribute("hidden") || element.getAttribute("aria-hidden") === "true") {
387
381
  return false;
388
382
  }
389
383
  return style.display !== "none" && style.visibility !== "hidden";
@@ -442,4 +436,3 @@ export function matchesText(value, matcher, exact = false) {
442
436
  const expected = normalizeText(matcher);
443
437
  return exact ? normalized === expected : normalized.includes(expected);
444
438
  }
445
- //# sourceMappingURL=dom.js.map
@@ -5,10 +5,11 @@ export class ActionFeedback {
5
5
  this.assertActive?.();
6
6
  const read = ["text", "exists", "waitFor", "waitForTimeout", "waitForURL"].includes(action);
7
7
  const scroll = ["scrollBy", "scrollTo", "scrollIntoView"].includes(action);
8
- return this.listener?.(scroll ? {} : {
9
- effect: read ? "read" : "action",
10
- ...(!read && target ? { target } : {}),
11
- });
8
+ return this.listener?.(scroll
9
+ ? {}
10
+ : {
11
+ effect: read ? "read" : "action",
12
+ ...(!read && target ? { target } : {}),
13
+ });
12
14
  }
13
15
  }
14
- //# sourceMappingURL=feedback.js.map
@@ -1,4 +1,3 @@
1
1
  export declare function isAgentActivation(): boolean;
2
2
  export declare function withAgentActivation<T>(activate: () => T): T;
3
- export declare function isAgentFocus(): boolean;
4
3
  export declare function focusForAgent(element: HTMLElement): void;
@@ -1,4 +1,3 @@
1
- let focusingForAgent = false;
2
1
  let activatingForAgent = false;
3
2
  export function isAgentActivation() {
4
3
  return activatingForAgent;
@@ -13,17 +12,6 @@ export function withAgentActivation(activate) {
13
12
  activatingForAgent = previous;
14
13
  }
15
14
  }
16
- export function isAgentFocus() {
17
- return focusingForAgent;
18
- }
19
15
  export function focusForAgent(element) {
20
- const previous = focusingForAgent;
21
- focusingForAgent = true;
22
- try {
23
- element.focus({ preventScroll: true });
24
- }
25
- finally {
26
- focusingForAgent = previous;
27
- }
16
+ element.focus({ preventScroll: true });
28
17
  }
29
- //# sourceMappingURL=focus.js.map
@@ -123,7 +123,7 @@ function animationFrame(signal) {
123
123
  reject(abortError());
124
124
  return;
125
125
  }
126
- requestAnimationFrame(() => signal.aborted ? reject(abortError()) : resolve());
126
+ requestAnimationFrame(() => (signal.aborted ? reject(abortError()) : resolve()));
127
127
  });
128
128
  }
129
129
  async function waitForStable(element, signal) {
@@ -159,15 +159,10 @@ function ensureNotCovered(element) {
159
159
  });
160
160
  }
161
161
  export function findElementHitTarget(element) {
162
- const candidates = [
163
- element,
164
- ...Array.from(walkComposedElements(element)).slice(0, 127),
165
- ].filter((candidate) => !isAgentIgnored(candidate));
162
+ const candidates = [element, ...Array.from(walkComposedElements(element)).slice(0, 127)].filter((candidate) => !isAgentIgnored(candidate));
166
163
  for (const candidate of candidates) {
167
164
  const clientRects = Array.from(candidate.getClientRects()).filter((rect) => rect.width > 0 && rect.height > 0);
168
- const rects = clientRects.length > 0
169
- ? clientRects
170
- : [candidate.getBoundingClientRect()];
165
+ const rects = clientRects.length > 0 ? clientRects : [candidate.getBoundingClientRect()];
171
166
  for (const rect of rects) {
172
167
  const left = Math.max(0, rect.left);
173
168
  const right = Math.min(window.innerWidth, rect.right);
@@ -274,4 +269,3 @@ export function requireValidRef(target) {
274
269
  validateIdentity(target);
275
270
  return target.element;
276
271
  }
277
- //# sourceMappingURL=locator.js.map