@eko-ai/eko 1.0.1 → 1.0.2

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.
Files changed (37) hide show
  1. package/README.md +56 -44
  2. package/dist/core/eko.d.ts +1 -0
  3. package/dist/core/tool-registry.d.ts +1 -1
  4. package/dist/extension/script/build_dom_tree.d.ts +40 -0
  5. package/dist/extension/tools/index.d.ts +1 -2
  6. package/dist/extension.cjs.js +171 -190
  7. package/dist/extension.esm.js +171 -190
  8. package/dist/index.cjs.js +59 -49
  9. package/dist/index.esm.js +59 -49
  10. package/dist/models/action.d.ts +3 -2
  11. package/dist/nodejs/core.d.ts +2 -0
  12. package/dist/nodejs/index.d.ts +1 -0
  13. package/dist/nodejs/tools/command_execute.d.ts +12 -0
  14. package/dist/nodejs/tools/file_read.d.ts +11 -0
  15. package/dist/nodejs/tools/file_write.d.ts +15 -0
  16. package/dist/nodejs/tools/index.d.ts +3 -1
  17. package/dist/nodejs.cjs.js +227 -3
  18. package/dist/nodejs.esm.js +226 -3
  19. package/dist/schemas/workflow.schema.d.ts +3 -0
  20. package/dist/services/llm/claude-provider.d.ts +1 -0
  21. package/dist/services/llm/openai-provider.d.ts +1 -0
  22. package/dist/types/action.types.d.ts +1 -0
  23. package/dist/web/core.d.ts +2 -0
  24. package/dist/web/index.d.ts +3 -0
  25. package/dist/web/script/build_dom_tree.d.ts +12 -0
  26. package/dist/web/tools/browser.d.ts +10 -0
  27. package/dist/web/tools/browser_use.d.ts +18 -0
  28. package/dist/web/tools/element_click.d.ts +12 -0
  29. package/dist/web/tools/export_file.d.ts +18 -0
  30. package/dist/web/tools/extract_content.d.ts +17 -0
  31. package/dist/web/tools/find_element_position.d.ts +12 -0
  32. package/dist/web/tools/html_script.d.ts +21 -0
  33. package/dist/web/tools/index.d.ts +7 -1
  34. package/dist/web/tools/screenshot.d.ts +18 -0
  35. package/dist/web.cjs.js +9307 -3
  36. package/dist/web.esm.js +9305 -3
  37. package/package.json +2 -1
@@ -233,6 +233,177 @@ var utils = /*#__PURE__*/Object.freeze({
233
233
  waitForTabComplete: waitForTabComplete
234
234
  });
235
235
 
