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.
@@ -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.debug(`[auto-webmcp] Registered: ${metadata.name}`, metadata);
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.debug(`[auto-webmcp] Unregistered: ${name}`);
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:not([type]):not([disabled])';
1556
- const SUBMIT_BTN_GROUPING_SELECTOR = '[type="submit"], button:not([type])';
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
- return rect.width > 0 && rect.height > 0;
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 key = el.name || el.dataset["webmcpName"] || el.id || el.getAttribute("aria-label") || null;
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
- if (safeKey && schemaProps[safeKey]) {
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
- if (!config.autoSubmit) {
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.debug(`[auto-webmcp] Orphan tool registered: ${metadata.name}`, metadata);
1712
+ console.log(`[auto-webmcp] Orphan tool registered: ${metadata.name}`, metadata);
1662
1713
  }
1663
1714
  } catch {
1664
1715
  }