auto-webmcp 0.2.8 → 0.2.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.
@@ -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;AAgcD;;;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,EAAmJ,MAAM,aAAa,CAAC;AAC1L,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;AAsgBD;;;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"}
@@ -240,6 +240,11 @@ function mapSelectElement(select) {
240
240
  return { type: "string" };
241
241
  return { type: "string", enum: enumValues, oneOf };
242
242
  }
243
+ function collectCheckboxEnum(form, name) {
244
+ return Array.from(
245
+ form.querySelectorAll(`input[type="checkbox"][name="${CSS.escape(name)}"]`)
246
+ ).map((cb) => cb.value).filter((v) => v !== "" && v !== "on");
247
+ }
243
248
  function collectRadioEnum(form, name) {
244
249
  const radios = Array.from(
245
250
  form.querySelectorAll(`input[type="radio"][name="${CSS.escape(name)}"]`)
@@ -426,6 +431,7 @@ function buildSchema(form) {
426
431
  const required = [];
427
432
  const fieldElements = /* @__PURE__ */ new Map();
428
433
  const processedRadioGroups = /* @__PURE__ */ new Set();
434
+ const processedCheckboxGroups = /* @__PURE__ */ new Set();
429
435
  const controls = Array.from(
430
436
  form.querySelectorAll(
431
437
  "input, textarea, select"
@@ -441,6 +447,11 @@ function buildSchema(form) {
441
447
  continue;
442
448
  processedRadioGroups.add(fieldKey);
443
449
  }
450
+ if (control instanceof HTMLInputElement && control.type === "checkbox") {
451
+ if (processedCheckboxGroups.has(fieldKey))
452
+ continue;
453
+ processedCheckboxGroups.add(fieldKey);
454
+ }
444
455
  const schemaProp = inputTypeToSchema(control);
445
456
  if (!schemaProp)
446
457
  continue;
@@ -456,6 +467,22 @@ function buildSchema(form) {
456
467
  if (radioOneOf.length > 0)
457
468
  schemaProp.oneOf = radioOneOf;
458
469
  }
470
+ if (control instanceof HTMLInputElement && control.type === "checkbox") {
471
+ const checkboxValues = collectCheckboxEnum(form, fieldKey);
472
+ if (checkboxValues.length > 1) {
473
+ const arrayProp = {
474
+ type: "array",
475
+ items: { type: "string", enum: checkboxValues },
476
+ title: schemaProp.title
477
+ };
478
+ if (schemaProp.description)
479
+ arrayProp.description = schemaProp.description;
480
+ properties[fieldKey] = arrayProp;
481
+ if (control.required)
482
+ required.push(fieldKey);
483
+ continue;
484
+ }
485
+ }
459
486
  properties[fieldKey] = schemaProp;
460
487
  if (!name) {
461
488
  fieldElements.set(fieldKey, control);
@@ -466,7 +493,7 @@ function buildSchema(form) {
466
493
  }
467
494
  const ariaControls = collectAriaControls(form);
468
495
  const processedAriaRadioGroups = /* @__PURE__ */ new Set();
469
- for (const { el, role, key } of ariaControls) {
496
+ for (const { el, role, key, enumValues, enumOneOf } of ariaControls) {
470
497
  if (properties[key])
471
498
  continue;
472
499
  if (role === "radio") {
@@ -475,6 +502,11 @@ function buildSchema(form) {
475
502
  processedAriaRadioGroups.add(key);
476
503
  }
477
504
  const schemaProp = ariaRoleToSchema(el, role);
505
+ if (enumValues && enumValues.length > 0) {
506
+ schemaProp.enum = enumValues;
507
+ if (enumOneOf && enumOneOf.length > 0)
508
+ schemaProp.oneOf = enumOneOf;
509
+ }
478
510
  schemaProp.title = inferAriaFieldTitle(el);
479
511
  const desc = inferAriaFieldDescription(el);
480
512
  if (desc)
@@ -506,7 +538,7 @@ function resolveNativeControlFallbackKey(control) {
506
538
  }
507
539
  function collectAriaControls(form) {
508
540
  const selector = ARIA_ROLES_TO_SCAN.map((r) => `[role="${r}"]`).join(", ");
509
- const results = [];
541
+ const rawResults = [];
510
542
  for (const el of Array.from(form.querySelectorAll(selector))) {
511
543
  if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement)
512
544
  continue;
@@ -516,9 +548,38 @@ function collectAriaControls(form) {
516
548
  const key = resolveAriaFieldKey(el);
517
549
  if (!key)
518
550
  continue;
519
- results.push({ el, role, key });
551
+ rawResults.push({ el, role, key });
552
+ }
553
+ const radioEntries = rawResults.filter((e) => e.role === "radio");
554
+ const nonRadioEntries = rawResults.filter((e) => e.role !== "radio");
555
+ const radioGroupMap = /* @__PURE__ */ new Map();
556
+ const ungroupedRadios = [];
557
+ for (const entry of radioEntries) {
558
+ const group = entry.el.closest('[role="radiogroup"]');
559
+ if (group) {
560
+ if (!radioGroupMap.has(group))
561
+ radioGroupMap.set(group, []);
562
+ radioGroupMap.get(group).push(entry.el);
563
+ } else {
564
+ ungroupedRadios.push(entry);
565
+ }
566
+ }
567
+ const groupedEntries = [];
568
+ for (const [group, members] of radioGroupMap) {
569
+ const groupKey = resolveAriaFieldKey(group);
570
+ if (!groupKey)
571
+ continue;
572
+ const enumValues = members.map((el) => (el.getAttribute("data-value") ?? el.getAttribute("aria-label") ?? el.textContent ?? "").trim()).filter(Boolean);
573
+ const enumOneOf = members.map((el) => {
574
+ const val = (el.getAttribute("data-value") ?? el.getAttribute("aria-label") ?? el.textContent ?? "").trim();
575
+ const title = (el.getAttribute("aria-label") ?? el.textContent ?? "").trim();
576
+ return { const: val, title: title || val };
577
+ }).filter((e) => e.const !== "");
578
+ if (enumValues.length > 0) {
579
+ groupedEntries.push({ el: group, role: "radio", key: groupKey, enumValues, enumOneOf });
580
+ }
520
581
  }
521
- return results;
582
+ return [...nonRadioEntries, ...groupedEntries, ...ungroupedRadios];
522
583
  }
523
584
  function resolveAriaFieldKey(el) {
524
585
  const htmlEl = el;
@@ -714,6 +775,7 @@ function buildSchemaFromInputs(inputs) {
714
775
  const required = [];
715
776
  const fieldElements = /* @__PURE__ */ new Map();
716
777
  const processedRadioGroups = /* @__PURE__ */ new Set();
778
+ const processedCheckboxGroups = /* @__PURE__ */ new Set();
717
779
  for (const control of inputs) {
718
780
  const name = control.name;
719
781
  const fieldKey = name || resolveNativeControlFallbackKey(control);
@@ -724,6 +786,11 @@ function buildSchemaFromInputs(inputs) {
724
786
  continue;
725
787
  processedRadioGroups.add(fieldKey);
726
788
  }
789
+ if (control instanceof HTMLInputElement && control.type === "checkbox") {
790
+ if (processedCheckboxGroups.has(fieldKey))
791
+ continue;
792
+ processedCheckboxGroups.add(fieldKey);
793
+ }
727
794
  const schemaProp = inputTypeToSchema(control);
728
795
  if (!schemaProp)
729
796
  continue;
@@ -733,6 +800,22 @@ function buildSchemaFromInputs(inputs) {
733
800
  const desc = inferFieldDescription(control);
734
801
  if (desc)
735
802
  schemaProp.description = desc;
803
+ if (control instanceof HTMLInputElement && control.type === "checkbox") {
804
+ const checkboxValues = inputs.filter((i) => i instanceof HTMLInputElement && i.type === "checkbox" && i.name === fieldKey).map((cb) => cb.value).filter((v) => v !== "" && v !== "on");
805
+ if (checkboxValues.length > 1) {
806
+ const arrayProp = {
807
+ type: "array",
808
+ items: { type: "string", enum: checkboxValues },
809
+ title: schemaProp.title
810
+ };
811
+ if (schemaProp.description)
812
+ arrayProp.description = schemaProp.description;
813
+ properties[fieldKey] = arrayProp;
814
+ if (control.required)
815
+ required.push(fieldKey);
816
+ continue;
817
+ }
818
+ }
736
819
  properties[fieldKey] = schemaProp;
737
820
  if (!name)
738
821
  fieldElements.set(fieldKey, control);
@@ -750,6 +833,7 @@ var pendingExecutions = /* @__PURE__ */ new WeakMap();
750
833
  var lastParams = /* @__PURE__ */ new WeakMap();
751
834
  var formFieldElements = /* @__PURE__ */ new WeakMap();
752
835
  var pendingWarnings = /* @__PURE__ */ new WeakMap();
836
+ var pendingFillWarnings = /* @__PURE__ */ new WeakMap();
753
837
  var _inputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
754
838
  var _textareaValueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
755
839
  var _checkedSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "checked")?.set;
@@ -759,6 +843,7 @@ function buildExecuteHandler(form, config, toolName, metadata) {
759
843
  }
760
844
  attachSubmitInterceptor(form, toolName);
761
845
  return async (params) => {
846
+ pendingFillWarnings.set(form, []);
762
847
  fillFormFields(form, params);
763
848
  window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
764
849
  return new Promise((resolve, reject) => {
@@ -811,7 +896,13 @@ function attachSubmitInterceptor(form, toolName) {
811
896
  const formData = serializeFormData(form, lastParams.get(form), formFieldElements.get(form));
812
897
  const missing = pendingWarnings.get(form);
813
898
  pendingWarnings.delete(form);
814
- const warningText = missing?.length ? ` Note: required fields were not filled: ${missing.join(", ")}.` : "";
899
+ const fillWarnings = pendingFillWarnings.get(form) ?? [];
900
+ pendingFillWarnings.delete(form);
901
+ const allWarnings = [
902
+ ...missing?.length ? [`required fields were not filled: ${missing.join(", ")}`] : [],
903
+ ...fillWarnings
904
+ ];
905
+ const warningText = allWarnings.length ? ` Note: ${allWarnings.join("; ")}.` : "";
815
906
  const text = `Form submitted. Fields: ${JSON.stringify(formData)}${warningText}`;
816
907
  const result = { content: [{ type: "text", text }] };
817
908
  if (e.agentInvoked && typeof e.respondWith === "function") {
@@ -913,9 +1004,38 @@ function fillFormFields(form, params) {
913
1004
  function fillInput(input, form, key, value) {
914
1005
  const type = input.type.toLowerCase();
915
1006
  if (type === "checkbox") {
1007
+ if (Array.isArray(value)) {
1008
+ const esc = CSS.escape(key);
1009
+ const allBoxes = form.querySelectorAll(`input[type="checkbox"][name="${esc}"]`);
1010
+ for (const box of allBoxes) {
1011
+ setReactChecked(box, value.map(String).includes(box.value));
1012
+ }
1013
+ return;
1014
+ }
916
1015
  setReactChecked(input, Boolean(value));
917
1016
  return;
918
1017
  }
1018
+ if (type === "number" || type === "range") {
1019
+ const raw = String(value ?? "");
1020
+ const num = Number(raw);
1021
+ if (raw === "" || isNaN(num)) {
1022
+ pendingFillWarnings.get(form)?.push(`"${key}" expects a number, got: ${JSON.stringify(value)}`);
1023
+ return;
1024
+ }
1025
+ const min = input.min !== "" ? parseFloat(input.min) : -Infinity;
1026
+ const max = input.max !== "" ? parseFloat(input.max) : Infinity;
1027
+ if (num < min || num > max) {
1028
+ pendingFillWarnings.get(form)?.push(
1029
+ `"${key}" value ${num} is outside allowed range [${input.min || "?"}, ${input.max || "?"}]`
1030
+ );
1031
+ input.value = String(Math.min(Math.max(num, min), max));
1032
+ } else {
1033
+ input.value = String(num);
1034
+ }
1035
+ input.dispatchEvent(new InputEvent("input", { bubbles: true, cancelable: true, inputType: "insertText", data: String(num) }));
1036
+ input.dispatchEvent(new Event("change", { bubbles: true }));
1037
+ return;
1038
+ }
919
1039
  if (type === "radio") {
920
1040
  const esc = CSS.escape(key);
921
1041
  const radios = form.querySelectorAll(
@@ -948,6 +1068,22 @@ function fillAriaField(el, value) {
948
1068
  el.dispatchEvent(new MouseEvent("click", { bubbles: true }));
949
1069
  return;
950
1070
  }
1071
+ if (role === "radiogroup") {
1072
+ const radios = Array.from(el.querySelectorAll('[role="radio"]'));
1073
+ for (const radio of radios) {
1074
+ const val = (radio.getAttribute("data-value") ?? radio.getAttribute("aria-label") ?? radio.textContent ?? "").trim();
1075
+ if (val === String(value)) {
1076
+ radio.setAttribute("aria-checked", "true");
1077
+ radio.dispatchEvent(new MouseEvent("click", { bubbles: true }));
1078
+ for (const other of radios) {
1079
+ if (other !== radio)
1080
+ other.setAttribute("aria-checked", "false");
1081
+ }
1082
+ break;
1083
+ }
1084
+ }
1085
+ return;
1086
+ }
951
1087
  const htmlEl = el;
952
1088
  if (htmlEl.isContentEditable) {
953
1089
  htmlEl.textContent = String(value ?? "");