236
+ function exportFile(filename, type, content) {
237
+ const blob = new Blob([content], { type: type });
238
+ const link = document.createElement('a');
239
+ link.href = URL.createObjectURL(blob);
240
+ link.download = filename;
241
+ document.body.appendChild(link);
242
+ link.click();
243
+ document.body.removeChild(link);
244
+ URL.revokeObjectURL(link.href);
245
+ }
246
+ function getDropdownOptions(xpath) {
247
+ const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
248
+ .singleNodeValue;
249
+ if (!select) {
250
+ return null;
251
+ }
252
+ return {
253
+ options: Array.from(select.options).map((opt) => ({
254
+ index: opt.index,
255
+ text: opt.text.trim(),
256
+ value: opt.value,
257
+ })),
258
+ id: select.id,
259
+ name: select.name,
260
+ };
261
+ }
262
+ function selectDropdownOption(xpath, text) {
263
+ const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
264
+ .singleNodeValue;
265
+ if (!select || select.tagName.toUpperCase() !== 'SELECT') {
266
+ return { success: false, error: 'Select not found or invalid element type' };
267
+ }
268
+ const option = Array.from(select.options).find((opt) => opt.text.trim() === text);
269
+ if (!option) {
270
+ return {
271
+ success: false,
272
+ error: 'Option not found',
273
+ availableOptions: Array.from(select.options).map((o) => o.text.trim()),
274
+ };
275
+ }
276
+ select.value = option.value;
277
+ select.dispatchEvent(new Event('change'));
278
+ return {
279
+ success: true,
280
+ selectedValue: option.value,
281
+ selectedText: option.text.trim(),
282
+ };
283
+ }
284
+ /**
285
+ * Extract the elements related to html operability and wrap them into pseudo-html code.
286
+ */
287
+ function extractOperableElements() {
288
+ // visible
289
+ const isElementVisible = (element) => {
290
+ const style = window.getComputedStyle(element);
291
+ return (style.display !== 'none' &&
292
+ style.visibility !== 'hidden' &&
293
+ style.opacity !== '0' &&
294
+ element.offsetWidth > 0 &&
295
+ element.offsetHeight > 0);
296
+ };
297
+ // element original index
298
+ const getElementIndex = (element) => {
299
+ const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
300
+ return xpath.snapshotLength;
301
+ };
302
+ // exclude
303
+ const addExclude = (excludes, children) => {
304
+ for (let i = 0; i < children.length; i++) {
305
+ excludes.push(children[i]);
306
+ if (children[i].children) {
307
+ addExclude(excludes, children[i].children);
308
+ }
309
+ }
310
+ };
311
+ // { pseudoId: element }
312
+ let elementMap = {};
313
+ let nextId = 1;
314
+ let elements = [];
315
+ let excludes = [];
316
+ // operable element
317
+ const operableSelectors = 'a, button, input, textarea, select';
318
+ document.querySelectorAll(operableSelectors).forEach((element) => {
319
+ if (isElementVisible(element) && excludes.indexOf(element) == -1) {
320
+ const id = nextId++;
321
+ elementMap[id.toString()] = element;
322
+ const tagName = element.tagName.toLowerCase();
323
+ const attributes = Array.from(element.attributes)
324
+ .filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
325
+ .map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
326
+ .join(' ');
327
+ elements.push({
328
+ originalIndex: getElementIndex(element),
329
+ id: id,
330
+ html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
331
+ });
332
+ addExclude(excludes, element.children);
333
+ }
334
+ });
335
+ // short text element
336
+ const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
337
+ acceptNode: function (node) {
338
+ var _a;
339
+ if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
340
+ // skip
341
+ return NodeFilter.FILTER_SKIP;
342
+ }
343
+ // text <= 100
344
+ const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
345
+ if (isElementVisible(node) &&
346
+ text &&
347
+ text.length <= 100 &&
348
+ text.length > 0 &&
349
+ node.children.length === 0) {
350
+ return NodeFilter.FILTER_ACCEPT;
351
+ }
352
+ // skip
353
+ return NodeFilter.FILTER_SKIP;
354
+ },
355
+ });
356
+ let currentNode;
357
+ while ((currentNode = textWalker.nextNode())) {
358
+ const id = nextId++;
359
+ elementMap[id.toString()] = currentNode;
360
+ const tagName = currentNode.tagName.toLowerCase();
361
+ elements.push({
362
+ originalIndex: getElementIndex(currentNode),
363
+ id: id,
364
+ html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
365
+ });
366
+ }
367
+ // element sort
368
+ elements.sort((a, b) => a.originalIndex - b.originalIndex);
369
+ // cache
370
+ window.operableElementMap = elementMap;
371
+ // pseudo html
372
+ return elements.map((e) => e.html).join('\n');
373
+ }
374
+ function clickOperableElement(id) {
375
+ let element = window.operableElementMap[id];
376
+ if (!element) {
377
+ return false;
378
+ }
379
+ if (element.click) {
380
+ element.click();
381
+ }
382
+ else {
383
+ element.dispatchEvent(new MouseEvent('click', {
384
+ view: window,
385
+ bubbles: true,
386
+ cancelable: true,
387
+ }));
388
+ }
389
+ return true;
390
+ }
391
+ function getOperableElementRect(id) {
392
+ let element = window.operableElementMap[id];
393
+ if (!element) {
394
+ return null;
395
+ }
396
+ const rect = element.getBoundingClientRect();
397
+ return {
398
+ left: rect.left + window.scrollX,
399
+ top: rect.top + window.scrollY,
400
+ right: rect.right + window.scrollX,
401
+ bottom: rect.bottom + window.scrollY,
402
+ width: rect.right - rect.left,
403
+ height: rect.bottom - rect.top,
404
+ };
405
+ }
406
+
236
407
  async function key(tabId, key, coordinate) {
237
408
  if (!coordinate) {
238
409
  coordinate = (await cursor_position(tabId)).coordinate;
@@ -442,177 +613,6 @@ var browser = /*#__PURE__*/Object.freeze({
442
613
  type_by_xpath: type_by_xpath
443
614
  });
444
615
 
445
- function exportFile(filename, type, content) {
446
- const blob = new Blob([content], { type: type });
447
- const link = document.createElement('a');
448
- link.href = URL.createObjectURL(blob);
449
- link.download = filename;
450
- document.body.appendChild(link);
451
- link.click();
452
- document.body.removeChild(link);
453
- URL.revokeObjectURL(link.href);
454
- }
455
- function getDropdownOptions(xpath) {
456
- const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
457
- .singleNodeValue;
458
- if (!select) {
459
- return null;
460
- }
461
- return {
462
- options: Array.from(select.options).map((opt) => ({
463
- index: opt.index,
464
- text: opt.text.trim(),
465
- value: opt.value,
466
- })),
467
- id: select.id,
468
- name: select.name,
469
- };
470
- }
471
- function selectDropdownOption(xpath, text) {
472
- const select = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)
473
- .singleNodeValue;
474
- if (!select || select.tagName.toUpperCase() !== 'SELECT') {
475
- return { success: false, error: 'Select not found or invalid element type' };
476
- }
477
- const option = Array.from(select.options).find((opt) => opt.text.trim() === text);
478
- if (!option) {
479
- return {
480
- success: false,
481
- error: 'Option not found',
482
- availableOptions: Array.from(select.options).map((o) => o.text.trim()),
483
- };
484
- }
485
- select.value = option.value;
486
- select.dispatchEvent(new Event('change'));
487
- return {
488
- success: true,
489
- selectedValue: option.value,
490
- selectedText: option.text.trim(),
491
- };
492
- }
493
- /**
494
- * Extract the elements related to html operability and wrap them into pseudo-html code.
495
- */
496
- function extractOperableElements() {
497
- // visible
498
- const isElementVisible = (element) => {
499
- const style = window.getComputedStyle(element);
500
- return (style.display !== 'none' &&
501
- style.visibility !== 'hidden' &&
502
- style.opacity !== '0' &&
503
- element.offsetWidth > 0 &&
504
- element.offsetHeight > 0);
505
- };
506
- // element original index
507
- const getElementIndex = (element) => {
508
- const xpath = document.evaluate('preceding::*', element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
509
- return xpath.snapshotLength;
510
- };
511
- // exclude
512
- const addExclude = (excludes, children) => {
513
- for (let i = 0; i < children.length; i++) {
514
- excludes.push(children[i]);
515
- if (children[i].children) {
516
- addExclude(excludes, children[i].children);
517
- }
518
- }
519
- };
520
- // { pseudoId: element }
521
- let elementMap = {};
522
- let nextId = 1;
523
- let elements = [];
524
- let excludes = [];
525
- // operable element
526
- const operableSelectors = 'a, button, input, textarea, select';
527
- document.querySelectorAll(operableSelectors).forEach((element) => {
528
- if (isElementVisible(element) && excludes.indexOf(element) == -1) {
529
- const id = nextId++;
530
- elementMap[id.toString()] = element;
531
- const tagName = element.tagName.toLowerCase();
532
- const attributes = Array.from(element.attributes)
533
- .filter((attr) => ['id', 'name', 'type', 'value', 'href', 'title', 'placeholder'].includes(attr.name))
534
- .map((attr) => `${attr.name == 'id' ? 'target' : attr.name}="${attr.value}"`)
535
- .join(' ');
536
- elements.push({
537
- originalIndex: getElementIndex(element),
538
- id: id,
539
- html: `<${tagName} id="${id}" ${attributes}>${tagName == 'select' ? element.innerHTML : element.innerText || ''}</${tagName}>`,
540
- });
541
- addExclude(excludes, element.children);
542
- }
543
- });
544
- // short text element
545
- const textWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
546
- acceptNode: function (node) {
547
- var _a;
548
- if (node.matches(operableSelectors) || excludes.indexOf(node) != -1) {
549
- // skip
550
- return NodeFilter.FILTER_SKIP;
551
- }
552
- // text <= 100
553
- const text = (_a = node.innerText) === null || _a === void 0 ? void 0 : _a.trim();
554
- if (isElementVisible(node) &&
555
- text &&
556
- text.length <= 100 &&
557
- text.length > 0 &&
558
- node.children.length === 0) {
559
- return NodeFilter.FILTER_ACCEPT;
560
- }
561
- // skip
562
- return NodeFilter.FILTER_SKIP;
563
- },
564
- });
565
- let currentNode;
566
- while ((currentNode = textWalker.nextNode())) {
567
- const id = nextId++;
568
- elementMap[id.toString()] = currentNode;
569
- const tagName = currentNode.tagName.toLowerCase();
570
- elements.push({
571
- originalIndex: getElementIndex(currentNode),
572
- id: id,
573
- html: `<${tagName} id="${id}">${currentNode.innerText.trim()}</${tagName}>`,
574
- });
575
- }
576
- // element sort
577
- elements.sort((a, b) => a.originalIndex - b.originalIndex);
578
- // cache
579
- window.operableElementMap = elementMap;
580
- // pseudo html
581
- return elements.map((e) => e.html).join('\n');
582
- }
583
- function clickOperableElement(id) {
584
- let element = window.operableElementMap[id];
585
- if (!element) {
586
- return false;
587
- }
588
- if (element.click) {
589
- element.click();
590
- }
591
- else {
592
- element.dispatchEvent(new MouseEvent('click', {
593
- view: window,
594
- bubbles: true,
595
- cancelable: true,
596
- }));
597
- }
598
- return true;
599
- }
600
- function getOperableElementRect(id) {
601
- let element = window.operableElementMap[id];
602
- if (!element) {
603
- return null;
604
- }
605
- const rect = element.getBoundingClientRect();
606
- return {
607
- left: rect.left + window.scrollX,
608
- top: rect.top + window.scrollY,
609
- right: rect.right + window.scrollX,
610
- bottom: rect.bottom + window.scrollY,
611
- width: rect.right - rect.left,
612
- height: rect.bottom - rect.top,
613
- };
614
- }
615
-
616
616
  /**
617
617
  * Browser Use for general
618
618
  */
