auto-webmcp 0.3.21 → 0.3.22

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.
@@ -1886,6 +1886,79 @@ function queryShadowAll(root, selector) {
1886
1886
  }
1887
1887
  return results;
1888
1888
  }
1889
+ async function fillLookupInput(el, value) {
1890
+ const text = String(value ?? "").trim();
1891
+ const input = el;
1892
+ console.log("[auto-webmcp] fillLookupInput: typing value=", JSON.stringify(text));
1893
+ setReactValue(input, text);
1894
+ input.dispatchEvent(new KeyboardEvent("keydown", { bubbles: true, cancelable: true, key: text.slice(-1) || "" }));
1895
+ input.dispatchEvent(new KeyboardEvent("keyup", { bubbles: true, cancelable: true, key: text.slice(-1) || "" }));
1896
+ const ariaControlsId = el.getAttribute("aria-controls") ?? el.getAttribute("aria-owns");
1897
+ const listbox = await new Promise((resolve) => {
1898
+ const deadline = Date.now() + 3e3;
1899
+ const poll = () => {
1900
+ if (ariaControlsId) {
1901
+ const byId = document.getElementById(ariaControlsId);
1902
+ if (byId) {
1903
+ resolve(byId);
1904
+ return;
1905
+ }
1906
+ const inShadow = queryShadowAll(document.body, `#${CSS.escape(ariaControlsId)}`)[0] ?? null;
1907
+ if (inShadow) {
1908
+ resolve(inShadow);
1909
+ return;
1910
+ }
1911
+ }
1912
+ const lightCandidate = document.querySelector('[role="listbox"]') ?? document.querySelector('[role="option"]')?.closest('[role="listbox"]') ?? null;
1913
+ if (lightCandidate) {
1914
+ resolve(lightCandidate);
1915
+ return;
1916
+ }
1917
+ const shadowCandidate = queryShadowAll(document.body, '[role="listbox"]')[0] ?? null;
1918
+ if (shadowCandidate) {
1919
+ resolve(shadowCandidate);
1920
+ return;
1921
+ }
1922
+ if (Date.now() >= deadline) {
1923
+ resolve(null);
1924
+ return;
1925
+ }
1926
+ setTimeout(poll, 50);
1927
+ };
1928
+ poll();
1929
+ });
1930
+ if (!listbox) {
1931
+ console.warn("[auto-webmcp] fillLookupInput: listbox did not appear after 3s, leaving text as-is");
1932
+ return;
1933
+ }
1934
+ const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
1935
+ const shadowOptions = queryShadowAll(listbox, '[role="option"]');
1936
+ const options = lightOptions.length > 0 ? lightOptions : shadowOptions;
1937
+ console.log("[auto-webmcp] fillLookupInput: listbox has", options.length, "option(s)");
1938
+ const lowerValue = text.toLowerCase();
1939
+ const match = options.find((opt) => {
1940
+ const dataValue = (opt.getAttribute("data-value") ?? "").toLowerCase();
1941
+ const ariaLabel = (opt.getAttribute("aria-label") ?? "").toLowerCase();
1942
+ const optText = (opt.textContent ?? "").trim().toLowerCase();
1943
+ return dataValue === lowerValue || ariaLabel === lowerValue || optText === lowerValue;
1944
+ }) ?? options.find((opt) => {
1945
+ const optText = (opt.textContent ?? "").trim().toLowerCase();
1946
+ return optText.startsWith(lowerValue) || optText.includes(lowerValue);
1947
+ });
1948
+ if (match) {
1949
+ console.log("[auto-webmcp] fillLookupInput: selecting option", match.textContent?.trim());
1950
+ match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
1951
+ match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
1952
+ match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
1953
+ } else {
1954
+ console.warn(
1955
+ "[auto-webmcp] fillLookupInput: no option matched",
1956
+ JSON.stringify(text),
1957
+ "available:",
1958
+ options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
1959
+ );
1960
+ }
1961
+ }
1889
1962
  async function fillComboboxButton(el, value) {
1890
1963
  const text = String(value ?? "").trim();
1891
1964
  console.log("[auto-webmcp] fillComboboxButton: clicking button, value=", JSON.stringify(text));
@@ -2425,7 +2498,9 @@ async function scanOrphanInputs(config) {
2425
2498
  for (const { key, el } of inputPairs) {
2426
2499
  if (params[key] !== void 0) {
2427
2500
  console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
2428
- if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "button") {
2501
+ if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "input" && (el.getAttribute("aria-autocomplete") === "list" || el.getAttribute("aria-haspopup") === "listbox")) {
2502
+ await fillLookupInput(el, params[key]);
2503
+ } else if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "button") {
2429
2504
  await fillComboboxButton(el, params[key]);
2430
2505
  } else {
2431
2506
  fillElement(el, params[key]);