@eko-ai/eko 1.0.1 → 1.0.3
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 +56 -44
- package/dist/core/eko.d.ts +1 -0
- package/dist/core/tool-registry.d.ts +1 -1
- package/dist/extension/content/index.d.ts +12 -4
- package/dist/extension/index.d.ts +0 -2
- package/dist/extension/script/build_dom_tree.d.ts +38 -0
- package/dist/extension/script/build_dom_tree.js +7 -3
- package/dist/extension/tools/browser.d.ts +8 -8
- package/dist/extension/tools/browser_use.d.ts +1 -0
- package/dist/extension/tools/html_script.d.ts +1 -12
- package/dist/extension/tools/index.d.ts +1 -2
- package/dist/extension.cjs.js +171 -346
- package/dist/extension.esm.js +172 -346
- package/dist/extension_content_script.js +105 -76
- package/dist/index.cjs.js +59 -49
- package/dist/index.esm.js +59 -49
- package/dist/models/action.d.ts +3 -2
- package/dist/nodejs/core.d.ts +2 -0
- package/dist/nodejs/index.d.ts +1 -0
- package/dist/nodejs/tools/command_execute.d.ts +12 -0
- package/dist/nodejs/tools/file_read.d.ts +11 -0
- package/dist/nodejs/tools/file_write.d.ts +15 -0
- package/dist/nodejs/tools/index.d.ts +3 -1
- package/dist/nodejs.cjs.js +227 -3
- package/dist/nodejs.esm.js +226 -3
- package/dist/schemas/workflow.schema.d.ts +3 -0
- package/dist/services/llm/claude-provider.d.ts +1 -0
- package/dist/services/llm/openai-provider.d.ts +1 -0
- package/dist/types/action.types.d.ts +2 -0
- package/dist/web/core.d.ts +2 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/script/build_dom_tree.d.ts +10 -0
- package/dist/web/tools/browser.d.ts +20 -0
- package/dist/web/tools/browser_use.d.ts +19 -0
- package/dist/web/tools/element_click.d.ts +12 -0
- package/dist/web/tools/export_file.d.ts +18 -0
- package/dist/web/tools/extract_content.d.ts +17 -0
- package/dist/web/tools/find_element_position.d.ts +12 -0
- package/dist/web/tools/html_script.d.ts +10 -0
- package/dist/web/tools/index.d.ts +7 -1
- package/dist/web/tools/screenshot.d.ts +18 -0
- package/dist/web.cjs.js +9377 -3
- package/dist/web.esm.js +9376 -3
- package/package.json +2 -1
package/dist/extension.esm.js
CHANGED
|
@@ -103,7 +103,7 @@ async function executeScript(tabId, func, args) {
|
|
|
103
103
|
});
|
|
104
104
|
return frameResults[0].result;
|
|
105
105
|
}
|
|
106
|
-
async function waitForTabComplete(tabId, timeout =
|
|
106
|
+
async function waitForTabComplete(tabId, timeout = 15000) {
|
|
107
107
|
return new Promise(async (resolve, reject) => {
|
|
108
108
|
let tab = await chrome.tabs.get(tabId);
|
|
109
109
|
if (tab.status === 'complete') {
|
|
@@ -233,100 +233,20 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
233
233
|
waitForTabComplete: waitForTabComplete
|
|
234
234
|
});
|
|
235
235
|
|
|
236
|
-
async function
|
|
237
|
-
if (!coordinate) {
|
|
238
|
-
coordinate = (await cursor_position(tabId)).coordinate;
|
|
239
|
-
}
|
|
240
|
-
await mouse_move(tabId, coordinate);
|
|
241
|
-
let mapping = {};
|
|
242
|
-
let keys = key.replace(/\s+/g, ' ').split(' ');
|
|
243
|
-
let result;
|
|
244
|
-
for (let i = 0; i < keys.length; i++) {
|
|
245
|
-
let _key = keys[i];
|
|
246
|
-
let keyEvents = {
|
|
247
|
-
key: '',
|
|
248
|
-
ctrlKey: false,
|
|
249
|
-
altKey: false,
|
|
250
|
-
shiftKey: false,
|
|
251
|
-
metaKey: false,
|
|
252
|
-
};
|
|
253
|
-
if (_key.indexOf('+') > -1) {
|
|
254
|
-
let mapped_keys = _key.split('+').map((k) => mapping[k] || k);
|
|
255
|
-
for (let i = 0; i < mapped_keys.length - 1; i++) {
|
|
256
|
-
let k = mapped_keys[i].toLowerCase();
|
|
257
|
-
if (k == 'ctrl' || k == 'control') {
|
|
258
|
-
keyEvents.ctrlKey = true;
|
|
259
|
-
}
|
|
260
|
-
else if (k == 'alt' || k == 'option') {
|
|
261
|
-
keyEvents.altKey = true;
|
|
262
|
-
}
|
|
263
|
-
else if (k == 'shift') {
|
|
264
|
-
keyEvents.shiftKey = true;
|
|
265
|
-
}
|
|
266
|
-
else if (k == 'meta' || k == 'command') {
|
|
267
|
-
keyEvents.metaKey = true;
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
console.log('Unknown Key: ' + k);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
keyEvents.key = mapped_keys[mapped_keys.length - 1];
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
keyEvents.key = mapping[_key] || _key;
|
|
277
|
-
}
|
|
278
|
-
if (!keyEvents.key) {
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
result = await chrome.tabs.sendMessage(tabId, {
|
|
282
|
-
type: 'computer:key',
|
|
283
|
-
coordinate,
|
|
284
|
-
...keyEvents,
|
|
285
|
-
});
|
|
286
|
-
await sleep(100);
|
|
287
|
-
}
|
|
288
|
-
return result;
|
|
289
|
-
}
|
|
290
|
-
async function type(tabId, text, coordinate) {
|
|
291
|
-
if (!coordinate) {
|
|
292
|
-
coordinate = (await cursor_position(tabId)).coordinate;
|
|
293
|
-
}
|
|
294
|
-
await mouse_move(tabId, coordinate);
|
|
295
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
296
|
-
type: 'computer:type',
|
|
297
|
-
text,
|
|
298
|
-
coordinate,
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
async function type_by_xpath(tabId, text, xpath) {
|
|
236
|
+
async function type_by(tabId, text, xpath, highlightIndex) {
|
|
302
237
|
return await chrome.tabs.sendMessage(tabId, {
|
|
303
238
|
type: 'computer:type',
|
|
304
239
|
text,
|
|
305
240
|
xpath,
|
|
241
|
+
highlightIndex,
|
|
306
242
|
});
|
|
307
243
|
}
|
|
308
|
-
async function
|
|
309
|
-
if (!coordinate) {
|
|
310
|
-
coordinate = (await cursor_position(tabId)).coordinate;
|
|
311
|
-
}
|
|
312
|
-
await mouse_move(tabId, coordinate);
|
|
313
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
314
|
-
type: 'computer:type',
|
|
315
|
-
text: '',
|
|
316
|
-
coordinate,
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
async function clear_input_by_xpath(tabId, xpath) {
|
|
244
|
+
async function clear_input_by(tabId, xpath, highlightIndex) {
|
|
320
245
|
return await chrome.tabs.sendMessage(tabId, {
|
|
321
246
|
type: 'computer:type',
|
|
322
247
|
text: '',
|
|
323
248
|
xpath,
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
async function mouse_move(tabId, coordinate) {
|
|
327
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
328
|
-
type: 'computer:mouse_move',
|
|
329
|
-
coordinate,
|
|
249
|
+
highlightIndex,
|
|
330
250
|
});
|
|
331
251
|
}
|
|
332
252
|
async function left_click(tabId, coordinate) {
|
|
@@ -338,48 +258,25 @@ async function left_click(tabId, coordinate) {
|
|
|
338
258
|
coordinate,
|
|
339
259
|
});
|
|
340
260
|
}
|
|
341
|
-
async function
|
|
261
|
+
async function left_click_by(tabId, xpath, highlightIndex) {
|
|
342
262
|
return await chrome.tabs.sendMessage(tabId, {
|
|
343
263
|
type: 'computer:left_click',
|
|
344
264
|
xpath,
|
|
265
|
+
highlightIndex,
|
|
345
266
|
});
|
|
346
267
|
}
|
|
347
|
-
async function
|
|
348
|
-
let from_coordinate = (await cursor_position(tabId)).coordinate;
|
|
349
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
350
|
-
type: 'computer:left_click_drag',
|
|
351
|
-
from_coordinate,
|
|
352
|
-
to_coordinate: coordinate,
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
async function right_click(tabId, coordinate) {
|
|
356
|
-
if (!coordinate) {
|
|
357
|
-
coordinate = (await cursor_position(tabId)).coordinate;
|
|
358
|
-
}
|
|
359
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
360
|
-
type: 'computer:right_click',
|
|
361
|
-
coordinate,
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
async function right_click_by_xpath(tabId, xpath) {
|
|
268
|
+
async function right_click_by(tabId, xpath, highlightIndex) {
|
|
365
269
|
return await chrome.tabs.sendMessage(tabId, {
|
|
366
270
|
type: 'computer:right_click',
|
|
367
271
|
xpath,
|
|
272
|
+
highlightIndex,
|
|
368
273
|
});
|
|
369
274
|
}
|
|
370
|
-
async function
|
|
371
|
-
if (!coordinate) {
|
|
372
|
-
coordinate = (await cursor_position(tabId)).coordinate;
|
|
373
|
-
}
|
|
374
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
375
|
-
type: 'computer:double_click',
|
|
376
|
-
coordinate,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
async function double_click_by_xpath(tabId, xpath) {
|
|
275
|
+
async function double_click_by(tabId, xpath, highlightIndex) {
|
|
380
276
|
return await chrome.tabs.sendMessage(tabId, {
|
|
381
277
|
type: 'computer:double_click',
|
|
382
278
|
xpath,
|
|
279
|
+
highlightIndex,
|
|
383
280
|
});
|
|
384
281
|
}
|
|
385
282
|
async function screenshot(windowId) {
|
|
@@ -396,18 +293,26 @@ async function screenshot(windowId) {
|
|
|
396
293
|
},
|
|
397
294
|
};
|
|
398
295
|
}
|
|
399
|
-
async function
|
|
400
|
-
let from_coordinate = (await cursor_position(tabId)).coordinate;
|
|
296
|
+
async function scroll_to_by(tabId, xpath, highlightIndex) {
|
|
401
297
|
return await chrome.tabs.sendMessage(tabId, {
|
|
402
298
|
type: 'computer:scroll_to',
|
|
403
|
-
|
|
404
|
-
|
|
299
|
+
xpath,
|
|
300
|
+
highlightIndex,
|
|
405
301
|
});
|
|
406
302
|
}
|
|
407
|
-
async function
|
|
303
|
+
async function get_dropdown_options(tabId, xpath, highlightIndex) {
|
|
408
304
|
return await chrome.tabs.sendMessage(tabId, {
|
|
409
|
-
type: 'computer:
|
|
305
|
+
type: 'computer:get_dropdown_options',
|
|
410
306
|
xpath,
|
|
307
|
+
highlightIndex,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
async function select_dropdown_option(tabId, text, xpath, highlightIndex) {
|
|
311
|
+
return await chrome.tabs.sendMessage(tabId, {
|
|
312
|
+
type: 'computer:select_dropdown_option',
|
|
313
|
+
text,
|
|
314
|
+
xpath,
|
|
315
|
+
highlightIndex,
|
|
411
316
|
});
|
|
412
317
|
}
|
|
413
318
|
async function cursor_position(tabId) {
|
|
@@ -416,202 +321,6 @@ async function cursor_position(tabId) {
|
|
|
416
321
|
});
|
|
417
322
|
return { coordinate: result.coordinate };
|
|
418
323
|
}
|
|
419
|
-
async function size(tabId) {
|
|
420
|
-
return await getPageSize(tabId);
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
var browser = /*#__PURE__*/Object.freeze({
|
|
424
|
-
__proto__: null,
|
|
425
|
-
clear_input: clear_input,
|
|
426
|
-
clear_input_by_xpath: clear_input_by_xpath,
|
|
427
|
-
cursor_position: cursor_position,
|
|
428
|
-
double_click: double_click,
|
|
429
|
-
double_click_by_xpath: double_click_by_xpath,
|
|
430
|
-
key: key,
|
|
431
|
-
left_click: left_click,
|
|
432
|
-
left_click_by_xpath: left_click_by_xpath,
|
|
433
|
-
left_click_drag: left_click_drag,
|
|
434
|
-
mouse_move: mouse_move,
|
|
435
|
-
right_click: right_click,
|
|
436
|
-
right_click_by_xpath: right_click_by_xpath,
|
|
437
|
-
screenshot: screenshot,
|
|
438
|
-
scroll_to: scroll_to,
|
|
439
|
-
scroll_to_xpath: scroll_to_xpath,
|
|
440
|
-
size: size,
|
|
441
|
-
type: type,
|
|
442
|
-
type_by_xpath: type_by_xpath
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
function exportFile(filename, type, content) {
|
|
446
|
-
const blob = new Blob([content], { type: type });
|
|
447
|
-
const link = document.createElement('a');
|
|
448
|
-
link.href = URL.createObjectURL(blob);
|
|
449
|
-
link.download = filename;
|
|
450
|
-
document.body.appendChild(link);
|
|
451
|
-
link.click();
|
|
452
|
-
document.body.removeChild(link);
|
|
453
|
-
URL.revokeObjectURL(link.href);
|
|
454
|
-
}
|
|
455
|
-
function getDropdownOptions(xpath) {
|
|
456
|
-
const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
457
|
-
.singleNodeValue;
|
|
458
|
-
if (!select) {
|
|
459
|
-
return null;
|
|
460
|
-
}
|
|
461
|
-
return {
|
|
462
|
-
options: Array.from(select.options).map((opt) => ({
|
|
463
|
-
index: opt.index,
|
|
464
|
-
text: opt.text.trim(),
|
|
465
|
-
value: opt.value,
|
|
466
|
-
})),
|
|
467
|
-
id: select.id,
|
|
468
|
-
name: select.name,
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
function selectDropdownOption(xpath, text) {
|
|
472
|
-
const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
|
|
473
|
-
.singleNodeValue;
|
|
474
|
-
if (!select || select.tagName.toUpperCase() !== 'SELECT') {
|
|
475
|
-
return { success: false, error: 'Select not found or invalid element type' };
|
|
476
|
-
}
|
|
477
|
-
const option = Array.from(select.options).find((opt) => opt.text.trim() === text);
|
|
478
|
-
if (!option) {
|
|
479
|
-
return {
|
|
480
|
-
success: false,
|
|
481
|
-
error: 'Option not found',
|
|
482
|
-
availableOptions: Array.from(select.options).map((o) => o.text.trim()),
|
|
483
|
-
};
|
|
484
|
-
}
|
|
485
|
-
select.value = option.value;
|
|
486
|
-
select.dispatchEvent(new Event('change'));
|
|
487
|
-
return {
|
|
488
|
-
success: true,
|
|
489
|
-
selectedValue: option.value,
|
|
490
|
-
selectedText: option.text.trim(),
|
|
491
|
-
};
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Extract the elements related to html operability and wrap them into pseudo-html code.
|
|
495
|
-
*/
|
|
496
|
-
function extractOperableElements() {
|
|
497
|
-
// visible
|
|
498
|
-
const isElementVisible = (element) => {
|
|
499
|
-
const style = window.getComputedStyle(element);
|
|
500
|
-
return (style.display !== 'none' &&
|
|
501
|
-
style.visibility !== 'hidden' &&
|
|
502
|
-
style.opacity !== '0' &&
|
|
503
|
-
element.offsetWidth > 0 &&
|
|
504
|
-
element.offsetHeight > 0);
|
|
505
|
-
};
|
|
506
|
-
// element original index
|
|
507
|
-
const getElementIndex = (element) => {
|
|
508
|
-
const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
509
|
-
return xpath.snapshotLength;
|
|
510
|
-
};
|
|
511
|
-
// exclude
|
|
512
|
-
const addExclude = (excludes, children) => {
|
|
513
|
-
for (let i = 0; i < children.length; i++) {
|
|
514
|
-
excludes.push(children[i]);
|
|
515
|
-
if (children[i].children) {
|
|
516
|
-
addExclude(excludes, children[i].children);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
};
|
|
520
|
-
// { pseudoId: element }
|
|
521
|
-
let elementMap = {};
|
|
522
|
-
let nextId = 1;
|
|
523
|
-
let elements = [];
|
|
524
|
-
let excludes = [];
|
|
525
|
-
// operable element
|
|
526
|
-
const operableSelectors = 'a, button, input, textarea, select';
|
|
527
|
-
document.querySelectorAll(operableSelectors).forEach((element) => {
|
|
528
|
-
if (isElementVisible(element) && excludes.indexOf(element) == -1) {
|
|
529
|
-
const id = nextId++;
|
|
530
|
-
elementMap[id.toString()] = element;
|
|
531
|
-
const tagName = element.tagName.toLowerCase();
|
|
532
|
-
const attributes = Array.from(element.attributes)
|
|
533
|
-
.filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
|
|
534
|
-
.map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
|
|
535
|
-
.join(' ');
|
|
536
|
-
elements.push({
|
|
537
|
-
originalIndex: getElementIndex(element),
|
|
538
|
-
id: id,
|
|
539
|
-
html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
|
|
540
|
-
});
|
|
541
|
-
addExclude(excludes, element.children);
|
|
542
|
-
}
|
|
543
|
-
});
|
|
544
|
-
// short text element
|
|
545
|
-
const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
546
|
-
acceptNode: function (node) {
|
|
547
|
-
var _a;
|
|
548
|
-
if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
|
|
549
|
-
// skip
|
|
550
|
-
return NodeFilter.FILTER_SKIP;
|
|
551
|
-
}
|
|
552
|
-
// text <= 100
|
|
553
|
-
const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
554
|
-
if (isElementVisible(node) &&
|
|
555
|
-
text &&
|
|
556
|
-
text.length <= 100 &&
|
|
557
|
-
text.length > 0 &&
|
|
558
|
-
node.children.length === 0) {
|
|
559
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
560
|
-
}
|
|
561
|
-
// skip
|
|
562
|
-
return NodeFilter.FILTER_SKIP;
|
|
563
|
-
},
|
|
564
|
-
});
|
|
565
|
-
let currentNode;
|
|
566
|
-
while ((currentNode = textWalker.nextNode())) {
|
|
567
|
-
const id = nextId++;
|
|
568
|
-
elementMap[id.toString()] = currentNode;
|
|
569
|
-
const tagName = currentNode.tagName.toLowerCase();
|
|
570
|
-
elements.push({
|
|
571
|
-
originalIndex: getElementIndex(currentNode),
|
|
572
|
-
id: id,
|
|
573
|
-
html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
// element sort
|
|
577
|
-
elements.sort((a, b) => a.originalIndex - b.originalIndex);
|
|
578
|
-
// cache
|
|
579
|
-
window.operableElementMap = elementMap;
|
|
580
|
-
// pseudo html
|
|
581
|
-
return elements.map((e) => e.html).join('\n');
|
|
582
|
-
}
|
|
583
|
-
function clickOperableElement(id) {
|
|
584
|
-
let element = window.operableElementMap[id];
|
|
585
|
-
if (!element) {
|
|
586
|
-
return false;
|
|
587
|
-
}
|
|
588
|
-
if (element.click) {
|
|
589
|
-
element.click();
|
|
590
|
-
}
|
|
591
|
-
else {
|
|
592
|
-
element.dispatchEvent(new MouseEvent('click', {
|
|
593
|
-
view: window,
|
|
594
|
-
bubbles: true,
|
|
595
|
-
cancelable: true,
|
|
596
|
-
}));
|
|
597
|
-
}
|
|
598
|
-
return true;
|
|
599
|
-
}
|
|
600
|
-
function getOperableElementRect(id) {
|
|
601
|
-
let element = window.operableElementMap[id];
|
|
602
|
-
if (!element) {
|
|
603
|
-
return null;
|
|
604
|
-
}
|
|
605
|
-
const rect = element.getBoundingClientRect();
|
|
606
|
-
return {
|
|
607
|
-
left: rect.left + window.scrollX,
|
|
608
|
-
top: rect.top + window.scrollY,
|
|
609
|
-
right: rect.right + window.scrollX,
|
|
610
|
-
bottom: rect.bottom + window.scrollY,
|
|
611
|
-
width: rect.right - rect.left,
|
|
612
|
-
height: rect.bottom - rect.top,
|
|
613
|
-
};
|
|
614
|
-
}
|
|
615
324
|
|
|
616
325
|
/**
|
|
617
326
|
* Browser Use for general
|
|
@@ -700,7 +409,7 @@ class BrowserUse {
|
|
|
700
409
|
}
|
|
701
410
|
let tabId = await getTabId(context);
|
|
702
411
|
let windowId = await getWindowId(context);
|
|
703
|
-
let selector_map = context.
|
|
412
|
+
let selector_map = context.selector_map;
|
|
704
413
|
let selector_xpath;
|
|
705
414
|
if (params.index != null && selector_map) {
|
|
706
415
|
selector_xpath = (_a = selector_map[params.index]) === null || _a === void 0 ? void 0 : _a.xpath;
|
|
@@ -717,42 +426,42 @@ class BrowserUse {
|
|
|
717
426
|
if (params.text == null) {
|
|
718
427
|
throw new Error('text parameter is required');
|
|
719
428
|
}
|
|
720
|
-
result = await
|
|
429
|
+
result = await type_by(tabId, params.text, selector_xpath, params.index);
|
|
721
430
|
await sleep(200);
|
|
722
431
|
break;
|
|
723
432
|
case 'clear_text':
|
|
724
433
|
if (params.index == null) {
|
|
725
434
|
throw new Error('index parameter is required');
|
|
726
435
|
}
|
|
727
|
-
result = await
|
|
436
|
+
result = await clear_input_by(tabId, selector_xpath, params.index);
|
|
728
437
|
await sleep(100);
|
|
729
438
|
break;
|
|
730
439
|
case 'click':
|
|
731
440
|
if (params.index == null) {
|
|
732
441
|
throw new Error('index parameter is required');
|
|
733
442
|
}
|
|
734
|
-
result = await
|
|
443
|
+
result = await left_click_by(tabId, selector_xpath, params.index);
|
|
735
444
|
await sleep(100);
|
|
736
445
|
break;
|
|
737
446
|
case 'right_click':
|
|
738
447
|
if (params.index == null) {
|
|
739
448
|
throw new Error('index parameter is required');
|
|
740
449
|
}
|
|
741
|
-
result = await
|
|
450
|
+
result = await right_click_by(tabId, selector_xpath, params.index);
|
|
742
451
|
await sleep(100);
|
|
743
452
|
break;
|
|
744
453
|
case 'double_click':
|
|
745
454
|
if (params.index == null) {
|
|
746
455
|
throw new Error('index parameter is required');
|
|
747
456
|
}
|
|
748
|
-
result = await
|
|
457
|
+
result = await double_click_by(tabId, selector_xpath, params.index);
|
|
749
458
|
await sleep(100);
|
|
750
459
|
break;
|
|
751
460
|
case 'scroll_to':
|
|
752
461
|
if (params.index == null) {
|
|
753
462
|
throw new Error('index parameter is required');
|
|
754
463
|
}
|
|
755
|
-
result = await
|
|
464
|
+
result = await scroll_to_by(tabId, selector_xpath, params.index);
|
|
756
465
|
await sleep(500);
|
|
757
466
|
break;
|
|
758
467
|
case 'extract_content':
|
|
@@ -772,7 +481,7 @@ class BrowserUse {
|
|
|
772
481
|
if (params.index == null) {
|
|
773
482
|
throw new Error('index parameter is required');
|
|
774
483
|
}
|
|
775
|
-
result = await
|
|
484
|
+
result = await get_dropdown_options(tabId, selector_xpath, params.index);
|
|
776
485
|
break;
|
|
777
486
|
case 'select_dropdown_option':
|
|
778
487
|
if (params.index == null) {
|
|
@@ -781,7 +490,7 @@ class BrowserUse {
|
|
|
781
490
|
if (params.text == null) {
|
|
782
491
|
throw new Error('text parameter is required');
|
|
783
492
|
}
|
|
784
|
-
result = await
|
|
493
|
+
result = await select_dropdown_option(tabId, params.text, selector_xpath, params.index);
|
|
785
494
|
break;
|
|
786
495
|
case 'screenshot_extract_element':
|
|
787
496
|
await sleep(100);
|
|
@@ -790,7 +499,7 @@ class BrowserUse {
|
|
|
790
499
|
let element_result = await executeScript(tabId, () => {
|
|
791
500
|
return window.get_clickable_elements(true);
|
|
792
501
|
}, []);
|
|
793
|
-
context.
|
|
502
|
+
context.selector_map = element_result.selector_map;
|
|
794
503
|
let screenshot$1 = await screenshot(windowId);
|
|
795
504
|
await executeScript(tabId, () => {
|
|
796
505
|
return window.remove_highlight();
|
|
@@ -811,6 +520,142 @@ class BrowserUse {
|
|
|
811
520
|
return { success: false, error: e === null || e === void 0 ? void 0 : e.message };
|
|
812
521
|
}
|
|
813
522
|
}
|
|
523
|
+
destroy(context) {
|
|
524
|
+
delete context.selector_map;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function exportFile(filename, type, content) {
|
|
529
|
+
const blob = new Blob([content], { type: type });
|
|
530
|
+
const link = document.createElement('a');
|
|
531
|
+
link.href = URL.createObjectURL(blob);
|
|
532
|
+
link.download = filename;
|
|
533
|
+
document.body.appendChild(link);
|
|
534
|
+
link.click();
|
|
535
|
+
document.body.removeChild(link);
|
|
536
|
+
URL.revokeObjectURL(link.href);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Extract the elements related to html operability and wrap them into pseudo-html code.
|
|
540
|
+
*/
|
|
541
|
+
function extractOperableElements() {
|
|
542
|
+
// visible
|
|
543
|
+
const isElementVisible = (element) => {
|
|
544
|
+
const style = window.getComputedStyle(element);
|
|
545
|
+
return (style.display !== 'none' &&
|
|
546
|
+
style.visibility !== 'hidden' &&
|
|
547
|
+
style.opacity !== '0' &&
|
|
548
|
+
element.offsetWidth > 0 &&
|
|
549
|
+
element.offsetHeight > 0);
|
|
550
|
+
};
|
|
551
|
+
// element original index
|
|
552
|
+
const getElementIndex = (element) => {
|
|
553
|
+
const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
554
|
+
return xpath.snapshotLength;
|
|
555
|
+
};
|
|
556
|
+
// exclude
|
|
557
|
+
const addExclude = (excludes, children) => {
|
|
558
|
+
for (let i = 0; i < children.length; i++) {
|
|
559
|
+
excludes.push(children[i]);
|
|
560
|
+
if (children[i].children) {
|
|
561
|
+
addExclude(excludes, children[i].children);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
// { pseudoId: element }
|
|
566
|
+
let elementMap = {};
|
|
567
|
+
let nextId = 1;
|
|
568
|
+
let elements = [];
|
|
569
|
+
let excludes = [];
|
|
570
|
+
// operable element
|
|
571
|
+
const operableSelectors = 'a, button, input, textarea, select';
|
|
572
|
+
document.querySelectorAll(operableSelectors).forEach((element) => {
|
|
573
|
+
if (isElementVisible(element) && excludes.indexOf(element) == -1) {
|
|
574
|
+
const id = nextId++;
|
|
575
|
+
elementMap[id.toString()] = element;
|
|
576
|
+
const tagName = element.tagName.toLowerCase();
|
|
577
|
+
const attributes = Array.from(element.attributes)
|
|
578
|
+
.filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
|
|
579
|
+
.map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
|
|
580
|
+
.join(' ');
|
|
581
|
+
elements.push({
|
|
582
|
+
originalIndex: getElementIndex(element),
|
|
583
|
+
id: id,
|
|
584
|
+
html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
|
|
585
|
+
});
|
|
586
|
+
addExclude(excludes, element.children);
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
// short text element
|
|
590
|
+
const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
591
|
+
acceptNode: function (node) {
|
|
592
|
+
var _a;
|
|
593
|
+
if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
|
|
594
|
+
// skip
|
|
595
|
+
return NodeFilter.FILTER_SKIP;
|
|
596
|
+
}
|
|
597
|
+
// text <= 100
|
|
598
|
+
const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
|
|
599
|
+
if (isElementVisible(node) &&
|
|
600
|
+
text &&
|
|
601
|
+
text.length <= 100 &&
|
|
602
|
+
text.length > 0 &&
|
|
603
|
+
node.children.length === 0) {
|
|
604
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
605
|
+
}
|
|
606
|
+
// skip
|
|
607
|
+
return NodeFilter.FILTER_SKIP;
|
|
608
|
+
},
|
|
609
|
+
});
|
|
610
|
+
let currentNode;
|
|
611
|
+
while ((currentNode = textWalker.nextNode())) {
|
|
612
|
+
const id = nextId++;
|
|
613
|
+
elementMap[id.toString()] = currentNode;
|
|
614
|
+
const tagName = currentNode.tagName.toLowerCase();
|
|
615
|
+
elements.push({
|
|
616
|
+
originalIndex: getElementIndex(currentNode),
|
|
617
|
+
id: id,
|
|
618
|
+
html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
// element sort
|
|
622
|
+
elements.sort((a, b) => a.originalIndex - b.originalIndex);
|
|
623
|
+
// cache
|
|
624
|
+
window.operableElementMap = elementMap;
|
|
625
|
+
// pseudo html
|
|
626
|
+
return elements.map((e) => e.html).join('\n');
|
|
627
|
+
}
|
|
628
|
+
function clickOperableElement(id) {
|
|
629
|
+
let element = window.operableElementMap[id];
|
|
630
|
+
if (!element) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
if (element.click) {
|
|
634
|
+
element.click();
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
element.dispatchEvent(new MouseEvent('click', {
|
|
638
|
+
view: window,
|
|
639
|
+
bubbles: true,
|
|
640
|
+
cancelable: true,
|
|
641
|
+
}));
|
|
642
|
+
}
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
function getOperableElementRect(id) {
|
|
646
|
+
let element = window.operableElementMap[id];
|
|
647
|
+
if (!element) {
|
|
648
|
+
return null;
|
|
649
|
+
}
|
|
650
|
+
const rect = element.getBoundingClientRect();
|
|
651
|
+
return {
|
|
652
|
+
left: rect.left + window.scrollX,
|
|
653
|
+
top: rect.top + window.scrollY,
|
|
654
|
+
right: rect.right + window.scrollX,
|
|
655
|
+
bottom: rect.bottom + window.scrollY,
|
|
656
|
+
width: rect.right - rect.left,
|
|
657
|
+
height: rect.bottom - rect.top,
|
|
658
|
+
};
|
|
814
659
|
}
|
|
815
660
|
|
|
816
661
|
/**
|
|
@@ -1183,24 +1028,6 @@ async function executeWithBrowserUse(context, task_prompt) {
|
|
|
1183
1028
|
};
|
|
1184
1029
|
}
|
|
1185
1030
|
|
|
1186
|
-
/**
|
|
1187
|
-
* Form Autofill
|
|
1188
|
-
*/
|
|
1189
|
-
class FormAutofill {
|
|
1190
|
-
constructor() {
|
|
1191
|
-
this.name = 'form_autofill';
|
|
1192
|
-
this.description = 'Automatically fill in form data on web pages';
|
|
1193
|
-
this.input_schema = {
|
|
1194
|
-
type: 'object',
|
|
1195
|
-
properties: {}
|
|
1196
|
-
};
|
|
1197
|
-
}
|
|
1198
|
-
async execute(context, params) {
|
|
1199
|
-
// form -> input, textarea, select ...
|
|
1200
|
-
throw new Error('Not implemented');
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
1031
|
/**
|
|
1205
1032
|
* Open Url
|
|
1206
1033
|
*/
|
|
@@ -1738,7 +1565,6 @@ var tools = /*#__PURE__*/Object.freeze({
|
|
|
1738
1565
|
ExportFile: ExportFile,
|
|
1739
1566
|
ExtractContent: ExtractContent,
|
|
1740
1567
|
FindElementPosition: FindElementPosition,
|
|
1741
|
-
FormAutofill: FormAutofill,
|
|
1742
1568
|
OpenUrl: OpenUrl,
|
|
1743
1569
|
Screenshot: Screenshot,
|
|
1744
1570
|
TabManagement: TabManagement,
|
|
@@ -1773,4 +1599,4 @@ function getAllTools() {
|
|
|
1773
1599
|
return toolsMap;
|
|
1774
1600
|
}
|
|
1775
1601
|
|
|
1776
|
-
export {
|
|
1602
|
+
export { getAllTools, getLLMConfig, pub, tools, utils };
|