auto-webmcp 0.3.16 → 0.3.18
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 +15 -0
- package/dist/auto-webmcp.cjs.js +308 -8
- package/dist/auto-webmcp.cjs.js.map +2 -2
- package/dist/auto-webmcp.esm.js +308 -8
- package/dist/auto-webmcp.esm.js.map +2 -2
- package/dist/auto-webmcp.iife.js +1 -1
- package/dist/auto-webmcp.iife.js.map +3 -3
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/discovery.d.ts.map +1 -1
- package/dist/interceptor.d.ts +12 -2
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/auto-webmcp.esm.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
// src/config.ts
|
|
2
2
|
function resolveConfig(userConfig) {
|
|
3
|
+
const strict = userConfig?.paramBinding?.strict ?? false;
|
|
4
|
+
const enableAliasResolution = strict ? false : userConfig?.paramBinding?.enableAliasResolution ?? true;
|
|
3
5
|
return {
|
|
4
6
|
exclude: userConfig?.exclude ?? [],
|
|
5
7
|
autoSubmit: userConfig?.autoSubmit ?? false,
|
|
8
|
+
declarativeMode: userConfig?.declarativeMode ?? "skip",
|
|
9
|
+
paramBinding: {
|
|
10
|
+
strict,
|
|
11
|
+
enableAliasResolution
|
|
12
|
+
},
|
|
13
|
+
execution: {
|
|
14
|
+
timeoutMs: Math.max(100, userConfig?.execution?.timeoutMs ?? 15e3)
|
|
15
|
+
},
|
|
6
16
|
overrides: userConfig?.overrides ?? {},
|
|
17
|
+
preserveExisting: userConfig?.preserveExisting ?? false,
|
|
7
18
|
debug: userConfig?.debug ?? false
|
|
8
19
|
};
|
|
9
20
|
}
|
|
@@ -963,6 +974,53 @@ function buildSchemaFromInputs(inputs) {
|
|
|
963
974
|
}
|
|
964
975
|
|
|
965
976
|
// src/registry.ts
|
|
977
|
+
var EXECUTE_OUTPUT_SCHEMA = {
|
|
978
|
+
type: "object",
|
|
979
|
+
properties: {
|
|
980
|
+
status: {
|
|
981
|
+
type: "string",
|
|
982
|
+
enum: ["success", "partial", "error", "awaiting_user_action", "timed_out", "blocked_invalid"],
|
|
983
|
+
description: "Outcome of the form execution."
|
|
984
|
+
},
|
|
985
|
+
filled_fields: {
|
|
986
|
+
type: "object",
|
|
987
|
+
description: "Field name to submitted value map."
|
|
988
|
+
},
|
|
989
|
+
skipped_fields: {
|
|
990
|
+
type: "array",
|
|
991
|
+
items: { type: "string" },
|
|
992
|
+
description: "Fields the agent provided but that could not be filled."
|
|
993
|
+
},
|
|
994
|
+
missing_required: {
|
|
995
|
+
type: "array",
|
|
996
|
+
items: { type: "string" },
|
|
997
|
+
description: "Required fields not supplied by the agent."
|
|
998
|
+
},
|
|
999
|
+
validation_errors: {
|
|
1000
|
+
type: "array",
|
|
1001
|
+
items: {
|
|
1002
|
+
type: "object",
|
|
1003
|
+
properties: {
|
|
1004
|
+
field: { type: "string" },
|
|
1005
|
+
constraint: { type: "string", description: "HTML ValidityState key that failed." },
|
|
1006
|
+
message: { type: "string" }
|
|
1007
|
+
},
|
|
1008
|
+
required: ["field", "constraint", "message"]
|
|
1009
|
+
},
|
|
1010
|
+
description: "Per-field HTML5 validation failures (present when status is blocked_invalid)."
|
|
1011
|
+
},
|
|
1012
|
+
existing_values: {
|
|
1013
|
+
type: "object",
|
|
1014
|
+
description: "Field values present in the form before the agent filled it."
|
|
1015
|
+
},
|
|
1016
|
+
warnings: {
|
|
1017
|
+
type: "array",
|
|
1018
|
+
items: { type: "object" },
|
|
1019
|
+
description: "Non-fatal fill warnings (alias_resolved, clamped, not_filled, etc.)."
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
required: ["status", "filled_fields", "skipped_fields", "missing_required", "warnings"]
|
|
1023
|
+
};
|
|
966
1024
|
var registeredTools = /* @__PURE__ */ new Map();
|
|
967
1025
|
var registrationControllers = /* @__PURE__ */ new Map();
|
|
968
1026
|
function isWebMCPSupported() {
|
|
@@ -979,6 +1037,7 @@ async function registerFormTool(form, metadata, execute) {
|
|
|
979
1037
|
name: metadata.name,
|
|
980
1038
|
description: metadata.description,
|
|
981
1039
|
inputSchema: metadata.inputSchema,
|
|
1040
|
+
outputSchema: EXECUTE_OUTPUT_SCHEMA,
|
|
982
1041
|
execute
|
|
983
1042
|
};
|
|
984
1043
|
if (metadata.annotations && Object.keys(metadata.annotations).length > 0) {
|
|
@@ -1032,9 +1091,128 @@ var formFieldElements = /* @__PURE__ */ new WeakMap();
|
|
|
1032
1091
|
var pendingWarnings = /* @__PURE__ */ new WeakMap();
|
|
1033
1092
|
var pendingFillWarnings = /* @__PURE__ */ new WeakMap();
|
|
1034
1093
|
var lastFilledSnapshot = /* @__PURE__ */ new WeakMap();
|
|
1094
|
+
var preFillValues = /* @__PURE__ */ new WeakMap();
|
|
1035
1095
|
var _inputValueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
|
1036
1096
|
var _textareaValueSetter = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set;
|
|
1037
1097
|
var _checkedSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "checked")?.set;
|
|
1098
|
+
function normalizeAliasKey(raw) {
|
|
1099
|
+
return raw.toLowerCase().replace(/[^a-z0-9]+/g, "");
|
|
1100
|
+
}
|
|
1101
|
+
function addAlias(index, alias, schemaKey) {
|
|
1102
|
+
if (!alias)
|
|
1103
|
+
return;
|
|
1104
|
+
const normalized = normalizeAliasKey(alias);
|
|
1105
|
+
if (!normalized)
|
|
1106
|
+
return;
|
|
1107
|
+
if (!index.has(normalized))
|
|
1108
|
+
index.set(normalized, /* @__PURE__ */ new Set());
|
|
1109
|
+
index.get(normalized).add(schemaKey);
|
|
1110
|
+
}
|
|
1111
|
+
function buildAliasIndex(form, metadata) {
|
|
1112
|
+
const index = /* @__PURE__ */ new Map();
|
|
1113
|
+
const properties = metadata?.inputSchema?.properties ?? {};
|
|
1114
|
+
for (const [schemaKey, prop] of Object.entries(properties)) {
|
|
1115
|
+
addAlias(index, schemaKey, schemaKey);
|
|
1116
|
+
addAlias(index, schemaKey.replace(/_/g, " "), schemaKey);
|
|
1117
|
+
addAlias(index, prop.title, schemaKey);
|
|
1118
|
+
const nativeEl = findNativeField(form, schemaKey);
|
|
1119
|
+
const mappedEl = metadata?.fieldElements?.get(schemaKey);
|
|
1120
|
+
const el = nativeEl ?? mappedEl ?? null;
|
|
1121
|
+
if (!el)
|
|
1122
|
+
continue;
|
|
1123
|
+
const htmlEl = el;
|
|
1124
|
+
addAlias(index, htmlEl.getAttribute("id"), schemaKey);
|
|
1125
|
+
addAlias(index, htmlEl.getAttribute("name"), schemaKey);
|
|
1126
|
+
addAlias(index, htmlEl.getAttribute("aria-label"), schemaKey);
|
|
1127
|
+
addAlias(index, htmlEl.getAttribute("placeholder"), schemaKey);
|
|
1128
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
|
|
1129
|
+
for (const label of Array.from(el.labels ?? [])) {
|
|
1130
|
+
addAlias(index, label.textContent?.trim(), schemaKey);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
return index;
|
|
1135
|
+
}
|
|
1136
|
+
function resolveParamsForSchema(form, params, metadata, config) {
|
|
1137
|
+
const resolved = {};
|
|
1138
|
+
const warnings = [];
|
|
1139
|
+
const properties = metadata?.inputSchema?.properties ?? {};
|
|
1140
|
+
const aliasEnabled = config.paramBinding.enableAliasResolution;
|
|
1141
|
+
for (const [key, value] of Object.entries(params)) {
|
|
1142
|
+
if (key in properties)
|
|
1143
|
+
resolved[key] = value;
|
|
1144
|
+
}
|
|
1145
|
+
if (!aliasEnabled)
|
|
1146
|
+
return { resolved, warnings };
|
|
1147
|
+
const aliasIndex = buildAliasIndex(form, metadata);
|
|
1148
|
+
for (const [rawKey, value] of Object.entries(params)) {
|
|
1149
|
+
if (rawKey in properties)
|
|
1150
|
+
continue;
|
|
1151
|
+
const candidates = aliasIndex.get(normalizeAliasKey(rawKey));
|
|
1152
|
+
if (!candidates || candidates.size !== 1)
|
|
1153
|
+
continue;
|
|
1154
|
+
const target = Array.from(candidates)[0];
|
|
1155
|
+
if (!target || target in resolved)
|
|
1156
|
+
continue;
|
|
1157
|
+
resolved[target] = value;
|
|
1158
|
+
warnings.push({
|
|
1159
|
+
field: target,
|
|
1160
|
+
type: "alias_resolved",
|
|
1161
|
+
original: rawKey,
|
|
1162
|
+
message: `resolved "${rawKey}" to schema field "${target}"`
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
return { resolved, warnings };
|
|
1166
|
+
}
|
|
1167
|
+
function collectInvalidFieldWarnings(form) {
|
|
1168
|
+
const warnings = [];
|
|
1169
|
+
const controls = Array.from(form.elements).filter(
|
|
1170
|
+
(el) => el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement
|
|
1171
|
+
);
|
|
1172
|
+
for (const control of controls) {
|
|
1173
|
+
if (!control.willValidate)
|
|
1174
|
+
continue;
|
|
1175
|
+
if (control.checkValidity())
|
|
1176
|
+
continue;
|
|
1177
|
+
const field = control.name || control.id || control.getAttribute("aria-label") || "unknown_field";
|
|
1178
|
+
warnings.push({
|
|
1179
|
+
field,
|
|
1180
|
+
type: "blocked_submit",
|
|
1181
|
+
message: control.validationMessage || `field "${field}" failed validation`
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
return warnings;
|
|
1185
|
+
}
|
|
1186
|
+
function captureCurrentValues(form) {
|
|
1187
|
+
const result = {};
|
|
1188
|
+
try {
|
|
1189
|
+
const data = new FormData(form);
|
|
1190
|
+
for (const [key, val] of data.entries()) {
|
|
1191
|
+
if (result[key] !== void 0) {
|
|
1192
|
+
const existing = result[key];
|
|
1193
|
+
result[key] = Array.isArray(existing) ? [...existing, val] : [existing, val];
|
|
1194
|
+
} else {
|
|
1195
|
+
result[key] = val;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
} catch {
|
|
1199
|
+
}
|
|
1200
|
+
return result;
|
|
1201
|
+
}
|
|
1202
|
+
function collectValidationErrors(form) {
|
|
1203
|
+
const errors = [];
|
|
1204
|
+
for (const control of Array.from(form.elements)) {
|
|
1205
|
+
if (!(control instanceof HTMLInputElement) && !(control instanceof HTMLTextAreaElement) && !(control instanceof HTMLSelectElement))
|
|
1206
|
+
continue;
|
|
1207
|
+
if (!control.willValidate || control.checkValidity())
|
|
1208
|
+
continue;
|
|
1209
|
+
const field = control.name || control.id || control.getAttribute("aria-label") || "unknown_field";
|
|
1210
|
+
const v = control.validity;
|
|
1211
|
+
const constraint = v.valueMissing ? "valueMissing" : v.typeMismatch ? "typeMismatch" : v.patternMismatch ? "patternMismatch" : v.tooLong ? "tooLong" : v.tooShort ? "tooShort" : v.rangeUnderflow ? "rangeUnderflow" : v.rangeOverflow ? "rangeOverflow" : v.stepMismatch ? "stepMismatch" : v.customError ? "customError" : "badInput";
|
|
1212
|
+
errors.push({ field, constraint, message: control.validationMessage || `field "${field}" failed validation` });
|
|
1213
|
+
}
|
|
1214
|
+
return errors;
|
|
1215
|
+
}
|
|
1038
1216
|
function buildExecuteHandler(form, config, toolName, metadata) {
|
|
1039
1217
|
if (metadata?.fieldElements) {
|
|
1040
1218
|
formFieldElements.set(form, metadata.fieldElements);
|
|
@@ -1056,22 +1234,86 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
1056
1234
|
}
|
|
1057
1235
|
pendingFillWarnings.set(form, []);
|
|
1058
1236
|
pendingWarnings.delete(form);
|
|
1059
|
-
|
|
1060
|
-
|
|
1237
|
+
const existingSnapshot = captureCurrentValues(form);
|
|
1238
|
+
preFillValues.set(form, existingSnapshot);
|
|
1239
|
+
const { resolved: resolvedParams, warnings: aliasWarnings } = resolveParamsForSchema(
|
|
1240
|
+
form,
|
|
1241
|
+
params,
|
|
1242
|
+
metadata,
|
|
1243
|
+
config
|
|
1244
|
+
);
|
|
1245
|
+
if (aliasWarnings.length > 0) {
|
|
1246
|
+
pendingFillWarnings.set(form, [...pendingFillWarnings.get(form) ?? [], ...aliasWarnings]);
|
|
1247
|
+
}
|
|
1248
|
+
let paramsToFill = resolvedParams;
|
|
1249
|
+
if (config.preserveExisting) {
|
|
1250
|
+
const preserved = [];
|
|
1251
|
+
paramsToFill = Object.fromEntries(
|
|
1252
|
+
Object.entries(resolvedParams).filter(([key]) => {
|
|
1253
|
+
const current = existingSnapshot[key];
|
|
1254
|
+
const hasValue = current !== void 0 && current !== "" && current !== null;
|
|
1255
|
+
if (hasValue) {
|
|
1256
|
+
preserved.push({
|
|
1257
|
+
field: key,
|
|
1258
|
+
type: "not_filled",
|
|
1259
|
+
message: `field "${key}" already has a value and preserveExisting is enabled`
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
return !hasValue;
|
|
1263
|
+
})
|
|
1264
|
+
);
|
|
1265
|
+
if (preserved.length > 0) {
|
|
1266
|
+
pendingFillWarnings.set(form, [...pendingFillWarnings.get(form) ?? [], ...preserved]);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
fillFormFields(form, paramsToFill);
|
|
1270
|
+
const missingNow = getMissingRequired(metadata, resolvedParams);
|
|
1061
1271
|
if (missingNow.length > 0)
|
|
1062
1272
|
pendingWarnings.set(form, missingNow);
|
|
1063
1273
|
window.dispatchEvent(new CustomEvent("toolactivated", { detail: { toolName } }));
|
|
1064
1274
|
return new Promise((resolve, reject) => {
|
|
1065
|
-
|
|
1275
|
+
const timeoutMs = config.execution.timeoutMs;
|
|
1276
|
+
const timeoutId = setTimeout(() => {
|
|
1277
|
+
const pending = pendingExecutions.get(form);
|
|
1278
|
+
if (!pending)
|
|
1279
|
+
return;
|
|
1280
|
+
pendingExecutions.delete(form);
|
|
1281
|
+
const timedOutState = config.autoSubmit || form.hasAttribute("toolautosubmit") || form.dataset["webmcpAutosubmit"] !== void 0 ? "timed_out" : "awaiting_user_action";
|
|
1282
|
+
const warn = {
|
|
1283
|
+
field: "__form__",
|
|
1284
|
+
type: "timeout",
|
|
1285
|
+
message: timedOutState === "timed_out" ? `tool execution timed out after ${timeoutMs}ms` : `waiting for user submit (timed out after ${timeoutMs}ms)`
|
|
1286
|
+
};
|
|
1287
|
+
const _existingValsTimeout = preFillValues.get(form);
|
|
1288
|
+
const structured = {
|
|
1289
|
+
status: timedOutState,
|
|
1290
|
+
filled_fields: serializeFormData(form, lastParams.get(form), formFieldElements.get(form)),
|
|
1291
|
+
skipped_fields: [],
|
|
1292
|
+
missing_required: pendingWarnings.get(form) ?? [],
|
|
1293
|
+
warnings: [...pendingFillWarnings.get(form) ?? [], warn],
|
|
1294
|
+
..._existingValsTimeout !== void 0 && { existing_values: _existingValsTimeout }
|
|
1295
|
+
};
|
|
1296
|
+
pendingWarnings.delete(form);
|
|
1297
|
+
pendingFillWarnings.delete(form);
|
|
1298
|
+
lastFilledSnapshot.delete(form);
|
|
1299
|
+
preFillValues.delete(form);
|
|
1300
|
+
resolve({
|
|
1301
|
+
content: [
|
|
1302
|
+
{ type: "text", text: warn.message },
|
|
1303
|
+
{ type: "text", text: JSON.stringify(structured) }
|
|
1304
|
+
]
|
|
1305
|
+
});
|
|
1306
|
+
}, timeoutMs);
|
|
1307
|
+
pendingExecutions.set(form, { resolve, reject, timeoutId });
|
|
1066
1308
|
if (config.autoSubmit || form.hasAttribute("toolautosubmit") || form.dataset["webmcpAutosubmit"] !== void 0) {
|
|
1067
1309
|
waitForDomStable(form).then(async () => {
|
|
1068
1310
|
try {
|
|
1069
|
-
fillFormFields(form,
|
|
1311
|
+
fillFormFields(form, resolvedParams);
|
|
1070
1312
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
1071
|
-
const reset = getResetFields(form,
|
|
1313
|
+
const reset = getResetFields(form, resolvedParams, formFieldElements.get(form));
|
|
1072
1314
|
if (reset.length === 0)
|
|
1073
1315
|
break;
|
|
1074
|
-
fillFormFields(form,
|
|
1316
|
+
fillFormFields(form, resolvedParams);
|
|
1075
1317
|
await waitForDomStable(form, 400, 100);
|
|
1076
1318
|
}
|
|
1077
1319
|
let submitForm = form;
|
|
@@ -1082,7 +1324,9 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
1082
1324
|
const found = liveBtn?.closest("form");
|
|
1083
1325
|
if (found) {
|
|
1084
1326
|
submitForm = found;
|
|
1085
|
-
pendingExecutions.
|
|
1327
|
+
const pending = pendingExecutions.get(form);
|
|
1328
|
+
const nextPending = pending?.timeoutId ? { resolve, reject, timeoutId: pending.timeoutId } : { resolve, reject };
|
|
1329
|
+
pendingExecutions.set(submitForm, nextPending);
|
|
1086
1330
|
attachSubmitInterceptor(submitForm, toolName);
|
|
1087
1331
|
}
|
|
1088
1332
|
}
|
|
@@ -1090,6 +1334,43 @@ function buildExecuteHandler(form, config, toolName, metadata) {
|
|
|
1090
1334
|
pendingWarnings.set(submitForm, pendingWarnings.get(form));
|
|
1091
1335
|
pendingWarnings.delete(form);
|
|
1092
1336
|
}
|
|
1337
|
+
if (!submitForm.checkValidity()) {
|
|
1338
|
+
const pending = pendingExecutions.get(submitForm) ?? pendingExecutions.get(form);
|
|
1339
|
+
if (pending) {
|
|
1340
|
+
if (pending.timeoutId)
|
|
1341
|
+
clearTimeout(pending.timeoutId);
|
|
1342
|
+
pendingExecutions.delete(submitForm);
|
|
1343
|
+
pendingExecutions.delete(form);
|
|
1344
|
+
const warnings = [
|
|
1345
|
+
...pendingFillWarnings.get(submitForm) ?? pendingFillWarnings.get(form) ?? [],
|
|
1346
|
+
...collectInvalidFieldWarnings(submitForm)
|
|
1347
|
+
];
|
|
1348
|
+
pendingFillWarnings.delete(submitForm);
|
|
1349
|
+
pendingFillWarnings.delete(form);
|
|
1350
|
+
const _existingValsBlocked = preFillValues.get(form);
|
|
1351
|
+
const structured = {
|
|
1352
|
+
status: "blocked_invalid",
|
|
1353
|
+
filled_fields: serializeFormData(submitForm, lastParams.get(submitForm) ?? lastParams.get(form), formFieldElements.get(submitForm) ?? formFieldElements.get(form)),
|
|
1354
|
+
skipped_fields: [],
|
|
1355
|
+
missing_required: pendingWarnings.get(submitForm) ?? pendingWarnings.get(form) ?? [],
|
|
1356
|
+
warnings,
|
|
1357
|
+
validation_errors: collectValidationErrors(submitForm),
|
|
1358
|
+
..._existingValsBlocked !== void 0 && { existing_values: _existingValsBlocked }
|
|
1359
|
+
};
|
|
1360
|
+
pendingWarnings.delete(submitForm);
|
|
1361
|
+
pendingWarnings.delete(form);
|
|
1362
|
+
lastFilledSnapshot.delete(submitForm);
|
|
1363
|
+
lastFilledSnapshot.delete(form);
|
|
1364
|
+
preFillValues.delete(form);
|
|
1365
|
+
resolve({
|
|
1366
|
+
content: [
|
|
1367
|
+
{ type: "text", text: "Form submission blocked by native validation." },
|
|
1368
|
+
{ type: "text", text: JSON.stringify(structured) }
|
|
1369
|
+
]
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1093
1374
|
submitForm.requestSubmit();
|
|
1094
1375
|
} catch (err) {
|
|
1095
1376
|
reject(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -1108,9 +1389,13 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
1108
1389
|
if (!pending)
|
|
1109
1390
|
return;
|
|
1110
1391
|
const { resolve } = pending;
|
|
1392
|
+
if (pending.timeoutId)
|
|
1393
|
+
clearTimeout(pending.timeoutId);
|
|
1111
1394
|
pendingExecutions.delete(form);
|
|
1112
1395
|
const formData = serializeFormData(form, lastParams.get(form), formFieldElements.get(form));
|
|
1396
|
+
const existingVals = preFillValues.get(form);
|
|
1113
1397
|
lastFilledSnapshot.delete(form);
|
|
1398
|
+
preFillValues.delete(form);
|
|
1114
1399
|
const missingRequired = pendingWarnings.get(form) ?? [];
|
|
1115
1400
|
pendingWarnings.delete(form);
|
|
1116
1401
|
const fillWarnings = pendingFillWarnings.get(form) ?? [];
|
|
@@ -1128,7 +1413,8 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
1128
1413
|
message: `required field "${f}" was not provided`
|
|
1129
1414
|
})),
|
|
1130
1415
|
...fillWarnings
|
|
1131
|
-
]
|
|
1416
|
+
],
|
|
1417
|
+
...existingVals !== void 0 && { existing_values: existingVals }
|
|
1132
1418
|
};
|
|
1133
1419
|
const allWarnMessages = [
|
|
1134
1420
|
...missingRequired.length ? [`required fields were not filled: ${missingRequired.join(", ")}`] : [],
|
|
@@ -1150,6 +1436,7 @@ function attachSubmitInterceptor(form, toolName) {
|
|
|
1150
1436
|
});
|
|
1151
1437
|
form.addEventListener("reset", () => {
|
|
1152
1438
|
lastFilledSnapshot.delete(form);
|
|
1439
|
+
preFillValues.delete(form);
|
|
1153
1440
|
window.dispatchEvent(new CustomEvent("toolcancel", { detail: { toolName } }));
|
|
1154
1441
|
});
|
|
1155
1442
|
}
|
|
@@ -1664,10 +1951,23 @@ function ensureUniqueToolName(baseName, excludeForm) {
|
|
|
1664
1951
|
}
|
|
1665
1952
|
return candidate;
|
|
1666
1953
|
}
|
|
1954
|
+
function hasNativeDeclarativeTool(form) {
|
|
1955
|
+
return form.getAttribute("toolname")?.trim().length ? true : false;
|
|
1956
|
+
}
|
|
1667
1957
|
async function registerForm(form, config) {
|
|
1668
1958
|
if (isExcluded(form, config))
|
|
1669
1959
|
return;
|
|
1670
1960
|
const previousName = getRegisteredToolName(form);
|
|
1961
|
+
if (hasNativeDeclarativeTool(form) && config.declarativeMode !== "force") {
|
|
1962
|
+
if (previousName) {
|
|
1963
|
+
await unregisterFormTool(form);
|
|
1964
|
+
}
|
|
1965
|
+
if (config.debug) {
|
|
1966
|
+
const mode = config.declarativeMode;
|
|
1967
|
+
console.log(`[auto-webmcp] Skipping imperative registration for native declarative form (mode=${mode})`);
|
|
1968
|
+
}
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1671
1971
|
let override;
|
|
1672
1972
|
for (const [selector, ovr] of Object.entries(config.overrides)) {
|
|
1673
1973
|
try {
|