@eko-ai/eko 1.0.6 → 1.0.8
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 +66 -23
- package/dist/core/eko.d.ts +2 -0
- package/dist/extension/content/index.d.ts +1 -0
- package/dist/extension/tools/browser.d.ts +2 -1
- package/dist/extension/tools/index.d.ts +2 -1
- package/dist/extension/tools/request_login.d.ts +10 -0
- package/dist/extension/utils.d.ts +1 -0
- package/dist/extension.cjs.js +137 -20
- package/dist/extension.esm.js +137 -20
- package/dist/extension_content_script.js +129 -2
- package/dist/index.cjs.js +155 -20
- package/dist/index.esm.js +155 -20
- package/dist/models/action.d.ts +1 -0
- package/dist/nodejs/script/build_dom_tree.d.ts +1 -0
- package/dist/nodejs/tools/browser_use.d.ts +28 -0
- package/dist/nodejs/tools/index.d.ts +1 -0
- package/dist/nodejs.cjs.js +71428 -11
- package/dist/nodejs.esm.js +71422 -5
- package/dist/services/workflow/generator.d.ts +4 -2
- package/dist/services/workflow/templates.d.ts +1 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/web/tools/browser.d.ts +2 -1
- package/dist/web.cjs.js +29 -17
- package/dist/web.esm.js +29 -17
- package/package.json +5 -7
|
@@ -40,6 +40,11 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
|
|
40
40
|
sendResponse(result);
|
|
41
41
|
break;
|
|
42
42
|
}
|
|
43
|
+
case 'request_user_help': {
|
|
44
|
+
request_user_help(request.task_id, request.failure_type, request.failure_message);
|
|
45
|
+
sendResponse(true);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
43
48
|
case 'computer:type': {
|
|
44
49
|
sendResponse(type(request));
|
|
45
50
|
break;
|
|
@@ -204,7 +209,7 @@ function scroll_to(request) {
|
|
|
204
209
|
return false;
|
|
205
210
|
}
|
|
206
211
|
element.scrollIntoView({
|
|
207
|
-
behavior: 'smooth'
|
|
212
|
+
behavior: 'smooth',
|
|
208
213
|
});
|
|
209
214
|
}
|
|
210
215
|
else if (request.xpath) {
|
|
@@ -215,7 +220,7 @@ function scroll_to(request) {
|
|
|
215
220
|
return false;
|
|
216
221
|
}
|
|
217
222
|
element.scrollIntoView({
|
|
218
|
-
behavior: 'smooth'
|
|
223
|
+
behavior: 'smooth',
|
|
219
224
|
});
|
|
220
225
|
}
|
|
221
226
|
else {
|
|
@@ -277,3 +282,125 @@ function select_dropdown_option(request) {
|
|
|
277
282
|
selectedText: option.text.trim(),
|
|
278
283
|
};
|
|
279
284
|
}
|
|
285
|
+
function request_user_help(task_id, failure_type, failure_message) {
|
|
286
|
+
const domId = 'eko-request-user-help';
|
|
287
|
+
if (document.getElementById(domId)) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const failureTitleMap = {
|
|
291
|
+
login_required: 'Login Required',
|
|
292
|
+
captcha: 'Captcha Detected',
|
|
293
|
+
blocked: 'Blocked',
|
|
294
|
+
other: 'Error',
|
|
295
|
+
rate_limited: 'Rate Limited',
|
|
296
|
+
};
|
|
297
|
+
const notification = document.createElement('div');
|
|
298
|
+
notification.id = domId;
|
|
299
|
+
notification.style.cssText = `
|
|
300
|
+
position: fixed;
|
|
301
|
+
top: 5px;
|
|
302
|
+
left: 18px;
|
|
303
|
+
z-index: 9999;
|
|
304
|
+
background-color: #FEF0ED;
|
|
305
|
+
color: white;
|
|
306
|
+
padding: 16px;
|
|
307
|
+
border-radius: 12px;
|
|
308
|
+
border: 1px solid #FBB8A5;
|
|
309
|
+
font-family: Arial, sans-serif;
|
|
310
|
+
width: 350px;
|
|
311
|
+
display: flex;
|
|
312
|
+
flex-direction: row;
|
|
313
|
+
gap: 10px;
|
|
314
|
+
cursor: move;
|
|
315
|
+
user-select: none;
|
|
316
|
+
`;
|
|
317
|
+
let isDragging = false;
|
|
318
|
+
let xOffset = 0;
|
|
319
|
+
let yOffset = 0;
|
|
320
|
+
let initialX = 0;
|
|
321
|
+
let initialY = 0;
|
|
322
|
+
notification.addEventListener('mousedown', (e) => {
|
|
323
|
+
isDragging = true;
|
|
324
|
+
initialX = e.clientX - xOffset;
|
|
325
|
+
initialY = e.clientY - yOffset;
|
|
326
|
+
e.preventDefault();
|
|
327
|
+
});
|
|
328
|
+
document.addEventListener('mousemove', (e) => {
|
|
329
|
+
if (!isDragging)
|
|
330
|
+
return;
|
|
331
|
+
const currentX = e.clientX - initialX;
|
|
332
|
+
const currentY = e.clientY - initialY;
|
|
333
|
+
xOffset = currentX;
|
|
334
|
+
yOffset = currentY;
|
|
335
|
+
notification.style.transform = `translate(${xOffset}px, ${yOffset}px)`;
|
|
336
|
+
});
|
|
337
|
+
document.addEventListener('mouseup', () => {
|
|
338
|
+
isDragging = false;
|
|
339
|
+
});
|
|
340
|
+
const leftContainer = document.createElement('div');
|
|
341
|
+
leftContainer.style.cssText = `
|
|
342
|
+
width: 28px;
|
|
343
|
+
height: 28px;
|
|
344
|
+
display: flex;
|
|
345
|
+
flex-direction: column;
|
|
346
|
+
align-items: center;
|
|
347
|
+
border-radius: 99px;
|
|
348
|
+
background: #FDCCCC;
|
|
349
|
+
justify-content: center;
|
|
350
|
+
`;
|
|
351
|
+
leftContainer.innerHTML = ``;
|
|
352
|
+
const rightContainer = document.createElement('div');
|
|
353
|
+
rightContainer.style.cssText = `
|
|
354
|
+
flex: 1;
|
|
355
|
+
display: flex;
|
|
356
|
+
flex-direction: column;
|
|
357
|
+
`;
|
|
358
|
+
const title = document.createElement('div');
|
|
359
|
+
title.style.cssText = `
|
|
360
|
+
font-size: 16px;
|
|
361
|
+
font-weight: 700;
|
|
362
|
+
line-height: 22px;
|
|
363
|
+
color: #DD342D;
|
|
364
|
+
text-align: left;
|
|
365
|
+
`;
|
|
366
|
+
title.innerText = failureTitleMap[failure_type] || failure_type;
|
|
367
|
+
const message2 = document.createElement('div');
|
|
368
|
+
message2.style.cssText = `
|
|
369
|
+
font-size: 16px;
|
|
370
|
+
font-weight: 400;
|
|
371
|
+
line-height: 22px;
|
|
372
|
+
color: #DD342D;
|
|
373
|
+
text-align: left;
|
|
374
|
+
`;
|
|
375
|
+
message2.innerText = failure_message + '\nWhen you resolve the issue, click the button below.';
|
|
376
|
+
const buttonDiv = document.createElement('div');
|
|
377
|
+
buttonDiv.style.cssText = `
|
|
378
|
+
margin-top: 16px;
|
|
379
|
+
display: flex;
|
|
380
|
+
flex-direction: row-reverse;
|
|
381
|
+
justify-content: flex-start;
|
|
382
|
+
align-items: center;
|
|
383
|
+
`;
|
|
384
|
+
const resolvedBut = document.createElement('div');
|
|
385
|
+
resolvedBut.innerText = 'Resolved';
|
|
386
|
+
resolvedBut.style.cssText = `
|
|
387
|
+
border-radius: 8px;
|
|
388
|
+
background: #DD342D;
|
|
389
|
+
color: white;
|
|
390
|
+
padding: 10px;
|
|
391
|
+
border: none;
|
|
392
|
+
cursor: pointer;
|
|
393
|
+
`;
|
|
394
|
+
resolvedBut.onclick = () => {
|
|
395
|
+
chrome.runtime.sendMessage({ type: 'issue_resolved', task_id, failure_type }, () => {
|
|
396
|
+
notification.remove();
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
buttonDiv.appendChild(resolvedBut);
|
|
400
|
+
rightContainer.appendChild(title);
|
|
401
|
+
rightContainer.appendChild(message2);
|
|
402
|
+
rightContainer.appendChild(buttonDiv);
|
|
403
|
+
notification.appendChild(leftContainer);
|
|
404
|
+
notification.appendChild(rightContainer);
|
|
405
|
+
document.body.appendChild(notification);
|
|
406
|
+
}
|
package/dist/index.cjs.js
CHANGED
|
@@ -243,6 +243,16 @@ class ActionImpl {
|
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
245
|
if (context.__skip || context.__abort) {
|
|
246
|
+
toolResultMessage = {
|
|
247
|
+
role: 'user',
|
|
248
|
+
content: [
|
|
249
|
+
{
|
|
250
|
+
type: 'tool_result',
|
|
251
|
+
tool_use_id: toolCall.id,
|
|
252
|
+
content: 'skip',
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
246
256
|
return;
|
|
247
257
|
}
|
|
248
258
|
// Execute the tool
|
|
@@ -303,6 +313,7 @@ class ActionImpl {
|
|
|
303
313
|
console.error('Stream Error:', error);
|
|
304
314
|
},
|
|
305
315
|
};
|
|
316
|
+
this.handleHistoryImageMessages(messages);
|
|
306
317
|
// Wait for stream to complete
|
|
307
318
|
await this.llmProvider.generateStream(messages, params, handler);
|
|
308
319
|
// Wait for tool execution to complete if it was started
|
|
@@ -310,7 +321,7 @@ class ActionImpl {
|
|
|
310
321
|
await toolExecutionPromise;
|
|
311
322
|
}
|
|
312
323
|
if (context.__abort) {
|
|
313
|
-
throw new Error(
|
|
324
|
+
throw new Error('Abort');
|
|
314
325
|
}
|
|
315
326
|
// Add messages in the correct order after everything is complete
|
|
316
327
|
if (assistantTextMessage) {
|
|
@@ -324,6 +335,37 @@ class ActionImpl {
|
|
|
324
335
|
}
|
|
325
336
|
return { response, hasToolUse, roundMessages };
|
|
326
337
|
}
|
|
338
|
+
handleHistoryImageMessages(messages) {
|
|
339
|
+
// Remove all images of the historical tool call results, except for the last one.
|
|
340
|
+
let last_user = true;
|
|
341
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
342
|
+
const message = messages[i];
|
|
343
|
+
if (message.role === 'user') {
|
|
344
|
+
if (last_user) {
|
|
345
|
+
last_user = false;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (message.content instanceof Array) {
|
|
349
|
+
let content = message.content;
|
|
350
|
+
for (let j = 0; j < content.length; j++) {
|
|
351
|
+
if (content[j].type === 'tool_result' && content[j].content instanceof Array) {
|
|
352
|
+
let tool_content = content[j].content;
|
|
353
|
+
if (tool_content.length > 0) {
|
|
354
|
+
for (let k = tool_content.length - 1; k >= 0; k--) {
|
|
355
|
+
if (tool_content[k].type === 'image') {
|
|
356
|
+
tool_content.splice(k, 1);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
else if (tool_content[0].type === 'image') {
|
|
361
|
+
tool_content = [{ type: 'text', text: 'ok' }];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
327
369
|
async execute(input, context, outputSchema) {
|
|
328
370
|
var _a;
|
|
329
371
|
// Create return tool with output schema
|
|
@@ -466,6 +508,7 @@ Generate a complete workflow that:
|
|
|
466
508
|
5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem`;
|
|
467
509
|
},
|
|
468
510
|
formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
|
|
511
|
+
modifyUserPrompt: (prompt) => `Modify workflow: ${prompt}`,
|
|
469
512
|
};
|
|
470
513
|
}
|
|
471
514
|
function createWorkflowGenerationTool(registry) {
|
|
@@ -540,30 +583,68 @@ class WorkflowGenerator {
|
|
|
540
583
|
constructor(llmProvider, toolRegistry) {
|
|
541
584
|
this.llmProvider = llmProvider;
|
|
542
585
|
this.toolRegistry = toolRegistry;
|
|
586
|
+
this.message_history = [];
|
|
543
587
|
}
|
|
544
588
|
async generateWorkflow(prompt) {
|
|
589
|
+
return this.doGenerateWorkflow(prompt, false);
|
|
590
|
+
}
|
|
591
|
+
async modifyWorkflow(prompt) {
|
|
592
|
+
return this.doGenerateWorkflow(prompt, true);
|
|
593
|
+
}
|
|
594
|
+
async doGenerateWorkflow(prompt, modify) {
|
|
545
595
|
// Create prompts with current set of tools
|
|
546
596
|
const prompts = createWorkflowPrompts(this.toolRegistry.getToolDefinitions());
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
},
|
|
552
|
-
{
|
|
597
|
+
let messages = [];
|
|
598
|
+
if (modify) {
|
|
599
|
+
messages = this.message_history;
|
|
600
|
+
messages.push({
|
|
553
601
|
role: 'user',
|
|
554
|
-
content: prompts.
|
|
555
|
-
}
|
|
556
|
-
|
|
602
|
+
content: prompts.modifyUserPrompt(prompt),
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
messages = this.message_history = [
|
|
607
|
+
{
|
|
608
|
+
role: 'system',
|
|
609
|
+
content: prompts.formatSystemPrompt(),
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
role: 'user',
|
|
613
|
+
content: prompts.formatUserPrompt(prompt),
|
|
614
|
+
},
|
|
615
|
+
];
|
|
616
|
+
}
|
|
557
617
|
const params = {
|
|
558
618
|
temperature: 0.7,
|
|
559
619
|
maxTokens: 8192,
|
|
560
620
|
tools: [createWorkflowGenerationTool(this.toolRegistry)],
|
|
561
|
-
toolChoice: { type: 'tool', name: 'generate_workflow' }
|
|
621
|
+
toolChoice: { type: 'tool', name: 'generate_workflow' },
|
|
562
622
|
};
|
|
563
623
|
const response = await this.llmProvider.generateText(messages, params);
|
|
564
624
|
if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
|
|
625
|
+
messages.pop();
|
|
565
626
|
throw new Error('Failed to generate workflow: Invalid response from LLM');
|
|
566
627
|
}
|
|
628
|
+
messages.push({
|
|
629
|
+
role: 'assistant',
|
|
630
|
+
content: [
|
|
631
|
+
{
|
|
632
|
+
type: 'tool_use',
|
|
633
|
+
id: response.toolCalls[0].id,
|
|
634
|
+
name: response.toolCalls[0].name,
|
|
635
|
+
input: response.toolCalls[0].input,
|
|
636
|
+
},
|
|
637
|
+
],
|
|
638
|
+
}, {
|
|
639
|
+
role: 'user',
|
|
640
|
+
content: [
|
|
641
|
+
{
|
|
642
|
+
type: 'tool_result',
|
|
643
|
+
tool_use_id: response.toolCalls[0].id,
|
|
644
|
+
content: 'ok',
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
});
|
|
567
648
|
const workflowData = response.toolCalls[0].input.workflow;
|
|
568
649
|
// Validate all tools exist
|
|
569
650
|
for (const node of workflowData.nodes) {
|
|
@@ -590,16 +671,13 @@ class WorkflowGenerator {
|
|
|
590
671
|
input: nodeData.input || { type: 'any', schema: {}, value: undefined },
|
|
591
672
|
output: nodeData.output || { type: 'any', schema: {}, value: undefined },
|
|
592
673
|
action: action,
|
|
593
|
-
dependencies: nodeData.dependencies || []
|
|
674
|
+
dependencies: nodeData.dependencies || [],
|
|
594
675
|
};
|
|
595
676
|
workflow.addNode(node);
|
|
596
677
|
});
|
|
597
678
|
}
|
|
598
679
|
return workflow;
|
|
599
680
|
}
|
|
600
|
-
async modifyWorkflow(workflow, prompt) {
|
|
601
|
-
throw new Error('Not implemented');
|
|
602
|
-
}
|
|
603
681
|
}
|
|
604
682
|
|
|
605
683
|
const VERSION$1 = '0.33.1'; // x-release-please-version
|
|
@@ -8830,13 +8908,61 @@ class OpenaiProvider {
|
|
|
8830
8908
|
content: content.text,
|
|
8831
8909
|
});
|
|
8832
8910
|
}
|
|
8833
|
-
else if (content.type == '
|
|
8911
|
+
else if (content.type == 'image') {
|
|
8834
8912
|
_messages.push({
|
|
8835
|
-
role: '
|
|
8836
|
-
content:
|
|
8837
|
-
|
|
8913
|
+
role: 'user',
|
|
8914
|
+
content: [
|
|
8915
|
+
{
|
|
8916
|
+
type: 'image_url',
|
|
8917
|
+
image_url: {
|
|
8918
|
+
url: `data:${content.source.media_type};base64,${content.source.data}`,
|
|
8919
|
+
},
|
|
8920
|
+
},
|
|
8921
|
+
],
|
|
8838
8922
|
});
|
|
8839
8923
|
}
|
|
8924
|
+
else if (content.type == 'tool_result') {
|
|
8925
|
+
let _content = [];
|
|
8926
|
+
if (content.content == 'string') {
|
|
8927
|
+
_content.push({ type: 'text', text: content.content });
|
|
8928
|
+
}
|
|
8929
|
+
else {
|
|
8930
|
+
for (let k = 0; k < content.content.length; k++) {
|
|
8931
|
+
let item = content.content[k];
|
|
8932
|
+
if (item.type == 'text') {
|
|
8933
|
+
_content.push({ ...item });
|
|
8934
|
+
}
|
|
8935
|
+
else if (item.type == 'image') {
|
|
8936
|
+
_content.push({
|
|
8937
|
+
type: 'image_url',
|
|
8938
|
+
image_url: {
|
|
8939
|
+
url: `data:${item.source.media_type};base64,${item.source.data}`,
|
|
8940
|
+
},
|
|
8941
|
+
});
|
|
8942
|
+
}
|
|
8943
|
+
}
|
|
8944
|
+
}
|
|
8945
|
+
let hasImage = _content.filter((s) => s.type == 'image_url').length > 0;
|
|
8946
|
+
if (hasImage) {
|
|
8947
|
+
// OpenAI does not support images returned by the tool.
|
|
8948
|
+
_messages.push({
|
|
8949
|
+
role: 'tool',
|
|
8950
|
+
content: 'ok',
|
|
8951
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8952
|
+
});
|
|
8953
|
+
_messages.push({
|
|
8954
|
+
role: 'user',
|
|
8955
|
+
content: _content,
|
|
8956
|
+
});
|
|
8957
|
+
}
|
|
8958
|
+
else {
|
|
8959
|
+
_messages.push({
|
|
8960
|
+
role: 'tool',
|
|
8961
|
+
content: _content,
|
|
8962
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8963
|
+
});
|
|
8964
|
+
}
|
|
8965
|
+
}
|
|
8840
8966
|
}
|
|
8841
8967
|
}
|
|
8842
8968
|
else {
|
|
@@ -9112,6 +9238,7 @@ class ToolRegistry {
|
|
|
9112
9238
|
class Eko {
|
|
9113
9239
|
constructor(config) {
|
|
9114
9240
|
this.toolRegistry = new ToolRegistry();
|
|
9241
|
+
this.workflowGeneratorMap = new Map();
|
|
9115
9242
|
if (typeof config == 'string') {
|
|
9116
9243
|
this.llmProvider = new ClaudeProvider(config);
|
|
9117
9244
|
}
|
|
@@ -9148,11 +9275,19 @@ class Eko {
|
|
|
9148
9275
|
}
|
|
9149
9276
|
}
|
|
9150
9277
|
const generator = new WorkflowGenerator(this.llmProvider, toolRegistry);
|
|
9151
|
-
|
|
9278
|
+
const workflow = await generator.generateWorkflow(prompt);
|
|
9279
|
+
this.workflowGeneratorMap.set(workflow, generator);
|
|
9280
|
+
return workflow;
|
|
9152
9281
|
}
|
|
9153
9282
|
async execute(workflow, callback) {
|
|
9154
9283
|
return await workflow.execute(callback);
|
|
9155
9284
|
}
|
|
9285
|
+
async modify(workflow, prompt) {
|
|
9286
|
+
const generator = this.workflowGeneratorMap.get(workflow);
|
|
9287
|
+
workflow = await generator.modifyWorkflow(prompt);
|
|
9288
|
+
this.workflowGeneratorMap.set(workflow, generator);
|
|
9289
|
+
return workflow;
|
|
9290
|
+
}
|
|
9156
9291
|
getTool(toolName) {
|
|
9157
9292
|
let tool;
|
|
9158
9293
|
if (this.toolRegistry.hasTools([toolName])) {
|
package/dist/index.esm.js
CHANGED
|
@@ -239,6 +239,16 @@ class ActionImpl {
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
if (context.__skip || context.__abort) {
|
|
242
|
+
toolResultMessage = {
|
|
243
|
+
role: 'user',
|
|
244
|
+
content: [
|
|
245
|
+
{
|
|
246
|
+
type: 'tool_result',
|
|
247
|
+
tool_use_id: toolCall.id,
|
|
248
|
+
content: 'skip',
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
};
|
|
242
252
|
return;
|
|
243
253
|
}
|
|
244
254
|
// Execute the tool
|
|
@@ -299,6 +309,7 @@ class ActionImpl {
|
|
|
299
309
|
console.error('Stream Error:', error);
|
|
300
310
|
},
|
|
301
311
|
};
|
|
312
|
+
this.handleHistoryImageMessages(messages);
|
|
302
313
|
// Wait for stream to complete
|
|
303
314
|
await this.llmProvider.generateStream(messages, params, handler);
|
|
304
315
|
// Wait for tool execution to complete if it was started
|
|
@@ -306,7 +317,7 @@ class ActionImpl {
|
|
|
306
317
|
await toolExecutionPromise;
|
|
307
318
|
}
|
|
308
319
|
if (context.__abort) {
|
|
309
|
-
throw new Error(
|
|
320
|
+
throw new Error('Abort');
|
|
310
321
|
}
|
|
311
322
|
// Add messages in the correct order after everything is complete
|
|
312
323
|
if (assistantTextMessage) {
|
|
@@ -320,6 +331,37 @@ class ActionImpl {
|
|
|
320
331
|
}
|
|
321
332
|
return { response, hasToolUse, roundMessages };
|
|
322
333
|
}
|
|
334
|
+
handleHistoryImageMessages(messages) {
|
|
335
|
+
// Remove all images of the historical tool call results, except for the last one.
|
|
336
|
+
let last_user = true;
|
|
337
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
338
|
+
const message = messages[i];
|
|
339
|
+
if (message.role === 'user') {
|
|
340
|
+
if (last_user) {
|
|
341
|
+
last_user = false;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (message.content instanceof Array) {
|
|
345
|
+
let content = message.content;
|
|
346
|
+
for (let j = 0; j < content.length; j++) {
|
|
347
|
+
if (content[j].type === 'tool_result' && content[j].content instanceof Array) {
|
|
348
|
+
let tool_content = content[j].content;
|
|
349
|
+
if (tool_content.length > 0) {
|
|
350
|
+
for (let k = tool_content.length - 1; k >= 0; k--) {
|
|
351
|
+
if (tool_content[k].type === 'image') {
|
|
352
|
+
tool_content.splice(k, 1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
else if (tool_content[0].type === 'image') {
|
|
357
|
+
tool_content = [{ type: 'text', text: 'ok' }];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
323
365
|
async execute(input, context, outputSchema) {
|
|
324
366
|
var _a;
|
|
325
367
|
// Create return tool with output schema
|
|
@@ -462,6 +504,7 @@ Generate a complete workflow that:
|
|
|
462
504
|
5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem`;
|
|
463
505
|
},
|
|
464
506
|
formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
|
|
507
|
+
modifyUserPrompt: (prompt) => `Modify workflow: ${prompt}`,
|
|
465
508
|
};
|
|
466
509
|
}
|
|
467
510
|
function createWorkflowGenerationTool(registry) {
|
|
@@ -536,30 +579,68 @@ class WorkflowGenerator {
|
|
|
536
579
|
constructor(llmProvider, toolRegistry) {
|
|
537
580
|
this.llmProvider = llmProvider;
|
|
538
581
|
this.toolRegistry = toolRegistry;
|
|
582
|
+
this.message_history = [];
|
|
539
583
|
}
|
|
540
584
|
async generateWorkflow(prompt) {
|
|
585
|
+
return this.doGenerateWorkflow(prompt, false);
|
|
586
|
+
}
|
|
587
|
+
async modifyWorkflow(prompt) {
|
|
588
|
+
return this.doGenerateWorkflow(prompt, true);
|
|
589
|
+
}
|
|
590
|
+
async doGenerateWorkflow(prompt, modify) {
|
|
541
591
|
// Create prompts with current set of tools
|
|
542
592
|
const prompts = createWorkflowPrompts(this.toolRegistry.getToolDefinitions());
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
},
|
|
548
|
-
{
|
|
593
|
+
let messages = [];
|
|
594
|
+
if (modify) {
|
|
595
|
+
messages = this.message_history;
|
|
596
|
+
messages.push({
|
|
549
597
|
role: 'user',
|
|
550
|
-
content: prompts.
|
|
551
|
-
}
|
|
552
|
-
|
|
598
|
+
content: prompts.modifyUserPrompt(prompt),
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
messages = this.message_history = [
|
|
603
|
+
{
|
|
604
|
+
role: 'system',
|
|
605
|
+
content: prompts.formatSystemPrompt(),
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
role: 'user',
|
|
609
|
+
content: prompts.formatUserPrompt(prompt),
|
|
610
|
+
},
|
|
611
|
+
];
|
|
612
|
+
}
|
|
553
613
|
const params = {
|
|
554
614
|
temperature: 0.7,
|
|
555
615
|
maxTokens: 8192,
|
|
556
616
|
tools: [createWorkflowGenerationTool(this.toolRegistry)],
|
|
557
|
-
toolChoice: { type: 'tool', name: 'generate_workflow' }
|
|
617
|
+
toolChoice: { type: 'tool', name: 'generate_workflow' },
|
|
558
618
|
};
|
|
559
619
|
const response = await this.llmProvider.generateText(messages, params);
|
|
560
620
|
if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
|
|
621
|
+
messages.pop();
|
|
561
622
|
throw new Error('Failed to generate workflow: Invalid response from LLM');
|
|
562
623
|
}
|
|
624
|
+
messages.push({
|
|
625
|
+
role: 'assistant',
|
|
626
|
+
content: [
|
|
627
|
+
{
|
|
628
|
+
type: 'tool_use',
|
|
629
|
+
id: response.toolCalls[0].id,
|
|
630
|
+
name: response.toolCalls[0].name,
|
|
631
|
+
input: response.toolCalls[0].input,
|
|
632
|
+
},
|
|
633
|
+
],
|
|
634
|
+
}, {
|
|
635
|
+
role: 'user',
|
|
636
|
+
content: [
|
|
637
|
+
{
|
|
638
|
+
type: 'tool_result',
|
|
639
|
+
tool_use_id: response.toolCalls[0].id,
|
|
640
|
+
content: 'ok',
|
|
641
|
+
},
|
|
642
|
+
],
|
|
643
|
+
});
|
|
563
644
|
const workflowData = response.toolCalls[0].input.workflow;
|
|
564
645
|
// Validate all tools exist
|
|
565
646
|
for (const node of workflowData.nodes) {
|
|
@@ -586,16 +667,13 @@ class WorkflowGenerator {
|
|
|
586
667
|
input: nodeData.input || { type: 'any', schema: {}, value: undefined },
|
|
587
668
|
output: nodeData.output || { type: 'any', schema: {}, value: undefined },
|
|
588
669
|
action: action,
|
|
589
|
-
dependencies: nodeData.dependencies || []
|
|
670
|
+
dependencies: nodeData.dependencies || [],
|
|
590
671
|
};
|
|
591
672
|
workflow.addNode(node);
|
|
592
673
|
});
|
|
593
674
|
}
|
|
594
675
|
return workflow;
|
|
595
676
|
}
|
|
596
|
-
async modifyWorkflow(workflow, prompt) {
|
|
597
|
-
throw new Error('Not implemented');
|
|
598
|
-
}
|
|
599
677
|
}
|
|
600
678
|
|
|
601
679
|
const VERSION$1 = '0.33.1'; // x-release-please-version
|
|
@@ -8826,13 +8904,61 @@ class OpenaiProvider {
|
|
|
8826
8904
|
content: content.text,
|
|
8827
8905
|
});
|
|
8828
8906
|
}
|
|
8829
|
-
else if (content.type == '
|
|
8907
|
+
else if (content.type == 'image') {
|
|
8830
8908
|
_messages.push({
|
|
8831
|
-
role: '
|
|
8832
|
-
content:
|
|
8833
|
-
|
|
8909
|
+
role: 'user',
|
|
8910
|
+
content: [
|
|
8911
|
+
{
|
|
8912
|
+
type: 'image_url',
|
|
8913
|
+
image_url: {
|
|
8914
|
+
url: `data:${content.source.media_type};base64,${content.source.data}`,
|
|
8915
|
+
},
|
|
8916
|
+
},
|
|
8917
|
+
],
|
|
8834
8918
|
});
|
|
8835
8919
|
}
|
|
8920
|
+
else if (content.type == 'tool_result') {
|
|
8921
|
+
let _content = [];
|
|
8922
|
+
if (content.content == 'string') {
|
|
8923
|
+
_content.push({ type: 'text', text: content.content });
|
|
8924
|
+
}
|
|
8925
|
+
else {
|
|
8926
|
+
for (let k = 0; k < content.content.length; k++) {
|
|
8927
|
+
let item = content.content[k];
|
|
8928
|
+
if (item.type == 'text') {
|
|
8929
|
+
_content.push({ ...item });
|
|
8930
|
+
}
|
|
8931
|
+
else if (item.type == 'image') {
|
|
8932
|
+
_content.push({
|
|
8933
|
+
type: 'image_url',
|
|
8934
|
+
image_url: {
|
|
8935
|
+
url: `data:${item.source.media_type};base64,${item.source.data}`,
|
|
8936
|
+
},
|
|
8937
|
+
});
|
|
8938
|
+
}
|
|
8939
|
+
}
|
|
8940
|
+
}
|
|
8941
|
+
let hasImage = _content.filter((s) => s.type == 'image_url').length > 0;
|
|
8942
|
+
if (hasImage) {
|
|
8943
|
+
// OpenAI does not support images returned by the tool.
|
|
8944
|
+
_messages.push({
|
|
8945
|
+
role: 'tool',
|
|
8946
|
+
content: 'ok',
|
|
8947
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8948
|
+
});
|
|
8949
|
+
_messages.push({
|
|
8950
|
+
role: 'user',
|
|
8951
|
+
content: _content,
|
|
8952
|
+
});
|
|
8953
|
+
}
|
|
8954
|
+
else {
|
|
8955
|
+
_messages.push({
|
|
8956
|
+
role: 'tool',
|
|
8957
|
+
content: _content,
|
|
8958
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8959
|
+
});
|
|
8960
|
+
}
|
|
8961
|
+
}
|
|
8836
8962
|
}
|
|
8837
8963
|
}
|
|
8838
8964
|
else {
|
|
@@ -9108,6 +9234,7 @@ class ToolRegistry {
|
|
|
9108
9234
|
class Eko {
|
|
9109
9235
|
constructor(config) {
|
|
9110
9236
|
this.toolRegistry = new ToolRegistry();
|
|
9237
|
+
this.workflowGeneratorMap = new Map();
|
|
9111
9238
|
if (typeof config == 'string') {
|
|
9112
9239
|
this.llmProvider = new ClaudeProvider(config);
|
|
9113
9240
|
}
|
|
@@ -9144,11 +9271,19 @@ class Eko {
|
|
|
9144
9271
|
}
|
|
9145
9272
|
}
|
|
9146
9273
|
const generator = new WorkflowGenerator(this.llmProvider, toolRegistry);
|
|
9147
|
-
|
|
9274
|
+
const workflow = await generator.generateWorkflow(prompt);
|
|
9275
|
+
this.workflowGeneratorMap.set(workflow, generator);
|
|
9276
|
+
return workflow;
|
|
9148
9277
|
}
|
|
9149
9278
|
async execute(workflow, callback) {
|
|
9150
9279
|
return await workflow.execute(callback);
|
|
9151
9280
|
}
|
|
9281
|
+
async modify(workflow, prompt) {
|
|
9282
|
+
const generator = this.workflowGeneratorMap.get(workflow);
|
|
9283
|
+
workflow = await generator.modifyWorkflow(prompt);
|
|
9284
|
+
this.workflowGeneratorMap.set(workflow, generator);
|
|
9285
|
+
return workflow;
|
|
9286
|
+
}
|
|
9152
9287
|
getTool(toolName) {
|
|
9153
9288
|
let tool;
|
|
9154
9289
|
if (this.toolRegistry.hasTools([toolName])) {
|