@eko-ai/eko 3.0.0 → 3.0.1-alpha.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.
package/dist/index.esm.js CHANGED
@@ -10,6 +10,8 @@ const config$1 = {
10
10
  fileTextMaxLength: 20000,
11
11
  maxDialogueImgFileNum: 1,
12
12
  toolResultMultimodal: true,
13
+ expertMode: false,
14
+ expertModeTodoLoopNum: 10,
13
15
  };
14
16
 
15
17
  var LogLevel;
@@ -30811,10 +30813,10 @@ ${agents.join("\n")}
30811
30813
  workflow.xml = xml;
30812
30814
  }
30813
30815
 
30814
- const TOOL_NAME$8 = "task_snapshot";
30816
+ const TOOL_NAME$a = "task_snapshot";
30815
30817
  class TaskSnapshotTool {
30816
30818
  constructor() {
30817
- this.name = TOOL_NAME$8;
30819
+ this.name = TOOL_NAME$a;
30818
30820
  this.description = `Task snapshot archive, recording key information of the current task, updating task node status, facilitating subsequent continuation of operation.`;
30819
30821
  this.parameters = {
30820
30822
  type: "object",
@@ -30907,7 +30909,7 @@ async function compressAgentMessages(agentContext, rlm, messages, tools) {
30907
30909
  return;
30908
30910
  }
30909
30911
  try {
30910
- doCompressAgentMessages(agentContext, rlm, messages, tools);
30912
+ await doCompressAgentMessages(agentContext, rlm, messages, tools);
30911
30913
  }
30912
30914
  catch (e) {
30913
30915
  Log.error("Error compressing agent messages:", e);
@@ -30915,9 +30917,9 @@ async function compressAgentMessages(agentContext, rlm, messages, tools) {
30915
30917
  }
30916
30918
  async function doCompressAgentMessages(agentContext, rlm, messages, tools) {
30917
30919
  // extract used tool
30918
- let usedTools = extractUsedTool(messages, tools);
30919
- let snapshotTool = new TaskSnapshotTool();
30920
- let newTools = mergeTools(usedTools, [
30920
+ const usedTools = extractUsedTool(messages, tools);
30921
+ const snapshotTool = new TaskSnapshotTool();
30922
+ const newTools = mergeTools(usedTools, [
30921
30923
  {
30922
30924
  type: "function",
30923
30925
  name: snapshotTool.name,
@@ -30945,16 +30947,16 @@ async function doCompressAgentMessages(agentContext, rlm, messages, tools) {
30945
30947
  ],
30946
30948
  });
30947
30949
  // compress snapshot
30948
- let result = await callAgentLLM(agentContext, rlm, newMessages, newTools, true, {
30950
+ const result = await callAgentLLM(agentContext, rlm, newMessages, newTools, true, {
30949
30951
  type: "tool",
30950
30952
  toolName: snapshotTool.name,
30951
30953
  });
30952
- let toolCall = result.filter((s) => s.type == "tool-call")[0];
30953
- let args = typeof toolCall.input == "string"
30954
+ const toolCall = result.filter((s) => s.type == "tool-call")[0];
30955
+ const args = typeof toolCall.input == "string"
30954
30956
  ? JSON.parse(toolCall.input || "{}")
30955
30957
  : toolCall.input || {};
30956
- let toolResult = await snapshotTool.execute(args, agentContext);
30957
- let callback = agentContext.context.config.callback;
30958
+ const toolResult = await snapshotTool.execute(args, agentContext);
30959
+ const callback = agentContext.context.config.callback;
30958
30960
  if (callback) {
30959
30961
  await callback.onMessage({
30960
30962
  taskId: agentContext.context.taskId,
@@ -33187,10 +33189,10 @@ function convertUserContent(content) {
33187
33189
  });
33188
33190
  }
33189
33191
 
33190
- const TOOL_NAME$7 = "taskPlanner";
33192
+ const TOOL_NAME$9 = "taskPlanner";
33191
33193
  class TaskPlannerTool {
33192
33194
  constructor(ekoDialogue, params) {
33193
- this.name = TOOL_NAME$7;
33195
+ this.name = TOOL_NAME$9;
33194
33196
  const agents = ekoDialogue.getConfig().agents || [];
33195
33197
  const agentNames = agents.map((agent) => agent.Name).join(", ");
33196
33198
  this.description = `Used for task planning, this tool is only responsible for generating task plans, not executing them, the following agents are available: ${agentNames}...`;
@@ -33256,17 +33258,17 @@ class TaskPlannerTool {
33256
33258
  }
33257
33259
  }
33258
33260
 
33259
- const TOOL_NAME$6 = "executeTask";
33261
+ const TOOL_NAME$8 = "executeTask";
33260
33262
  class ExecuteTaskTool {
33261
33263
  constructor(ekoDialogue) {
33262
- this.name = TOOL_NAME$6;
33263
- this.description = `Responsible for executing the task plan generated by the ${TOOL_NAME$7}. Use this tool if you need to execute planned tasks.`;
33264
+ this.name = TOOL_NAME$8;
33265
+ this.description = `Responsible for executing the task plan generated by the ${TOOL_NAME$9}. Use this tool if you need to execute planned tasks.`;
33264
33266
  this.parameters = {
33265
33267
  type: "object",
33266
33268
  properties: {
33267
33269
  taskId: {
33268
33270
  type: "string",
33269
- description: `Task ID, generated by the \`${TOOL_NAME$7}\` tool.`,
33271
+ description: `Task ID, generated by the \`${TOOL_NAME$9}\` tool.`,
33270
33272
  },
33271
33273
  },
33272
33274
  required: ["taskId"],
@@ -33331,10 +33333,10 @@ class ExecuteTaskTool {
33331
33333
  }
33332
33334
  }
33333
33335
 
33334
- const TOOL_NAME$5 = "taskVariableStorage";
33336
+ const TOOL_NAME$7 = "taskVariableStorage";
33335
33337
  class TaskVariableStorageTool {
33336
33338
  constructor(ekoDialogue) {
33337
- this.name = TOOL_NAME$5;
33339
+ this.name = TOOL_NAME$7;
33338
33340
  this.description = `Used for storing, reading, and retrieving variable data, and maintaining input/output variables in task nodes.`;
33339
33341
  this.parameters = {
33340
33342
  type: "object",
@@ -33413,9 +33415,9 @@ You are {name}, a helpful AI assistant.
33413
33415
 
33414
33416
  # Tool Usage Instructions
33415
33417
  For non-chat related tasks issued by users, the following tools need to be called to complete them:
33416
- - ${TOOL_NAME$7}: This tool is used to plan tasks and generate task execution plans. For action tasks, this tool needs to be called for planning, then handed over to the \`${TOOL_NAME$6}\` tool for execution.
33417
- - ${TOOL_NAME$6}: This tool is used to execute tasks planned by the \`${TOOL_NAME$7}\` tool.
33418
- - ${TOOL_NAME$5}: This tool is used to read output variables from task nodes and write input variables to task nodes, mainly used to retrieve variable results after task execution is completed.
33418
+ - ${TOOL_NAME$9}: This tool is used to plan tasks and generate task execution plans. For action tasks, this tool needs to be called for planning, then handed over to the \`${TOOL_NAME$8}\` tool for execution.
33419
+ - ${TOOL_NAME$8}: This tool is used to execute tasks planned by the \`${TOOL_NAME$9}\` tool.
33420
+ - ${TOOL_NAME$7}: This tool is used to read output variables from task nodes and write input variables to task nodes, mainly used to retrieve variable results after task execution is completed.
33419
33421
  {prompt}
33420
33422
 
33421
33423
  The output language should match the user's conversation language.
@@ -33444,7 +33446,7 @@ class EkoDialogue {
33444
33446
  const messages = this.memory.getMessages();
33445
33447
  const lastMessage = messages[messages.length - 1];
33446
33448
  if (lastMessage.role !== "tool" ||
33447
- !lastMessage.content.some((part) => part.toolName === TOOL_NAME$7)) {
33449
+ !lastMessage.content.some((part) => part.toolName === TOOL_NAME$9)) {
33448
33450
  throw new Error("No task planner tool call found");
33449
33451
  }
33450
33452
  const userMessages = messages.filter((message) => message.role === "user");
@@ -33475,7 +33477,7 @@ class EkoDialogue {
33475
33477
  return finalResult;
33476
33478
  }
33477
33479
  if (this.config.segmentedExecution &&
33478
- results.some((r) => r.type == "tool-call" && r.toolName == TOOL_NAME$7)) {
33480
+ results.some((r) => r.type == "tool-call" && r.toolName == TOOL_NAME$9)) {
33479
33481
  return "segmentedExecution";
33480
33482
  }
33481
33483
  }
@@ -33673,11 +33675,23 @@ class SimpleSseMcpClient {
33673
33675
  version: "1.0.0",
33674
33676
  },
33675
33677
  });
33676
- this.request("notifications/initialized", {});
33678
+ // this.request("notifications/initialized", {});
33677
33679
  }
33678
33680
  ping() {
33679
33681
  this.request("ping", {});
33680
33682
  }
33683
+ async listTools(param, signal) {
33684
+ const message = await this.request("tools/list", {
33685
+ ...param,
33686
+ }, signal);
33687
+ return message.result.tools || [];
33688
+ }
33689
+ async callTool(param, signal) {
33690
+ const message = await this.request("tools/call", {
33691
+ ...param,
33692
+ }, signal);
33693
+ return message.result;
33694
+ }
33681
33695
  async request(method, params, signal) {
33682
33696
  const id = uuidv4();
33683
33697
  try {
@@ -33710,36 +33724,35 @@ class SimpleSseMcpClient {
33710
33724
  });
33711
33725
  const body = await response.text();
33712
33726
  if (body == "Accepted") {
33713
- return await callback;
33727
+ const message = await callback;
33728
+ if (message.error) {
33729
+ Log.error(`MCP ${method} error: ` + message.error);
33730
+ throw new Error(`MCP ${method} error: ` +
33731
+ (typeof message.error === "string"
33732
+ ? message.error
33733
+ : message.error.message));
33734
+ }
33735
+ if (message.result?.isError == true) {
33736
+ if (message.result.content) {
33737
+ throw new Error(`MCP ${method} error: ` +
33738
+ (typeof message.result.content === "string"
33739
+ ? message.result.content
33740
+ : message.result.content[0].text));
33741
+ }
33742
+ else {
33743
+ throw new Error(`MCP ${method} error: ` + JSON.stringify(message.result));
33744
+ }
33745
+ }
33746
+ return message;
33714
33747
  }
33715
33748
  else {
33716
- throw new Error("SseClient Response Exception: " + body);
33749
+ throw new Error(`MCP ${method} error:` + body);
33717
33750
  }
33718
33751
  }
33719
33752
  finally {
33720
33753
  this.requestMap.delete(id);
33721
33754
  }
33722
33755
  }
33723
- async listTools(param, signal) {
33724
- const message = await this.request("tools/list", {
33725
- ...param,
33726
- }, signal);
33727
- if (message.error) {
33728
- Log.error("McpClient listTools error: ", param, message);
33729
- throw new Error("listTools Exception");
33730
- }
33731
- return message.result.tools || [];
33732
- }
33733
- async callTool(param, signal) {
33734
- const message = await this.request("tools/call", {
33735
- ...param,
33736
- }, signal);
33737
- if (message.error) {
33738
- Log.error("McpClient callTool error: ", param, message);
33739
- throw new Error("callTool Exception");
33740
- }
33741
- return message.result;
33742
- }
33743
33756
  isConnected() {
33744
33757
  if (this.sseHandler && this.sseHandler.readyState == 1) {
33745
33758
  return true;
@@ -33865,20 +33878,12 @@ class SimpleHttpMcpClient {
33865
33878
  const message = await this.request("tools/list", {
33866
33879
  ...param,
33867
33880
  }, signal);
33868
- if (message.error) {
33869
- Log.error("McpClient listTools error: ", param, message);
33870
- throw new Error("listTools Exception");
33871
- }
33872
33881
  return message.result.tools || [];
33873
33882
  }
33874
33883
  async callTool(param, signal) {
33875
33884
  const message = await this.request("tools/call", {
33876
33885
  ...param,
33877
33886
  }, signal);
33878
- if (message.error) {
33879
- Log.error("McpClient callTool error: ", param, message);
33880
- throw new Error("callTool Exception");
33881
- }
33882
33887
  return message.result;
33883
33888
  }
33884
33889
  isConnected() {
@@ -33906,7 +33911,7 @@ class SimpleHttpMcpClient {
33906
33911
  headers: {
33907
33912
  "Cache-Control": "no-cache",
33908
33913
  "Content-Type": "application/json",
33909
- "Accept": "application/json, text/event-stream",
33914
+ Accept: "application/json, text/event-stream",
33910
33915
  "MCP-Protocol-Version": this.protocolVersion,
33911
33916
  ...extHeaders,
33912
33917
  ...this.headers,
@@ -33958,11 +33963,13 @@ class SimpleHttpMcpClient {
33958
33963
  str = chunks[chunks.length - 1];
33959
33964
  }
33960
33965
  }
33966
+ this.handleError(method, message);
33961
33967
  return message;
33962
33968
  }
33963
33969
  else {
33964
33970
  // JSON
33965
33971
  const message = await response.json();
33972
+ this.handleError(method, message);
33966
33973
  return message;
33967
33974
  }
33968
33975
  }
@@ -33973,6 +33980,29 @@ class SimpleHttpMcpClient {
33973
33980
  throw e;
33974
33981
  }
33975
33982
  }
33983
+ handleError(method, message) {
33984
+ if (!message) {
33985
+ throw new Error(`MCP ${method} error: no response`);
33986
+ }
33987
+ if (message?.error) {
33988
+ Log.error(`MCP ${method} error: ` + message.error);
33989
+ throw new Error(`MCP ${method} error: ` +
33990
+ (typeof message.error === "string"
33991
+ ? message.error
33992
+ : message.error.message));
33993
+ }
33994
+ if (message.result?.isError == true) {
33995
+ if (message.result.content) {
33996
+ throw new Error(`MCP ${method} error: ` +
33997
+ (typeof message.result.content === "string"
33998
+ ? message.result.content
33999
+ : message.result.content[0].text));
34000
+ }
34001
+ else {
34002
+ throw new Error(`MCP ${method} error: ` + JSON.stringify(message.result));
34003
+ }
34004
+ }
34005
+ }
33976
34006
  parseChunk(chunk) {
33977
34007
  const lines = chunk.split("\n");
33978
34008
  const chunk_obj = {};
@@ -34014,10 +34044,10 @@ class ToolWrapper {
34014
34044
  }
34015
34045
  }
34016
34046
 
34017
- const TOOL_NAME$4 = "foreach_task";
34047
+ const TOOL_NAME$6 = "foreach_task";
34018
34048
  class ForeachTaskTool {
34019
34049
  constructor() {
34020
- this.name = TOOL_NAME$4;
34050
+ this.name = TOOL_NAME$6;
34021
34051
  this.description = `When executing the \`forEach\` node, please use the current tool for counting to ensure tasks are executed sequentially, the tool needs to be called with each loop iteration.`;
34022
34052
  this.parameters = {
34023
34053
  type: "object",
@@ -34073,10 +34103,10 @@ class ForeachTaskTool {
34073
34103
  }
34074
34104
  }
34075
34105
 
34076
- const TOOL_NAME$3 = "human_interact";
34106
+ const TOOL_NAME$5 = "human_interact";
34077
34107
  class HumanInteractTool {
34078
34108
  constructor() {
34079
- this.name = TOOL_NAME$3;
34109
+ this.name = TOOL_NAME$5;
34080
34110
  this.noPlan = true;
34081
34111
  this.description = `AI interacts with humans:
34082
34112
  confirm: Ask the user to confirm whether to execute an operation, especially when performing dangerous actions such as deleting system files, users will choose Yes or No.
@@ -34212,10 +34242,10 @@ request_help: Request assistance from the user; for instance, when an operation
34212
34242
  }
34213
34243
  }
34214
34244
 
34215
- const TOOL_NAME$2 = "task_node_status";
34245
+ const TOOL_NAME$4 = "task_node_status";
34216
34246
  class TaskNodeStatusTool {
34217
34247
  constructor() {
34218
- this.name = TOOL_NAME$2;
34248
+ this.name = TOOL_NAME$4;
34219
34249
  this.description = `After completing each step of the task, you need to call this tool to update the status of the task node, and think about the tasks to be processed and the next action plan.`;
34220
34250
  this.parameters = {
34221
34251
  type: "object",
@@ -34267,11 +34297,11 @@ class TaskNodeStatusTool {
34267
34297
  }
34268
34298
  }
34269
34299
 
34270
- const TOOL_NAME$1 = "variable_storage";
34300
+ const TOOL_NAME$3 = "variable_storage";
34271
34301
  class VariableStorageTool {
34272
34302
  constructor() {
34273
- this.name = TOOL_NAME$1;
34274
- this.description = `Used for storing, reading, and retrieving variable data, and maintaining input/output variables in task nodes.`;
34303
+ this.name = TOOL_NAME$3;
34304
+ this.description = `Used for storing, reading, and retrieving variable data, and maintaining input/output variables in task nodes. When the same variable is stored repeatedly, it will overwrite the previous value.`;
34275
34305
  this.parameters = {
34276
34306
  type: "object",
34277
34307
  properties: {
@@ -34343,7 +34373,7 @@ class VariableStorageTool {
34343
34373
  }
34344
34374
  }
34345
34375
 
34346
- const TOOL_NAME = "watch_trigger";
34376
+ const TOOL_NAME$2 = "watch_trigger";
34347
34377
  const watch_system_prompt = `You are a tool for detecting element changes. Given a task description, compare two images to determine whether the changes described in the task have occurred.
34348
34378
  If the changes have occurred, return an json with \`changed\` set to true and \`changeInfo\` containing a description of the changes. If no changes have occurred, return an object with \`changed\` set to false.
34349
34379
 
@@ -34362,7 +34392,7 @@ Output:
34362
34392
  }`;
34363
34393
  class WatchTriggerTool {
34364
34394
  constructor() {
34365
- this.name = TOOL_NAME;
34395
+ this.name = TOOL_NAME$2;
34366
34396
  this.description = `When executing the \`watch\` node, please use it to monitor DOM element changes, it will block the listener until the element changes or times out.`;
34367
34397
  this.parameters = {
34368
34398
  type: "object",
@@ -34563,6 +34593,111 @@ class McpTool {
34563
34593
  }
34564
34594
  }
34565
34595
 
34596
+ const TOOL_NAME$1 = "task_result_check";
34597
+ class TaskResultCheckTool {
34598
+ constructor() {
34599
+ this.name = TOOL_NAME$1;
34600
+ this.description = `Check the current task execution process and results, evaluate the overall completion status of the current task, and whether the output variables in the nodes are stored.`;
34601
+ this.parameters = {
34602
+ type: "object",
34603
+ properties: {
34604
+ thought: {
34605
+ type: "string",
34606
+ description: "Please conduct thoughtful analysis of the overall execution process and results of the current task, analyzing whether the task has been completed.",
34607
+ },
34608
+ completionStatus: {
34609
+ type: "string",
34610
+ description: "The completion status of the current task is only considered complete when the entire current task is finished; partial completion or task failure is considered incomplete",
34611
+ enum: ["completed", "incomplete"],
34612
+ },
34613
+ todoList: {
34614
+ type: "string",
34615
+ description: "Pending task list for incomplete tasks, when tasks are not fully completed, please describe which tasks remain to be completed",
34616
+ },
34617
+ },
34618
+ required: ["thought", "completionStatus"],
34619
+ };
34620
+ }
34621
+ async execute(args, agentContext) {
34622
+ return {
34623
+ content: [
34624
+ {
34625
+ type: "text",
34626
+ text: "success",
34627
+ },
34628
+ ],
34629
+ };
34630
+ }
34631
+ }
34632
+ async function doTaskResultCheck(agentContext, rlm, messages, tools) {
34633
+ try {
34634
+ // extract used tool
34635
+ const usedTools = extractUsedTool(messages, tools);
34636
+ const taskResultCheck = new TaskResultCheckTool();
34637
+ const newTools = mergeTools(usedTools, [
34638
+ {
34639
+ type: "function",
34640
+ name: taskResultCheck.name,
34641
+ description: taskResultCheck.description,
34642
+ inputSchema: taskResultCheck.parameters,
34643
+ },
34644
+ ]);
34645
+ // handle messages
34646
+ const newMessages = [...messages];
34647
+ newMessages.push({
34648
+ role: "user",
34649
+ content: [
34650
+ {
34651
+ type: "text",
34652
+ text: `Task:\n${agentContext.agentChain.agent.xml}\n\nPlease check the completion status of the current task.`,
34653
+ },
34654
+ ],
34655
+ });
34656
+ const result = await callAgentLLM(agentContext, rlm, newMessages, newTools, true, {
34657
+ type: "tool",
34658
+ toolName: taskResultCheck.name,
34659
+ });
34660
+ const toolCall = result.filter((s) => s.type == "tool-call")[0];
34661
+ const args = typeof toolCall.input == "string"
34662
+ ? JSON.parse(toolCall.input || "{}")
34663
+ : toolCall.input || {};
34664
+ const toolResult = await taskResultCheck.execute(args, agentContext);
34665
+ const callback = agentContext.context.config.callback;
34666
+ if (callback) {
34667
+ await callback.onMessage({
34668
+ taskId: agentContext.context.taskId,
34669
+ agentName: agentContext.agent.Name,
34670
+ nodeId: agentContext.agentChain.agent.id,
34671
+ type: "tool_result",
34672
+ toolId: toolCall.toolCallId,
34673
+ toolName: toolCall.toolName,
34674
+ params: args,
34675
+ toolResult: toolResult,
34676
+ }, agentContext);
34677
+ }
34678
+ if (args.completionStatus == "incomplete") {
34679
+ messages.push({
34680
+ role: "user",
34681
+ content: [
34682
+ {
34683
+ type: "text",
34684
+ text: `It seems that your task has not been fully completed. Please continue with the remaining steps:\n${args.todoList || ""}`,
34685
+ },
34686
+ ],
34687
+ });
34688
+ }
34689
+ return {
34690
+ completionStatus: args.completionStatus,
34691
+ };
34692
+ }
34693
+ catch (e) {
34694
+ Log.error("TaskResultCheckTool error", e);
34695
+ return {
34696
+ completionStatus: "completed",
34697
+ };
34698
+ }
34699
+ }
34700
+
34566
34701
  const AGENT_SYSTEM_TEMPLATE = `
34567
34702
  You are {name}, an autonomous AI agent for {agent} agent.
34568
34703
 
@@ -34587,14 +34722,14 @@ The output language should follow the language corresponding to the user's task.
34587
34722
  `;
34588
34723
  const HUMAN_PROMPT = `
34589
34724
  * HUMAN INTERACT
34590
- During the task execution process, you can use the \`${TOOL_NAME$3}\` tool to interact with humans, please call it in the following situations:
34725
+ During the task execution process, you can use the \`${TOOL_NAME$5}\` tool to interact with humans, please call it in the following situations:
34591
34726
  - When performing dangerous operations such as deleting files, confirmation from humans is required.
34592
34727
  - When encountering obstacles while accessing websites, such as requiring user login, captcha verification, QR code scanning, or human verification, you need to request manual assistance.
34593
- - Please do not use the \`${TOOL_NAME$3}\` tool frequently.
34728
+ - Please do not use the \`${TOOL_NAME$5}\` tool frequently.
34594
34729
  `;
34595
34730
  const VARIABLE_PROMPT = `
34596
34731
  * VARIABLE STORAGE
34597
- When a step node has input/output variable attributes, use the \`${TOOL_NAME$1}\` tool to read from and write to these variables, these variables enable context sharing and coordination between multiple agents.
34732
+ When a step node has input/output variable attributes, use the \`${TOOL_NAME$3}\` tool to read from and write to these variables, these variables enable context sharing and coordination between multiple agents.
34598
34733
  `;
34599
34734
  const FOR_EACH_NODE = `
34600
34735
  <!-- duplicate task node, items support list and variable -->
@@ -34603,7 +34738,7 @@ const FOR_EACH_NODE = `
34603
34738
  </forEach>`;
34604
34739
  const FOR_EACH_PROMPT = `
34605
34740
  * forEach node
34606
- repetitive tasks, when executing to the forEach node, require the use of the \`${TOOL_NAME$4}\` tool.
34741
+ repetitive tasks, when executing to the forEach node, require the use of the \`${TOOL_NAME$6}\` tool.
34607
34742
  `;
34608
34743
  const WATCH_NODE = `
34609
34744
  <!-- monitor task node, the loop attribute specifies whether to listen in a loop or listen once -->
@@ -34616,7 +34751,7 @@ const WATCH_NODE = `
34616
34751
  </watch>`;
34617
34752
  const WATCH_PROMPT = `
34618
34753
  * watch node
34619
- monitor changes in webpage DOM elements, when executing to the watch node, require the use of the \`${TOOL_NAME}\` tool.
34754
+ monitor changes in webpage DOM elements, when executing to the watch node, require the use of the \`${TOOL_NAME$2}\` tool.
34620
34755
  `;
34621
34756
  function getAgentSystemPrompt(agent, agentNode, context, tools, extSysPrompt) {
34622
34757
  let prompt = "";
@@ -34625,10 +34760,10 @@ function getAgentSystemPrompt(agent, agentNode, context, tools, extSysPrompt) {
34625
34760
  let agentNodeXml = agentNode.xml;
34626
34761
  let hasWatchNode = agentNodeXml.indexOf("</watch>") > -1;
34627
34762
  let hasForEachNode = agentNodeXml.indexOf("</forEach>") > -1;
34628
- let hasHumanTool = tools.filter((tool) => tool.name == TOOL_NAME$3).length > 0;
34763
+ let hasHumanTool = tools.filter((tool) => tool.name == TOOL_NAME$5).length > 0;
34629
34764
  let hasVariable = agentNodeXml.indexOf("input=") > -1 ||
34630
34765
  agentNodeXml.indexOf("output=") > -1 ||
34631
- tools.filter((tool) => tool.name == TOOL_NAME$1).length > 0;
34766
+ tools.filter((tool) => tool.name == TOOL_NAME$3).length > 0;
34632
34767
  if (hasHumanTool) {
34633
34768
  prompt += HUMAN_PROMPT;
34634
34769
  }
@@ -34636,13 +34771,13 @@ function getAgentSystemPrompt(agent, agentNode, context, tools, extSysPrompt) {
34636
34771
  prompt += VARIABLE_PROMPT;
34637
34772
  }
34638
34773
  if (hasForEachNode) {
34639
- if (tools.filter((tool) => tool.name == TOOL_NAME$4).length > 0) {
34774
+ if (tools.filter((tool) => tool.name == TOOL_NAME$6).length > 0) {
34640
34775
  prompt += FOR_EACH_PROMPT;
34641
34776
  }
34642
34777
  nodePrompt += FOR_EACH_NODE;
34643
34778
  }
34644
34779
  if (hasWatchNode) {
34645
- if (tools.filter((tool) => tool.name == TOOL_NAME).length > 0) {
34780
+ if (tools.filter((tool) => tool.name == TOOL_NAME$2).length > 0) {
34646
34781
  prompt += WATCH_PROMPT;
34647
34782
  }
34648
34783
  nodePrompt += WATCH_NODE;
@@ -34670,7 +34805,7 @@ function getAgentSystemPrompt(agent, agentNode, context, tools, extSysPrompt) {
34670
34805
  .trim();
34671
34806
  }
34672
34807
  function getAgentUserPrompt(agent, agentNode, context, tools) {
34673
- let hasTaskNodeStatusTool = (tools || agent.Tools).filter((tool) => tool.name == TOOL_NAME$2)
34808
+ const hasTaskNodeStatusTool = (tools || agent.Tools).filter((tool) => tool.name == TOOL_NAME$4)
34674
34809
  .length > 0;
34675
34810
  return buildAgentRootXml(agentNode.xml, context.chain.taskPrompt, (nodeId, node) => {
34676
34811
  if (hasTaskNodeStatusTool) {
@@ -34679,6 +34814,129 @@ function getAgentUserPrompt(agent, agentNode, context, tools) {
34679
34814
  });
34680
34815
  }
34681
34816
 
34817
+ const TOOL_NAME = "todo_list_manager";
34818
+ class TodoListManagerTool {
34819
+ constructor() {
34820
+ this.name = TOOL_NAME;
34821
+ this.description =
34822
+ "Current task to-do list management, used for managing the to-do list of current tasks. During task execution, the to-do list needs to be updated according to the task execution status: completed, pending. It also detects whether tasks are being executed in repetitive loops during the execution process.";
34823
+ this.parameters = {
34824
+ type: "object",
34825
+ properties: {
34826
+ completedList: {
34827
+ type: "array",
34828
+ description: "Current completed task list items. Please update the completed list items based on the current task completion status.",
34829
+ items: {
34830
+ type: "string",
34831
+ },
34832
+ },
34833
+ todoList: {
34834
+ type: "array",
34835
+ description: "Current pending task list items. Please update the pending list items based on the current task pending status.",
34836
+ items: {
34837
+ type: "string",
34838
+ },
34839
+ },
34840
+ loopDetection: {
34841
+ type: "string",
34842
+ description: "Check if the current step is being repeatedly executed by comparing with previous steps.",
34843
+ enum: ["loop", "no_loop"],
34844
+ },
34845
+ },
34846
+ required: ["completedList", "todoList", "loopDetection"],
34847
+ };
34848
+ }
34849
+ async execute(args, agentContext) {
34850
+ return {
34851
+ content: [
34852
+ {
34853
+ type: "text",
34854
+ text: "success",
34855
+ },
34856
+ ],
34857
+ };
34858
+ }
34859
+ }
34860
+ async function doTodoListManager(agentContext, rlm, messages, tools) {
34861
+ try {
34862
+ // extract used tool
34863
+ const usedTools = extractUsedTool(messages, tools);
34864
+ const todoListManager = new TodoListManagerTool();
34865
+ const newTools = mergeTools(usedTools, [
34866
+ {
34867
+ type: "function",
34868
+ name: todoListManager.name,
34869
+ description: todoListManager.description,
34870
+ inputSchema: todoListManager.parameters,
34871
+ },
34872
+ ]);
34873
+ // handle messages
34874
+ const newMessages = [...messages];
34875
+ newMessages.push({
34876
+ role: "user",
34877
+ content: [
34878
+ {
34879
+ type: "text",
34880
+ text: `Task:\n${agentContext.agentChain.agent.xml}\n\nPlease check the completion status of the current task.`,
34881
+ },
34882
+ ],
34883
+ });
34884
+ const result = await callAgentLLM(agentContext, rlm, newMessages, newTools, true, {
34885
+ type: "tool",
34886
+ toolName: todoListManager.name,
34887
+ });
34888
+ const toolCall = result.filter((s) => s.type == "tool-call")[0];
34889
+ const args = typeof toolCall.input == "string"
34890
+ ? JSON.parse(toolCall.input || "{}")
34891
+ : toolCall.input || {};
34892
+ const toolResult = await todoListManager.execute(args, agentContext);
34893
+ const callback = agentContext.context.config.callback;
34894
+ if (callback) {
34895
+ await callback.onMessage({
34896
+ taskId: agentContext.context.taskId,
34897
+ agentName: agentContext.agent.Name,
34898
+ nodeId: agentContext.agentChain.agent.id,
34899
+ type: "tool_result",
34900
+ toolId: toolCall.toolCallId,
34901
+ toolName: toolCall.toolName,
34902
+ params: args,
34903
+ toolResult: toolResult,
34904
+ }, agentContext);
34905
+ }
34906
+ let userPrompt = "# Task Execution Status\n";
34907
+ if (args.completedList && args.completedList.length > 0) {
34908
+ userPrompt += "## Completed task list\n";
34909
+ for (let i = 0; i < args.completedList.length; i++) {
34910
+ userPrompt += `- ${args.completedList[i]}\n`;
34911
+ }
34912
+ userPrompt += "\n";
34913
+ }
34914
+ if (args.todoList && args.todoList.length > 0) {
34915
+ userPrompt += "## Pending task list\n";
34916
+ for (let i = 0; i < args.todoList.length; i++) {
34917
+ userPrompt += `- ${args.todoList[i]}\n`;
34918
+ }
34919
+ userPrompt += "\n";
34920
+ }
34921
+ if (args.loopDetection == "loop") {
34922
+ userPrompt += `## Loop detection\nIt seems that your task is being executed in a loop, Please change the execution strategy and try other methods to complete the current task.\n\n`;
34923
+ }
34924
+ userPrompt += "Please continue executing the remaining tasks.";
34925
+ messages.push({
34926
+ role: "user",
34927
+ content: [
34928
+ {
34929
+ type: "text",
34930
+ text: userPrompt.trim(),
34931
+ },
34932
+ ],
34933
+ });
34934
+ }
34935
+ catch (e) {
34936
+ Log.error("TodoListManagerTool error", e);
34937
+ }
34938
+ }
34939
+
34682
34940
  class Agent {
34683
34941
  constructor(params) {
34684
34942
  this.tools = [];
@@ -34706,21 +34964,24 @@ class Agent {
34706
34964
  }
34707
34965
  async runWithContext(agentContext, mcpClient, maxReactNum = 100, historyMessages = []) {
34708
34966
  let loopNum = 0;
34967
+ let checkNum = 0;
34709
34968
  this.agentContext = agentContext;
34710
34969
  const context = agentContext.context;
34711
34970
  const agentNode = agentContext.agentChain.agent;
34712
34971
  const tools = [...this.tools, ...this.system_auto_tools(agentNode)];
34972
+ const systemPrompt = await this.buildSystemPrompt(agentContext, tools);
34973
+ const userPrompt = await this.buildUserPrompt(agentContext, tools);
34713
34974
  const messages = [
34714
34975
  {
34715
34976
  role: "system",
34716
- content: await this.buildSystemPrompt(agentContext, tools),
34717
- providerOptions: defaultMessageProviderOptions()
34977
+ content: systemPrompt,
34978
+ providerOptions: defaultMessageProviderOptions(),
34718
34979
  },
34719
34980
  ...historyMessages,
34720
34981
  {
34721
34982
  role: "user",
34722
- content: await this.buildUserPrompt(agentContext, tools),
34723
- providerOptions: defaultMessageProviderOptions()
34983
+ content: userPrompt,
34984
+ providerOptions: defaultMessageProviderOptions(),
34724
34985
  },
34725
34986
  ];
34726
34987
  agentContext.messages = messages;
@@ -34738,20 +34999,32 @@ class Agent {
34738
34999
  }
34739
35000
  }
34740
35001
  await this.handleMessages(agentContext, messages, tools);
34741
- const results = await callAgentLLM(agentContext, rlm, messages, convertTools(agentTools), false, undefined, 0, this.callback, this.requestHandler);
34742
- const finalResult = await this.handleCallResult(agentContext, messages, agentTools, results);
34743
- if (finalResult) {
34744
- return finalResult;
35002
+ const llm_tools = convertTools(agentTools);
35003
+ const results = await callAgentLLM(agentContext, rlm, messages, llm_tools, false, undefined, 0, this.callback, this.requestHandler);
35004
+ const forceStop = agentContext.variables.get("forceStop");
35005
+ if (forceStop) {
35006
+ return forceStop;
34745
35007
  }
35008
+ const finalResult = await this.handleCallResult(agentContext, messages, agentTools, results);
34746
35009
  loopNum++;
35010
+ if (!finalResult) {
35011
+ if (config$1.expertMode && loopNum % config$1.expertModeTodoLoopNum == 0) {
35012
+ await doTodoListManager(agentContext, rlm, messages, llm_tools);
35013
+ }
35014
+ continue;
35015
+ }
35016
+ if (config$1.expertMode && checkNum == 0) {
35017
+ checkNum++;
35018
+ const { completionStatus } = await doTaskResultCheck(agentContext, rlm, messages, llm_tools);
35019
+ if (completionStatus == "incomplete") {
35020
+ continue;
35021
+ }
35022
+ }
35023
+ return finalResult;
34747
35024
  }
34748
35025
  return "Unfinished";
34749
35026
  }
34750
35027
  async handleCallResult(agentContext, messages, agentTools, results) {
34751
- const forceStop = agentContext.variables.get("forceStop");
34752
- if (forceStop) {
34753
- return forceStop;
34754
- }
34755
35028
  let text = null;
34756
35029
  let context = agentContext.context;
34757
35030
  let user_messages = [];