@@ -1183,24 +1183,6 @@ async function executeWithBrowserUse(context, task_prompt) {
1183
1183
  };
1184
1184
  }
1185
1185
 
1186
- /**
1187
- * Form Autofill
1188
- */
1189
- class FormAutofill {
1190
- constructor() {
1191
- this.name = 'form_autofill';
1192
- this.description = 'Automatically fill in form data on web pages';
1193
- this.input_schema = {
1194
- type: 'object',
1195
- properties: {}
1196
- };
1197
- }
1198
- async execute(context, params) {
1199
- // form -> input, textarea, select ...
1200
- throw new Error('Not implemented');
1201
- }
1202
- }
1203
-
1204
1186
  /**
1205
1187
  * Open Url
1206
1188
  */
@@ -1738,7 +1720,6 @@ var tools = /*#__PURE__*/Object.freeze({
1738
1720
  ExportFile: ExportFile,
1739
1721
  ExtractContent: ExtractContent,
1740
1722
  FindElementPosition: FindElementPosition,
1741
- FormAutofill: FormAutofill,
1742
1723
  OpenUrl: OpenUrl,
1743
1724
  Screenshot: Screenshot,
1744
1725
  TabManagement: TabManagement,
package/dist/index.cjs.js CHANGED
@@ -169,9 +169,10 @@ function createReturnTool(outputSchema) {
169
169
  }
170
170
  class ActionImpl {
171
171
  constructor(type, // Only support prompt type
172
- name, tools, llmProvider, llmConfig, config) {
172
+ name, description, tools, llmProvider, llmConfig, config) {
173
173
  this.type = type;
174
174
  this.name = name;
175
+ this.description = description;
175
176
  this.tools = tools;
176
177
  this.llmProvider = llmProvider;
177
178
  this.llmConfig = llmConfig;
@@ -195,7 +196,6 @@ class ActionImpl {
195
196
  const handler = {
196
197
  onContent: (content) => {
197
198
  if (content.trim()) {
198
- console.log('LLM:', content);
199
199
  assistantTextMessage += content;
200
200
  }
201
201
  },
@@ -313,12 +313,10 @@ class ActionImpl {
313
313
  (_a = context.tools) === null || _a === void 0 ? void 0 : _a.forEach((tool) => toolMap.set(tool.name, tool));
314
314
  toolMap.set(returnTool.name, returnTool);
315
315
  // Prepare initial messages
316
- const messages = input && Object.keys(input).length > 0
317
- ? [
318
- { role: 'system', content: this.formatSystemPrompt(context) },
319
- { role: 'user', content: this.formatUserPrompt(input) },
320
- ]
321
- : [{ role: 'user', content: this.formatSystemPrompt(context) }];
316
+ const messages = [
317
+ { role: 'system', content: this.formatSystemPrompt() },
318
+ { role: 'user', content: this.formatUserPrompt(context, input) },
319
+ ];
322
320
  console.log('Starting LLM conversation...');
323
321
  console.log('Initial messages:', messages);
324
322
  console.log('Output schema:', outputSchema);
@@ -343,6 +341,7 @@ class ActionImpl {
343
341
  if (!hasToolUse && response) {
344
342
  // LLM sent a message without using tools - request explicit return
345
343
  console.log('No tool use detected, requesting explicit return');
344
+ console.log('Response:', response);
346
345
  const returnOnlyParams = {
347
346
  ...params,
348
347
  tools: [
@@ -395,32 +394,30 @@ class ActionImpl {
395
394
  }
396
395
  return output;
397
396
  }
398
- formatSystemPrompt(context) {
397
+ formatSystemPrompt() {
398
+ return `You are a task executor. You need to complete the task specified by the user, using the tools provided. When you need to store results or outputs, use the write_context tool. When you are ready to return the final output, use the return_output tool.
399
+
400
+ Remember to:
401
+ 1. Use tools when needed to accomplish the task
402
+ 2. Store important results using write_context, including intermediate and final results
403
+ 3. Think step by step about what needs to be done`;
404
+ }
405
+ formatUserPrompt(context, input) {
399
406
  // Create a description of the current context
400
407
  const contextDescription = Array.from(context.variables.entries())
401
408
  .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
402
409
  .join('\n');
403
- return `You are executing the action "${this.name}". You have access to the following context:
404
-
405
- ${contextDescription || 'No context variables set'}
410
+ return `You are executing the action "${this.name}". The specific instructions are: "${this.description}". You have access to the following context:
406
411
 
407
- You can use the provided tools to accomplish your task. When you need to store results or outputs,
408
- use the write_context tool to save them to the workflow context.
412
+ ${contextDescription || 'No context variables set'}
409
413
 
410
- Remember to:
411
- 1. Use tools when needed to accomplish the task
412
- 2. Store important results using write_context
413
- 3. Think step by step about what needs to be done`;
414
- }
415
- formatUserPrompt(input) {
416
- if (typeof input === 'string') {
417
- return input;
418
- }
419
- return JSON.stringify(input, null, 2);
414
+ You have been provided with the following input:
415
+ ${(typeof input === 'string' ? input : JSON.stringify(input, null, 2)) || 'No additional input provided'}
416
+ `;
420
417
  }
421
418
  // Static factory method
422
- static createPromptAction(name, tools, llmProvider, llmConfig) {
423
- return new ActionImpl('prompt', name, tools, llmProvider, llmConfig);
419
+ static createPromptAction(name, description, tools, llmProvider, llmConfig) {
420
+ return new ActionImpl('prompt', name, description, tools, llmProvider, llmConfig);
424
421
  }
425
422
  }
426
423
 
@@ -444,7 +441,8 @@ Generate a complete workflow that:
444
441
  1. Only uses the tools listed above
445
442
  2. Properly sequences tool usage based on dependencies
446
443
  3. Ensures each action has appropriate input/output schemas
447
- 4. Creates a clear, logical flow to accomplish the user's goal`;
444
+ 4. Creates a clear, logical flow to accomplish the user's goal
445
+ 5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem`;
448
446
  },
449
447
  formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
450
448
  };
@@ -564,7 +562,7 @@ class WorkflowGenerator {
564
562
  if (Array.isArray(data.nodes)) {
565
563
  data.nodes.forEach((nodeData) => {
566
564
  const tools = nodeData.action.tools.map((toolName) => this.toolRegistry.getTool(toolName));
567
- const action = ActionImpl.createPromptAction(nodeData.action.name, tools, this.llmProvider, { maxTokens: 1000 });
565
+ const action = ActionImpl.createPromptAction(nodeData.action.name, nodeData.action.description, tools, this.llmProvider, { maxTokens: 1000 });
568
566
  const node = {
569
567
  id: nodeData.id,
570
568
  name: nodeData.name || nodeData.id,
@@ -3286,16 +3284,21 @@ Anthropic.ModelInfosPage = ModelInfosPage;
3286
3284
  Anthropic.Beta = Beta$1;
3287
3285
 
3288
3286
  class ClaudeProvider {
3289
- constructor(apiKey, defaultModel, options) {
3287
+ constructor(param, defaultModel, options) {
3290
3288
  this.defaultModel = 'claude-3-5-sonnet-20241022';
3291
3289
  if (defaultModel) {
3292
3290
  this.defaultModel = defaultModel;
3293
3291
  }
3294
- this.client = new Anthropic({
3295
- apiKey: apiKey,
3296
- dangerouslyAllowBrowser: true,
3297
- ...options,
3298
- });
3292
+ if (typeof param == 'string') {
3293
+ this.client = new Anthropic({
3294
+ apiKey: param,
3295
+ dangerouslyAllowBrowser: true,
3296
+ ...options,
3297
+ });
3298
+ }
3299
+ else {
3300
+ this.client = new Anthropic(param);
3301
+ }
3299
3302
  }
3300
3303
  processResponse(response) {
3301
3304
  const toolCalls = response.content
@@ -3389,7 +3392,7 @@ class ClaudeProvider {
3389
3392
  const toolCall = {
3390
3393
  id: currentToolUse.id,
3391
3394
  name: currentToolUse.name,
3392
- input: JSON.parse(currentToolUse.accumulatedJson),
3395
+ input: JSON.parse(currentToolUse.accumulatedJson || '{}'),
3393
3396
  };
3394
3397
  (_d = handler.onToolUse) === null || _d === void 0 ? void 0 : _d.call(handler, toolCall);
3395
3398
  currentToolUse = null;
@@ -8688,16 +8691,21 @@ OpenAI.BatchesPage = BatchesPage;
8688
8691
  OpenAI.Uploads = Uploads;
8689
8692
 
8690
8693
  class OpenaiProvider {
8691
- constructor(apiKey, defaultModel, options) {
8694
+ constructor(param, defaultModel, options) {
8692
8695
  this.defaultModel = 'gpt-4o';
8693
8696
  if (defaultModel) {
8694
8697
  this.defaultModel = defaultModel;
8695
8698
  }
8696
- this.client = new OpenAI({
8697
- apiKey,
8698
- dangerouslyAllowBrowser: true,
8699
- ...options,
8700
- });
8699
+ if (typeof param == 'string') {
8700
+ this.client = new OpenAI({
8701
+ apiKey: param,
8702
+ dangerouslyAllowBrowser: true,
8703
+ ...options,
8704
+ });
8705
+ }
8706
+ else {
8707
+ this.client = new OpenAI(param);
8708
+ }
8701
8709
  }
8702
8710
  buildParams(messages, params, stream) {
8703
8711
  let tools = undefined;
@@ -8975,7 +8983,7 @@ const workflowSchema = {
8975
8983
  },
8976
8984
  action: {
8977
8985
  type: "object",
8978
- required: ["type", "name"],
8986
+ required: ["type", "name", "description"],
8979
8987
  properties: {
8980
8988
  type: {
8981
8989
  type: "string",
@@ -8983,6 +8991,7 @@ const workflowSchema = {
8983
8991
  enum: ["prompt"],
8984
8992
  },
8985
8993
  name: { type: "string" },
8994
+ description: { type: "string" },
8986
8995
  params: { type: "object" },
8987
8996
  tools: {
8988
8997
  type: "array",
@@ -9006,16 +9015,10 @@ class ToolRegistry {
9006
9015
  this.tools = new Map();
9007
9016
  }
9008
9017
  registerTool(tool) {
9009
- if (this.tools.has(tool.name)) {
9010
- throw new Error(`Tool with name ${tool.name} already registered`);
9011
- }
9012
9018
  this.tools.set(tool.name, tool);
9013
9019
  }
9014
9020
  unregisterTool(toolName) {
9015
- if (!this.tools.has(toolName)) {
9016
- throw new Error(`Tool with name ${toolName} not found`);
9017
- }
9018
- this.tools.delete(toolName);
9021
+ return this.tools.delete(toolName);
9019
9022
  }
9020
9023
  getTool(toolName) {
9021
9024
  const tool = this.tools.get(toolName);
@@ -9081,6 +9084,7 @@ class Eko {
9081
9084
  else {
9082
9085
  this.llmProvider = config;
9083
9086
  }
9087
+ Eko.tools.forEach((tool) => this.toolRegistry.registerTool(tool));
9084
9088
  }
9085
9089
  async generateWorkflow(prompt, param) {
9086
9090
  let toolRegistry = this.toolRegistry;
@@ -9107,6 +9111,9 @@ class Eko {
9107
9111
  if (this.toolRegistry.hasTools([toolName])) {
9108
9112
  tool = this.toolRegistry.getTool(toolName);
9109
9113
  }
9114
+ else if (Eko.tools.has(toolName)) {
9115
+ tool = Eko.tools.get(toolName);
9116
+ }
9110
9117
  else {
9111
9118
  throw new Error(`Tool with name ${toolName} not found`);
9112
9119
  }
@@ -9135,6 +9142,7 @@ class Eko {
9135
9142
  this.toolRegistry.unregisterTool(toolName);
9136
9143
  }
9137
9144
  }
9145
+ Eko.tools = new Map();
9138
9146
 
9139
9147
  class WorkflowParser {
9140
9148
  /**
@@ -9293,6 +9301,7 @@ class WorkflowParser {
9293
9301
  action: {
9294
9302
  type: nodeJson.action.type,
9295
9303
  name: nodeJson.action.name,
9304
+ description: nodeJson.action.description,
9296
9305
  tools: nodeJson.action.tools || [],
9297
9306
  execute: async (input, context) => {
9298
9307
  // Default implementation - should be overridden by specific action types
@@ -9323,6 +9332,7 @@ class WorkflowParser {
9323
9332
  action: {
9324
9333
  type: node.action.type,
9325
9334
  name: node.action.name,
9335
+ description: node.action.description,
9326
9336
  tools: node.action.tools,
9327
9337
  },
9328
9338
  })),