@eko-ai/eko 1.0.8 → 1.0.9
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 +14 -6
- package/dist/core/eko.d.ts +3 -2
- package/dist/extension/tools/get_all_tabs.d.ts +9 -0
- package/dist/extension/tools/index.d.ts +3 -1
- package/dist/extension/tools/tab_management.d.ts +1 -1
- package/dist/extension/utils.d.ts +1 -1
- package/dist/extension.cjs.js +687 -216
- package/dist/extension.esm.js +687 -216
- package/dist/index.cjs.js +451 -127
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +451 -128
- package/dist/models/action.d.ts +8 -4
- package/dist/models/workflow.d.ts +8 -3
- package/dist/nodejs/tools/index.d.ts +1 -0
- package/dist/nodejs.cjs.js +211 -2
- package/dist/nodejs.esm.js +211 -2
- package/dist/schemas/workflow.schema.d.ts +2 -13
- package/dist/services/llm/claude-provider.d.ts +2 -1
- package/dist/services/llm/openai-provider.d.ts +2 -1
- package/dist/services/parser/workflow-parser.d.ts +0 -7
- package/dist/types/action.types.d.ts +8 -3
- package/dist/types/tools.types.d.ts +44 -1
- package/dist/types/workflow.types.d.ts +22 -9
- package/dist/universal_tools/cancel_workflow.d.ts +9 -0
- package/dist/universal_tools/human.d.ts +30 -0
- package/dist/universal_tools/index.d.ts +4 -0
- package/dist/universal_tools/summary_workflow.d.ts +9 -0
- package/dist/utils/execution-logger.d.ts +69 -0
- package/package.json +2 -3
package/dist/extension.cjs.js
CHANGED
|
@@ -30,12 +30,21 @@ async function getWindowId(context) {
|
|
|
30
30
|
async function getTabId(context) {
|
|
31
31
|
let tabId = context.variables.get('tabId');
|
|
32
32
|
if (tabId) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
tabId = null;
|
|
33
|
+
// Ensure tabId is a number
|
|
34
|
+
tabId = Number(tabId);
|
|
35
|
+
// Check if it's a valid integer
|
|
36
|
+
if (!Number.isInteger(tabId)) {
|
|
38
37
|
context.variables.delete('tabId');
|
|
38
|
+
tabId = null;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
try {
|
|
42
|
+
await chrome.tabs.get(tabId);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
tabId = null;
|
|
46
|
+
context.variables.delete('tabId');
|
|
47
|
+
}
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
50
|
if (!tabId) {
|
|
@@ -52,28 +61,31 @@ async function getTabId(context) {
|
|
|
52
61
|
else {
|
|
53
62
|
tabId = await getCurrentTabId();
|
|
54
63
|
}
|
|
64
|
+
if (!tabId) {
|
|
65
|
+
throw new Error('Could not find a valid tab');
|
|
66
|
+
}
|
|
67
|
+
context.variables.set('tabId', tabId);
|
|
55
68
|
}
|
|
56
69
|
return tabId;
|
|
57
70
|
}
|
|
58
|
-
function getCurrentTabId(windowId) {
|
|
59
|
-
return new Promise((resolve) => {
|
|
60
|
-
chrome.tabs.query({
|
|
61
|
-
if (
|
|
62
|
-
|
|
71
|
+
async function getCurrentTabId(windowId) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
|
|
74
|
+
if (chrome.runtime.lastError) {
|
|
75
|
+
console.error('Chrome runtime error:', chrome.runtime.lastError);
|
|
76
|
+
reject(chrome.runtime.lastError);
|
|
77
|
+
return;
|
|
63
78
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
resolve(__tabs.length ? __tabs[__tabs.length - 1].id : undefined);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
});
|
|
79
|
+
if (!tabs || tabs.length === 0) {
|
|
80
|
+
reject(new Error('No active tab found'));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const tabId = tabs[0].id;
|
|
84
|
+
if (typeof tabId !== 'number') {
|
|
85
|
+
reject(new Error('Invalid tab ID'));
|
|
86
|
+
return;
|
|
76
87
|
}
|
|
88
|
+
resolve(tabId);
|
|
77
89
|
});
|
|
78
90
|
});
|
|
79
91
|
}
|
|
@@ -262,176 +274,348 @@ var utils = /*#__PURE__*/Object.freeze({
|
|
|
262
274
|
});
|
|
263
275
|
|
|
264
276
|
async function type(tabId, text, coordinate) {
|
|
265
|
-
|
|
266
|
-
|
|
277
|
+
console.log('Sending type message to tab:', tabId, { text, coordinate });
|
|
278
|
+
try {
|
|
279
|
+
if (!coordinate) {
|
|
280
|
+
coordinate = (await cursor_position(tabId)).coordinate;
|
|
281
|
+
}
|
|
282
|
+
await mouse_move(tabId, coordinate);
|
|
283
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
284
|
+
type: 'computer:type',
|
|
285
|
+
text,
|
|
286
|
+
coordinate,
|
|
287
|
+
});
|
|
288
|
+
console.log('Got response:', response);
|
|
289
|
+
return response;
|
|
290
|
+
}
|
|
291
|
+
catch (e) {
|
|
292
|
+
console.error('Failed to send type message:', e);
|
|
293
|
+
throw e;
|
|
267
294
|
}
|
|
268
|
-
await mouse_move(tabId, coordinate);
|
|
269
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
270
|
-
type: 'computer:type',
|
|
271
|
-
text,
|
|
272
|
-
coordinate,
|
|
273
|
-
});
|
|
274
295
|
}
|
|
275
296
|
async function type_by(tabId, text, xpath, highlightIndex) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
297
|
+
console.log('Sending type message to tab:', tabId, { text, xpath, highlightIndex });
|
|
298
|
+
try {
|
|
299
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
300
|
+
type: 'computer:type',
|
|
301
|
+
text,
|
|
302
|
+
xpath,
|
|
303
|
+
highlightIndex,
|
|
304
|
+
});
|
|
305
|
+
console.log('Got response:', response);
|
|
306
|
+
return response;
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
console.error('Failed to send type message:', e);
|
|
310
|
+
throw e;
|
|
311
|
+
}
|
|
282
312
|
}
|
|
283
313
|
async function clear_input(tabId, coordinate) {
|
|
284
|
-
|
|
285
|
-
|
|
314
|
+
console.log('Sending clear_input message to tab:', tabId, { coordinate });
|
|
315
|
+
try {
|
|
316
|
+
if (!coordinate) {
|
|
317
|
+
coordinate = (await cursor_position(tabId)).coordinate;
|
|
318
|
+
}
|
|
319
|
+
await mouse_move(tabId, coordinate);
|
|
320
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
321
|
+
type: 'computer:type',
|
|
322
|
+
text: '',
|
|
323
|
+
coordinate,
|
|
324
|
+
});
|
|
325
|
+
console.log('Got response:', response);
|
|
326
|
+
return response;
|
|
327
|
+
}
|
|
328
|
+
catch (e) {
|
|
329
|
+
console.error('Failed to send clear_input message:', e);
|
|
330
|
+
throw e;
|
|
286
331
|
}
|
|
287
|
-
await mouse_move(tabId, coordinate);
|
|
288
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
289
|
-
type: 'computer:type',
|
|
290
|
-
text: '',
|
|
291
|
-
coordinate,
|
|
292
|
-
});
|
|
293
332
|
}
|
|
294
333
|
async function clear_input_by(tabId, xpath, highlightIndex) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
334
|
+
console.log('Sending clear_input_by message to tab:', tabId, { xpath, highlightIndex });
|
|
335
|
+
try {
|
|
336
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
337
|
+
type: 'computer:type',
|
|
338
|
+
text: '',
|
|
339
|
+
xpath,
|
|
340
|
+
highlightIndex,
|
|
341
|
+
});
|
|
342
|
+
console.log('Got response:', response);
|
|
343
|
+
return response;
|
|
344
|
+
}
|
|
345
|
+
catch (e) {
|
|
346
|
+
console.error('Failed to send clear_input_by message:', e);
|
|
347
|
+
throw e;
|
|
348
|
+
}
|
|
301
349
|
}
|
|
302
350
|
async function mouse_move(tabId, coordinate) {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
351
|
+
console.log('Sending mouse_move message to tab:', tabId, { coordinate });
|
|
352
|
+
try {
|
|
353
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
354
|
+
type: 'computer:mouse_move',
|
|
355
|
+
coordinate,
|
|
356
|
+
});
|
|
357
|
+
console.log('Got response:', response);
|
|
358
|
+
return response;
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
console.error('Failed to send mouse_move message:', e);
|
|
362
|
+
throw e;
|
|
363
|
+
}
|
|
307
364
|
}
|
|
308
365
|
async function left_click(tabId, coordinate) {
|
|
309
|
-
|
|
310
|
-
|
|
366
|
+
console.log('Sending left_click message to tab:', tabId, { coordinate });
|
|
367
|
+
try {
|
|
368
|
+
if (!coordinate) {
|
|
369
|
+
coordinate = (await cursor_position(tabId)).coordinate;
|
|
370
|
+
}
|
|
371
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
372
|
+
type: 'computer:left_click',
|
|
373
|
+
coordinate,
|
|
374
|
+
});
|
|
375
|
+
console.log('Got response:', response);
|
|
376
|
+
return response;
|
|
377
|
+
}
|
|
378
|
+
catch (e) {
|
|
379
|
+
console.error('Failed to send left_click message:', e);
|
|
380
|
+
throw e;
|
|
311
381
|
}
|
|
312
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
313
|
-
type: 'computer:left_click',
|
|
314
|
-
coordinate,
|
|
315
|
-
});
|
|
316
382
|
}
|
|
317
383
|
async function left_click_by(tabId, xpath, highlightIndex) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
384
|
+
console.log('Sending left_click_by message to tab:', tabId, { xpath, highlightIndex });
|
|
385
|
+
try {
|
|
386
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
387
|
+
type: 'computer:left_click',
|
|
388
|
+
xpath,
|
|
389
|
+
highlightIndex,
|
|
390
|
+
});
|
|
391
|
+
console.log('Got response:', response);
|
|
392
|
+
return response;
|
|
393
|
+
}
|
|
394
|
+
catch (e) {
|
|
395
|
+
console.error('Failed to send left_click_by message:', e);
|
|
396
|
+
throw e;
|
|
397
|
+
}
|
|
323
398
|
}
|
|
324
399
|
async function right_click(tabId, coordinate) {
|
|
325
|
-
|
|
326
|
-
|
|
400
|
+
console.log('Sending right_click message to tab:', tabId, { coordinate });
|
|
401
|
+
try {
|
|
402
|
+
if (!coordinate) {
|
|
403
|
+
coordinate = (await cursor_position(tabId)).coordinate;
|
|
404
|
+
}
|
|
405
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
406
|
+
type: 'computer:right_click',
|
|
407
|
+
coordinate,
|
|
408
|
+
});
|
|
409
|
+
console.log('Got response:', response);
|
|
410
|
+
return response;
|
|
411
|
+
}
|
|
412
|
+
catch (e) {
|
|
413
|
+
console.error('Failed to send right_click message:', e);
|
|
414
|
+
throw e;
|
|
327
415
|
}
|
|
328
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
329
|
-
type: 'computer:right_click',
|
|
330
|
-
coordinate,
|
|
331
|
-
});
|
|
332
416
|
}
|
|
333
417
|
async function right_click_by(tabId, xpath, highlightIndex) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
418
|
+
console.log('Sending right_click_by message to tab:', tabId, { xpath, highlightIndex });
|
|
419
|
+
try {
|
|
420
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
421
|
+
type: 'computer:right_click',
|
|
422
|
+
xpath,
|
|
423
|
+
highlightIndex,
|
|
424
|
+
});
|
|
425
|
+
console.log('Got response:', response);
|
|
426
|
+
return response;
|
|
427
|
+
}
|
|
428
|
+
catch (e) {
|
|
429
|
+
console.error('Failed to send right_click_by message:', e);
|
|
430
|
+
throw e;
|
|
431
|
+
}
|
|
339
432
|
}
|
|
340
433
|
async function double_click(tabId, coordinate) {
|
|
341
|
-
|
|
342
|
-
|
|
434
|
+
console.log('Sending double_click message to tab:', tabId, { coordinate });
|
|
435
|
+
try {
|
|
436
|
+
if (!coordinate) {
|
|
437
|
+
coordinate = (await cursor_position(tabId)).coordinate;
|
|
438
|
+
}
|
|
439
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
440
|
+
type: 'computer:double_click',
|
|
441
|
+
coordinate,
|
|
442
|
+
});
|
|
443
|
+
console.log('Got response:', response);
|
|
444
|
+
return response;
|
|
445
|
+
}
|
|
446
|
+
catch (e) {
|
|
447
|
+
console.error('Failed to send double_click message:', e);
|
|
448
|
+
throw e;
|
|
343
449
|
}
|
|
344
|
-
return await chrome.tabs.sendMessage(tabId, {
|
|
345
|
-
type: 'computer:double_click',
|
|
346
|
-
coordinate,
|
|
347
|
-
});
|
|
348
450
|
}
|
|
349
451
|
async function double_click_by(tabId, xpath, highlightIndex) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
452
|
+
console.log('Sending double_click_by message to tab:', tabId, { xpath, highlightIndex });
|
|
453
|
+
try {
|
|
454
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
455
|
+
type: 'computer:double_click',
|
|
456
|
+
xpath,
|
|
457
|
+
highlightIndex,
|
|
458
|
+
});
|
|
459
|
+
console.log('Got response:', response);
|
|
460
|
+
return response;
|
|
461
|
+
}
|
|
462
|
+
catch (e) {
|
|
463
|
+
console.error('Failed to send double_click_by message:', e);
|
|
464
|
+
throw e;
|
|
465
|
+
}
|
|
355
466
|
}
|
|
356
467
|
async function screenshot(windowId, compress) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
dataUrl
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
468
|
+
console.log('Taking screenshot of window:', windowId, { compress });
|
|
469
|
+
try {
|
|
470
|
+
let dataUrl;
|
|
471
|
+
if (compress) {
|
|
472
|
+
dataUrl = await chrome.tabs.captureVisibleTab(windowId, {
|
|
473
|
+
format: 'jpeg',
|
|
474
|
+
quality: 60, // 0-100
|
|
475
|
+
});
|
|
476
|
+
dataUrl = await compress_image(dataUrl, 0.7, 1);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
dataUrl = await chrome.tabs.captureVisibleTab(windowId, {
|
|
480
|
+
format: 'jpeg',
|
|
481
|
+
quality: 50,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
let data = dataUrl.substring(dataUrl.indexOf('base64,') + 7);
|
|
485
|
+
const result = {
|
|
486
|
+
image: {
|
|
487
|
+
type: 'base64',
|
|
488
|
+
media_type: dataUrl.indexOf('image/png') > -1 ? 'image/png' : 'image/jpeg',
|
|
489
|
+
data: data,
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
console.log('Got screenshot result:', result);
|
|
493
|
+
return result;
|
|
364
494
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
quality: 50,
|
|
369
|
-
});
|
|
495
|
+
catch (e) {
|
|
496
|
+
console.error('Failed to take screenshot:', e);
|
|
497
|
+
throw e;
|
|
370
498
|
}
|
|
371
|
-
let data = dataUrl.substring(dataUrl.indexOf('base64,') + 7);
|
|
372
|
-
return {
|
|
373
|
-
image: {
|
|
374
|
-
type: 'base64',
|
|
375
|
-
media_type: dataUrl.indexOf('image/png') > -1 ? 'image/png' : 'image/jpeg',
|
|
376
|
-
data: data,
|
|
377
|
-
},
|
|
378
|
-
};
|
|
379
499
|
}
|
|
380
500
|
async function compress_image(dataUrl, scale = 0.8, quality = 0.8) {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
501
|
+
console.log('Compressing image', { scale, quality });
|
|
502
|
+
try {
|
|
503
|
+
const bitmap = await createImageBitmap(await (await fetch(dataUrl)).blob());
|
|
504
|
+
let width = bitmap.width * scale;
|
|
505
|
+
let height = bitmap.height * scale;
|
|
506
|
+
const canvas = new OffscreenCanvas(width, height);
|
|
507
|
+
const ctx = canvas.getContext('2d');
|
|
508
|
+
ctx.drawImage(bitmap, 0, 0, width, height);
|
|
509
|
+
const blob = await canvas.convertToBlob({
|
|
510
|
+
type: 'image/jpeg',
|
|
511
|
+
quality: quality,
|
|
512
|
+
});
|
|
513
|
+
return new Promise((resolve) => {
|
|
514
|
+
const reader = new FileReader();
|
|
515
|
+
reader.onloadend = () => {
|
|
516
|
+
const result = reader.result;
|
|
517
|
+
console.log('Got compressed image result:', result);
|
|
518
|
+
resolve(result);
|
|
519
|
+
};
|
|
520
|
+
reader.readAsDataURL(blob);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
catch (e) {
|
|
524
|
+
console.error('Failed to compress image:', e);
|
|
525
|
+
throw e;
|
|
526
|
+
}
|
|
396
527
|
}
|
|
397
528
|
async function scroll_to(tabId, coordinate) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
529
|
+
console.log('Sending scroll_to message to tab:', tabId, { coordinate });
|
|
530
|
+
try {
|
|
531
|
+
let from_coordinate = (await cursor_position(tabId)).coordinate;
|
|
532
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
533
|
+
type: 'computer:scroll_to',
|
|
534
|
+
from_coordinate,
|
|
535
|
+
to_coordinate: coordinate,
|
|
536
|
+
});
|
|
537
|
+
console.log('Got response:', response);
|
|
538
|
+
return response;
|
|
539
|
+
}
|
|
540
|
+
catch (e) {
|
|
541
|
+
console.error('Failed to send scroll_to message:', e);
|
|
542
|
+
throw e;
|
|
543
|
+
}
|
|
404
544
|
}
|
|
405
545
|
async function scroll_to_by(tabId, xpath, highlightIndex) {
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
546
|
+
console.log('Sending scroll_to_by message to tab:', tabId, { xpath, highlightIndex });
|
|
547
|
+
try {
|
|
548
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
549
|
+
type: 'computer:scroll_to',
|
|
550
|
+
xpath,
|
|
551
|
+
highlightIndex,
|
|
552
|
+
});
|
|
553
|
+
console.log('Got response:', response);
|
|
554
|
+
return response;
|
|
555
|
+
}
|
|
556
|
+
catch (e) {
|
|
557
|
+
console.error('Failed to send scroll_to_by message:', e);
|
|
558
|
+
throw e;
|
|
559
|
+
}
|
|
411
560
|
}
|
|
412
561
|
async function get_dropdown_options(tabId, xpath, highlightIndex) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
562
|
+
console.log('Sending get_dropdown_options message to tab:', tabId, { xpath, highlightIndex });
|
|
563
|
+
try {
|
|
564
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
565
|
+
type: 'computer:get_dropdown_options',
|
|
566
|
+
xpath,
|
|
567
|
+
highlightIndex,
|
|
568
|
+
});
|
|
569
|
+
console.log('Got response:', response);
|
|
570
|
+
return response;
|
|
571
|
+
}
|
|
572
|
+
catch (e) {
|
|
573
|
+
console.error('Failed to send get_dropdown_options message:', e);
|
|
574
|
+
throw e;
|
|
575
|
+
}
|
|
418
576
|
}
|
|
419
577
|
async function select_dropdown_option(tabId, text, xpath, highlightIndex) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
578
|
+
console.log('Sending select_dropdown_option message to tab:', tabId, { text, xpath, highlightIndex });
|
|
579
|
+
try {
|
|
580
|
+
const response = await chrome.tabs.sendMessage(tabId, {
|
|
581
|
+
type: 'computer:select_dropdown_option',
|
|
582
|
+
text,
|
|
583
|
+
xpath,
|
|
584
|
+
highlightIndex,
|
|
585
|
+
});
|
|
586
|
+
console.log('Got response:', response);
|
|
587
|
+
return response;
|
|
588
|
+
}
|
|
589
|
+
catch (e) {
|
|
590
|
+
console.error('Failed to send select_dropdown_option message:', e);
|
|
591
|
+
throw e;
|
|
592
|
+
}
|
|
426
593
|
}
|
|
427
594
|
async function cursor_position(tabId) {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
595
|
+
console.log('Sending cursor_position message to tab:', tabId);
|
|
596
|
+
try {
|
|
597
|
+
let result = await chrome.tabs.sendMessage(tabId, {
|
|
598
|
+
type: 'computer:cursor_position',
|
|
599
|
+
});
|
|
600
|
+
console.log('Got cursor position:', result.coordinate);
|
|
601
|
+
return { coordinate: result.coordinate };
|
|
602
|
+
}
|
|
603
|
+
catch (e) {
|
|
604
|
+
console.error('Failed to send cursor_position message:', e);
|
|
605
|
+
throw e;
|
|
606
|
+
}
|
|
432
607
|
}
|
|
433
608
|
async function size(tabId) {
|
|
434
|
-
|
|
609
|
+
console.log('Getting page size for tab:', tabId);
|
|
610
|
+
try {
|
|
611
|
+
const pageSize = await getPageSize(tabId);
|
|
612
|
+
console.log('Got page size:', pageSize);
|
|
613
|
+
return pageSize;
|
|
614
|
+
}
|
|
615
|
+
catch (e) {
|
|
616
|
+
console.error('Failed to get page size:', e);
|
|
617
|
+
throw e;
|
|
618
|
+
}
|
|
435
619
|
}
|
|
436
620
|
|
|
437
621
|
var browser = /*#__PURE__*/Object.freeze({
|
|
@@ -529,7 +713,17 @@ class BrowserUse {
|
|
|
529
713
|
if (params === null || !params.action) {
|
|
530
714
|
throw new Error('Invalid parameters. Expected an object with a "action" property.');
|
|
531
715
|
}
|
|
532
|
-
let tabId
|
|
716
|
+
let tabId;
|
|
717
|
+
try {
|
|
718
|
+
tabId = await getTabId(context);
|
|
719
|
+
if (!tabId || !Number.isInteger(tabId)) {
|
|
720
|
+
throw new Error('Could not get valid tab ID');
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch (e) {
|
|
724
|
+
console.error('Tab ID error:', e);
|
|
725
|
+
return { success: false, error: 'Could not access browser tab' };
|
|
726
|
+
}
|
|
533
727
|
let windowId = await getWindowId(context);
|
|
534
728
|
let selector_map = context.selector_map;
|
|
535
729
|
let selector_xpath;
|
|
@@ -633,6 +827,7 @@ class BrowserUse {
|
|
|
633
827
|
}
|
|
634
828
|
}
|
|
635
829
|
catch (e) {
|
|
830
|
+
console.error('Browser use error:', e);
|
|
636
831
|
return { success: false, error: e === null || e === void 0 ? void 0 : e.message };
|
|
637
832
|
}
|
|
638
833
|
}
|
|
@@ -928,6 +1123,7 @@ class ExportFile {
|
|
|
928
1123
|
* @returns > { success: true }
|
|
929
1124
|
*/
|
|
930
1125
|
async execute(context, params) {
|
|
1126
|
+
var _a, _b, _c;
|
|
931
1127
|
if (typeof params !== 'object' || params === null || !('content' in params)) {
|
|
932
1128
|
throw new Error('Invalid parameters. Expected an object with a "content" property.');
|
|
933
1129
|
}
|
|
@@ -962,8 +1158,8 @@ class ExportFile {
|
|
|
962
1158
|
else {
|
|
963
1159
|
filename = params.filename;
|
|
964
1160
|
}
|
|
965
|
-
let tabId = await getTabId(context);
|
|
966
1161
|
try {
|
|
1162
|
+
let tabId = await getTabId(context);
|
|
967
1163
|
await chrome.scripting.executeScript({
|
|
968
1164
|
target: { tabId: tabId },
|
|
969
1165
|
func: exportFile,
|
|
@@ -972,13 +1168,14 @@ class ExportFile {
|
|
|
972
1168
|
}
|
|
973
1169
|
catch (e) {
|
|
974
1170
|
let tab = await open_new_tab('https://www.google.com', true);
|
|
975
|
-
|
|
1171
|
+
(_c = (_b = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.onTabCreated) === null || _c === void 0 ? void 0 : _c.call(_b, tab.id);
|
|
1172
|
+
let tabId = tab.id;
|
|
976
1173
|
await chrome.scripting.executeScript({
|
|
977
1174
|
target: { tabId: tabId },
|
|
978
1175
|
func: exportFile,
|
|
979
1176
|
args: [filename, type, params.content],
|
|
980
1177
|
});
|
|
981
|
-
await sleep(
|
|
1178
|
+
await sleep(5000);
|
|
982
1179
|
await chrome.tabs.remove(tabId);
|
|
983
1180
|
}
|
|
984
1181
|
return { success: true };
|
|
@@ -1144,6 +1341,48 @@ async function executeWithBrowserUse(context, task_prompt) {
|
|
|
1144
1341
|
};
|
|
1145
1342
|
}
|
|
1146
1343
|
|
|
1344
|
+
class GetAllTabs {
|
|
1345
|
+
constructor() {
|
|
1346
|
+
this.name = 'get_all_tabs';
|
|
1347
|
+
this.description = 'Get the tabId, title, url and content from current all tabs without opening new tab.';
|
|
1348
|
+
this.input_schema = {
|
|
1349
|
+
type: 'object',
|
|
1350
|
+
properties: {},
|
|
1351
|
+
};
|
|
1352
|
+
}
|
|
1353
|
+
async execute(context, params) {
|
|
1354
|
+
const currentWindow = await chrome.windows.getCurrent();
|
|
1355
|
+
const windowId = currentWindow.id;
|
|
1356
|
+
const tabs = await chrome.tabs.query({ windowId });
|
|
1357
|
+
const tabsInfo = [];
|
|
1358
|
+
for (const tab of tabs) {
|
|
1359
|
+
if (tab.id === undefined) {
|
|
1360
|
+
console.warn(`Tab ID is undefined for tab with URL: ${tab.url}`);
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
await injectScript(tab.id);
|
|
1364
|
+
await sleep(500);
|
|
1365
|
+
let content = await executeScript(tab.id, () => {
|
|
1366
|
+
return eko.extractHtmlContent();
|
|
1367
|
+
}, []);
|
|
1368
|
+
// Use title as description, but requirement may evolve
|
|
1369
|
+
let description = tab.title ? tab.title : "No description available.";
|
|
1370
|
+
const tabInfo = {
|
|
1371
|
+
id: tab.id,
|
|
1372
|
+
url: tab.url,
|
|
1373
|
+
title: tab.title,
|
|
1374
|
+
content: content,
|
|
1375
|
+
description: description,
|
|
1376
|
+
};
|
|
1377
|
+
console.log("url: " + tab.url);
|
|
1378
|
+
console.log("title: " + tab.title);
|
|
1379
|
+
console.log("description: " + description);
|
|
1380
|
+
tabsInfo.push(tabInfo);
|
|
1381
|
+
}
|
|
1382
|
+
return tabsInfo;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1147
1386
|
/**
|
|
1148
1387
|
* Open Url
|
|
1149
1388
|
*/
|
|
@@ -1173,6 +1412,7 @@ class OpenUrl {
|
|
|
1173
1412
|
* @returns > { tabId, windowId, title, success: true }
|
|
1174
1413
|
*/
|
|
1175
1414
|
async execute(context, params) {
|
|
1415
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1176
1416
|
if (typeof params !== 'object' || params === null || !params.url) {
|
|
1177
1417
|
throw new Error('Invalid parameters. Expected an object with a "url" property.');
|
|
1178
1418
|
}
|
|
@@ -1185,10 +1425,12 @@ class OpenUrl {
|
|
|
1185
1425
|
let tab;
|
|
1186
1426
|
if (newWindow) {
|
|
1187
1427
|
tab = await open_new_tab(url, true);
|
|
1428
|
+
(_c = (_b = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.onTabCreated) === null || _c === void 0 ? void 0 : _c.call(_b, tab.id);
|
|
1188
1429
|
}
|
|
1189
1430
|
else {
|
|
1190
1431
|
let windowId = await getWindowId(context);
|
|
1191
1432
|
tab = await open_new_tab(url, false, windowId);
|
|
1433
|
+
(_f = (_e = (_d = context.callback) === null || _d === void 0 ? void 0 : _d.hooks) === null || _e === void 0 ? void 0 : _e.onTabCreated) === null || _f === void 0 ? void 0 : _f.call(_e, tab.id);
|
|
1192
1434
|
}
|
|
1193
1435
|
let windowId = tab.windowId;
|
|
1194
1436
|
let tabId = tab.id;
|
|
@@ -1245,9 +1487,9 @@ class TabManagement {
|
|
|
1245
1487
|
this.input_schema = {
|
|
1246
1488
|
type: 'object',
|
|
1247
1489
|
properties: {
|
|
1248
|
-
|
|
1490
|
+
command: {
|
|
1249
1491
|
type: 'string',
|
|
1250
|
-
description: `The
|
|
1492
|
+
description: `The command to perform. The available commands are:
|
|
1251
1493
|
* \`tab_all\`: View all tabs and return the tabId and title.
|
|
1252
1494
|
* \`current_tab\`: Get current tab information (tabId, url, title).
|
|
1253
1495
|
* \`go_back\`: Go back to the previous page in the current tab.
|
|
@@ -1257,29 +1499,30 @@ class TabManagement {
|
|
|
1257
1499
|
* \`new_tab [url]\`: Open a new tab window and open the URL, eg: \`new_tab https://www.google.com\``,
|
|
1258
1500
|
},
|
|
1259
1501
|
},
|
|
1260
|
-
required: ['
|
|
1502
|
+
required: ['command'],
|
|
1261
1503
|
};
|
|
1262
1504
|
}
|
|
1263
1505
|
/**
|
|
1264
1506
|
* Tab management
|
|
1265
1507
|
*
|
|
1266
|
-
* @param {*} params {
|
|
1508
|
+
* @param {*} params { command: `new_tab [url]` | 'tab_all' | 'current_tab' | 'go_back' | 'close_tab' | 'switch_tab [tabId]' | `change_url [url]` }
|
|
1267
1509
|
* @returns > { result, success: true }
|
|
1268
1510
|
*/
|
|
1269
1511
|
async execute(context, params) {
|
|
1270
|
-
|
|
1271
|
-
|
|
1512
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1513
|
+
if (params === null || !params.command) {
|
|
1514
|
+
throw new Error('Invalid parameters. Expected an object with a "command" property.');
|
|
1272
1515
|
}
|
|
1273
1516
|
let windowId = await getWindowId(context);
|
|
1274
|
-
let
|
|
1275
|
-
if (
|
|
1276
|
-
|
|
1517
|
+
let command = params.command.trim();
|
|
1518
|
+
if (command.startsWith('`')) {
|
|
1519
|
+
command = command.substring(1);
|
|
1277
1520
|
}
|
|
1278
|
-
if (
|
|
1279
|
-
|
|
1521
|
+
if (command.endsWith('`')) {
|
|
1522
|
+
command = command.substring(0, command.length - 1);
|
|
1280
1523
|
}
|
|
1281
1524
|
let result;
|
|
1282
|
-
if (
|
|
1525
|
+
if (command == 'tab_all') {
|
|
1283
1526
|
result = [];
|
|
1284
1527
|
let tabs = await chrome.tabs.query({ windowId: windowId });
|
|
1285
1528
|
for (let i = 0; i < tabs.length; i++) {
|
|
@@ -1296,20 +1539,20 @@ class TabManagement {
|
|
|
1296
1539
|
result.push(tabInfo);
|
|
1297
1540
|
}
|
|
1298
1541
|
}
|
|
1299
|
-
else if (
|
|
1542
|
+
else if (command == 'current_tab') {
|
|
1300
1543
|
let tabId = await getTabId(context);
|
|
1301
1544
|
let tab = await chrome.tabs.get(tabId);
|
|
1302
1545
|
let tabInfo = { tabId, windowId: tab.windowId, title: tab.title, url: tab.url };
|
|
1303
1546
|
result = tabInfo;
|
|
1304
1547
|
}
|
|
1305
|
-
else if (
|
|
1548
|
+
else if (command == 'go_back') {
|
|
1306
1549
|
let tabId = await getTabId(context);
|
|
1307
1550
|
await chrome.tabs.goBack(tabId);
|
|
1308
1551
|
let tab = await chrome.tabs.get(tabId);
|
|
1309
1552
|
let tabInfo = { tabId, windowId: tab.windowId, title: tab.title, url: tab.url };
|
|
1310
1553
|
result = tabInfo;
|
|
1311
1554
|
}
|
|
1312
|
-
else if (
|
|
1555
|
+
else if (command == 'close_tab') {
|
|
1313
1556
|
let closedTabId = await getTabId(context);
|
|
1314
1557
|
await chrome.tabs.remove(closedTabId);
|
|
1315
1558
|
await sleep(100);
|
|
@@ -1327,16 +1570,16 @@ class TabManagement {
|
|
|
1327
1570
|
let closeTabInfo = { closedTabId, newTabId, newTabTitle: tab.title };
|
|
1328
1571
|
result = closeTabInfo;
|
|
1329
1572
|
}
|
|
1330
|
-
else if (
|
|
1331
|
-
let tabId = parseInt(
|
|
1573
|
+
else if (command.startsWith('switch_tab')) {
|
|
1574
|
+
let tabId = parseInt(command.replace('switch_tab', '').replace('[', '').replace(']', ''));
|
|
1332
1575
|
let tab = await chrome.tabs.update(tabId, { active: true });
|
|
1333
1576
|
context.variables.set('tabId', tab.id);
|
|
1334
1577
|
context.variables.set('windowId', tab.windowId);
|
|
1335
1578
|
let tabInfo = { tabId, windowId: tab.windowId, title: tab.title, url: tab.url };
|
|
1336
1579
|
result = tabInfo;
|
|
1337
1580
|
}
|
|
1338
|
-
else if (
|
|
1339
|
-
let url =
|
|
1581
|
+
else if (command.startsWith('change_url')) {
|
|
1582
|
+
let url = command.substring('change_url'.length).replace('[', '').replace(']', '').trim();
|
|
1340
1583
|
let tabId = await getTabId(context);
|
|
1341
1584
|
// await chrome.tabs.update(tabId, { url: url });
|
|
1342
1585
|
await executeScript(tabId, () => {
|
|
@@ -1346,17 +1589,19 @@ class TabManagement {
|
|
|
1346
1589
|
let tabInfo = { tabId, windowId: tab.windowId, title: tab.title, url: tab.url };
|
|
1347
1590
|
result = tabInfo;
|
|
1348
1591
|
}
|
|
1349
|
-
else if (
|
|
1350
|
-
let url =
|
|
1592
|
+
else if (command.startsWith('new_tab')) {
|
|
1593
|
+
let url = command.replace('new_tab', '').replace('[', '').replace(']', '').replace(/"/g, '');
|
|
1351
1594
|
// First mandatory opening of a new window
|
|
1352
1595
|
let newWindow = !context.variables.get('windowId') && !context.variables.get('tabId');
|
|
1353
1596
|
let tab;
|
|
1354
1597
|
if (newWindow) {
|
|
1355
1598
|
tab = await open_new_tab(url, true);
|
|
1599
|
+
(_c = (_b = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.onTabCreated) === null || _c === void 0 ? void 0 : _c.call(_b, tab.id);
|
|
1356
1600
|
}
|
|
1357
1601
|
else {
|
|
1358
1602
|
let windowId = await getWindowId(context);
|
|
1359
1603
|
tab = await open_new_tab(url, false, windowId);
|
|
1604
|
+
(_f = (_e = (_d = context.callback) === null || _d === void 0 ? void 0 : _d.hooks) === null || _e === void 0 ? void 0 : _e.onTabCreated) === null || _f === void 0 ? void 0 : _f.call(_e, tab.id);
|
|
1360
1605
|
}
|
|
1361
1606
|
let windowId = tab.windowId;
|
|
1362
1607
|
let tabId = tab.id;
|
|
@@ -1380,7 +1625,7 @@ class TabManagement {
|
|
|
1380
1625
|
result = tabInfo;
|
|
1381
1626
|
}
|
|
1382
1627
|
else {
|
|
1383
|
-
throw Error('Unknown
|
|
1628
|
+
throw Error('Unknown command: ' + command);
|
|
1384
1629
|
}
|
|
1385
1630
|
return result;
|
|
1386
1631
|
}
|
|
@@ -1400,7 +1645,7 @@ class TabManagement {
|
|
|
1400
1645
|
class WebSearch {
|
|
1401
1646
|
constructor() {
|
|
1402
1647
|
this.name = 'web_search';
|
|
1403
|
-
this.description = '
|
|
1648
|
+
this.description = 'Search the web based on keywords and return relevant extracted content from webpages.';
|
|
1404
1649
|
this.input_schema = {
|
|
1405
1650
|
type: 'object',
|
|
1406
1651
|
properties: {
|
|
@@ -1435,7 +1680,7 @@ class WebSearch {
|
|
|
1435
1680
|
}
|
|
1436
1681
|
let taskId = new Date().getTime() + '';
|
|
1437
1682
|
let searchs = [{ url: url, keyword: query }];
|
|
1438
|
-
let searchInfo = await deepSearch(taskId, searchs, maxResults || 5);
|
|
1683
|
+
let searchInfo = await deepSearch(context, taskId, searchs, maxResults || 5);
|
|
1439
1684
|
let links = ((_a = searchInfo.result[0]) === null || _a === void 0 ? void 0 : _a.links) || [];
|
|
1440
1685
|
return links.filter((s) => s.content);
|
|
1441
1686
|
}
|
|
@@ -1508,7 +1753,7 @@ chrome.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) {
|
|
|
1508
1753
|
* @param {array} searchs search list => [{ url: 'https://bing.com', keyword: 'ai' }]
|
|
1509
1754
|
* @param {number} detailsMaxNum Maximum crawling quantity per search detail page
|
|
1510
1755
|
*/
|
|
1511
|
-
async function deepSearch(taskId, searchs, detailsMaxNum, window) {
|
|
1756
|
+
async function deepSearch(context, taskId, searchs, detailsMaxNum, window) {
|
|
1512
1757
|
let closeWindow = false;
|
|
1513
1758
|
if (!window) {
|
|
1514
1759
|
// open new window
|
|
@@ -1521,9 +1766,9 @@ async function deepSearch(taskId, searchs, detailsMaxNum, window) {
|
|
|
1521
1766
|
}
|
|
1522
1767
|
// crawler the search page details page link
|
|
1523
1768
|
// [{ links: [{ title, url }] }]
|
|
1524
|
-
let detailLinkGroups = await doDetailLinkGroups(taskId, searchs, detailsMaxNum, window);
|
|
1769
|
+
let detailLinkGroups = await doDetailLinkGroups(context, taskId, searchs, detailsMaxNum, window);
|
|
1525
1770
|
// crawler all details page content and comments
|
|
1526
|
-
let searchInfo = await doPageContent(taskId, detailLinkGroups, window);
|
|
1771
|
+
let searchInfo = await doPageContent(context, taskId, detailLinkGroups, window);
|
|
1527
1772
|
console.log('searchInfo: ', searchInfo);
|
|
1528
1773
|
// close window
|
|
1529
1774
|
closeWindow && chrome.windows.remove(window.id);
|
|
@@ -1538,7 +1783,8 @@ async function deepSearch(taskId, searchs, detailsMaxNum, window) {
|
|
|
1538
1783
|
* @param {*} window
|
|
1539
1784
|
* @returns [{ links: [{ title, url }] }]
|
|
1540
1785
|
*/
|
|
1541
|
-
async function doDetailLinkGroups(taskId, searchs, detailsMaxNum, window) {
|
|
1786
|
+
async function doDetailLinkGroups(context, taskId, searchs, detailsMaxNum, window) {
|
|
1787
|
+
var _a, _b, _c;
|
|
1542
1788
|
let detailLinkGroups = [];
|
|
1543
1789
|
let countDownLatch = new CountDownLatch(searchs.length);
|
|
1544
1790
|
for (let i = 0; i < searchs.length; i++) {
|
|
@@ -1550,6 +1796,7 @@ async function doDetailLinkGroups(taskId, searchs, detailsMaxNum, window) {
|
|
|
1550
1796
|
url: url,
|
|
1551
1797
|
windowId: window.id,
|
|
1552
1798
|
});
|
|
1799
|
+
(_c = (_b = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.onTabCreated) === null || _c === void 0 ? void 0 : _c.call(_b, tab.id);
|
|
1553
1800
|
let eventId = taskId + '_' + i;
|
|
1554
1801
|
// monitor Tab status
|
|
1555
1802
|
tabsUpdateEvent.addListener(async function (obj) {
|
|
@@ -1600,7 +1847,8 @@ async function doDetailLinkGroups(taskId, searchs, detailsMaxNum, window) {
|
|
|
1600
1847
|
* @param {*} window
|
|
1601
1848
|
* @returns search info
|
|
1602
1849
|
*/
|
|
1603
|
-
async function doPageContent(taskId, detailLinkGroups, window) {
|
|
1850
|
+
async function doPageContent(context, taskId, detailLinkGroups, window) {
|
|
1851
|
+
var _a, _b, _c;
|
|
1604
1852
|
const searchInfo = {
|
|
1605
1853
|
total: 0,
|
|
1606
1854
|
running: 0,
|
|
@@ -1624,50 +1872,67 @@ async function doPageContent(taskId, detailLinkGroups, window) {
|
|
|
1624
1872
|
url: link.url,
|
|
1625
1873
|
windowId: window.id,
|
|
1626
1874
|
});
|
|
1875
|
+
(_c = (_b = (_a = context.callback) === null || _a === void 0 ? void 0 : _a.hooks) === null || _b === void 0 ? void 0 : _b.onTabCreated) === null || _c === void 0 ? void 0 : _c.call(_b, tab.id);
|
|
1627
1876
|
searchInfo.running++;
|
|
1628
1877
|
let eventId = taskId + '_' + i + '_' + j;
|
|
1629
|
-
//
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1878
|
+
// Create a timeout promise
|
|
1879
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
1880
|
+
setTimeout(() => reject(new Error('Page load timeout')), 10000); // Timeout after 10 seconds
|
|
1881
|
+
});
|
|
1882
|
+
// Create a tab monitoring promise
|
|
1883
|
+
const monitorTabPromise = new Promise(async (resolve, reject) => {
|
|
1884
|
+
tabsUpdateEvent.addListener(async function onTabUpdated(obj) {
|
|
1885
|
+
if (obj.tabId !== tab.id)
|
|
1886
|
+
return;
|
|
1887
|
+
if (obj.changeInfo.status === 'complete') {
|
|
1636
1888
|
tabsUpdateEvent.removeListener(eventId);
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1889
|
+
try {
|
|
1890
|
+
// Inject script and get page content
|
|
1891
|
+
await injectScript(tab.id, filename);
|
|
1892
|
+
await sleep(1000);
|
|
1893
|
+
let result = await chrome.tabs.sendMessage(tab.id, {
|
|
1894
|
+
type: 'page:getContent',
|
|
1895
|
+
});
|
|
1896
|
+
if (!result)
|
|
1897
|
+
throw new Error('No Result');
|
|
1898
|
+
link.content = result.content;
|
|
1899
|
+
link.page_title = result.title;
|
|
1900
|
+
searchInfo.succeed++;
|
|
1901
|
+
resolve(); // Resolve the promise if successful
|
|
1902
|
+
}
|
|
1903
|
+
catch (error) {
|
|
1904
|
+
searchInfo.failed++;
|
|
1905
|
+
searchInfo.failedLinks.push(link);
|
|
1906
|
+
reject(error); // Reject the promise on error
|
|
1907
|
+
}
|
|
1908
|
+
finally {
|
|
1909
|
+
searchInfo.running--;
|
|
1910
|
+
countDownLatch.countDown();
|
|
1911
|
+
chrome.tabs.remove(tab.id);
|
|
1912
|
+
tabsUpdateEvent.removeListener(eventId);
|
|
1647
1913
|
}
|
|
1648
|
-
link.content = result.content;
|
|
1649
|
-
link.page_title = result.title;
|
|
1650
|
-
searchInfo.succeed++;
|
|
1651
|
-
}
|
|
1652
|
-
catch (e) {
|
|
1653
|
-
searchInfo.failed++;
|
|
1654
|
-
searchInfo.failedLinks.push(link);
|
|
1655
|
-
console.error(link.title + ' crawler error', link.url, e);
|
|
1656
1914
|
}
|
|
1657
|
-
|
|
1915
|
+
else if (obj.changeInfo.status === 'unloaded') {
|
|
1658
1916
|
searchInfo.running--;
|
|
1659
1917
|
countDownLatch.countDown();
|
|
1660
1918
|
chrome.tabs.remove(tab.id);
|
|
1661
1919
|
tabsUpdateEvent.removeListener(eventId);
|
|
1920
|
+
reject(new Error('Tab unloaded')); // Reject if the tab is unloaded
|
|
1662
1921
|
}
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1922
|
+
}, eventId);
|
|
1923
|
+
});
|
|
1924
|
+
// Use Promise.race to enforce the timeout
|
|
1925
|
+
try {
|
|
1926
|
+
await Promise.race([monitorTabPromise, timeoutPromise]);
|
|
1927
|
+
}
|
|
1928
|
+
catch (e) {
|
|
1929
|
+
console.error(`${link.title} failed:`, e);
|
|
1930
|
+
searchInfo.running--;
|
|
1931
|
+
searchInfo.failed++;
|
|
1932
|
+
searchInfo.failedLinks.push(link);
|
|
1933
|
+
countDownLatch.countDown();
|
|
1934
|
+
chrome.tabs.remove(tab.id); // Clean up tab on failure
|
|
1935
|
+
}
|
|
1671
1936
|
}
|
|
1672
1937
|
}
|
|
1673
1938
|
await countDownLatch.await(60000);
|
|
@@ -1759,16 +2024,222 @@ class RequestLogin {
|
|
|
1759
2024
|
}
|
|
1760
2025
|
}
|
|
1761
2026
|
|
|
2027
|
+
class CancelWorkflow {
|
|
2028
|
+
constructor() {
|
|
2029
|
+
this.name = 'cancel_workflow';
|
|
2030
|
+
this.description = 'Cancel the workflow. If any tool consistently encounters exceptions, invoke this tool to cancel the workflow.';
|
|
2031
|
+
this.input_schema = {
|
|
2032
|
+
type: 'object',
|
|
2033
|
+
properties: {
|
|
2034
|
+
reason: {
|
|
2035
|
+
type: 'string',
|
|
2036
|
+
description: 'Why the workflow should be cancelled.',
|
|
2037
|
+
},
|
|
2038
|
+
},
|
|
2039
|
+
required: ['reason'],
|
|
2040
|
+
};
|
|
2041
|
+
}
|
|
2042
|
+
async execute(context, params) {
|
|
2043
|
+
var _a;
|
|
2044
|
+
if (typeof params !== 'object' || params === null || !params.reason) {
|
|
2045
|
+
throw new Error('Invalid parameters. Expected an object with a "reason" property.');
|
|
2046
|
+
}
|
|
2047
|
+
const reason = params.reason;
|
|
2048
|
+
console.log("The workflow has been cancelled because: " + reason);
|
|
2049
|
+
await ((_a = context.workflow) === null || _a === void 0 ? void 0 : _a.cancel());
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
|
|
2054
|
+
class HumanInputText {
|
|
2055
|
+
constructor() {
|
|
2056
|
+
this.name = 'human_input_text';
|
|
2057
|
+
this.description = 'When you are unsure about the details of your next action, call me and ask the user for details in the "question" field. The user will provide you with a text as an answer.';
|
|
2058
|
+
this.input_schema = {
|
|
2059
|
+
type: 'object',
|
|
2060
|
+
properties: {
|
|
2061
|
+
question: {
|
|
2062
|
+
type: 'string',
|
|
2063
|
+
description: 'Ask the user here.',
|
|
2064
|
+
},
|
|
2065
|
+
},
|
|
2066
|
+
required: ['question'],
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
async execute(context, params) {
|
|
2070
|
+
var _a, _b, _c;
|
|
2071
|
+
if (typeof params !== 'object' || params === null || !params.question) {
|
|
2072
|
+
throw new Error('Invalid parameters. Expected an object with a "question" property.');
|
|
2073
|
+
}
|
|
2074
|
+
const question = params.question;
|
|
2075
|
+
console.log("question: " + question);
|
|
2076
|
+
let answer = await ((_c = (_a = context.callback) === null || _a === void 0 ? void 0 : (_b = _a.hooks).onHumanInputText) === null || _c === void 0 ? void 0 : _c.call(_b, question));
|
|
2077
|
+
if (!answer) {
|
|
2078
|
+
console.error("Cannot get user's answer.");
|
|
2079
|
+
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
2080
|
+
}
|
|
2081
|
+
else {
|
|
2082
|
+
console.log("answer: " + answer);
|
|
2083
|
+
return { status: "OK", answer: answer };
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
class HumanInputSingleChoice {
|
|
2088
|
+
constructor() {
|
|
2089
|
+
this.name = 'human_input_single_choice';
|
|
2090
|
+
this.description = 'When you are unsure about the details of your next action, call me and ask the user for details in the "question" field with at least 2 choices. The user will provide you with ONE choice as an answer.';
|
|
2091
|
+
this.input_schema = {
|
|
2092
|
+
type: 'object',
|
|
2093
|
+
properties: {
|
|
2094
|
+
question: {
|
|
2095
|
+
type: 'string',
|
|
2096
|
+
description: 'Ask the user here.',
|
|
2097
|
+
},
|
|
2098
|
+
choices: {
|
|
2099
|
+
type: 'array',
|
|
2100
|
+
description: 'All of the choices.',
|
|
2101
|
+
}
|
|
2102
|
+
},
|
|
2103
|
+
required: ['question', 'choices'],
|
|
2104
|
+
};
|
|
2105
|
+
}
|
|
2106
|
+
async execute(context, params) {
|
|
2107
|
+
var _a, _b, _c;
|
|
2108
|
+
if (typeof params !== 'object' || params === null || !params.question || !params.choices) {
|
|
2109
|
+
throw new Error('Invalid parameters. Expected an object with a "question" and "choices" property.');
|
|
2110
|
+
}
|
|
2111
|
+
const question = params.question;
|
|
2112
|
+
const choices = params.choices;
|
|
2113
|
+
console.log("question: " + question);
|
|
2114
|
+
console.log("choices: " + choices);
|
|
2115
|
+
let answer = await ((_c = (_a = context.callback) === null || _a === void 0 ? void 0 : (_b = _a.hooks).onHumanInputSingleChoice) === null || _c === void 0 ? void 0 : _c.call(_b, question, choices));
|
|
2116
|
+
if (!answer) {
|
|
2117
|
+
console.error("Cannot get user's answer.");
|
|
2118
|
+
return { status: "Error: Cannot get user's answer.", answer: "" };
|
|
2119
|
+
}
|
|
2120
|
+
else {
|
|
2121
|
+
console.log("answer: " + answer);
|
|
2122
|
+
return { status: "OK", answer: answer };
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
class HumanInputMultipleChoice {
|
|
2127
|
+
constructor() {
|
|
2128
|
+
this.name = 'human_input_multiple_choice';
|
|
2129
|
+
this.description = 'When you are unsure about the details of your next action, call me and ask the user for details in the "question" field with at least 2 choices. The user will provide you with ONE or MORE choice as an answer.';
|
|
2130
|
+
this.input_schema = {
|
|
2131
|
+
type: 'object',
|
|
2132
|
+
properties: {
|
|
2133
|
+
question: {
|
|
2134
|
+
type: 'string',
|
|
2135
|
+
description: 'Ask the user here.',
|
|
2136
|
+
},
|
|
2137
|
+
choices: {
|
|
2138
|
+
type: 'array',
|
|
2139
|
+
description: 'All of the choices.',
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
required: ['question', 'choices'],
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
async execute(context, params) {
|
|
2146
|
+
var _a, _b, _c;
|
|
2147
|
+
if (typeof params !== 'object' || params === null || !params.question || !params.choices) {
|
|
2148
|
+
throw new Error('Invalid parameters. Expected an object with a "question" and "choices" property.');
|
|
2149
|
+
}
|
|
2150
|
+
const question = params.question;
|
|
2151
|
+
const choices = params.choices;
|
|
2152
|
+
console.log("question: " + question);
|
|
2153
|
+
console.log("choices: " + choices);
|
|
2154
|
+
let answer = await ((_c = (_a = context.callback) === null || _a === void 0 ? void 0 : (_b = _a.hooks).onHumanInputMultipleChoice) === null || _c === void 0 ? void 0 : _c.call(_b, question, choices));
|
|
2155
|
+
if (!answer) {
|
|
2156
|
+
console.error("Cannot get user's answer.");
|
|
2157
|
+
return { status: "Error: Cannot get user's answer.", answer: [] };
|
|
2158
|
+
}
|
|
2159
|
+
else {
|
|
2160
|
+
console.log("answer: " + answer);
|
|
2161
|
+
return { status: "OK", answer: answer };
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
class HumanOperate {
|
|
2166
|
+
constructor() {
|
|
2167
|
+
this.name = 'human_operate';
|
|
2168
|
+
this.description = 'When you encounter operations that require login, CAPTCHA verification, or other tasks that you cannot complete, please call this tool, transfer control to the user, and explain why.';
|
|
2169
|
+
this.input_schema = {
|
|
2170
|
+
type: 'object',
|
|
2171
|
+
properties: {
|
|
2172
|
+
reason: {
|
|
2173
|
+
type: 'string',
|
|
2174
|
+
description: 'The reason why you need to transfer control.',
|
|
2175
|
+
},
|
|
2176
|
+
},
|
|
2177
|
+
required: ['reason'],
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
async execute(context, params) {
|
|
2181
|
+
var _a, _b, _c;
|
|
2182
|
+
if (typeof params !== 'object' || params === null || !params.reason) {
|
|
2183
|
+
throw new Error('Invalid parameters. Expected an object with a "reason" property.');
|
|
2184
|
+
}
|
|
2185
|
+
const reason = params.reason;
|
|
2186
|
+
console.log("reason: " + reason);
|
|
2187
|
+
let userOperation = await ((_c = (_a = context.callback) === null || _a === void 0 ? void 0 : (_b = _a.hooks).onHumanOperate) === null || _c === void 0 ? void 0 : _c.call(_b, reason));
|
|
2188
|
+
if (!userOperation) {
|
|
2189
|
+
console.error("Cannot get user's operation.");
|
|
2190
|
+
return { status: "Error: Cannot get user's operation.", userOperation: "" };
|
|
2191
|
+
}
|
|
2192
|
+
else {
|
|
2193
|
+
console.log("userOperation: " + userOperation);
|
|
2194
|
+
return { status: "OK", userOperation: userOperation };
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
class SummaryWorkflow {
|
|
2200
|
+
constructor() {
|
|
2201
|
+
this.name = 'summary_workflow';
|
|
2202
|
+
this.description = 'Summarize what this workflow has done from start to finish using an ordered list .';
|
|
2203
|
+
this.input_schema = {
|
|
2204
|
+
type: 'object',
|
|
2205
|
+
properties: {
|
|
2206
|
+
summary: {
|
|
2207
|
+
type: 'string',
|
|
2208
|
+
description: 'Your summary in markdown format.',
|
|
2209
|
+
},
|
|
2210
|
+
},
|
|
2211
|
+
required: ['summary'],
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
async execute(context, params) {
|
|
2215
|
+
var _a, _b, _c;
|
|
2216
|
+
if (typeof params !== 'object' || params === null || !params.summary) {
|
|
2217
|
+
throw new Error('Invalid parameters. Expected an object with a "summary" property.');
|
|
2218
|
+
}
|
|
2219
|
+
const summary = params.summary;
|
|
2220
|
+
console.log("summary: " + summary);
|
|
2221
|
+
await ((_c = (_a = context.callback) === null || _a === void 0 ? void 0 : (_b = _a.hooks).onSummaryWorkflow) === null || _c === void 0 ? void 0 : _c.call(_b, summary));
|
|
2222
|
+
return { status: "OK" };
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
|
|
1762
2226
|
var tools = /*#__PURE__*/Object.freeze({
|
|
1763
2227
|
__proto__: null,
|
|
1764
2228
|
BrowserUse: BrowserUse,
|
|
2229
|
+
CancelWorkflow: CancelWorkflow,
|
|
1765
2230
|
ElementClick: ElementClick,
|
|
1766
2231
|
ExportFile: ExportFile,
|
|
1767
2232
|
ExtractContent: ExtractContent,
|
|
1768
2233
|
FindElementPosition: FindElementPosition,
|
|
2234
|
+
GetAllTabs: GetAllTabs,
|
|
2235
|
+
HumanInputMultipleChoice: HumanInputMultipleChoice,
|
|
2236
|
+
HumanInputSingleChoice: HumanInputSingleChoice,
|
|
2237
|
+
HumanInputText: HumanInputText,
|
|
2238
|
+
HumanOperate: HumanOperate,
|
|
1769
2239
|
OpenUrl: OpenUrl,
|
|
1770
2240
|
RequestLogin: RequestLogin,
|
|
1771
2241
|
Screenshot: Screenshot,
|
|
2242
|
+
SummaryWorkflow: SummaryWorkflow,
|
|
1772
2243
|
TabManagement: TabManagement,
|
|
1773
2244
|
WebSearch: WebSearch
|
|
1774
2245
|
});
|