@eko-ai/eko 1.2.4 → 1.3.0

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.
@@ -0,0 +1,10 @@
1
+ import { Message } from "@/types";
2
+ export declare abstract class ContextComporessor {
3
+ abstract comporess(messages: Message[]): Message[];
4
+ }
5
+ export declare class NoComporess extends ContextComporessor {
6
+ comporess(messages: Message[]): Message[];
7
+ }
8
+ export declare class SimpleQAComporess extends ContextComporessor {
9
+ comporess(messages: Message[]): Message[];
10
+ }
@@ -696,7 +696,7 @@ async function getTabId(context) {
696
696
  }
697
697
  if (!tabId) {
698
698
  const fellouTabId = window.__FELLOU_TAB_ID__;
699
- if (tabId) {
699
+ if (fellouTabId) {
700
700
  tabId = fellouTabId;
701
701
  }
702
702
  else {
@@ -1227,6 +1227,9 @@ async function screenshot(chromeProxy, windowId, compress) {
1227
1227
  },
1228
1228
  };
1229
1229
  logger.debug('screenshot Got screenshot result:', result);
1230
+ if (!data || data.length < 30) {
1231
+ throw new Error('image error');
1232
+ }
1230
1233
  return result;
1231
1234
  }
1232
1235
  catch (e) {
@@ -1272,6 +1275,9 @@ async function compress_image(dataUrl, scale = 0.8, quality = 0.8) {
1272
1275
  logger.debug('Got compressed image result (sliced):', result.slice(0, 200));
1273
1276
  resolve(result);
1274
1277
  };
1278
+ reader.onerror = () => {
1279
+ resolve(dataUrl);
1280
+ };
1275
1281
  reader.readAsDataURL(blob);
1276
1282
  });
1277
1283
  }
@@ -694,7 +694,7 @@ async function getTabId(context) {
694
694
  }
695
695
  if (!tabId) {
696
696
  const fellouTabId = window.__FELLOU_TAB_ID__;
697
- if (tabId) {
697
+ if (fellouTabId) {
698
698
  tabId = fellouTabId;
699
699
  }
700
700
  else {
@@ -1225,6 +1225,9 @@ async function screenshot(chromeProxy, windowId, compress) {
1225
1225
  },
1226
1226
  };
1227
1227
  logger.debug('screenshot Got screenshot result:', result);
1228
+ if (!data || data.length < 30) {
1229
+ throw new Error('image error');
1230
+ }
1228
1231
  return result;
1229
1232
  }
1230
1233
  catch (e) {
@@ -1270,6 +1273,9 @@ async function compress_image(dataUrl, scale = 0.8, quality = 0.8) {
1270
1273
  logger.debug('Got compressed image result (sliced):', result.slice(0, 200));
1271
1274
  resolve(result);
1272
1275
  };
1276
+ reader.onerror = () => {
1277
+ resolve(dataUrl);
1278
+ };
1273
1279
  reader.readAsDataURL(blob);
1274
1280
  });
1275
1281
  }
package/dist/index.cjs.js CHANGED
@@ -10027,7 +10027,7 @@ ${JSON.stringify(nodeOutputs)}
10027
10027
  return {
10028
10028
  isSuccessful: contextVariables.get("__isSuccessful__"),
10029
10029
  summary: response.toolCalls[0].input.summary,
10030
- payload: response.toolCalls[0].input.document,
10030
+ payload: (response.toolCalls[0].input.isDocumentGenerationTask ? response.toolCalls[0].input.document : undefined),
10031
10031
  };
10032
10032
  }
10033
10033
 
