auto-webmcp 0.3.0 → 0.3.2
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.
- package/README.md +156 -38
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/auto-webmcp.cjs.js +76 -100
- package/dist/auto-webmcp.cjs.js.map +3 -3
- package/dist/auto-webmcp.esm.js +76 -100
- package/dist/auto-webmcp.esm.js.map +3 -3
- package/dist/auto-webmcp.iife.js +1 -9
- package/dist/auto-webmcp.iife.js.map +4 -4
- package/dist/config.d.ts +0 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/discovery.d.ts.map +1 -1
- package/dist/interceptor.d.ts +14 -0
- package/dist/interceptor.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/auto-webmcp.esm.js
CHANGED
|
@@ -83,7 +83,6 @@ function resolveConfig(userConfig) {
|
|
|
83
83
|
return {
|
|
84
84
|
exclude: userConfig?.exclude ?? [],
|
|
85
85
|
autoSubmit: userConfig?.autoSubmit ?? false,
|
|
86
|
-
enhance: userConfig?.enhance ?? null,
|
|
87
86
|
overrides: userConfig?.overrides ?? {},
|
|
88
87
|
debug: userConfig?.debug ?? false
|
|
89
88
|
};
|
|
@@ -484,17 +483,39 @@ function extractDefaultValue(control) {
|
|
|
484
483
|
}
|
|
485
484
|
return void 0;
|
|
486
485
|
}
|
|
486
|
+
function collectShadowControls(root, visited = /* @__PURE__ */ new Set()) {
|
|
487
|
+
if (visited.has(root))
|
|
488
|
+
return [];
|
|
489
|
+
visited.add(root);
|
|
490
|
+
const results = [];
|
|
491
|
+
for (const el of Array.from(root.querySelectorAll("*"))) {
|
|
492
|
+
if (el.shadowRoot) {
|
|
493
|
+
results.push(
|
|
494
|
+
...Array.from(
|
|
495
|
+
el.shadowRoot.querySelectorAll(
|
|
496
|
+
"input, textarea, select"
|
|
497
|
+
)
|
|
498
|
+
),
|
|
499
|
+
...collectShadowControls(el.shadowRoot, visited)
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return results;
|
|
504
|
+
}
|
|
487
505
|
function buildSchema(form) {
|
|
488
506
|
const properties = {};
|
|
489
507
|
const required = [];
|
|
490
508
|
const fieldElements = /* @__PURE__ */ new Map();
|
|
491
509
|
const processedRadioGroups = /* @__PURE__ */ new Set();
|
|
492
510
|
const processedCheckboxGroups = /* @__PURE__ */ new Set();
|
|
493
|
-
const controls =
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
511
|
+
const controls = [
|
|
512
|
+
...Array.from(
|
|
513
|
+
form.querySelectorAll(
|
|
514
|
+
"input, textarea, select"
|
|
515
|
+
)
|
|
516
|
+
),
|
|
517
|
+
...collectShadowControls(form)
|
|
518
|
+
];
|
|
498
519
|
for (const control of controls) {
|
|
499
520
|
const name = control.name;
|
|
500
521
|
const fieldKey = name || resolveNativeControlFallbackKey(control);
|
|
@@ -672,9 +693,6 @@ function resolveAriaFieldKey(el) {
|
|
|
672
693
|
return null;
|
|
673
694
|
}
|
|
674
695
|
function inferAriaFieldTitle(el) {
|
|
675
|
-
const nativeTitle = el.getAttribute("toolparamtitle");
|
|
676
|
-
if (nativeTitle?.trim())
|
|
677
|
-
return nativeTitle.trim();
|
|
678
696
|
const htmlEl = el;
|
|
679
697
|
if (htmlEl.dataset?.["webmcpTitle"])
|
|
680
698
|
return htmlEl.dataset["webmcpTitle"];
|
|
@@ -713,9 +731,6 @@ function inferAriaFieldDescription(el) {
|
|
|
713
731
|
return "";
|
|
714
732
|
}
|
|
715
733
|
function inferFieldTitle(control) {
|
|
716
|
-
const nativeTitle = control.getAttribute("toolparamtitle");
|
|
717
|
-
if (nativeTitle?.trim())
|
|
718
|
-
return nativeTitle.trim();
|
|
719
734
|
if ("dataset" in control && control.dataset["webmcpTitle"]) {
|
|
720
735
|
return control.dataset["webmcpTitle"];
|
|
721
736
|
}
|
|
@@ -925,6 +940,9 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
925
940
|
return async (params) => {
|
|
926
941
|
pendingFillWarnings.set(form, []);
|
|
927
942
|
fillFormFields(form, params);
|
|
943
|
+
const missingNow = getMissingRequired(metadata, params);
|
|
944
|
+
if (missingNow.length > 0)
|
|
945
|
+
pendingWarnings.set(form, missingNow);
|
|
928
946
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
929
947
|
return new Promise((resolve, reject) => {
|
|
930
948
|
pendingExecutions.set(form, { resolve, reject });
|
|
@@ -951,9 +969,10 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
951
969
|
attachSubmitInterceptor(submitForm, toolName);
|
|
952
970
|
}
|
|
953
971
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
pendingWarnings.
|
|
972
|
+
if (submitForm !== form && pendingWarnings.has(form)) {
|
|
973
|
+
pendingWarnings.set(submitForm, pendingWarnings.get(form));
|
|
974
|
+
pendingWarnings.delete(form);
|
|
975
|
+
}
|
|
957
976
|
submitForm.requestSubmit();
|
|
958
977
|
} catch (err) {
|
|
959
978
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -975,17 +994,37 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
975
994
|
pendingExecutions.delete(form);
|
|
976
995
|
const formData = serializeFormData(form, lastParams.get(form), formFieldElements.get(form));
|
|
977
996
|
lastFilledSnapshot.delete(form);
|
|
978
|
-
const
|
|
997
|
+
const missingRequired = pendingWarnings.get(form) ?? [];
|
|
979
998
|
pendingWarnings.delete(form);
|
|
980
999
|
const fillWarnings = pendingFillWarnings.get(form) ?? [];
|
|
981
1000
|
pendingFillWarnings.delete(form);
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
|
|
1001
|
+
const skippedFields = fillWarnings.filter((w) => w.type === "not_filled").map((w) => w.field);
|
|
1002
|
+
const structured = {
|
|
1003
|
+
status: missingRequired.length > 0 || skippedFields.length > 0 ? "partial" : "success",
|
|
1004
|
+
filled_fields: formData,
|
|
1005
|
+
skipped_fields: skippedFields,
|
|
1006
|
+
missing_required: missingRequired,
|
|
1007
|
+
warnings: [
|
|
1008
|
+
...missingRequired.map((f) => ({
|
|
1009
|
+
field: f,
|
|
1010
|
+
type: "missing_required",
|
|
1011
|
+
message: `required field "${f}" was not provided`
|
|
1012
|
+
})),
|
|
1013
|
+
...fillWarnings
|
|
1014
|
+
]
|
|
1015
|
+
};
|
|
1016
|
+
const allWarnMessages = [
|
|
1017
|
+
...missingRequired.length ? [`required fields were not filled: ${missingRequired.join(", ")}`] : [],
|
|
1018
|
+
...fillWarnings.map((w) => w.message)
|
|
985
1019
|
];
|
|
986
|
-
const warningText =
|
|
1020
|
+
const warningText = allWarnMessages.length ? ` Note: ${allWarnMessages.join("; ")}.` : "";
|
|
987
1021
|
const text = `Form submitted. Fields: ${JSON.stringify(formData)}${warningText}`;
|
|
988
|
-
const result = {
|
|
1022
|
+
const result = {
|
|
1023
|
+
content: [
|
|
1024
|
+
{ type: "text", text },
|
|
1025
|
+
{ type: "text", text: JSON.stringify(structured) }
|
|
1026
|
+
]
|
|
1027
|
+
};
|
|
989
1028
|
if (e.agentInvoked && typeof e.respondWith === "function") {
|
|
990
1029
|
e.preventDefault();
|
|
991
1030
|
e.respondWith(Promise.resolve(result));
|
|
@@ -1119,16 +1158,26 @@ function fillInput(input, form, key, value) {
|
|
|
1119
1158
|
const raw = String(value ?? "");
|
|
1120
1159
|
const num = Number(raw);
|
|
1121
1160
|
if (raw === "" || isNaN(num)) {
|
|
1122
|
-
pendingFillWarnings.get(form)?.push(
|
|
1161
|
+
pendingFillWarnings.get(form)?.push({
|
|
1162
|
+
field: key,
|
|
1163
|
+
type: "type_mismatch",
|
|
1164
|
+
message: `"${key}" expects a number, got: ${JSON.stringify(value)}`,
|
|
1165
|
+
original: value
|
|
1166
|
+
});
|
|
1123
1167
|
return;
|
|
1124
1168
|
}
|
|
1125
1169
|
const min = input.min !== "" ? parseFloat(input.min) : -Infinity;
|
|
1126
1170
|
const max = input.max !== "" ? parseFloat(input.max) : Infinity;
|
|
1127
1171
|
if (num < min || num > max) {
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1172
|
+
const clamped = Math.min(Math.max(num, min), max);
|
|
1173
|
+
pendingFillWarnings.get(form)?.push({
|
|
1174
|
+
field: key,
|
|
1175
|
+
type: "clamped",
|
|
1176
|
+
message: `"${key}" value ${num} is outside allowed range [${input.min || "?"}, ${input.max || "?"}], clamped to ${clamped}`,
|
|
1177
|
+
original: num,
|
|
1178
|
+
actual: clamped
|
|
1179
|
+
});
|
|
1180
|
+
input.value = String(clamped);
|
|
1132
1181
|
} else {
|
|
1133
1182
|
input.value = String(num);
|
|
1134
1183
|
}
|
|
@@ -1315,74 +1364,6 @@ function getMissingRequired(metadata, params) {
|
|
|
1315
1364
|
return metadata.inputSchema.required.filter((fieldKey) => !(fieldKey in params));
|
|
1316
1365
|
}
|
|
1317
1366
|
|
|
1318
|
-
// src/enhancer.ts
|
|
1319
|
-
async function enrichMetadata(metadata, enhancer) {
|
|
1320
|
-
try {
|
|
1321
|
-
const enriched = await callLLM(metadata, enhancer);
|
|
1322
|
-
return { ...metadata, description: enriched };
|
|
1323
|
-
} catch (err) {
|
|
1324
|
-
console.warn("[auto-webmcp] Enrichment failed, using heuristic description:", err);
|
|
1325
|
-
return metadata;
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
async function callLLM(metadata, config) {
|
|
1329
|
-
const prompt = buildPrompt(metadata);
|
|
1330
|
-
if (config.provider === "claude") {
|
|
1331
|
-
return callClaude(prompt, config);
|
|
1332
|
-
} else {
|
|
1333
|
-
return callGemini(prompt, config);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
function buildPrompt(metadata) {
|
|
1337
|
-
const fields = Object.entries(metadata.inputSchema.properties).map(([name, prop]) => `- ${prop.title ?? name} (${prop.type}): ${prop.description ?? ""}`).join("\n");
|
|
1338
|
-
return `You are helping describe a web form as an AI tool. Given this form information:
|
|
1339
|
-
|
|
1340
|
-
Name: ${metadata.name}
|
|
1341
|
-
Current description: ${metadata.description}
|
|
1342
|
-
Fields:
|
|
1343
|
-
${fields}
|
|
1344
|
-
|
|
1345
|
-
Write a concise (1-2 sentence) description of what this tool does and when an AI agent should use it. Be specific and actionable. Respond with only the description, no preamble.`;
|
|
1346
|
-
}
|
|
1347
|
-
async function callClaude(prompt, config) {
|
|
1348
|
-
const model = config.model ?? "claude-haiku-4-5-20251001";
|
|
1349
|
-
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
1350
|
-
method: "POST",
|
|
1351
|
-
headers: {
|
|
1352
|
-
"x-api-key": config.apiKey,
|
|
1353
|
-
"anthropic-version": "2023-06-01",
|
|
1354
|
-
"content-type": "application/json"
|
|
1355
|
-
},
|
|
1356
|
-
body: JSON.stringify({
|
|
1357
|
-
model,
|
|
1358
|
-
max_tokens: 150,
|
|
1359
|
-
messages: [{ role: "user", content: prompt }]
|
|
1360
|
-
})
|
|
1361
|
-
});
|
|
1362
|
-
if (!response.ok) {
|
|
1363
|
-
throw new Error(`Claude API error: ${response.status}`);
|
|
1364
|
-
}
|
|
1365
|
-
const data = await response.json();
|
|
1366
|
-
return data.content.filter((block) => block.type === "text").map((block) => block.text).join("").trim();
|
|
1367
|
-
}
|
|
1368
|
-
async function callGemini(prompt, config) {
|
|
1369
|
-
const model = config.model ?? "gemini-1.5-flash";
|
|
1370
|
-
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${config.apiKey}`;
|
|
1371
|
-
const response = await fetch(url, {
|
|
1372
|
-
method: "POST",
|
|
1373
|
-
headers: { "content-type": "application/json" },
|
|
1374
|
-
body: JSON.stringify({
|
|
1375
|
-
contents: [{ parts: [{ text: prompt }] }],
|
|
1376
|
-
generationConfig: { maxOutputTokens: 150, temperature: 0.2 }
|
|
1377
|
-
})
|
|
1378
|
-
});
|
|
1379
|
-
if (!response.ok) {
|
|
1380
|
-
throw new Error(`Gemini API error: ${response.status}`);
|
|
1381
|
-
}
|
|
1382
|
-
const data = await response.json();
|
|
1383
|
-
return data.candidates[0]?.content.parts.map((p) => p.text).join("").trim() ?? "";
|
|
1384
|
-
}
|
|
1385
|
-
|
|
1386
1367
|
// src/discovery.ts
|
|
1387
1368
|
function emit(type, form, toolName) {
|
|
1388
1369
|
window.dispatchEvent(
|
|
@@ -1414,12 +1395,7 @@ async function registerForm(form, config) {
|
|
|
1414
1395
|
} catch {
|
|
1415
1396
|
}
|
|
1416
1397
|
}
|
|
1417
|
-
|
|
1418
|
-
if (config.enhance) {
|
|
1419
|
-
if (config.debug)
|
|
1420
|
-
console.debug(`[auto-webmcp] Enriching: ${metadata.name}\u2026`);
|
|
1421
|
-
metadata = await enrichMetadata(metadata, config.enhance);
|
|
1422
|
-
}
|
|
1398
|
+
const metadata = analyzeForm(form, override);
|
|
1423
1399
|
if (config.debug) {
|
|
1424
1400
|
warnToolQuality(metadata.name, metadata.description);
|
|
1425
1401
|
}
|