auto-webmcp 0.3.23 → 0.3.24

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.
@@ -1388,9 +1388,11 @@ function buildExecuteHandler(form, config, toolName, metadata) {
1388
1388
  lastFilledSnapshot.delete(submitForm);
1389
1389
  lastFilledSnapshot.delete(form);
1390
1390
  preFillValues.delete(form);
1391
+ const valErrors = structured.validation_errors ?? [];
1392
+ const valSummary = valErrors.length > 0 ? ` Fix: ${valErrors.map((e) => `"${e.field}" (${e.message})`).join("; ")}.` : "";
1391
1393
  resolve({
1392
1394
  content: [
1393
- { type: "text", text: "Form submission blocked by native validation." },
1395
+ { type: "text", text: `Form blocked by validation.${valSummary}` },
1394
1396
  { type: "text", text: JSON.stringify(structured) }
1395
1397
  ]
1396
1398
  });
@@ -1442,12 +1444,20 @@ function attachSubmitInterceptor(form, toolName) {
1442
1444
  ],
1443
1445
  ...existingVals !== void 0 && { existing_values: existingVals }
1444
1446
  };
1447
+ const notFilledFields = fillWarnings.filter((w) => w.type === "not_filled").map((w) => w.field);
1448
+ const totalParams = Object.keys(lastParams.get(form) ?? {}).length;
1449
+ const filledCount = Object.keys(formData).length;
1445
1450
  const allWarnMessages = [
1446
- ...missingRequired.length ? [`required fields were not filled: ${missingRequired.join(", ")}`] : [],
1447
- ...fillWarnings.map((w) => w.message)
1451
+ ...missingRequired.length ? [`required fields not provided: ${missingRequired.join(", ")}`] : [],
1452
+ ...notFilledFields.map((f) => {
1453
+ const w = fillWarnings.find((fw) => fw.field === f);
1454
+ return `"${f}" could not be filled (${w?.message ?? "no matching option"})`;
1455
+ }),
1456
+ ...fillWarnings.filter((w) => w.type !== "not_filled").map((w) => w.message)
1448
1457
  ];
1449
- const warningText = allWarnMessages.length ? ` Note: ${allWarnMessages.join("; ")}.` : "";
1450
- const text = `Form submitted. Fields: ${JSON.stringify(formData)}${warningText}`;
1458
+ const warningText = allWarnMessages.length ? ` Issues: ${allWarnMessages.join("; ")}.` : "";
1459
+ const fillSummary = notFilledFields.length > 0 || missingRequired.length > 0 ? `Filled ${filledCount} of ${totalParams} field(s).` : "Form submitted successfully.";
1460
+ const text = `${fillSummary}${warningText} Fields: ${JSON.stringify(formData)}`;
1451
1461
  const result = {
1452
1462
  content: [
1453
1463
  { type: "text", text },
@@ -1955,7 +1965,7 @@ async function fillLookupInput(el, value) {
1955
1965
  });
1956
1966
  if (!listbox) {
1957
1967
  console.warn("[auto-webmcp] fillLookupInput: listbox did not appear after 3s, leaving text as-is");
1958
- return;
1968
+ return false;
1959
1969
  }
1960
1970
  const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
1961
1971
  const shadowOptions = queryShadowAll(listbox, '[role="option"]');
@@ -1976,6 +1986,7 @@ async function fillLookupInput(el, value) {
1976
1986
  match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
1977
1987
  match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
1978
1988
  match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
1989
+ return true;
1979
1990
  } else {
1980
1991
  console.warn(
1981
1992
  "[auto-webmcp] fillLookupInput: no option matched",
@@ -1983,6 +1994,7 @@ async function fillLookupInput(el, value) {
1983
1994
  "available:",
1984
1995
  options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
1985
1996
  );
1997
+ return false;
1986
1998
  }
1987
1999
  }
1988
2000
  async function fillComboboxButton(el, value) {
@@ -2027,7 +2039,7 @@ async function fillComboboxButton(el, value) {
2027
2039
  });
2028
2040
  if (!listbox) {
2029
2041
  console.warn("[auto-webmcp] fillComboboxButton: listbox did not appear after 3s");
2030
- return;
2042
+ return false;
2031
2043
  }
2032
2044
  const lightOptions = Array.from(listbox.querySelectorAll('[role="option"]'));
2033
2045
  const shadowOptions = queryShadowAll(listbox, '[role="option"]');
@@ -2045,6 +2057,7 @@ async function fillComboboxButton(el, value) {
2045
2057
  match.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true }));
2046
2058
  match.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true }));
2047
2059
  match.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
2060
+ return true;
2048
2061
  } else {
2049
2062
  console.warn(
2050
2063
  "[auto-webmcp] fillComboboxButton: no option matched",
@@ -2052,6 +2065,7 @@ async function fillComboboxButton(el, value) {
2052
2065
  "available:",
2053
2066
  options.map((o) => o.getAttribute("data-value") ?? o.textContent?.trim())
2054
2067
  );
2068
+ return false;
2055
2069
  }
2056
2070
  }
2057
2071
 
@@ -2521,13 +2535,18 @@ async function scanOrphanInputs(config) {
2521
2535
  const execute = async (params, _client) => {
2522
2536
  console.log(`[auto-webmcp] orphan execute: tool="${toolName}" params=`, params);
2523
2537
  console.log(`[auto-webmcp] orphan execute: inputPairs=`, inputPairs.map((p) => p.key));
2538
+ const notFilled = [];
2524
2539
  for (const { key, el } of inputPairs) {
2525
2540
  if (params[key] !== void 0) {
2526
2541
  console.log(`[auto-webmcp] orphan execute: filling key="${key}" value=`, params[key], "element=", el);
2527
2542
  if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "input" && (el.getAttribute("aria-autocomplete") === "list" || el.getAttribute("aria-haspopup") === "listbox")) {
2528
- await fillLookupInput(el, params[key]);
2543
+ const filled = await fillLookupInput(el, params[key]);
2544
+ if (!filled)
2545
+ notFilled.push(key);
2529
2546
  } else if (el.getAttribute("role") === "combobox" && el.tagName.toLowerCase() === "button") {
2530
- await fillComboboxButton(el, params[key]);
2547
+ const filled = await fillComboboxButton(el, params[key]);
2548
+ if (!filled)
2549
+ notFilled.push(key);
2531
2550
  } else {
2532
2551
  fillElement(el, params[key]);
2533
2552
  }
@@ -2539,8 +2558,10 @@ async function scanOrphanInputs(config) {
2539
2558
  window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
2540
2559
  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;
2541
2560
  if (!shouldAutoSubmit) {
2561
+ const issueText = notFilled.length > 0 ? ` Could not fill: ${notFilled.map((f) => `"${f}" (no matching option)`).join(", ")}.` : "";
2562
+ const readyText = notFilled.length > 0 ? `Fields partially filled.${issueText} Review in browser, then click Save.` : "Fields filled. Ready to submit.";
2542
2563
  console.log(`[auto-webmcp] orphan execute: autoSubmit=false, returning without clicking submit`);
2543
- return { content: [{ type: "text", text: "Fields filled. Ready to submit." }] };
2564
+ return { content: [{ type: "text", text: readyText }] };
2544
2565
  }
2545
2566
  console.log(`[auto-webmcp] orphan execute: resolving submit button (up to 2s)...`);
2546
2567
  let btn = null;