auto-webmcp 0.2.5 → 0.2.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAA8H,MAAM,aAAa,CAAC;AACrK,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,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,CAMxF;AA8YD;;;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,CAKd"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAA8H,MAAM,aAAa,CAAC;AACrK,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,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,CAMxF;AAkaD;;;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,CAKd"}
@@ -192,7 +192,7 @@ function buildStringSchema(input) {
192
192
  return prop;
193
193
  }
194
194
  function mapSelectElement(select) {
195
- const filtered = Array.from(select.options).filter((o) => o.value !== "");
195
+ const filtered = Array.from(select.options).filter((o) => o.value !== "" && !o.disabled);
196
196
  if (filtered.length === 0) {
197
197
  return { type: "string" };
198
198
  }
@@ -454,6 +454,12 @@ function resolveNativeControlFallbackKey(control) {
454
454
  const label = control.getAttribute("aria-label");
455
455
  if (label)
456
456
  return sanitizeName(label);
457
+ if ((control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement) && control.placeholder?.trim()) {
458
+ return sanitizeName(control.placeholder.trim());
459
+ }
460
+ if (control instanceof HTMLInputElement && control.type !== "text") {
461
+ return control.type;
462
+ }
457
463
  return null;
458
464
  }
459
465
  function collectAriaControls(form) {
@@ -538,6 +544,9 @@ function inferFieldTitle(control) {
538
544
  return humanizeName(control.name);
539
545
  if (control.id)
540
546
  return humanizeName(control.id);
547
+ if ((control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement) && control.placeholder?.trim()) {
548
+ return control.placeholder.trim();
549
+ }
541
550
  return "";
542
551
  }
543
552
  function inferFieldDescription(control) {
@@ -678,6 +687,7 @@ init_registry();
678
687
  var pendingExecutions = /* @__PURE__ */ new WeakMap();
679
688
  var lastParams = /* @__PURE__ */ new WeakMap();
680
689
  var formFieldElements = /* @__PURE__ */ new WeakMap();
690
+ var pendingWarnings = /* @__PURE__ */ new WeakMap();
681
691
  var _inputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
682
692
  var _textareaValueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
683
693
  var _checkedSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "checked")?.set;
@@ -692,22 +702,36 @@ function buildExecuteHandler(form, config, toolName, metadata) {
692
702
  return new Promise((resolve, reject) => {
693
703
  pendingExecutions.set(form, { resolve, reject });
694
704
  if (config.autoSubmit || form.hasAttribute("toolautosubmit") || form.dataset["webmcpAutosubmit"] !== void 0) {
695
- setTimeout(() => {
696
- fillFormFields(form, params);
697
- let submitForm = form;
698
- if (!form.isConnected) {
699
- const liveBtn = document.querySelector(
700
- 'button[type="submit"]:not([disabled]), input[type="submit"]:not([disabled])'
701
- );
702
- const found = liveBtn?.closest("form");
703
- if (found) {
704
- submitForm = found;
705
- pendingExecutions.set(submitForm, { resolve, reject });
706
- attachSubmitInterceptor(submitForm, toolName);
705
+ waitForDomStable(form).then(async () => {
706
+ try {
707
+ fillFormFields(form, params);
708
+ for (let attempt = 0; attempt < 2; attempt++) {
709
+ const reset = getResetFields(form, params, formFieldElements.get(form));
710
+ if (reset.length === 0)
711
+ break;
712
+ fillFormFields(form, params);
713
+ await waitForDomStable(form, 400, 100);
714
+ }
715
+ let submitForm = form;
716
+ if (!form.isConnected) {
717
+ const liveBtn = document.querySelector(
718
+ 'button[type="submit"]:not([disabled]), input[type="submit"]:not([disabled])'
719
+ );
720
+ const found = liveBtn?.closest("form");
721
+ if (found) {
722
+ submitForm = found;
723
+ pendingExecutions.set(submitForm, { resolve, reject });
724
+ attachSubmitInterceptor(submitForm, toolName);
725
+ }
707
726
  }
727
+ const missing = getMissingRequired(metadata, params);
728
+ if (missing.length > 0)
729
+ pendingWarnings.set(submitForm, missing);
730
+ submitForm.requestSubmit();
731
+ } catch (err) {
732
+ reject(err instanceof Error ? err : new Error(String(err)));
708
733
  }
709
- submitForm.requestSubmit();
710
- }, 300);
734
+ });
711
735
  }
712
736
  });
713
737
  };
@@ -723,7 +747,10 @@ function attachSubmitInterceptor(form, toolName) {
723
747
  const { resolve } = pending;
724
748
  pendingExecutions.delete(form);
725
749
  const formData = serializeFormData(form, lastParams.get(form), formFieldElements.get(form));
726
- const text = `Form submitted. Fields: ${JSON.stringify(formData)}`;
750
+ const missing = pendingWarnings.get(form);
751
+ pendingWarnings.delete(form);
752
+ const warningText = missing?.length ? ` Note: required fields were not filled: ${missing.join(", ")}.` : "";
753
+ const text = `Form submitted. Fields: ${JSON.stringify(formData)}${warningText}`;
727
754
  const result = { content: [{ type: "text", text }] };
728
755
  if (e.agentInvoked && typeof e.respondWith === "function") {
729
756
  e.preventDefault();
@@ -929,6 +956,50 @@ function fillElement(el, value) {
929
956
  fillAriaField(el, value);
930
957
  }
931
958
  }
959
+ function waitForDomStable(form, maxMs = 800, debounceMs = 150) {
960
+ return new Promise((resolve) => {
961
+ let settled = false;
962
+ let debounceTimer = null;
963
+ const settle = () => {
964
+ if (settled)
965
+ return;
966
+ settled = true;
967
+ observer2.disconnect();
968
+ if (debounceTimer !== null)
969
+ clearTimeout(debounceTimer);
970
+ resolve();
971
+ };
972
+ const observer2 = new MutationObserver(() => {
973
+ if (debounceTimer !== null)
974
+ clearTimeout(debounceTimer);
975
+ debounceTimer = setTimeout(settle, debounceMs);
976
+ });
977
+ observer2.observe(form, { childList: true, subtree: true, attributes: true, characterData: true });
978
+ setTimeout(settle, maxMs);
979
+ debounceTimer = setTimeout(settle, debounceMs);
980
+ });
981
+ }
982
+ function getResetFields(form, params, fieldEls) {
983
+ const reset = [];
984
+ for (const [key, expected] of Object.entries(params)) {
985
+ const el = findNativeField(form, key) ?? (fieldEls?.get(key) ?? null);
986
+ if (!el)
987
+ continue;
988
+ if (el instanceof HTMLInputElement && el.type === "checkbox") {
989
+ if (el.checked !== Boolean(expected))
990
+ reset.push(key);
991
+ } else if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
992
+ if (el.value !== String(expected ?? ""))
993
+ reset.push(key);
994
+ }
995
+ }
996
+ return reset;
997
+ }
998
+ function getMissingRequired(metadata, params) {
999
+ if (!metadata?.inputSchema?.required?.length)
1000
+ return [];
1001
+ return metadata.inputSchema.required.filter((fieldKey) => !(fieldKey in params));
1002
+ }
932
1003
 
933
1004
  // src/enhancer.ts
934
1005
  async function enrichMetadata(metadata, enhancer) {