@cutleryapp/agent 1.0.14 → 1.0.15
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/dist/mcp-executor.js +44 -11
- package/package.json +1 -1
package/dist/mcp-executor.js
CHANGED
|
@@ -221,21 +221,54 @@ async function tryClickScoped(page, nameRe, target, scope) {
|
|
|
221
221
|
const FAST = 3000;
|
|
222
222
|
// Strip trailing generic nouns that won't appear verbatim on the page
|
|
223
223
|
const cleanScope = scope.replace(/\s+(?:product|item|section|card|row|container|element|button|link|area|panel|block)$/i, '').trim();
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
224
|
+
// Use card/item container selectors — these are tight enough to contain the button
|
|
225
|
+
// but not so deep that they exclude it. Filter by scope text, then click target within.
|
|
226
|
+
const containerSelectors = [
|
|
227
|
+
'[class*="item"]',
|
|
228
|
+
'[class*="card"]',
|
|
229
|
+
'[class*="product"]',
|
|
230
|
+
'li',
|
|
231
|
+
'article',
|
|
232
|
+
'tr',
|
|
233
|
+
'[role="listitem"]',
|
|
234
|
+
'[role="row"]',
|
|
231
235
|
];
|
|
232
|
-
for (const
|
|
236
|
+
for (const containerSel of containerSelectors) {
|
|
233
237
|
try {
|
|
234
|
-
|
|
235
|
-
|
|
238
|
+
const container = page.locator(containerSel).filter({ hasText: cleanScope });
|
|
239
|
+
const count = await container.count();
|
|
240
|
+
if (count === 0)
|
|
241
|
+
continue;
|
|
242
|
+
// Try button first, then any clickable element
|
|
243
|
+
try {
|
|
244
|
+
await container.first().getByRole('button', { name: nameRe }).first().click({ timeout: FAST });
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
catch { /* try next */ }
|
|
248
|
+
try {
|
|
249
|
+
await container.first().getByRole('link', { name: nameRe }).first().click({ timeout: FAST });
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
catch { /* try next */ }
|
|
253
|
+
try {
|
|
254
|
+
await container.first().getByText(nameRe).first().click({ timeout: FAST });
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
catch { /* try next */ }
|
|
236
258
|
}
|
|
237
|
-
catch { /* try next */ }
|
|
259
|
+
catch { /* try next container */ }
|
|
260
|
+
}
|
|
261
|
+
// Fallback: ignore scope
|
|
262
|
+
try {
|
|
263
|
+
await page.getByRole('button', { name: nameRe }).first().click({ timeout: FAST });
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
catch { }
|
|
267
|
+
try {
|
|
268
|
+
await page.getByText(nameRe).first().click({ timeout: FAST });
|
|
269
|
+
return true;
|
|
238
270
|
}
|
|
271
|
+
catch { }
|
|
239
272
|
return false;
|
|
240
273
|
}
|
|
241
274
|
async function tryFill(page, label, value) {
|