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.esm.js
CHANGED
|
@@ -1874,16 +1874,121 @@ function getMissingRequired(metadata, params) {
|
|
|
1874
1874
|
return [];
|
|
1875
1875
|
return metadata.inputSchema.required.filter((fieldKey) => !(fieldKey in params));
|
|
1876
1876
|
}
|
|
1877
|
+
function queryShadowAll(root, selector) {
|
|
1878
|
+
const results = [];
|
|
1879
|
+
const hosts = Array.from(root.querySelectorAll?.("*") ?? []);
|
|
1880
|
+
for (const host of hosts) {
|
|
1881
|
+
const sr = host.shadowRoot;
|
|
1882
|
+
if (!sr)
|
|
1883
|
+
continue;
|
|
1884
|
+
results.push(...Array.from(sr.querySelectorAll(selector)));
|
|
1885
|
+
results.push(...queryShadowAll(sr, selector));
|
|
1886
|
+
}
|
|
1887
|
+
return results;
|
|
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
|
+
}
|
|
1877
1962
|
async function fillComboboxButton(el, value) {
|
|
1878
1963
|
const text = String(value ?? "").trim();
|
|
1879
1964
|
console.log("[auto-webmcp] fillComboboxButton: clicking button, value=", JSON.stringify(text));
|
|
1965
|
+
el.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
|
|
1966
|
+
el.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
|
|
1880
1967
|
el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
1968
|
+
const ariaControlsId = el.getAttribute("aria-controls");
|
|
1881
1969
|
const listbox = await new Promise((resolve) => {
|
|
1882
1970
|
const deadline = Date.now() + 3e3;
|
|
1883
1971
|
const poll = () => {
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1972
|
+
if (ariaControlsId) {
|
|
1973
|
+
const byId = document.getElementById(ariaControlsId);
|
|
1974
|
+
if (byId) {
|
|
1975
|
+
resolve(byId);
|
|
1976
|
+
return;
|
|
1977
|
+
}
|
|
1978
|
+
const inShadow = queryShadowAll(document.body, `#${CSS.escape(ariaControlsId)}`)[0] ?? null;
|
|
1979
|
+
if (inShadow) {
|
|
1980
|
+
resolve(inShadow);
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
const lightCandidate = document.querySelector('[role="listbox"]') ?? document.querySelector('[role="option"]')?.closest('[role="listbox"]') ?? null;
|
|
1985
|
+
if (lightCandidate) {
|
|
1986
|
+
resolve(lightCandidate);
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
const shadowCandidate = queryShadowAll(document.body, '[role="listbox"]')[0] ?? null;
|
|
1990
|
+
if (shadowCandidate) {
|
|
1991
|
+
resolve(shadowCandidate);
|
|
1887
1992
|
return;
|
|
1888
1993
|
}
|
|
1889
1994
|
if (Date.now() >= deadline) {
|
|
@@ -1895,11 +2000,13 @@ async function fillComboboxButton(el, value) {
|
|
|
1895
2000
|
poll();
|
|
1896
2001
|
});
|
|
1897
2002
|
if (!listbox) {
|
|
1898
|
-
console.warn("[auto-webmcp] fillComboboxButton: listbox did not appear after
|
|
2003
|
+
console.warn("[auto-webmcp] fillComboboxButton: listbox did not appear after 3s");
|
|
1899
2004
|
return;
|
|
1900
2005
|
}
|
|
1901
|
-
const
|
|
1902
|
-
|
|
2006
|
+
const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
|
|
2007
|
+
const shadowOptions = queryShadowAll(listbox, '[role="option"]');
|
|
2008
|
+
const options = lightOptions.length > 0 ? lightOptions : shadowOptions;
|
|
2009
|
+
console.log("[auto-webmcp] fillComboboxButton: listbox has", options.length, "option(s)");
|
|
1903
2010
|
const lowerValue = text.toLowerCase();
|
|
1904
2011
|
const match = options.find((opt) => {
|
|
1905
2012
|
const dataValue = (opt.getAttribute("data-value") ?? "").toLowerCase();
|
|
@@ -1908,14 +2015,16 @@ async function fillComboboxButton(el, value) {
|
|
|
1908
2015
|
return dataValue === lowerValue || ariaLabel === lowerValue || optText === lowerValue;
|
|
1909
2016
|
});
|
|
1910
2017
|
if (match) {
|
|
1911
|
-
console.log("[auto-webmcp] fillComboboxButton:
|
|
2018
|
+
console.log("[auto-webmcp] fillComboboxButton: selecting option", match.textContent?.trim());
|
|
2019
|
+
match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
|
|
2020
|
+
match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
|
|
1912
2021
|
match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
1913
2022
|
} else {
|
|
1914
2023
|
console.warn(
|
|
1915
2024
|
"[auto-webmcp] fillComboboxButton: no option matched",
|
|
1916
2025
|
JSON.stringify(text),
|
|
1917
2026
|
"available:",
|
|
1918
|
-
options.map((o) => o.textContent?.trim())
|
|
2027
|
+
options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
|
|
1919
2028
|
);
|
|
1920
2029
|
}
|
|
1921
2030
|
}
|
|
@@ -2389,7 +2498,9 @@ async function scanOrphanInputs(config) {
|
|
|
2389
2498
|
for (const { key, el } of inputPairs) {
|
|
2390
2499
|
if (params[key] !== void 0) {
|
|
2391
2500
|
console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
|
|
2392
|
-
if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "
|
|
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") {
|
|
2393
2504
|
await fillComboboxButton(el, params[key]);
|
|
2394
2505
|
} else {
|
|
2395
2506
|
fillElement(el, params[key]);
|