@tooluminati/testing 0.1.0
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/LICENSE +21 -0
- package/dist/browser-helpers-RSQLRHHZ.js +8 -0
- package/dist/browser-helpers.d.ts +6 -0
- package/dist/browser-helpers.d.ts.map +1 -0
- package/dist/browser-helpers.js +23 -0
- package/dist/chunk-6YAIOYYZ.js +30 -0
- package/dist/chunk-EG3BG65X.js +146 -0
- package/dist/comparative-proof-QUN7C3KM.js +11 -0
- package/dist/comparative-proof.d.ts +22 -0
- package/dist/comparative-proof.d.ts.map +1 -0
- package/dist/comparative-proof.js +29 -0
- package/dist/devtools-mcp-helper.d.ts +17 -0
- package/dist/devtools-mcp-helper.d.ts.map +1 -0
- package/dist/devtools-mcp-helper.js +34 -0
- package/dist/dom-only-inspection.d.ts +13 -0
- package/dist/dom-only-inspection.d.ts.map +1 -0
- package/dist/dom-only-inspection.js +86 -0
- package/dist/dom-only-inspection.test.d.ts +2 -0
- package/dist/dom-only-inspection.test.d.ts.map +1 -0
- package/dist/dom-only-inspection.test.js +25 -0
- package/dist/index.cjs +473 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/install-model-context-mock.d.ts +3 -0
- package/dist/install-model-context-mock.d.ts.map +1 -0
- package/dist/install-model-context-mock.js +10 -0
- package/dist/mock-model-context.d.ts +14 -0
- package/dist/mock-model-context.d.ts.map +1 -0
- package/dist/mock-model-context.js +45 -0
- package/dist/model-context-mock-script.d.ts +2 -0
- package/dist/model-context-mock-script.d.ts.map +1 -0
- package/dist/model-context-mock-script.js +40 -0
- package/dist/webmcp-evals.d.ts +32 -0
- package/dist/webmcp-evals.d.ts.map +1 -0
- package/dist/webmcp-evals.js +81 -0
- package/package.json +50 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// src/browser-helpers.ts
|
|
24
|
+
var browser_helpers_exports = {};
|
|
25
|
+
__export(browser_helpers_exports, {
|
|
26
|
+
expectWebMcpTool: () => expectWebMcpTool,
|
|
27
|
+
invokeWebMcpTool: () => invokeWebMcpTool
|
|
28
|
+
});
|
|
29
|
+
async function expectWebMcpTool(page, name) {
|
|
30
|
+
const exists = await page.evaluate(async (toolName) => {
|
|
31
|
+
const context = document.modelContext;
|
|
32
|
+
const tools = await context?.getTools?.() ?? [];
|
|
33
|
+
return tools.some((tool) => tool.name === toolName);
|
|
34
|
+
}, name);
|
|
35
|
+
if (!exists) {
|
|
36
|
+
throw new Error(`Expected WebMCP tool "${name}" to be registered.`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function invokeWebMcpTool(page, name, args) {
|
|
40
|
+
return page.evaluate(
|
|
41
|
+
async ({ toolName, input }) => {
|
|
42
|
+
const context = document.modelContext;
|
|
43
|
+
const tools = await context?.getTools?.() ?? [];
|
|
44
|
+
const tool = tools.find((candidate) => candidate.name === toolName);
|
|
45
|
+
if (!tool || !context?.executeTool) {
|
|
46
|
+
throw new Error(`WebMCP tool "${toolName}" cannot be invoked.`);
|
|
47
|
+
}
|
|
48
|
+
return context.executeTool(tool, JSON.stringify(input));
|
|
49
|
+
},
|
|
50
|
+
{ toolName: name, input: args }
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
var init_browser_helpers = __esm({
|
|
54
|
+
"src/browser-helpers.ts"() {
|
|
55
|
+
"use strict";
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// src/dom-only-inspection.ts
|
|
60
|
+
function pushUnique(target, value) {
|
|
61
|
+
const trimmed = value?.trim();
|
|
62
|
+
if (!trimmed || target.includes(trimmed)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
target.push(trimmed);
|
|
66
|
+
}
|
|
67
|
+
function collectDisabledActionReasonsFromDom(root, buttonLabel) {
|
|
68
|
+
const buttons = [...root.querySelectorAll("button")];
|
|
69
|
+
const button = buttons.find(
|
|
70
|
+
(candidate) => candidate.textContent?.includes(buttonLabel)
|
|
71
|
+
);
|
|
72
|
+
if (!button) {
|
|
73
|
+
return {
|
|
74
|
+
label: buttonLabel,
|
|
75
|
+
disabled: false,
|
|
76
|
+
visibleBlockerReasons: []
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const visibleBlockerReasons = [];
|
|
80
|
+
pushUnique(visibleBlockerReasons, button.getAttribute("title"));
|
|
81
|
+
pushUnique(
|
|
82
|
+
visibleBlockerReasons,
|
|
83
|
+
button.getAttribute("aria-label")?.includes("because") ? button.getAttribute("aria-label") : null
|
|
84
|
+
);
|
|
85
|
+
const describedBy = button.getAttribute("aria-describedby");
|
|
86
|
+
if (describedBy) {
|
|
87
|
+
for (const id of describedBy.split(/\s+/)) {
|
|
88
|
+
pushUnique(
|
|
89
|
+
visibleBlockerReasons,
|
|
90
|
+
root.getElementById(id)?.textContent
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const fieldset = button.closest("fieldset");
|
|
95
|
+
if (fieldset) {
|
|
96
|
+
pushUnique(
|
|
97
|
+
visibleBlockerReasons,
|
|
98
|
+
fieldset.querySelector("legend")?.textContent
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const row = button.closest('[data-testid="checkout-row"]');
|
|
102
|
+
if (row) {
|
|
103
|
+
pushUnique(
|
|
104
|
+
visibleBlockerReasons,
|
|
105
|
+
row.querySelector("[data-dom-blocker-hint]")?.textContent
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
label: buttonLabel,
|
|
110
|
+
disabled: button.disabled,
|
|
111
|
+
visibleBlockerReasons
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function inspectDisabledActionFromDom(page, buttonLabel) {
|
|
115
|
+
return page.evaluate((label) => {
|
|
116
|
+
const buttons = [...document.querySelectorAll("button")];
|
|
117
|
+
const button = buttons.find(
|
|
118
|
+
(candidate) => candidate.textContent?.includes(label)
|
|
119
|
+
);
|
|
120
|
+
if (!button) {
|
|
121
|
+
return {
|
|
122
|
+
label,
|
|
123
|
+
disabled: false,
|
|
124
|
+
visibleBlockerReasons: []
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const visibleBlockerReasons = [];
|
|
128
|
+
const push = (value) => {
|
|
129
|
+
const trimmed = value?.trim();
|
|
130
|
+
if (trimmed && !visibleBlockerReasons.includes(trimmed)) {
|
|
131
|
+
visibleBlockerReasons.push(trimmed);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
push(button.getAttribute("title"));
|
|
135
|
+
const ariaLabel = button.getAttribute("aria-label");
|
|
136
|
+
if (ariaLabel?.includes("because")) {
|
|
137
|
+
push(ariaLabel);
|
|
138
|
+
}
|
|
139
|
+
const describedBy = button.getAttribute("aria-describedby");
|
|
140
|
+
if (describedBy) {
|
|
141
|
+
for (const id of describedBy.split(/\s+/)) {
|
|
142
|
+
push(document.getElementById(id)?.textContent);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const fieldset = button.closest("fieldset");
|
|
146
|
+
if (fieldset) {
|
|
147
|
+
push(fieldset.querySelector("legend")?.textContent);
|
|
148
|
+
}
|
|
149
|
+
const row = button.closest('[data-testid="checkout-row"]');
|
|
150
|
+
if (row) {
|
|
151
|
+
push(row.querySelector("[data-dom-blocker-hint]")?.textContent);
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
label,
|
|
155
|
+
disabled: button.disabled,
|
|
156
|
+
visibleBlockerReasons
|
|
157
|
+
};
|
|
158
|
+
}, buttonLabel);
|
|
159
|
+
}
|
|
160
|
+
var init_dom_only_inspection = __esm({
|
|
161
|
+
"src/dom-only-inspection.ts"() {
|
|
162
|
+
"use strict";
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// src/comparative-proof.ts
|
|
167
|
+
var comparative_proof_exports = {};
|
|
168
|
+
__export(comparative_proof_exports, {
|
|
169
|
+
diagnoseCheckoutBlockerFromDomOnly: () => diagnoseCheckoutBlockerFromDomOnly,
|
|
170
|
+
diagnoseCheckoutBlockerFromWebMcp: () => diagnoseCheckoutBlockerFromWebMcp,
|
|
171
|
+
runComparativeProof: () => runComparativeProof
|
|
172
|
+
});
|
|
173
|
+
async function diagnoseCheckoutBlockerFromDomOnly(page, buttonLabel) {
|
|
174
|
+
return inspectDisabledActionFromDom(page, buttonLabel);
|
|
175
|
+
}
|
|
176
|
+
async function diagnoseCheckoutBlockerFromWebMcp(page, actionId, toolName = "why_is_action_unavailable") {
|
|
177
|
+
const result = await invokeWebMcpTool(page, toolName, { actionId });
|
|
178
|
+
return {
|
|
179
|
+
actionId: result.actionId,
|
|
180
|
+
available: result.available,
|
|
181
|
+
reasons: result.reasons ?? []
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
async function runComparativeProof(page, options) {
|
|
185
|
+
const domOnly = await diagnoseCheckoutBlockerFromDomOnly(
|
|
186
|
+
page,
|
|
187
|
+
options.buttonLabel
|
|
188
|
+
);
|
|
189
|
+
const webMcp = await diagnoseCheckoutBlockerFromWebMcp(
|
|
190
|
+
page,
|
|
191
|
+
options.actionId,
|
|
192
|
+
options.toolName
|
|
193
|
+
);
|
|
194
|
+
const domBlockerCount = domOnly.visibleBlockerReasons.length;
|
|
195
|
+
const webMcpBlockerCount = webMcp.reasons.length;
|
|
196
|
+
return {
|
|
197
|
+
domOnly,
|
|
198
|
+
webMcp,
|
|
199
|
+
domBlockerCount,
|
|
200
|
+
webMcpBlockerCount,
|
|
201
|
+
webMcpIsStrictlyMoreInformative: domOnly.disabled && domBlockerCount === 0 && webMcpBlockerCount > 0 && !webMcp.available
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
var init_comparative_proof = __esm({
|
|
205
|
+
"src/comparative-proof.ts"() {
|
|
206
|
+
"use strict";
|
|
207
|
+
init_browser_helpers();
|
|
208
|
+
init_dom_only_inspection();
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// src/index.ts
|
|
213
|
+
var index_exports = {};
|
|
214
|
+
__export(index_exports, {
|
|
215
|
+
MODEL_CONTEXT_MOCK_INIT_SCRIPT: () => MODEL_CONTEXT_MOCK_INIT_SCRIPT,
|
|
216
|
+
MockModelContext: () => MockModelContext,
|
|
217
|
+
assertToolSchemaBudgets: () => assertToolSchemaBudgets,
|
|
218
|
+
collectDisabledActionReasonsFromDom: () => collectDisabledActionReasonsFromDom,
|
|
219
|
+
createToolCallEvalFixture: () => createToolCallEvalFixture,
|
|
220
|
+
diagnoseCheckoutBlockerFromDomOnly: () => diagnoseCheckoutBlockerFromDomOnly,
|
|
221
|
+
diagnoseCheckoutBlockerFromWebMcp: () => diagnoseCheckoutBlockerFromWebMcp,
|
|
222
|
+
executeWebMcpTool: () => executeWebMcpTool,
|
|
223
|
+
expectWebMcpTool: () => expectWebMcpTool,
|
|
224
|
+
inspectDisabledActionFromDom: () => inspectDisabledActionFromDom,
|
|
225
|
+
installModelContextMock: () => installModelContextMock,
|
|
226
|
+
invokeWebMcpTool: () => invokeWebMcpTool,
|
|
227
|
+
listWebMcpTools: () => listWebMcpTools,
|
|
228
|
+
runComparativeProof: () => runComparativeProof,
|
|
229
|
+
runTimelineComparativeProof: () => runTimelineComparativeProof,
|
|
230
|
+
runToolSelectionSmokeTest: () => runToolSelectionSmokeTest,
|
|
231
|
+
snapshotRegisteredTools: () => snapshotRegisteredTools
|
|
232
|
+
});
|
|
233
|
+
module.exports = __toCommonJS(index_exports);
|
|
234
|
+
init_browser_helpers();
|
|
235
|
+
init_comparative_proof();
|
|
236
|
+
|
|
237
|
+
// src/devtools-mcp-helper.ts
|
|
238
|
+
function getModelContext(host = document) {
|
|
239
|
+
return host.modelContext;
|
|
240
|
+
}
|
|
241
|
+
async function listWebMcpTools(host = document) {
|
|
242
|
+
const context = getModelContext(host);
|
|
243
|
+
if (!context?.getTools) {
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
const tools = await context.getTools();
|
|
247
|
+
return tools.map((tool) => ({
|
|
248
|
+
name: tool.name,
|
|
249
|
+
description: tool.description
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
252
|
+
async function executeWebMcpTool(name, args = {}, host = document) {
|
|
253
|
+
const context = getModelContext(host);
|
|
254
|
+
if (!context?.getTools || !context.executeTool) {
|
|
255
|
+
throw new Error(
|
|
256
|
+
"WebMCP model context is unavailable. Use installModelContextMock() in tests."
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
const tools = await context.getTools();
|
|
260
|
+
const tool = tools.find((candidate) => candidate.name === name);
|
|
261
|
+
if (!tool) {
|
|
262
|
+
throw new Error(`WebMCP tool not found: ${name}`);
|
|
263
|
+
}
|
|
264
|
+
return context.executeTool(tool, JSON.stringify(args));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/index.ts
|
|
268
|
+
init_dom_only_inspection();
|
|
269
|
+
|
|
270
|
+
// src/mock-model-context.ts
|
|
271
|
+
var MockModelContext = class extends EventTarget {
|
|
272
|
+
tools = /* @__PURE__ */ new Map();
|
|
273
|
+
invocations = [];
|
|
274
|
+
registerTool(tool, options = {}) {
|
|
275
|
+
if (this.tools.has(tool.name)) {
|
|
276
|
+
throw new Error(`Tool already registered: ${tool.name}`);
|
|
277
|
+
}
|
|
278
|
+
if (options.signal?.aborted) {
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
this.tools.set(tool.name, tool);
|
|
282
|
+
this.dispatchEvent(new Event("toolchange"));
|
|
283
|
+
options.signal?.addEventListener(
|
|
284
|
+
"abort",
|
|
285
|
+
() => {
|
|
286
|
+
this.tools.delete(tool.name);
|
|
287
|
+
this.dispatchEvent(new Event("toolchange"));
|
|
288
|
+
},
|
|
289
|
+
{ once: true }
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
async getTools() {
|
|
293
|
+
return [...this.tools.values()];
|
|
294
|
+
}
|
|
295
|
+
async executeTool(toolOrName, argsJson = "{}") {
|
|
296
|
+
const name = typeof toolOrName === "string" ? toolOrName : toolOrName.name;
|
|
297
|
+
if (!name) {
|
|
298
|
+
throw new Error("Tool name is required.");
|
|
299
|
+
}
|
|
300
|
+
const tool = this.tools.get(name);
|
|
301
|
+
if (!tool) {
|
|
302
|
+
throw new Error(`Tool not found: ${name}`);
|
|
303
|
+
}
|
|
304
|
+
const args = JSON.parse(argsJson);
|
|
305
|
+
try {
|
|
306
|
+
const result = await tool.execute(args, {
|
|
307
|
+
signal: new AbortController().signal
|
|
308
|
+
});
|
|
309
|
+
this.invocations.push({ name, args, result });
|
|
310
|
+
return result;
|
|
311
|
+
} catch (error) {
|
|
312
|
+
this.invocations.push({ name, args, error });
|
|
313
|
+
throw error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// src/install-model-context-mock.ts
|
|
319
|
+
function installModelContextMock(target = "document") {
|
|
320
|
+
const mock = new MockModelContext();
|
|
321
|
+
const host = target === "document" ? document : navigator;
|
|
322
|
+
Object.defineProperty(host, "modelContext", {
|
|
323
|
+
configurable: true,
|
|
324
|
+
value: mock
|
|
325
|
+
});
|
|
326
|
+
return mock;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/model-context-mock-script.ts
|
|
330
|
+
var MODEL_CONTEXT_MOCK_INIT_SCRIPT = `
|
|
331
|
+
(() => {
|
|
332
|
+
const tools = new Map();
|
|
333
|
+
|
|
334
|
+
Object.defineProperty(document, 'modelContext', {
|
|
335
|
+
configurable: true,
|
|
336
|
+
value: {
|
|
337
|
+
registerTool(tool, options = {}) {
|
|
338
|
+
if (options.signal?.aborted) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
tools.set(tool.name, tool);
|
|
343
|
+
options.signal?.addEventListener(
|
|
344
|
+
'abort',
|
|
345
|
+
() => {
|
|
346
|
+
tools.delete(tool.name);
|
|
347
|
+
},
|
|
348
|
+
{ once: true },
|
|
349
|
+
);
|
|
350
|
+
},
|
|
351
|
+
async getTools() {
|
|
352
|
+
return [...tools.values()];
|
|
353
|
+
},
|
|
354
|
+
async executeTool(toolOrName, argsJson = '{}') {
|
|
355
|
+
const name =
|
|
356
|
+
typeof toolOrName === 'string'
|
|
357
|
+
? toolOrName
|
|
358
|
+
: toolOrName?.name;
|
|
359
|
+
const tool = name ? tools.get(name) : undefined;
|
|
360
|
+
if (!tool) {
|
|
361
|
+
throw new Error('Tool not found: ' + name);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return tool.execute(JSON.parse(argsJson));
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
})();
|
|
369
|
+
`;
|
|
370
|
+
|
|
371
|
+
// src/webmcp-evals.ts
|
|
372
|
+
var BUDGETS = {
|
|
373
|
+
name: 30,
|
|
374
|
+
paramName: 30,
|
|
375
|
+
paramDescription: 150,
|
|
376
|
+
description: 500,
|
|
377
|
+
output: 1500
|
|
378
|
+
};
|
|
379
|
+
function walkSchemaProperties(schema, visit) {
|
|
380
|
+
if (!schema || typeof schema !== "object") {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const node = schema;
|
|
384
|
+
const properties = node.properties;
|
|
385
|
+
if (properties && typeof properties === "object") {
|
|
386
|
+
for (const [name, child] of Object.entries(properties)) {
|
|
387
|
+
if (child && typeof child === "object") {
|
|
388
|
+
visit(name, child);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
async function snapshotRegisteredTools(page) {
|
|
394
|
+
return page.evaluate(() => {
|
|
395
|
+
const context = document.modelContext;
|
|
396
|
+
if (!context?.getTools) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
return context.getTools().then(
|
|
400
|
+
(tools) => tools.map((tool) => ({
|
|
401
|
+
name: String(tool.name ?? ""),
|
|
402
|
+
description: String(tool.description ?? ""),
|
|
403
|
+
inputSchema: tool.inputSchema,
|
|
404
|
+
...tool.annotations ? { annotations: tool.annotations } : {}
|
|
405
|
+
}))
|
|
406
|
+
);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
function createToolCallEvalFixture(tools, cases) {
|
|
410
|
+
return { tools, cases };
|
|
411
|
+
}
|
|
412
|
+
function assertToolSchemaBudgets(tools) {
|
|
413
|
+
const violations = [];
|
|
414
|
+
for (const tool of tools) {
|
|
415
|
+
if (tool.name.length > BUDGETS.name) {
|
|
416
|
+
violations.push(`Tool name too long: ${tool.name}`);
|
|
417
|
+
}
|
|
418
|
+
if (tool.description.length > BUDGETS.description) {
|
|
419
|
+
violations.push(`Description too long: ${tool.name}`);
|
|
420
|
+
}
|
|
421
|
+
walkSchemaProperties(tool.inputSchema, (name, node) => {
|
|
422
|
+
if (name.length > BUDGETS.paramName) {
|
|
423
|
+
violations.push(`Param name too long on ${tool.name}: ${name}`);
|
|
424
|
+
}
|
|
425
|
+
const description = node.description;
|
|
426
|
+
if (typeof description === "string" && description.length > BUDGETS.paramDescription) {
|
|
427
|
+
violations.push(`Param description too long on ${tool.name}.${name}`);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
return violations;
|
|
432
|
+
}
|
|
433
|
+
function runToolSelectionSmokeTest(tools, prompt, expected) {
|
|
434
|
+
const haystack = `${prompt} ${tools.map((t) => t.description).join(" ")}`.toLowerCase();
|
|
435
|
+
return haystack.includes(expected.toLowerCase()) || tools.some((t) => t.name === expected);
|
|
436
|
+
}
|
|
437
|
+
async function runTimelineComparativeProof(page, options) {
|
|
438
|
+
const { runComparativeProof: runComparativeProof2 } = await Promise.resolve().then(() => (init_comparative_proof(), comparative_proof_exports));
|
|
439
|
+
const { invokeWebMcpTool: invokeWebMcpTool2 } = await Promise.resolve().then(() => (init_browser_helpers(), browser_helpers_exports));
|
|
440
|
+
const proof = await runComparativeProof2(page, {
|
|
441
|
+
buttonLabel: options.buttonLabel,
|
|
442
|
+
actionId: options.actionId
|
|
443
|
+
});
|
|
444
|
+
const timeline = await invokeWebMcpTool2(
|
|
445
|
+
page,
|
|
446
|
+
options.timelineTool ?? "get_troubleshooting_timeline",
|
|
447
|
+
{}
|
|
448
|
+
);
|
|
449
|
+
return {
|
|
450
|
+
domBlockerCount: proof.domBlockerCount,
|
|
451
|
+
timelineEventCount: timeline.events?.length ?? 0
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
455
|
+
0 && (module.exports = {
|
|
456
|
+
MODEL_CONTEXT_MOCK_INIT_SCRIPT,
|
|
457
|
+
MockModelContext,
|
|
458
|
+
assertToolSchemaBudgets,
|
|
459
|
+
collectDisabledActionReasonsFromDom,
|
|
460
|
+
createToolCallEvalFixture,
|
|
461
|
+
diagnoseCheckoutBlockerFromDomOnly,
|
|
462
|
+
diagnoseCheckoutBlockerFromWebMcp,
|
|
463
|
+
executeWebMcpTool,
|
|
464
|
+
expectWebMcpTool,
|
|
465
|
+
inspectDisabledActionFromDom,
|
|
466
|
+
installModelContextMock,
|
|
467
|
+
invokeWebMcpTool,
|
|
468
|
+
listWebMcpTools,
|
|
469
|
+
runComparativeProof,
|
|
470
|
+
runTimelineComparativeProof,
|
|
471
|
+
runToolSelectionSmokeTest,
|
|
472
|
+
snapshotRegisteredTools
|
|
473
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @experimental Tooluminati testing utilities — public APIs may change.
|
|
3
|
+
*/
|
|
4
|
+
export * from './browser-helpers';
|
|
5
|
+
export * from './comparative-proof';
|
|
6
|
+
export * from './devtools-mcp-helper';
|
|
7
|
+
export * from './dom-only-inspection';
|
|
8
|
+
export * from './install-model-context-mock';
|
|
9
|
+
export * from './mock-model-context';
|
|
10
|
+
export * from './model-context-mock-script';
|
|
11
|
+
export * from './webmcp-evals';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC"}
|