auto-webmcp 0.3.21 → 0.3.23

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.
@@ -1912,6 +1912,79 @@ function queryShadowAll(root, selector) {
1912
1912
  }
1913
1913
  return results;
1914
1914
  }
1915
+ async function fillLookupInput(el, value) {
1916
+ const text = String(value ?? "").trim();
1917
+ const input = el;
1918
+ console.log("[auto-webmcp] fillLookupInput: typing value=", JSON.stringify(text));
1919
+ setReactValue(input, text);
1920
+ input.dispatchEvent(new KeyboardEvent("keydown", { bubbles: true, cancelable: true, key: text.slice(-1) || "" }));
1921
+ input.dispatchEvent(new KeyboardEvent("keyup", { bubbles: true, cancelable: true, key: text.slice(-1) || "" }));
1922
+ const ariaControlsId = el.getAttribute("aria-controls") ?? el.getAttribute("aria-owns");
1923
+ const listbox = await new Promise((resolve) => {
1924
+ const deadline = Date.now() + 3e3;
1925
+ const poll = () => {
1926
+ if (ariaControlsId) {
1927
+ const byId = document.getElementById(ariaControlsId);
1928
+ if (byId) {
1929
+ resolve(byId);
1930
+ return;
1931
+ }
1932
+ const inShadow = queryShadowAll(document.body, `#${CSS.escape(ariaControlsId)}`)[0] ?? null;
1933
+ if (inShadow) {
1934
+ resolve(inShadow);
1935
+ return;
1936
+ }
1937
+ }
1938
+ const lightCandidate = document.querySelector('[role="listbox"]') ?? document.querySelector('[role="option"]')?.closest('[role="listbox"]') ?? null;
1939
+ if (lightCandidate) {
1940
+ resolve(lightCandidate);
1941
+ return;
1942
+ }
1943
+ const shadowCandidate = queryShadowAll(document.body, '[role="listbox"]')[0] ?? null;
1944
+ if (shadowCandidate) {
1945
+ resolve(shadowCandidate);
1946
+ return;
1947
+ }
1948
+ if (Date.now() >= deadline) {
1949
+ resolve(null);
1950
+ return;
1951
+ }
1952
+ setTimeout(poll, 50);
1953
+ };
1954
+ poll();
1955
+ });
1956
+ if (!listbox) {
1957
+ console.warn("[auto-webmcp] fillLookupInput: listbox did not appear after 3s, leaving text as-is");
1958
+ return;
1959
+ }
1960
+ const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
1961
+ const shadowOptions = queryShadowAll(listbox, '[role="option"]');
1962
+ const options = lightOptions.length > 0 ? lightOptions : shadowOptions;
1963
+ console.log("[auto-webmcp] fillLookupInput: listbox has", options.length, "option(s)");
1964
+ const lowerValue = text.toLowerCase();
1965
+ const match = options.find((opt) => {
1966
+ const dataValue = (opt.getAttribute("data-value") ?? "").toLowerCase();
1967
+ const ariaLabel = (opt.getAttribute("aria-label") ?? "").toLowerCase();
1968
+ const optText = (opt.textContent ?? "").trim().toLowerCase();
1969
+ return dataValue === lowerValue || ariaLabel === lowerValue || optText === lowerValue;
1970
+ }) ?? options.find((opt) => {
1971
+ const optText = (opt.textContent ?? "").trim().toLowerCase();
1972
+ return optText.startsWith(lowerValue) || optText.includes(lowerValue);
1973
+ });
1974
+ if (match) {
1975
+ console.log("[auto-webmcp] fillLookupInput: selecting option", match.textContent?.trim());
1976
+ match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
1977
+ match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
1978
+ match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
1979
+ } else {
1980
+ console.warn(
1981
+ "[auto-webmcp] fillLookupInput: no option matched",
1982
+ JSON.stringify(text),
1983
+ "available:",
1984
+ options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
1985
+ );
1986
+ }
1987
+ }
1915
1988
  async function fillComboboxButton(el, value) {
1916
1989
  const text = String(value ?? "").trim();
1917
1990
  console.log("[auto-webmcp] fillComboboxButton: clicking button, value=", JSON.stringify(text));
@@ -2451,7 +2524,9 @@ async function scanOrphanInputs(config) {
2451
2524
  for (const { key, el } of inputPairs) {
2452
2525
  if (params[key] !== void 0) {
2453
2526
  console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
2454
- if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "button") {
2527
+ if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "input" && (el.getAttribute("aria-autocomplete") === "list" || el.getAttribute("aria-haspopup") === "listbox")) {
2528
+ await fillLookupInput(el, params[key]);
2529
+ } else if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "button") {
2455
2530
  await fillComboboxButton(el, params[key]);
2456
2531
  } else {
2457
2532
  fillElement(el, params[key]);