auto-webmcp 0.3.20 → 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.
- package/dist/auto-webmcp.cjs.js +120 -9
- package/dist/auto-webmcp.cjs.js.map +2 -2
- package/dist/auto-webmcp.esm.js +120 -9
- package/dist/auto-webmcp.esm.js.map +2 -2
- package/dist/auto-webmcp.iife.js +1 -1
- package/dist/auto-webmcp.iife.js.map +3 -3
- package/dist/discovery.d.ts.map +1 -1
- package/dist/interceptor.d.ts +4 -5
- package/dist/interceptor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/auto-webmcp.cjs.js
CHANGED
|
@@ -1900,16 +1900,121 @@ function getMissingRequired(metadata, params) {
|
|
|
1900
1900
|
return [];
|
|
1901
1901
|
return metadata.inputSchema.required.filter((fieldKey) => !(fieldKey in params));
|
|
1902
1902
|
}
|
|
1903
|
+
function queryShadowAll(root, selector) {
|
|
1904
|
+
const results = [];
|
|
1905
|
+
const hosts = Array.from(root.querySelectorAll?.("*") ?? []);
|
|
1906
|
+
for (const host of hosts) {
|
|
1907
|
+
const sr = host.shadowRoot;
|
|
1908
|
+
if (!sr)
|
|
1909
|
+
continue;
|
|
1910
|
+
results.push(...Array.from(sr.querySelectorAll(selector)));
|
|
1911
|
+
results.push(...queryShadowAll(sr, selector));
|
|
1912
|
+
}
|
|
1913
|
+
return results;
|
|
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
|
+
}
|
|
1903
1988
|
async function fillComboboxButton(el, value) {
|
|
1904
1989
|
const text = String(value ?? "").trim();
|
|
1905
1990
|
console.log("[auto-webmcp] fillComboboxButton: clicking button, value=", JSON.stringify(text));
|
|
1991
|
+
el.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
|
|
1992
|
+
el.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
|
|
1906
1993
|
el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
1994
|
+
const ariaControlsId = el.getAttribute("aria-controls");
|
|
1907
1995
|
const listbox = await new Promise((resolve) => {
|
|
1908
1996
|
const deadline = Date.now() + 3e3;
|
|
1909
1997
|
const poll = () => {
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1998
|
+
if (ariaControlsId) {
|
|
1999
|
+
const byId = document.getElementById(ariaControlsId);
|
|
2000
|
+
if (byId) {
|
|
2001
|
+
resolve(byId);
|
|
2002
|
+
return;
|
|
2003
|
+
}
|
|
2004
|
+
const inShadow = queryShadowAll(document.body, `#${CSS.escape(ariaControlsId)}`)[0] ?? null;
|
|
2005
|
+
if (inShadow) {
|
|
2006
|
+
resolve(inShadow);
|
|
2007
|
+
return;
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
const lightCandidate = document.querySelector('[role="listbox"]') ?? document.querySelector('[role="option"]')?.closest('[role="listbox"]') ?? null;
|
|
2011
|
+
if (lightCandidate) {
|
|
2012
|
+
resolve(lightCandidate);
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
const shadowCandidate = queryShadowAll(document.body, '[role="listbox"]')[0] ?? null;
|
|
2016
|
+
if (shadowCandidate) {
|
|
2017
|
+
resolve(shadowCandidate);
|
|
1913
2018
|
return;
|
|
1914
2019
|
}
|
|
1915
2020
|
if (Date.now() >= deadline) {
|
|
@@ -1921,11 +2026,13 @@ async function fillComboboxButton(el, value) {
|
|
|
1921
2026
|
poll();
|
|
1922
2027
|
});
|
|
1923
2028
|
if (!listbox) {
|
|
1924
|
-
console.warn("[auto-webmcp] fillComboboxButton: listbox did not appear after
|
|
2029
|
+
console.warn("[auto-webmcp] fillComboboxButton: listbox did not appear after 3s");
|
|
1925
2030
|
return;
|
|
1926
2031
|
}
|
|
1927
|
-
const
|
|
1928
|
-
|
|
2032
|
+
const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
|
|
2033
|
+
const shadowOptions = queryShadowAll(listbox, '[role="option"]');
|
|
2034
|
+
const options = lightOptions.length > 0 ? lightOptions : shadowOptions;
|
|
2035
|
+
console.log("[auto-webmcp] fillComboboxButton: listbox has", options.length, "option(s)");
|
|
1929
2036
|
const lowerValue = text.toLowerCase();
|
|
1930
2037
|
const match = options.find((opt) => {
|
|
1931
2038
|
const dataValue = (opt.getAttribute("data-value") ?? "").toLowerCase();
|
|
@@ -1934,14 +2041,16 @@ async function fillComboboxButton(el, value) {
|
|
|
1934
2041
|
return dataValue === lowerValue || ariaLabel === lowerValue || optText === lowerValue;
|
|
1935
2042
|
});
|
|
1936
2043
|
if (match) {
|
|
1937
|
-
console.log("[auto-webmcp] fillComboboxButton:
|
|
2044
|
+
console.log("[auto-webmcp] fillComboboxButton: selecting option", match.textContent?.trim());
|
|
2045
|
+
match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
|
|
2046
|
+
match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
|
|
1938
2047
|
match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
1939
2048
|
} else {
|
|
1940
2049
|
console.warn(
|
|
1941
2050
|
"[auto-webmcp] fillComboboxButton: no option matched",
|
|
1942
2051
|
JSON.stringify(text),
|
|
1943
2052
|
"available:",
|
|
1944
|
-
options.map((o) => o.textContent?.trim())
|
|
2053
|
+
options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
|
|
1945
2054
|
);
|
|
1946
2055
|
}
|
|
1947
2056
|
}
|
|
@@ -2415,7 +2524,9 @@ async function scanOrphanInputs(config) {
|
|
|
2415
2524
|
for (const { key, el } of inputPairs) {
|
|
2416
2525
|
if (params[key] !== void 0) {
|
|
2417
2526
|
console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
|
|
2418
|
-
if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "
|
|
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") {
|
|
2419
2530
|
await fillComboboxButton(el, params[key]);
|
|
2420
2531
|
} else {
|
|
2421
2532
|
fillElement(el, params[key]);
|