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/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAmJ,MAAM,aAAa,CAAC;AAC1L,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,6FAA6F;IAC7F,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAKD,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,YAAY,CAOxF;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAmJ,MAAM,aAAa,CAAC;AAC1L,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,6FAA6F;IAC7F,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAKD,iDAAiD;AACjD,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,CAAC,EAAE,YAAY,GAAG,YAAY,CAOxF;AAspBD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,KAAK,CAAC,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC,EACzE,SAAS,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,IAAI,GACrD,YAAY,CAMd"}
|
package/dist/auto-webmcp.cjs.js
CHANGED
|
@@ -632,11 +632,12 @@ function buildSchema(form) {
|
|
|
632
632
|
}
|
|
633
633
|
return { schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", type: "object", properties, required }, fieldElements };
|
|
634
634
|
}
|
|
635
|
+
var AUTO_GENERATED_ID_RE = /^_r_[0-9a-z]+_$|^:[a-z0-9]+:$/i;
|
|
635
636
|
function resolveNativeControlFallbackKey(control) {
|
|
636
637
|
const el = control;
|
|
637
638
|
if (el.dataset["webmcpName"])
|
|
638
639
|
return sanitizeName(el.dataset["webmcpName"]);
|
|
639
|
-
if (control.id)
|
|
640
|
+
if (control.id && !AUTO_GENERATED_ID_RE.test(control.id))
|
|
640
641
|
return sanitizeName(control.id);
|
|
641
642
|
const label = control.getAttribute("aria-label");
|
|
642
643
|
if (label)
|
|
@@ -1458,8 +1459,13 @@ async function registerForm(form, config) {
|
|
|
1458
1459
|
await registerFormTool(form, metadata, execute);
|
|
1459
1460
|
registeredForms.add(form);
|
|
1460
1461
|
registeredFormCount++;
|
|
1462
|
+
const formSubmitBtn = form.querySelector(
|
|
1463
|
+
'[type="submit"], button[data-variant="primary"], button:not([type])'
|
|
1464
|
+
) ?? null;
|
|
1465
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1466
|
+
pendingBtns[metadata.name] = formSubmitBtn;
|
|
1461
1467
|
if (config.debug) {
|
|
1462
|
-
console.
|
|
1468
|
+
console.log(`[auto-webmcp] Registered: ${metadata.name}`, metadata);
|
|
1463
1469
|
}
|
|
1464
1470
|
emit("form:registered", form, metadata.name);
|
|
1465
1471
|
}
|
|
@@ -1471,7 +1477,7 @@ async function unregisterForm(form, config) {
|
|
|
1471
1477
|
await unregisterFormTool(form);
|
|
1472
1478
|
registeredForms.delete(form);
|
|
1473
1479
|
if (config.debug) {
|
|
1474
|
-
console.
|
|
1480
|
+
console.log(`[auto-webmcp] Unregistered: ${name}`);
|
|
1475
1481
|
}
|
|
1476
1482
|
emit("form:unregistered", form, name);
|
|
1477
1483
|
}
|
|
@@ -1571,8 +1577,8 @@ var ORPHAN_EXCLUDED_TYPES = /* @__PURE__ */ new Set([
|
|
|
1571
1577
|
async function scanOrphanInputs(config) {
|
|
1572
1578
|
if (!isWebMCPSupported())
|
|
1573
1579
|
return;
|
|
1574
|
-
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button
|
|
1575
|
-
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button
|
|
1580
|
+
const SUBMIT_BTN_SELECTOR = '[type="submit"]:not([disabled]), button[data-variant="primary"]:not([disabled])';
|
|
1581
|
+
const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button[data-variant="primary"]';
|
|
1576
1582
|
const SUBMIT_TEXT_RE = /subscribe|submit|sign[\s-]?up|send|join|go|search/i;
|
|
1577
1583
|
const orphanInputs = Array.from(
|
|
1578
1584
|
document.querySelectorAll(
|
|
@@ -1580,11 +1586,17 @@ async function scanOrphanInputs(config) {
|
|
|
1580
1586
|
)
|
|
1581
1587
|
).filter((el) => {
|
|
1582
1588
|
if (el instanceof HTMLInputElement && ORPHAN_EXCLUDED_TYPES.has(el.type.toLowerCase())) {
|
|
1589
|
+
console.log(`[auto-webmcp] orphan: skipping excluded type "${el.type}" (name="${el.name}" id="${el.id}")`);
|
|
1583
1590
|
return false;
|
|
1584
1591
|
}
|
|
1585
1592
|
const rect = el.getBoundingClientRect();
|
|
1586
|
-
|
|
1593
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
1594
|
+
console.log(`[auto-webmcp] orphan: skipping invisible input (name="${el.name}" id="${el.id}")`);
|
|
1595
|
+
return false;
|
|
1596
|
+
}
|
|
1597
|
+
return true;
|
|
1587
1598
|
});
|
|
1599
|
+
console.log(`[auto-webmcp] orphan: found ${orphanInputs.length} visible orphan input(s)`);
|
|
1588
1600
|
if (orphanInputs.length === 0)
|
|
1589
1601
|
return;
|
|
1590
1602
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -1601,10 +1613,12 @@ async function scanOrphanInputs(config) {
|
|
|
1601
1613
|
}
|
|
1602
1614
|
container = container.parentElement;
|
|
1603
1615
|
}
|
|
1616
|
+
console.log(`[auto-webmcp] orphan: input (name="${input.name}" id="${input.id}") grouped into container`, foundContainer);
|
|
1604
1617
|
if (!groups.has(foundContainer))
|
|
1605
1618
|
groups.set(foundContainer, []);
|
|
1606
1619
|
groups.get(foundContainer).push(input);
|
|
1607
1620
|
}
|
|
1621
|
+
console.log(`[auto-webmcp] orphan: ${groups.size} group(s) found`);
|
|
1608
1622
|
for (const [container, inputs] of groups) {
|
|
1609
1623
|
const allCandidates = Array.from(
|
|
1610
1624
|
container.querySelectorAll(SUBMIT_BTN_SELECTOR)
|
|
@@ -1613,6 +1627,17 @@ async function scanOrphanInputs(config) {
|
|
|
1613
1627
|
return r.width > 0 && r.height > 0;
|
|
1614
1628
|
});
|
|
1615
1629
|
let submitBtn = allCandidates[allCandidates.length - 1] ?? null;
|
|
1630
|
+
if (!submitBtn) {
|
|
1631
|
+
const disabledCandidates = Array.from(
|
|
1632
|
+
container.querySelectorAll(SUBMIT_BTN_GROUPING_SELECTOR)
|
|
1633
|
+
).filter((b) => {
|
|
1634
|
+
const r = b.getBoundingClientRect();
|
|
1635
|
+
return r.width > 0 && r.height > 0 && b.disabled;
|
|
1636
|
+
});
|
|
1637
|
+
submitBtn = disabledCandidates[disabledCandidates.length - 1] ?? null;
|
|
1638
|
+
if (submitBtn)
|
|
1639
|
+
console.log(`[auto-webmcp] orphan: using disabled submit button as reference: "${submitBtn.textContent?.trim()}"`);
|
|
1640
|
+
}
|
|
1616
1641
|
if (!submitBtn) {
|
|
1617
1642
|
const pageBtns = Array.from(document.querySelectorAll("button")).filter(
|
|
1618
1643
|
(b) => {
|
|
@@ -1621,28 +1646,50 @@ async function scanOrphanInputs(config) {
|
|
|
1621
1646
|
}
|
|
1622
1647
|
);
|
|
1623
1648
|
submitBtn = pageBtns[pageBtns.length - 1] ?? null;
|
|
1649
|
+
if (submitBtn)
|
|
1650
|
+
console.log(`[auto-webmcp] orphan: using page-wide fallback submit button: "${submitBtn.textContent?.trim()}"`);
|
|
1624
1651
|
}
|
|
1652
|
+
console.log(`[auto-webmcp] orphan: submit button for group:`, submitBtn ? `"${submitBtn.textContent?.trim()}" disabled=${submitBtn.disabled}` : "none");
|
|
1625
1653
|
const metadata = analyzeOrphanInputGroup(container, inputs, submitBtn);
|
|
1654
|
+
console.log(`[auto-webmcp] orphan: tool="${metadata.name}" schema keys:`, Object.keys(metadata.inputSchema.properties));
|
|
1626
1655
|
const inputPairs = [];
|
|
1627
1656
|
const schemaProps = metadata.inputSchema.properties;
|
|
1657
|
+
const AUTO_ID_RE = /^_r_[0-9a-z]+_$/i;
|
|
1628
1658
|
for (const el of inputs) {
|
|
1629
|
-
const
|
|
1659
|
+
const id = el.id && !AUTO_ID_RE.test(el.id) ? el.id : null;
|
|
1660
|
+
const key = el.name || el.dataset["webmcpName"] || id || el.getAttribute("aria-label") || (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement ? el.placeholder || null : null) || null;
|
|
1630
1661
|
const safeKey = key ? key.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) : null;
|
|
1631
|
-
|
|
1662
|
+
const matched = !!(safeKey && schemaProps[safeKey]);
|
|
1663
|
+
console.log(`[auto-webmcp] orphan: field (name="${el.name}" id="${el.id}") rawKey="${key}" safeKey="${safeKey}" matched=${matched}`);
|
|
1664
|
+
if (matched) {
|
|
1632
1665
|
inputPairs.push({ key: safeKey, el });
|
|
1633
1666
|
}
|
|
1634
1667
|
}
|
|
1668
|
+
console.log(`[auto-webmcp] orphan: ${inputPairs.length}/${inputs.length} input(s) mapped to schema keys`);
|
|
1669
|
+
if (inputPairs.length === 0) {
|
|
1670
|
+
console.log(`[auto-webmcp] orphan: skipping group "${metadata.name}" \u2014 no inputs mapped to schema keys`);
|
|
1671
|
+
continue;
|
|
1672
|
+
}
|
|
1635
1673
|
const toolName = metadata.name;
|
|
1636
1674
|
const execute = async (params) => {
|
|
1675
|
+
console.log(`[auto-webmcp] orphan execute: tool="${toolName}" params=`, params);
|
|
1676
|
+
console.log(`[auto-webmcp] orphan execute: inputPairs=`, inputPairs.map((p) => p.key));
|
|
1637
1677
|
for (const { key, el } of inputPairs) {
|
|
1638
1678
|
if (params[key] !== void 0) {
|
|
1679
|
+
console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
|
|
1639
1680
|
fillElement(el, params[key]);
|
|
1681
|
+
console.log(`[auto-webmcp] orphan execute: after fill, element value=`, el.value);
|
|
1682
|
+
} else {
|
|
1683
|
+
console.log(`[auto-webmcp] orphan execute: key="${key}" not in params, skipping`);
|
|
1640
1684
|
}
|
|
1641
1685
|
}
|
|
1642
1686
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
1643
|
-
|
|
1687
|
+
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;
|
|
1688
|
+
if (!shouldAutoSubmit) {
|
|
1689
|
+
console.log(`[auto-webmcp] orphan execute: autoSubmit=false, returning without clicking submit`);
|
|
1644
1690
|
return { content: [{ type: "text", text: "Fields filled. Ready to submit." }] };
|
|
1645
1691
|
}
|
|
1692
|
+
console.log(`[auto-webmcp] orphan execute: polling for enabled submit button (up to 2s)...`);
|
|
1646
1693
|
let btn = null;
|
|
1647
1694
|
const deadline = Date.now() + 2e3;
|
|
1648
1695
|
while (Date.now() < deadline) {
|
|
@@ -1660,8 +1707,10 @@ async function scanOrphanInputs(config) {
|
|
|
1660
1707
|
await new Promise((r) => setTimeout(r, 100));
|
|
1661
1708
|
}
|
|
1662
1709
|
if (!btn) {
|
|
1710
|
+
console.warn(`[auto-webmcp] orphan execute: submit button still disabled after 2s`);
|
|
1663
1711
|
return { content: [{ type: "text", text: "Fields filled but the submit button is still disabled. The page may require additional input before submitting." }] };
|
|
1664
1712
|
}
|
|
1713
|
+
console.log(`[auto-webmcp] orphan execute: clicking submit button "${btn.textContent?.trim()}"`);
|
|
1665
1714
|
btn.click();
|
|
1666
1715
|
return { content: [{ type: "text", text: "Fields filled and form submitted." }] };
|
|
1667
1716
|
};
|
|
@@ -1676,8 +1725,10 @@ async function scanOrphanInputs(config) {
|
|
|
1676
1725
|
toolDef.annotations = metadata.annotations;
|
|
1677
1726
|
}
|
|
1678
1727
|
await navigator.modelContext.registerTool(toolDef);
|
|
1728
|
+
const pendingBtns = window["__pendingSubmitBtns"] ??= {};
|
|
1729
|
+
pendingBtns[metadata.name] = submitBtn;
|
|
1679
1730
|
if (config.debug) {
|
|
1680
|
-
console.
|
|
1731
|
+
console.log(`[auto-webmcp] Orphan tool registered: ${metadata.name}`, metadata);
|
|
1681
1732
|
}
|
|
1682
1733
|
} catch {
|
|
1683
1734
|
}
|