auto-webmcp 0.3.18 → 0.3.19

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.
@@ -2025,6 +2025,8 @@ var reAnalysisTimers = /* @__PURE__ */ new Map();
2025
2025
  var RE_ANALYSIS_DEBOUNCE_MS = 300;
2026
2026
  var orphanRescanTimer = null;
2027
2027
  var ORPHAN_RESCAN_DEBOUNCE_MS = 500;
2028
+ var orphanRescanDelayedTimer = null;
2029
+ var ORPHAN_RESCAN_DELAYED_MS = 2e3;
2028
2030
  var registeredOrphanToolNames = /* @__PURE__ */ new Set();
2029
2031
  function scheduleOrphanRescan(config) {
2030
2032
  if (orphanRescanTimer)
@@ -2034,10 +2036,20 @@ function scheduleOrphanRescan(config) {
2034
2036
  void scanOrphanInputs(config);
2035
2037
  }, ORPHAN_RESCAN_DEBOUNCE_MS);
2036
2038
  }
2039
+ function scheduleOrphanRescanDelayed(config) {
2040
+ if (orphanRescanDelayedTimer)
2041
+ clearTimeout(orphanRescanDelayedTimer);
2042
+ orphanRescanDelayedTimer = setTimeout(() => {
2043
+ orphanRescanDelayedTimer = null;
2044
+ void scanOrphanInputs(config);
2045
+ }, ORPHAN_RESCAN_DELAYED_MS);
2046
+ }
2037
2047
  function isInterestingNode(node) {
2038
2048
  const tag = node.tagName.toLowerCase();
2039
2049
  if (tag === "input" || tag === "textarea" || tag === "select")
2040
2050
  return true;
2051
+ if (tag.includes("-"))
2052
+ return true;
2041
2053
  const role = node.getAttribute("role");
2042
2054
  if (role && ARIA_ROLES_TO_SCAN.includes(role))
2043
2055
  return true;
@@ -2118,6 +2130,9 @@ function startObserver(config) {
2118
2130
  }
2119
2131
  if (isInterestingNode(node) && !node.closest("form")) {
2120
2132
  scheduleOrphanRescan(config);
2133
+ if (node.tagName.toLowerCase().includes("-")) {
2134
+ scheduleOrphanRescanDelayed(config);
2135
+ }
2121
2136
  }
2122
2137
  }
2123
2138
  for (const node of mutation.removedNodes) {
@@ -2166,6 +2181,35 @@ var ORPHAN_EXCLUDED_TYPES = /* @__PURE__ */ new Set([
2166
2181
  "button",
2167
2182
  "image"
2168
2183
  ]);
2184
+ function collectShadowOrphanInputs(root, outerHost, visited = /* @__PURE__ */ new Set()) {
2185
+ if (visited.has(root))
2186
+ return [];
2187
+ visited.add(root);
2188
+ const results = [];
2189
+ for (const el of Array.from(root.querySelectorAll("*"))) {
2190
+ const sr = el.shadowRoot;
2191
+ if (!sr)
2192
+ continue;
2193
+ const host = outerHost ?? el;
2194
+ results.push(...collectShadowOrphanInputs(sr, host, visited));
2195
+ }
2196
+ if (root instanceof ShadowRoot) {
2197
+ const selector = 'input, textarea, select, [role="textbox"]:not(input):not(textarea), [role="searchbox"]:not(input):not(textarea), button[role="combobox"]';
2198
+ for (const el of Array.from(root.querySelectorAll(selector))) {
2199
+ if (el instanceof HTMLInputElement && ORPHAN_EXCLUDED_TYPES.has(el.type.toLowerCase()))
2200
+ continue;
2201
+ if (el.closest("form"))
2202
+ continue;
2203
+ const rect = el.getBoundingClientRect();
2204
+ if (rect.width === 0 || rect.height === 0)
2205
+ continue;
2206
+ if (outerHost) {
2207
+ results.push({ el, shadowHost: outerHost });
2208
+ }
2209
+ }
2210
+ }
2211
+ return results;
2212
+ }
2169
2213
  async function scanOrphanInputs(config) {
2170
2214
  if (!isWebMCPSupported())
2171
2215
  return;
@@ -2188,8 +2232,9 @@ async function scanOrphanInputs(config) {
2188
2232
  }
2189
2233
  return true;
2190
2234
  });
2191
- console.log(`[auto-webmcp] orphan: found ${orphanInputs.length} visible orphan input(s)`);
2192
- if (orphanInputs.length === 0)
2235
+ const shadowOrphans = collectShadowOrphanInputs(document.body, null);
2236
+ console.log(`[auto-webmcp] orphan: found ${orphanInputs.length} light-DOM + ${shadowOrphans.length} shadow-DOM orphan inputs`);
2237
+ if (orphanInputs.length === 0 && shadowOrphans.length === 0)
2193
2238
  return;
2194
2239
  const groups = /* @__PURE__ */ new Map();
2195
2240
  for (const input of orphanInputs) {
@@ -2210,6 +2255,24 @@ async function scanOrphanInputs(config) {
2210
2255
  groups.set(foundContainer, []);
2211
2256
  groups.get(foundContainer).push(input);
2212
2257
  }
2258
+ for (const { el, shadowHost } of shadowOrphans) {
2259
+ let container = shadowHost.parentElement;
2260
+ let foundContainer = shadowHost.parentElement ?? document.body;
2261
+ while (container && container !== document.body) {
2262
+ const hasSubmitBtn = container.querySelector(SUBMIT_BTN_GROUPING_SELECTOR) !== null || Array.from(container.querySelectorAll("button")).some(
2263
+ (b) => SUBMIT_TEXT_RE.test(b.textContent ?? "")
2264
+ );
2265
+ if (hasSubmitBtn) {
2266
+ foundContainer = container;
2267
+ break;
2268
+ }
2269
+ container = container.parentElement;
2270
+ }
2271
+ console.log(`[auto-webmcp] orphan (shadow): input (id="${el.id}") via host <${shadowHost.tagName.toLowerCase()}> grouped into container`, foundContainer);
2272
+ if (!groups.has(foundContainer))
2273
+ groups.set(foundContainer, []);
2274
+ groups.get(foundContainer).push(el);
2275
+ }
2213
2276
  console.log(`[auto-webmcp] orphan: ${groups.size} group(s) found`);
2214
2277
  for (const [container, inputs] of groups) {
2215
2278
  const allCandidates = Array.from(