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