auto-webmcp 0.3.8 → 0.3.10
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/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/auto-webmcp.cjs.js +77 -15
- package/dist/auto-webmcp.cjs.js.map +3 -3
- package/dist/auto-webmcp.esm.js +77 -15
- package/dist/auto-webmcp.esm.js.map +3 -3
- 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.map +1 -1
- package/package.json +1 -1
package/dist/auto-webmcp.esm.js
CHANGED
|
@@ -631,6 +631,19 @@ function resolveNativeControlFallbackKey(control) {
|
|
|
631
631
|
}
|
|
632
632
|
return null;
|
|
633
633
|
}
|
|
634
|
+
function resolveAriaElementKey(el) {
|
|
635
|
+
if (el.dataset["webmcpName"])
|
|
636
|
+
return sanitizeName(el.dataset["webmcpName"]);
|
|
637
|
+
if (el.id && !AUTO_GENERATED_ID_RE.test(el.id))
|
|
638
|
+
return sanitizeName(el.id);
|
|
639
|
+
const label = el.getAttribute("aria-label");
|
|
640
|
+
if (label)
|
|
641
|
+
return sanitizeName(label);
|
|
642
|
+
const placeholder = el.getAttribute("placeholder");
|
|
643
|
+
if (placeholder)
|
|
644
|
+
return sanitizeName(placeholder);
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
634
647
|
function collectAriaControls(form) {
|
|
635
648
|
const selector = ARIA_ROLES_TO_SCAN.map((r) => `[role="${r}"]`).join(", ");
|
|
636
649
|
const rawResults = [];
|
|
@@ -889,6 +902,22 @@ function buildSchemaFromInputs(inputs) {
|
|
|
889
902
|
const processedRadioGroups = /* @__PURE__ */ new Set();
|
|
890
903
|
const processedCheckboxGroups = /* @__PURE__ */ new Set();
|
|
891
904
|
for (const control of inputs) {
|
|
905
|
+
if (!(control instanceof HTMLInputElement) && !(control instanceof HTMLTextAreaElement) && !(control instanceof HTMLSelectElement)) {
|
|
906
|
+
const fieldKey2 = resolveAriaElementKey(control);
|
|
907
|
+
if (!fieldKey2)
|
|
908
|
+
continue;
|
|
909
|
+
if (!isControlVisible(control))
|
|
910
|
+
continue;
|
|
911
|
+
const prop = { type: "string" };
|
|
912
|
+
prop.title = control.getAttribute("aria-label") ?? fieldKey2;
|
|
913
|
+
const desc2 = control.getAttribute("aria-description") ?? control.getAttribute("aria-describedby") ? null : null;
|
|
914
|
+
if (desc2)
|
|
915
|
+
prop.description = desc2;
|
|
916
|
+
properties[fieldKey2] = prop;
|
|
917
|
+
fieldElements.set(fieldKey2, control);
|
|
918
|
+
required.push(fieldKey2);
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
892
921
|
const rawName = control.name;
|
|
893
922
|
const fieldKey = (rawName ? sanitizeName(rawName) : null) || resolveNativeControlFallbackKey(control);
|
|
894
923
|
if (!fieldKey)
|
|
@@ -1284,10 +1313,17 @@ function fillAriaField(el, value) {
|
|
|
1284
1313
|
}
|
|
1285
1314
|
const htmlEl = el;
|
|
1286
1315
|
if (htmlEl.isContentEditable) {
|
|
1287
|
-
htmlEl.
|
|
1316
|
+
htmlEl.focus();
|
|
1317
|
+
const range = document.createRange();
|
|
1318
|
+
range.selectNodeContents(htmlEl);
|
|
1319
|
+
const sel = window.getSelection();
|
|
1320
|
+
sel?.removeAllRanges();
|
|
1321
|
+
sel?.addRange(range);
|
|
1322
|
+
document.execCommand("insertText", false, String(value ?? ""));
|
|
1323
|
+
} else {
|
|
1324
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1325
|
+
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1288
1326
|
}
|
|
1289
|
-
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1290
|
-
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1291
1327
|
}
|
|
1292
1328
|
function serializeFormData(form, params, fieldEls) {
|
|
1293
1329
|
const result = {};
|
|
@@ -1440,6 +1476,11 @@ async function registerForm(form, config) {
|
|
|
1440
1476
|
await registerFormTool(form, metadata, execute);
|
|
1441
1477
|
registeredForms.add(form);
|
|
1442
1478
|
registeredFormCount++;
|
|
1479
|
+
const formSubmitBtn = form.querySelector(
|
|
1480
|
+
'[type="submit"], button[data-variant="primary"], button:not([type])'
|
|
1481
|
+
) ?? null;
|
|
1482
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1483
|
+
pendingBtns[metadata.name] = formSubmitBtn;
|
|
1443
1484
|
if (config.debug) {
|
|
1444
1485
|
console.log(`[auto-webmcp] Registered: ${metadata.name}`, metadata);
|
|
1445
1486
|
}
|
|
@@ -1553,12 +1594,12 @@ var ORPHAN_EXCLUDED_TYPES = /* @__PURE__ */ new Set([
|
|
|
1553
1594
|
async function scanOrphanInputs(config) {
|
|
1554
1595
|
if (!isWebMCPSupported())
|
|
1555
1596
|
return;
|
|
1556
|
-
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button
|
|
1557
|
-
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"]';
|
|
1558
|
-
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search/i;
|
|
1597
|
+
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button[data-variant="primary"]:not([disabled])';
|
|
1598
|
+
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button[data-variant="primary"]';
|
|
1599
|
+
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search|post|tweet|publish/i;
|
|
1559
1600
|
const orphanInputs = Array.from(
|
|
1560
1601
|
document.querySelectorAll(
|
|
1561
|
-
|
|
1602
|
+
'input:not(form input), textarea:not(form textarea), select:not(form select), [role="textbox"]:not(form [role="textbox"]):not(input):not(textarea), [role="searchbox"]:not(form [role="searchbox"]):not(input):not(textarea), [contenteditable="true"]:not(form [contenteditable="true"]):not(input):not(textarea)'
|
|
1562
1603
|
)
|
|
1563
1604
|
).filter((el) => {
|
|
1564
1605
|
if (el instanceof HTMLInputElement && ORPHAN_EXCLUDED_TYPES.has(el.type.toLowerCase())) {
|
|
@@ -1603,11 +1644,25 @@ async function scanOrphanInputs(config) {
|
|
|
1603
1644
|
return r.width > 0 && r.height > 0;
|
|
1604
1645
|
});
|
|
1605
1646
|
let submitBtn = allCandidates[allCandidates.length - 1] ?? null;
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1647
|
+
if (!submitBtn) {
|
|
1648
|
+
const disabledCandidates = Array.from(
|
|
1649
|
+
container.querySelectorAll(SUBMIT_BTN_GROUPING_SELECTOR)
|
|
1650
|
+
).filter((b) => {
|
|
1651
|
+
const r = b.getBoundingClientRect();
|
|
1652
|
+
return r.width > 0 && r.height > 0 && b.disabled;
|
|
1653
|
+
});
|
|
1654
|
+
submitBtn = disabledCandidates[disabledCandidates.length - 1] ?? null;
|
|
1655
|
+
if (submitBtn)
|
|
1656
|
+
console.log(`[auto-webmcp] orphan: using disabled submit button as reference: "${submitBtn.textContent?.trim()}"`);
|
|
1657
|
+
}
|
|
1658
|
+
if (!submitBtn) {
|
|
1659
|
+
const containerBtns = Array.from(container.querySelectorAll("button")).filter((b) => {
|
|
1660
|
+
const r = b.getBoundingClientRect();
|
|
1661
|
+
return r.width > 0 && r.height > 0 && !b.disabled && SUBMIT_TEXT_RE.test(b.textContent ?? "");
|
|
1662
|
+
});
|
|
1663
|
+
submitBtn = containerBtns[containerBtns.length - 1] ?? null;
|
|
1664
|
+
if (submitBtn)
|
|
1665
|
+
console.log(`[auto-webmcp] orphan: using text-matched button in container: "${submitBtn.textContent?.trim()}"`);
|
|
1611
1666
|
}
|
|
1612
1667
|
if (!submitBtn) {
|
|
1613
1668
|
const pageBtns = Array.from(document.querySelectorAll("button")).filter(
|
|
@@ -1628,15 +1683,19 @@ async function scanOrphanInputs(config) {
|
|
|
1628
1683
|
const AUTO_ID_RE = /^_r_[0-9a-z]+_$/i;
|
|
1629
1684
|
for (const el of inputs) {
|
|
1630
1685
|
const id = el.id && !AUTO_ID_RE.test(el.id) ? el.id : null;
|
|
1631
|
-
const key = el.name || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") ||
|
|
1686
|
+
const key = el.name || el.getAttribute("name") || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") || el.getAttribute("placeholder") || null;
|
|
1632
1687
|
const safeKey = key ? key.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) : null;
|
|
1633
1688
|
const matched = !!(safeKey && schemaProps[safeKey]);
|
|
1634
|
-
console.log(`[auto-webmcp] orphan: field (name="${el.name}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1689
|
+
console.log(`[auto-webmcp] orphan: field (name="${el.name ?? ""}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1635
1690
|
if (matched) {
|
|
1636
1691
|
inputPairs.push({ key: safeKey, el });
|
|
1637
1692
|
}
|
|
1638
1693
|
}
|
|
1639
1694
|
console.log(`[auto-webmcp] orphan: ${inputPairs.length}/${inputs.length} input(s) mapped to schema keys`);
|
|
1695
|
+
if (inputPairs.length === 0) {
|
|
1696
|
+
console.log(`[auto-webmcp] orphan: skipping group "${metadata.name}" \u2014 no inputs mapped to schema keys`);
|
|
1697
|
+
continue;
|
|
1698
|
+
}
|
|
1640
1699
|
const toolName = metadata.name;
|
|
1641
1700
|
const execute = async (params) => {
|
|
1642
1701
|
console.log(`[auto-webmcp] orphan execute: tool="${toolName}" params=`, params);
|
|
@@ -1651,7 +1710,8 @@ async function scanOrphanInputs(config) {
|
|
|
1651
1710
|
}
|
|
1652
1711
|
}
|
|
1653
1712
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
1654
|
-
|
|
1713
|
+
const shouldAutoSubmit = config.autoSubmit || !!submitBtn?.hasAttribute("toolautosubmit") || submitBtn instanceof HTMLElement && submitBtn.dataset["webmcpAutosubmit"] !== void 0 || container.hasAttribute("toolautosubmit") || container instanceof HTMLElement && container.dataset["webmcpAutosubmit"] !== void 0;
|
|
1714
|
+
if (!shouldAutoSubmit) {
|
|
1655
1715
|
console.log(`[auto-webmcp] orphan execute: autoSubmit=false, returning without clicking submit`);
|
|
1656
1716
|
return { content: [{ type: "text", text: "Fields filled. Ready to submit." }] };
|
|
1657
1717
|
}
|
|
@@ -1691,6 +1751,8 @@ async function scanOrphanInputs(config) {
|
|
|
1691
1751
|
toolDef.annotations = metadata.annotations;
|
|
1692
1752
|
}
|
|
1693
1753
|
await navigator.modelContext.registerTool(toolDef);
|
|
1754
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1755
|
+
pendingBtns[metadata.name] = submitBtn;
|
|
1694
1756
|
if (config.debug) {
|
|
1695
1757
|
console.log(`[auto-webmcp] Orphan tool registered: ${metadata.name}`, metadata);
|
|
1696
1758
|
}
|