auto-webmcp 0.3.7 → 0.3.9
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.map +1 -1
- package/dist/auto-webmcp.cjs.js +61 -10
- package/dist/auto-webmcp.cjs.js.map +2 -2
- package/dist/auto-webmcp.esm.js +61 -10
- 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/package.json +1 -1
package/dist/auto-webmcp.esm.js
CHANGED
|
@@ -613,11 +613,12 @@ function buildSchema(form) {
|
|
|
613
613
|
}
|
|
614
614
|
return { schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", type: "object", properties, required }, fieldElements };
|
|
615
615
|
}
|
|
616
|
+
var AUTO_GENERATED_ID_RE = /^_r_[0-9a-z]+_$|^:[a-z0-9]+:$/i;
|
|
616
617
|
function resolveNativeControlFallbackKey(control) {
|
|
617
618
|
const el = control;
|
|
618
619
|
if (el.dataset["webmcpName"])
|
|
619
620
|
return sanitizeName(el.dataset["webmcpName"]);
|
|
620
|
-
if (control.id)
|
|
621
|
+
if (control.id && !AUTO_GENERATED_ID_RE.test(control.id))
|
|
621
622
|
return sanitizeName(control.id);
|
|
622
623
|
const label = control.getAttribute("aria-label");
|
|
623
624
|
if (label)
|
|
@@ -1439,8 +1440,13 @@ async function registerForm(form, config) {
|
|
|
1439
1440
|
await registerFormTool(form, metadata, execute);
|
|
1440
1441
|
registeredForms.add(form);
|
|
1441
1442
|
registeredFormCount++;
|
|
1443
|
+
const formSubmitBtn = form.querySelector(
|
|
1444
|
+
'[type="submit"], button[data-variant="primary"], button:not([type])'
|
|
1445
|
+
) ?? null;
|
|
1446
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1447
|
+
pendingBtns[metadata.name] = formSubmitBtn;
|
|
1442
1448
|
if (config.debug) {
|
|
1443
|
-
console.
|
|
1449
|
+
console.log(`[auto-webmcp] Registered: ${metadata.name}`, metadata);
|
|
1444
1450
|
}
|
|
1445
1451
|
emit("form:registered", form, metadata.name);
|
|
1446
1452
|
}
|
|
@@ -1452,7 +1458,7 @@ async function unregisterForm(form, config) {
|
|
|
1452
1458
|
await unregisterFormTool(form);
|
|
1453
1459
|
registeredForms.delete(form);
|
|
1454
1460
|
if (config.debug) {
|
|
1455
|
-
console.
|
|
1461
|
+
console.log(`[auto-webmcp] Unregistered: ${name}`);
|
|
1456
1462
|
}
|
|
1457
1463
|
emit("form:unregistered", form, name);
|
|
1458
1464
|
}
|
|
@@ -1552,8 +1558,8 @@ var ORPHAN_EXCLUDED_TYPES = /* @__PURE__ */ new Set([
|
|
|
1552
1558
|
async function scanOrphanInputs(config) {
|
|
1553
1559
|
if (!isWebMCPSupported())
|
|
1554
1560
|
return;
|
|
1555
|
-
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button
|
|
1556
|
-
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button
|
|
1561
|
+
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button[data-variant="primary"]:not([disabled])';
|
|
1562
|
+
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button[data-variant="primary"]';
|
|
1557
1563
|
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search/i;
|
|
1558
1564
|
const orphanInputs = Array.from(
|
|
1559
1565
|
document.querySelectorAll(
|
|
@@ -1561,11 +1567,17 @@ async function scanOrphanInputs(config) {
|
|
|
1561
1567
|
)
|
|
1562
1568
|
).filter((el) => {
|
|
1563
1569
|
if (el instanceof HTMLInputElement && ORPHAN_EXCLUDED_TYPES.has(el.type.toLowerCase())) {
|
|
1570
|
+
console.log(`[auto-webmcp] orphan: skipping excluded type "${el.type}" (name="${el.name}" id="${el.id}")`);
|
|
1564
1571
|
return false;
|
|
1565
1572
|
}
|
|
1566
1573
|
const rect = el.getBoundingClientRect();
|
|
1567
|
-
|
|
1574
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
1575
|
+
console.log(`[auto-webmcp] orphan: skipping invisible input (name="${el.name}" id="${el.id}")`);
|
|
1576
|
+
return false;
|
|
1577
|
+
}
|
|
1578
|
+
return true;
|
|
1568
1579
|
});
|
|
1580
|
+
console.log(`[auto-webmcp] orphan: found ${orphanInputs.length} visible orphan input(s)`);
|
|
1569
1581
|
if (orphanInputs.length === 0)
|
|
1570
1582
|
return;
|
|
1571
1583
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -1582,10 +1594,12 @@ async function scanOrphanInputs(config) {
|
|
|
1582
1594
|
}
|
|
1583
1595
|
container = container.parentElement;
|
|
1584
1596
|
}
|
|
1597
|
+
console.log(`[auto-webmcp] orphan: input (name="${input.name}" id="${input.id}") grouped into container`, foundContainer);
|
|
1585
1598
|
if (!groups.has(foundContainer))
|
|
1586
1599
|
groups.set(foundContainer, []);
|
|
1587
1600
|
groups.get(foundContainer).push(input);
|
|
1588
1601
|
}
|
|
1602
|
+
console.log(`[auto-webmcp] orphan: ${groups.size} group(s) found`);
|
|
1589
1603
|
for (const [container, inputs] of groups) {
|
|
1590
1604
|
const allCandidates = Array.from(
|
|
1591
1605
|
container.querySelectorAll(SUBMIT_BTN_SELECTOR)
|
|
@@ -1594,6 +1608,17 @@ async function scanOrphanInputs(config) {
|
|
|
1594
1608
|
return r.width > 0 && r.height > 0;
|
|
1595
1609
|
});
|
|
1596
1610
|
let submitBtn = allCandidates[allCandidates.length - 1] ?? null;
|
|
1611
|
+
if (!submitBtn) {
|
|
1612
|
+
const disabledCandidates = Array.from(
|
|
1613
|
+
container.querySelectorAll(SUBMIT_BTN_GROUPING_SELECTOR)
|
|
1614
|
+
).filter((b) => {
|
|
1615
|
+
const r = b.getBoundingClientRect();
|
|
1616
|
+
return r.width > 0 && r.height > 0 && b.disabled;
|
|
1617
|
+
});
|
|
1618
|
+
submitBtn = disabledCandidates[disabledCandidates.length - 1] ?? null;
|
|
1619
|
+
if (submitBtn)
|
|
1620
|
+
console.log(`[auto-webmcp] orphan: using disabled submit button as reference: "${submitBtn.textContent?.trim()}"`);
|
|
1621
|
+
}
|
|
1597
1622
|
if (!submitBtn) {
|
|
1598
1623
|
const pageBtns = Array.from(document.querySelectorAll("button")).filter(
|
|
1599
1624
|
(b) => {
|
|
@@ -1602,28 +1627,50 @@ async function scanOrphanInputs(config) {
|
|
|
1602
1627
|
}
|
|
1603
1628
|
);
|
|
1604
1629
|
submitBtn = pageBtns[pageBtns.length - 1] ?? null;
|
|
1630
|
+
if (submitBtn)
|
|
1631
|
+
console.log(`[auto-webmcp] orphan: using page-wide fallback submit button: "${submitBtn.textContent?.trim()}"`);
|
|
1605
1632
|
}
|
|
1633
|
+
console.log(`[auto-webmcp] orphan: submit button for group:`, submitBtn ? `"${submitBtn.textContent?.trim()}" disabled=${submitBtn.disabled}` : "none");
|
|
1606
1634
|
const metadata = analyzeOrphanInputGroup(container, inputs, submitBtn);
|
|
1635
|
+
console.log(`[auto-webmcp] orphan: tool="${metadata.name}" schema keys:`, Object.keys(metadata.inputSchema.properties));
|
|
1607
1636
|
const inputPairs = [];
|
|
1608
1637
|
const schemaProps = metadata.inputSchema.properties;
|
|
1638
|
+
const AUTO_ID_RE = /^_r_[0-9a-z]+_$/i;
|
|
1609
1639
|
for (const el of inputs) {
|
|
1610
|
-
const
|
|
1640
|
+
const id = el.id && !AUTO_ID_RE.test(el.id) ? el.id : null;
|
|
1641
|
+
const key = el.name || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") || (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement ? el.placeholder || null : null) || null;
|
|
1611
1642
|
const safeKey = key ? key.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) : null;
|
|
1612
|
-
|
|
1643
|
+
const matched = !!(safeKey && schemaProps[safeKey]);
|
|
1644
|
+
console.log(`[auto-webmcp] orphan: field (name="${el.name}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1645
|
+
if (matched) {
|
|
1613
1646
|
inputPairs.push({ key: safeKey, el });
|
|
1614
1647
|
}
|
|
1615
1648
|
}
|
|
1649
|
+
console.log(`[auto-webmcp] orphan: ${inputPairs.length}/${inputs.length} input(s) mapped to schema keys`);
|
|
1650
|
+
if (inputPairs.length === 0) {
|
|
1651
|
+
console.log(`[auto-webmcp] orphan: skipping group "${metadata.name}" \u2014 no inputs mapped to schema keys`);
|
|
1652
|
+
continue;
|
|
1653
|
+
}
|
|
1616
1654
|
const toolName = metadata.name;
|
|
1617
1655
|
const execute = async (params) => {
|
|
1656
|
+
console.log(`[auto-webmcp] orphan execute: tool="${toolName}" params=`, params);
|
|
1657
|
+
console.log(`[auto-webmcp] orphan execute: inputPairs=`, inputPairs.map((p) => p.key));
|
|
1618
1658
|
for (const { key, el } of inputPairs) {
|
|
1619
1659
|
if (params[key] !== void 0) {
|
|
1660
|
+
console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
|
|
1620
1661
|
fillElement(el, params[key]);
|
|
1662
|
+
console.log(`[auto-webmcp] orphan execute: after fill, element value=`, el.value);
|
|
1663
|
+
} else {
|
|
1664
|
+
console.log(`[auto-webmcp] orphan execute: key="${key}" not in params, skipping`);
|
|
1621
1665
|
}
|
|
1622
1666
|
}
|
|
1623
1667
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
1624
|
-
|
|
1668
|
+
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;
|
|
1669
|
+
if (!shouldAutoSubmit) {
|
|
1670
|
+
console.log(`[auto-webmcp] orphan execute: autoSubmit=false, returning without clicking submit`);
|
|
1625
1671
|
return { content: [{ type: "text", text: "Fields filled. Ready to submit." }] };
|
|
1626
1672
|
}
|
|
1673
|
+
console.log(`[auto-webmcp] orphan execute: polling for enabled submit button (up to 2s)...`);
|
|
1627
1674
|
let btn = null;
|
|
1628
1675
|
const deadline = Date.now() + 2e3;
|
|
1629
1676
|
while (Date.now() < deadline) {
|
|
@@ -1641,8 +1688,10 @@ async function scanOrphanInputs(config) {
|
|
|
1641
1688
|
await new Promise((r) => setTimeout(r, 100));
|
|
1642
1689
|
}
|
|
1643
1690
|
if (!btn) {
|
|
1691
|
+
console.warn(`[auto-webmcp] orphan execute: submit button still disabled after 2s`);
|
|
1644
1692
|
return { content: [{ type: "text", text: "Fields filled but the submit button is still disabled. The page may require additional input before submitting." }] };
|
|
1645
1693
|
}
|
|
1694
|
+
console.log(`[auto-webmcp] orphan execute: clicking submit button "${btn.textContent?.trim()}"`);
|
|
1646
1695
|
btn.click();
|
|
1647
1696
|
return { content: [{ type: "text", text: "Fields filled and form submitted." }] };
|
|
1648
1697
|
};
|
|
@@ -1657,8 +1706,10 @@ async function scanOrphanInputs(config) {
|
|
|
1657
1706
|
toolDef.annotations = metadata.annotations;
|
|
1658
1707
|
}
|
|
1659
1708
|
await navigator.modelContext.registerTool(toolDef);
|
|
1709
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1710
|
+
pendingBtns[metadata.name] = submitBtn;
|
|
1660
1711
|
if (config.debug) {
|
|
1661
|
-
console.
|
|
1712
|
+
console.log(`[auto-webmcp] Orphan tool registered: ${metadata.name}`, metadata);
|
|
1662
1713
|
}
|
|
1663
1714
|
} catch {
|
|
1664
1715
|
}
|