@@ -10395,7 +10395,7 @@ class ActionImpl {
10395
10395
  // unwrap the toolCall
10396
10396
  let unwrapped = this.unwrapToolCall(toolCall);
10397
10397
  let input = unwrapped.toolCall.input;
10398
- logger.debug("unwrapped", unwrapped);
10398
+ logger.info("LLM Response:", unwrapped);
10399
10399
  if (unwrapped.thinking) {
10400
10400
  (_d = (_b = context.callback) === null || _b === void 0 ? void 0 : (_c = _b.hooks).onLlmMessage) === null || _d === void 0 ? void 0 : _d.call(_c, unwrapped.thinking);
10401
10401
  }
@@ -10585,9 +10585,11 @@ class ActionImpl {
10585
10585
  toolMap.set(returnTool.name, returnTool);
10586
10586
  // get already existing tabs as task background
10587
10587
  const currentWindow = await context.ekoConfig.chromeProxy.windows.getCurrent();
10588
- const existingTabs = await context.ekoConfig.chromeProxy.tabs.query({
10588
+ let existingTabs = await context.ekoConfig.chromeProxy.tabs.query({
10589
10589
  windowId: currentWindow.id,
10590
10590
  });
10591
+ existingTabs = existingTabs.filter((tab) => { tab.title && tab.url; });
10592
+ logger.debug("existingTabs:", existingTabs);
10591
10593
  // get patchs for task
10592
10594
  let patchs = [];
10593
10595
  if (context.ekoConfig.patchServerUrl) {
@@ -10830,6 +10832,18 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10830
10832
  // "type": "string",
10831
10833
  // "description": 'Your observation of the previous steps. Should start with "In the previous step, I\'ve ...".',
10832
10834
  // },
10835
+ evaluate_previous_goal: {
10836
+ "type": "string",
10837
+ "description": "Success|Failed|Unknown - Analyze the current elements and the image to check if the previous goals/actions are successful like intended by the task. Mention if something unexpected happened. Shortly state why/why not"
10838
+ },
10839
+ memory: {
10840
+ "type": "string",
10841
+ "description": "Description of what has been done and what you need to remember. Be very specific. Count here ALWAYS how many times you have done something and how many remain. E.g. 0 out of 10 websites analyzed. Continue with abc and xyz",
10842
+ },
10843
+ next_goal: {
10844
+ "type": "string",
10845
+ "description": "What needs to be done with the next immediate action",
10846
+ },
10833
10847
  thinking: {
10834
10848
  "type": "string",
10835
10849
  "description": 'Your thinking draft.',
@@ -10845,6 +10859,9 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10845
10859
  // "observation",
10846
10860
  "thinking",
10847
10861
  "userSidePrompt",
10862
+ "memory",
10863
+ "next_goal",
10864
+ "evaluate_previous_goal",
10848
10865
  "toolCall",
10849
10866
  ],
10850
10867
  };
@@ -10855,6 +10872,9 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10855
10872
  observation: toolCall.input.observation,
10856
10873
  thinking: toolCall.input.thinking,
10857
10874
  userSidePrompt: toolCall.input.userSidePrompt,
10875
+ evaluate_previous_goal: toolCall.input.evaluate_previous_goal,
10876
+ memory: toolCall.input.memory,
10877
+ next_goal: toolCall.input.next_goal,
10858
10878
  toolCall: {
10859
10879
  id: toolCall.id,
10860
10880
  name: toolCall.name,
@@ -10915,6 +10935,8 @@ class WorkflowGenerator {
10915
10935
  }
10916
10936
  async doGenerateWorkflow(prompt, modify, ekoConfig) {
10917
10937
  // Create prompts with current set of tools
10938
+ logger.debug("doGenerateWorkflow...");
10939
+ let retry_counter = 3;
10918
10940
  const prompts = createWorkflowPrompts(this.toolRegistry.getToolDefinitions());
10919
10941
  let messages = [];
10920
10942
  if (modify) {
@@ -10942,41 +10964,38 @@ class WorkflowGenerator {
10942
10964
  tools: [createWorkflowGenerationTool(this.toolRegistry)],
10943
10965
  toolChoice: { type: 'tool', name: 'generate_workflow' },
10944
10966
  };
10945
- console.time('Workflow Generation Time'); // 开始计时
10946
- const response = await this.llmProvider.generateText(messages, params);
10947
- console.timeEnd('Workflow Generation Time'); // 结束计时并输出时间差
10948
- if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
10949
- messages.pop();
10950
- throw new Error('Failed to generate workflow: Invalid response from LLM');
10951
- }
10952
- messages.push({
10953
- role: 'assistant',
10954
- content: [
10955
- {
10956
- type: 'tool_use',
10957
- id: response.toolCalls[0].id,
10958
- name: response.toolCalls[0].name,
10959
- input: response.toolCalls[0].input,
10960
- },
10961
- ],
10962
- }, {
10963
- role: 'user',
10964
- content: [
10965
- {
10966
- type: 'tool_result',
10967
- tool_use_id: response.toolCalls[0].id,
10968
- content: 'ok',
10969
- },
10970
- ],
10971
- });
10972
- const workflowData = response.toolCalls[0].input.workflow;
10973
- // debug
10974
- logger.debug("Debug the workflow...", { ...workflowData });
10975
- // Generate a new UUID if not provided
10976
- if (!workflowData.id) {
10977
- workflowData.id = uuid.v4();
10967
+ while (retry_counter > 0) {
10968
+ try {
10969
+ console.time('Workflow Generation Time'); // 开始计时
10970
+ const response = await this.llmProvider.generateText(messages, params);
10971
+ console.timeEnd('Workflow Generation Time'); // 结束计时并输出时间差
10972
+ logger.debug("generateText() done!");
10973
+ if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
10974
+ messages.pop();
10975
+ throw new Error('Failed to generate workflow: Invalid response from LLM');
10976
+ }
10977
+ let workflowData = response.toolCalls[0].input.workflow;
10978
+ // debug
10979
+ if (typeof workflowData == "string") {
10980
+ logger.warn("workflowData is string, try to transform it into object...");
10981
+ logger.debug("workflowData string:", workflowData);
10982
+ workflowData = JSON.parse(workflowData);
10983
+ }
10984
+ logger.debug("Debug the workflow...", { ...workflowData });
10985
+ // Generate a new UUID if not provided
10986
+ if (!workflowData.id) {
10987
+ workflowData.id = uuid.v4();
10988
+ }
10989
+ return this.createFastWorkflowFromData(workflowData, ekoConfig);
10990
+ }
10991
+ catch (e) {
10992
+ logger.warn("an error occured when generating workflow:", e);
10993
+ logger.info(`retry...${retry_counter}`);
10994
+ retry_counter -= 1;
10995
+ }
10978
10996
  }
10979
- return this.createFastWorkflowFromData(workflowData, ekoConfig);
10997
+ logger.error("cannot generate workflow with retry");
10998
+ throw Error("many errors occured when generating workflow");
10980
10999
  }
10981
11000
  createWorkflowFromData(data, ekoConfig) {
10982
11001
  const workflow = new WorkflowImpl(data.id, data.name, ekoConfig, data, data.description || '', [], new Map(Object.entries(data.variables || {})), this.llmProvider, {
@@ -11046,44 +11065,23 @@ const workflowSchema = {
11046
11065
  type: "array",
11047
11066
  items: {
11048
11067
  type: "object",
11049
- required: ["id", "type", "action"],
11068
+ required: ["id", "action"],
11050
11069
  properties: {
11051
11070
  id: { type: "string" },
11052
- type: {
11053
- type: "string",
11054
- enum: ["action"], // only action nodes for now; reserved for future types like condition, loop, etc.
11055
- },
11056
- dependencies: {
11057
- type: "array",
11058
- items: { type: "string" },
11059
- },
11060
- output: {
11061
- type: "object",
11062
- properties: {
11063
- name: { type: "string" },
11064
- description: { type: "string" },
11065
- },
11066
- },
11067
11071
  action: {
11068
11072
  type: "object",
11069
- required: ["type", "name", "description"],
11073
+ required: ["name", "description"],
11070
11074
  properties: {
11071
- type: {
11075
+ name: { type: "string" },
11076
+ description: {
11072
11077
  type: "string",
11073
- // enum: ["prompt", "script", "hybrid"],
11074
- enum: ["prompt"],
11078
+ description: "Note that do not use \" mark.",
11075
11079
  },
11076
- name: { type: "string" },
11077
- description: { type: "string" },
11078
11080
  },
11079
11081
  },
11080
11082
  },
11081
11083
  },
11082
11084
  },
11083
- variables: {
11084
- type: "object",
11085
- additionalProperties: true,
11086
- },
11087
11085
  },
11088
11086
  };
11089
11087
 
@@ -11146,7 +11144,7 @@ class Eko {
11146
11144
  this.llmProvider = LLMProviderFactory.buildLLMProvider(llmConfig);
11147
11145
  this.ekoConfig = this.buildEkoConfig(ekoConfig);
11148
11146
  this.registerTools();
11149
- logger.info("using Eko@" + "0b8135fc46d59eb59eb56c57564e2db06526249b");
11147
+ logger.info("using Eko@" + "416349eaa1535085d74b14170d4e0741756da46f");
11150
11148
  logger.debug("caller's ekoConfig:", ekoConfig);
11151
11149
  }
11152
11150
  static getLogger() {
package/dist/index.esm.js CHANGED
@@ -10023,7 +10023,7 @@ ${JSON.stringify(nodeOutputs)}
10023
10023
  return {
10024
10024
  isSuccessful: contextVariables.get("__isSuccessful__"),
10025
10025
  summary: response.toolCalls[0].input.summary,
10026
- payload: response.toolCalls[0].input.document,
10026
+ payload: (response.toolCalls[0].input.isDocumentGenerationTask ? response.toolCalls[0].input.document : undefined),
10027
10027
  };
10028
10028
  }
10029
10029
 
@@ -10391,7 +10391,7 @@ class ActionImpl {
10391
10391
  // unwrap the toolCall
10392
10392
  let unwrapped = this.unwrapToolCall(toolCall);
10393
10393
  let input = unwrapped.toolCall.input;
10394
- logger.debug("unwrapped", unwrapped);
10394
+ logger.info("LLM Response:", unwrapped);
10395
10395
  if (unwrapped.thinking) {
10396
10396
  (_d = (_b = context.callback) === null || _b === void 0 ? void 0 : (_c = _b.hooks).onLlmMessage) === null || _d === void 0 ? void 0 : _d.call(_c, unwrapped.thinking);
10397
10397
  }
@@ -10581,9 +10581,11 @@ class ActionImpl {
10581
10581
  toolMap.set(returnTool.name, returnTool);
10582
10582
  // get already existing tabs as task background
10583
10583
  const currentWindow = await context.ekoConfig.chromeProxy.windows.getCurrent();
10584
- const existingTabs = await context.ekoConfig.chromeProxy.tabs.query({
10584
+ let existingTabs = await context.ekoConfig.chromeProxy.tabs.query({
10585
10585
  windowId: currentWindow.id,
10586
10586
  });
10587
+ existingTabs = existingTabs.filter((tab) => { tab.title && tab.url; });
10588
+ logger.debug("existingTabs:", existingTabs);
10587
10589
  // get patchs for task
10588
10590
  let patchs = [];
10589
10591
  if (context.ekoConfig.patchServerUrl) {
@@ -10826,6 +10828,18 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10826
10828
  // "type": "string",
10827
10829
  // "description": 'Your observation of the previous steps. Should start with "In the previous step, I\'ve ...".',
10828
10830
  // },
10831
+ evaluate_previous_goal: {
10832
+ "type": "string",
10833
+ "description": "Success|Failed|Unknown - Analyze the current elements and the image to check if the previous goals/actions are successful like intended by the task. Mention if something unexpected happened. Shortly state why/why not"
10834
+ },
10835
+ memory: {
10836
+ "type": "string",
10837
+ "description": "Description of what has been done and what you need to remember. Be very specific. Count here ALWAYS how many times you have done something and how many remain. E.g. 0 out of 10 websites analyzed. Continue with abc and xyz",
10838
+ },
10839
+ next_goal: {
10840
+ "type": "string",
10841
+ "description": "What needs to be done with the next immediate action",
10842
+ },
10829
10843
  thinking: {
10830
10844
  "type": "string",
10831
10845
  "description": 'Your thinking draft.',
@@ -10841,6 +10855,9 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10841
10855
  // "observation",
10842
10856
  "thinking",
10843
10857
  "userSidePrompt",
10858
+ "memory",
10859
+ "next_goal",
10860
+ "evaluate_previous_goal",
10844
10861
  "toolCall",
10845
10862
  ],
10846
10863
  };
@@ -10851,6 +10868,9 @@ Navigation Bar or Menu Changes: After logging in, the navigation bar will includ
10851
10868
  observation: toolCall.input.observation,
10852
10869
  thinking: toolCall.input.thinking,
10853
10870
  userSidePrompt: toolCall.input.userSidePrompt,
10871
+ evaluate_previous_goal: toolCall.input.evaluate_previous_goal,
10872
+ memory: toolCall.input.memory,
10873
+ next_goal: toolCall.input.next_goal,
10854
10874
  toolCall: {
10855
10875
  id: toolCall.id,
10856
10876
  name: toolCall.name,
@@ -10911,6 +10931,8 @@ class WorkflowGenerator {
10911
10931
  }
10912
10932
  async doGenerateWorkflow(prompt, modify, ekoConfig) {
10913
10933
  // Create prompts with current set of tools
10934
+ logger.debug("doGenerateWorkflow...");
10935
+ let retry_counter = 3;
10914
10936
  const prompts = createWorkflowPrompts(this.toolRegistry.getToolDefinitions());
10915
10937
  let messages = [];
10916
10938
  if (modify) {
@@ -10938,41 +10960,38 @@ class WorkflowGenerator {
10938
10960
  tools: [createWorkflowGenerationTool(this.toolRegistry)],
10939
10961
  toolChoice: { type: 'tool', name: 'generate_workflow' },
10940
10962
  };
10941
- console.time('Workflow Generation Time'); // 开始计时
10942
- const response = await this.llmProvider.generateText(messages, params);
10943
- console.timeEnd('Workflow Generation Time'); // 结束计时并输出时间差
10944
- if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
10945
- messages.pop();
10946
- throw new Error('Failed to generate workflow: Invalid response from LLM');
10947
- }
10948
- messages.push({
10949
- role: 'assistant',
10950
- content: [
10951
- {
10952
- type: 'tool_use',
10953
- id: response.toolCalls[0].id,
10954
- name: response.toolCalls[0].name,
10955
- input: response.toolCalls[0].input,
10956
- },
10957
- ],
10958
- }, {
10959
- role: 'user',
10960
- content: [
10961
- {
10962
- type: 'tool_result',
10963
- tool_use_id: response.toolCalls[0].id,
10964
- content: 'ok',
10965
- },
10966
- ],
10967
- });
10968
- const workflowData = response.toolCalls[0].input.workflow;
10969
- // debug
10970
- logger.debug("Debug the workflow...", { ...workflowData });
10971
- // Generate a new UUID if not provided
10972
- if (!workflowData.id) {
10973
- workflowData.id = v4();
10963
+ while (retry_counter > 0) {
10964
+ try {
10965
+ console.time('Workflow Generation Time'); // 开始计时
10966
+ const response = await this.llmProvider.generateText(messages, params);
10967
+ console.timeEnd('Workflow Generation Time'); // 结束计时并输出时间差
10968
+ logger.debug("generateText() done!");
10969
+ if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
10970
+ messages.pop();
10971
+ throw new Error('Failed to generate workflow: Invalid response from LLM');
10972
+ }
10973
+ let workflowData = response.toolCalls[0].input.workflow;
10974
+ // debug
10975
+ if (typeof workflowData == "string") {
10976
+ logger.warn("workflowData is string, try to transform it into object...");
10977
+ logger.debug("workflowData string:", workflowData);
10978
+ workflowData = JSON.parse(workflowData);
10979
+ }
10980
+ logger.debug("Debug the workflow...", { ...workflowData });
10981
+ // Generate a new UUID if not provided
10982
+ if (!workflowData.id) {
10983
+ workflowData.id = v4();
10984
+ }
10985
+ return this.createFastWorkflowFromData(workflowData, ekoConfig);
10986
+ }
10987
+ catch (e) {
10988
+ logger.warn("an error occured when generating workflow:", e);
10989
+ logger.info(`retry...${retry_counter}`);
10990
+ retry_counter -= 1;
10991
+ }
10974
10992
  }
10975
- return this.createFastWorkflowFromData(workflowData, ekoConfig);
10993
+ logger.error("cannot generate workflow with retry");
10994
+ throw Error("many errors occured when generating workflow");
10976
10995
  }
10977
10996
  createWorkflowFromData(data, ekoConfig) {
10978
10997
  const workflow = new WorkflowImpl(data.id, data.name, ekoConfig, data, data.description || '', [], new Map(Object.entries(data.variables || {})), this.llmProvider, {
@@ -11042,44 +11061,23 @@ const workflowSchema = {
11042
11061
  type: "array",
11043
11062
  items: {
11044
11063
  type: "object",
11045
- required: ["id", "type", "action"],
11064
+ required: ["id", "action"],
11046
11065
  properties: {
11047
11066
  id: { type: "string" },
11048
- type: {
11049
- type: "string",
11050
- enum: ["action"], // only action nodes for now; reserved for future types like condition, loop, etc.
11051
- },
11052
- dependencies: {
11053
- type: "array",
11054
- items: { type: "string" },
11055
- },
11056
- output: {
11057
- type: "object",
11058
- properties: {
11059
- name: { type: "string" },
11060
- description: { type: "string" },
11061
- },
11062
- },
11063
11067
  action: {
11064
11068
  type: "object",
11065
- required: ["type", "name", "description"],
11069
+ required: ["name", "description"],
11066
11070
  properties: {
11067
- type: {
11071
+ name: { type: "string" },
11072
+ description: {
11068
11073
  type: "string",
11069
- // enum: ["prompt", "script", "hybrid"],
11070
- enum: ["prompt"],
11074
+ description: "Note that do not use \" mark.",
11071
11075
  },
11072
- name: { type: "string" },
11073
- description: { type: "string" },
11074
11076
  },
11075
11077
  },
11076
11078
  },
11077
11079
  },
11078
11080
  },
11079
- variables: {
11080
- type: "object",
11081
- additionalProperties: true,
11082
- },
11083
11081
  },
11084
11082
  };
11085
11083
 
@@ -11142,7 +11140,7 @@ class Eko {
11142
11140
  this.llmProvider = LLMProviderFactory.buildLLMProvider(llmConfig);
11143
11141
  this.ekoConfig = this.buildEkoConfig(ekoConfig);
11144
11142
  this.registerTools();
11145
- logger.info("using Eko@" + "0b8135fc46d59eb59eb56c57564e2db06526249b");
11143
+ logger.info("using Eko@" + "416349eaa1535085d74b14170d4e0741756da46f");
11146
11144
  logger.debug("caller's ekoConfig:", ekoConfig);
11147
11145
  }
11148
11146
  static getLogger() {
@@ -24,49 +24,21 @@ export declare const workflowSchema: {
24
24
  id: {
25
25
  type: string;
26
26
  };
27
- type: {
28
- type: string;
29
- enum: string[];
30
- };
31
- dependencies: {
32
- type: string;
33
- items: {
34
- type: string;
35
- };
36
- };
37
- output: {
38
- type: string;
39
- properties: {
40
- name: {
41
- type: string;
42
- };
43
- description: {
44
- type: string;
45
- };
46
- };
47
- };
48
27
  action: {
49
28
  type: string;
50
29
  required: string[];
51
30
  properties: {
52
- type: {
53
- type: string;
54
- enum: string[];
55
- };
56
31
  name: {
57
32
  type: string;
58
33
  };
59
34
  description: {
60
35
  type: string;
36
+ description: string;
61
37
  };
62
38
  };
63
39
  };
64
40
  };
65
41
  };
66
42
  };
67
- variables: {
68
- type: string;
69
- additionalProperties: boolean;
70
- };
71
43
  };
72
44
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eko-ai/eko",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "Empowering language to transform human words into action.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",