@eko-ai/eko 2.1.7 → 2.1.8-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
@@ -357,8 +357,10 @@ function fixXmlTag(code) {
357
357
  const top = stack.pop();
358
358
  if (top.startsWith("<")) {
359
359
  let arr = top.match(/<(\w+)/);
360
- const tagName = arr[1];
361
- missingParts.push(`</${tagName}>`);
360
+ if (arr) {
361
+ const tagName = arr[1];
362
+ missingParts.push(`</${tagName}>`);
363
+ }
362
364
  }
363
365
  else {
364
366
  missingParts.push(top);
@@ -370,8 +372,9 @@ function fixXmlTag(code) {
370
372
 
371
373
  class Context {
372
374
  constructor(taskId, config, agents, chain) {
373
- this.paused = false;
374
375
  this.conversation = [];
376
+ this.pauseStatus = 0;
377
+ this.currentStepControllers = new Set();
375
378
  this.taskId = taskId;
376
379
  this.config = config;
377
380
  this.agents = agents;
@@ -379,15 +382,20 @@ class Context {
379
382
  this.variables = new Map();
380
383
  this.controller = new AbortController();
381
384
  }
382
- async checkAborted() {
383
- // this.controller.signal.throwIfAborted();
385
+ async checkAborted(noCheckPause) {
384
386
  if (this.controller.signal.aborted) {
385
387
  const error = new Error("Operation was interrupted");
386
388
  error.name = "AbortError";
387
389
  throw error;
388
390
  }
389
- while (this.paused) {
391
+ while (this.pauseStatus > 0 && !noCheckPause) {
390
392
  await sleep(500);
393
+ if (this.pauseStatus == 2) {
394
+ this.currentStepControllers.forEach((c) => {
395
+ c.abort("Pause");
396
+ });
397
+ this.currentStepControllers.clear();
398
+ }
391
399
  if (this.controller.signal.aborted) {
392
400
  const error = new Error("Operation was interrupted");
393
401
  error.name = "AbortError";
@@ -404,9 +412,21 @@ class Context {
404
412
  if (!agent) {
405
413
  return null;
406
414
  }
407
- const agentContext = agent["agentContext"];
415
+ const agentContext = agent.AgentContext;
408
416
  return [agent, agentNode.agent, agentContext];
409
417
  }
418
+ get pause() {
419
+ return this.pauseStatus > 0;
420
+ }
421
+ setPause(pause, abortCurrentStep) {
422
+ this.pauseStatus = pause ? (abortCurrentStep ? 2 : 1) : 0;
423
+ if (this.pauseStatus == 2) {
424
+ this.currentStepControllers.forEach((c) => {
425
+ c.abort("Pause");
426
+ });
427
+ this.currentStepControllers.clear();
428
+ }
429
+ }
410
430
  }
411
431
  class AgentContext {
412
432
  constructor(context, agent, agentChain) {
@@ -14102,10 +14122,11 @@ createOpenRouter({
14102
14122
  });
14103
14123
 
14104
14124
  class RetryLanguageModel {
14105
- constructor(llms, names, stream_first_timeout) {
14125
+ constructor(llms, names, stream_first_timeout, stream_token_timeout) {
14106
14126
  this.llms = llms;
14107
14127
  this.names = names || [];
14108
14128
  this.stream_first_timeout = stream_first_timeout || 30000;
14129
+ this.stream_token_timeout = stream_token_timeout || 180000;
14109
14130
  if (this.names.indexOf("default") == -1) {
14110
14131
  this.names.push("default");
14111
14132
  }
@@ -14130,41 +14151,49 @@ class RetryLanguageModel {
14130
14151
  const maxTokens = options.maxTokens;
14131
14152
  const providerMetadata = options.providerMetadata;
14132
14153
  const names = [...this.names, ...this.names];
14154
+ let lastError;
14133
14155
  for (let i = 0; i < names.length; i++) {
14134
14156
  const name = names[i];
14157
+ const llmConfig = this.llms[name];
14135
14158
  const llm = await this.getLLM(name);
14136
14159
  if (!llm) {
14137
14160
  continue;
14138
14161
  }
14139
14162
  if (!maxTokens) {
14140
- options.maxTokens =
14141
- this.llms[name].config?.maxTokens || config.maxTokens;
14163
+ options.maxTokens = llmConfig.config?.maxTokens || config.maxTokens;
14142
14164
  }
14143
14165
  if (!providerMetadata) {
14144
14166
  options.providerMetadata = {};
14145
- options.providerMetadata[llm.provider] = this.llms[name].options || {};
14167
+ options.providerMetadata[llm.provider] = llmConfig.options || {};
14168
+ }
14169
+ let _options = options;
14170
+ if (llmConfig.handler) {
14171
+ _options = await llmConfig.handler(_options);
14146
14172
  }
14147
14173
  try {
14148
- let result = await llm.doGenerate(options);
14174
+ let result = (await llm.doGenerate(_options));
14149
14175
  if (Log.isEnableDebug()) {
14150
14176
  Log.debug(`LLM nonstream body, name: ${name} => `, result.request?.body);
14151
14177
  }
14178
+ result.llm = name;
14179
+ result.llmConfig = llmConfig;
14152
14180
  return result;
14153
14181
  }
14154
14182
  catch (e) {
14155
14183
  if (e?.name === "AbortError") {
14156
14184
  throw e;
14157
14185
  }
14186
+ lastError = e;
14158
14187
  if (Log.isEnableInfo()) {
14159
14188
  Log.info(`LLM nonstream request, name: ${name} => `, {
14160
- tools: options.mode?.tools,
14161
- messages: options.prompt,
14189
+ tools: _options.mode?.tools,
14190
+ messages: _options.prompt,
14162
14191
  });
14163
14192
  }
14164
14193
  Log.error(`LLM error, name: ${name} => `, e);
14165
14194
  }
14166
14195
  }
14167
- return Promise.reject(new Error("No LLM available"));
14196
+ return Promise.reject(lastError ? lastError : new Error("No LLM available"));
14168
14197
  }
14169
14198
  async callStream(request) {
14170
14199
  return await this.doStream({
@@ -14186,28 +14215,33 @@ class RetryLanguageModel {
14186
14215
  const maxTokens = options.maxTokens;
14187
14216
  const providerMetadata = options.providerMetadata;
14188
14217
  const names = [...this.names, ...this.names];
14218
+ let lastError;
14189
14219
  for (let i = 0; i < names.length; i++) {
14190
14220
  const name = names[i];
14221
+ const llmConfig = this.llms[name];
14191
14222
  const llm = await this.getLLM(name);
14192
14223
  if (!llm) {
14193
14224
  continue;
14194
14225
  }
14195
14226
  if (!maxTokens) {
14196
- options.maxTokens =
14197
- this.llms[name].config?.maxTokens || config.maxTokens;
14227
+ options.maxTokens = llmConfig.config?.maxTokens || config.maxTokens;
14198
14228
  }
14199
14229
  if (!providerMetadata) {
14200
14230
  options.providerMetadata = {};
14201
- options.providerMetadata[llm.provider] = this.llms[name].options || {};
14231
+ options.providerMetadata[llm.provider] = llmConfig.options || {};
14232
+ }
14233
+ let _options = options;
14234
+ if (llmConfig.handler) {
14235
+ _options = await llmConfig.handler(_options);
14202
14236
  }
14203
14237
  try {
14204
14238
  const controller = new AbortController();
14205
- const signal = options.abortSignal
14206
- ? AbortSignal.any([options.abortSignal, controller.signal])
14239
+ const signal = _options.abortSignal
14240
+ ? AbortSignal.any([_options.abortSignal, controller.signal])
14207
14241
  : controller.signal;
14208
- const result = await call_timeout(async () => await llm.doStream({ ...options, abortSignal: signal }), this.stream_first_timeout, (e) => {
14242
+ const result = (await call_timeout(async () => await llm.doStream({ ..._options, abortSignal: signal }), this.stream_first_timeout, (e) => {
14209
14243
  controller.abort();
14210
- });
14244
+ }));
14211
14245
  const stream = result.stream;
14212
14246
  const reader = stream.getReader();
14213
14247
  const { done, value } = await call_timeout(async () => await reader.read(), this.stream_first_timeout, (e) => {
@@ -14229,23 +14263,26 @@ class RetryLanguageModel {
14229
14263
  reader.releaseLock();
14230
14264
  continue;
14231
14265
  }
14232
- result.stream = this.streamWrapper([chunk], reader);
14266
+ result.llm = name;
14267
+ result.llmConfig = llmConfig;
14268
+ result.stream = this.streamWrapper([chunk], reader, controller);
14233
14269
  return result;
14234
14270
  }
14235
14271
  catch (e) {
14236
14272
  if (e?.name === "AbortError") {
14237
14273
  throw e;
14238
14274
  }
14275
+ lastError = e;
14239
14276
  if (Log.isEnableInfo()) {
14240
14277
  Log.info(`LLM stream request, name: ${name} => `, {
14241
- tools: options.mode?.tools,
14242
- messages: options.prompt,
14278
+ tools: _options.mode?.tools,
14279
+ messages: _options.prompt,
14243
14280
  });
14244
14281
  }
14245
14282
  Log.error(`LLM error, name: ${name} => `, e);
14246
14283
  }
14247
14284
  }
14248
- return Promise.reject(new Error("No LLM available"));
14285
+ return Promise.reject(lastError ? lastError : new Error("No LLM available"));
14249
14286
  }
14250
14287
  async getLLM(name) {
14251
14288
  const llm = this.llms[name];
@@ -14320,7 +14357,8 @@ class RetryLanguageModel {
14320
14357
  return llm.provider.languageModel(llm.model);
14321
14358
  }
14322
14359
  }
14323
- streamWrapper(parts, reader) {
14360
+ streamWrapper(parts, reader, abortController) {
14361
+ let timer = null;
14324
14362
  return new ReadableStream({
14325
14363
  start: (controller) => {
14326
14364
  if (parts != null && parts.length > 0) {
@@ -14330,7 +14368,11 @@ class RetryLanguageModel {
14330
14368
  }
14331
14369
  },
14332
14370
  pull: async (controller) => {
14371
+ timer = setTimeout(() => {
14372
+ abortController.abort("Streaming request timeout");
14373
+ }, this.stream_token_timeout);
14333
14374
  const { done, value } = await reader.read();
14375
+ clearTimeout(timer);
14334
14376
  if (done) {
14335
14377
  controller.close();
14336
14378
  reader.releaseLock();
@@ -14339,10 +14381,17 @@ class RetryLanguageModel {
14339
14381
  controller.enqueue(value);
14340
14382
  },
14341
14383
  cancel: (reason) => {
14384
+ timer && clearTimeout(timer);
14342
14385
  reader.cancel(reason);
14343
14386
  },
14344
14387
  });
14345
14388
  }
14389
+ get Llms() {
14390
+ return this.llms;
14391
+ }
14392
+ get Names() {
14393
+ return this.names;
14394
+ }
14346
14395
  }
14347
14396
 
14348
14397
  var domParser = {};
@@ -16790,11 +16839,21 @@ function requireDomParser () {
16790
16839
 
16791
16840
  var domParserExports = requireDomParser();
16792
16841
 
16793
- function parseWorkflow(taskId, xml, done) {
16842
+ function parseWorkflow(taskId, xml, done, thinking) {
16843
+ let _workflow = null;
16794
16844
  try {
16845
+ if (thinking) {
16846
+ _workflow = {
16847
+ taskId: taskId,
16848
+ name: "",
16849
+ thought: thinking,
16850
+ agents: [],
16851
+ xml: xml,
16852
+ };
16853
+ }
16795
16854
  let sIdx = xml.indexOf("<root>");
16796
16855
  if (sIdx == -1) {
16797
- return null;
16856
+ return _workflow;
16798
16857
  }
16799
16858
  xml = xml.substring(sIdx);
16800
16859
  let eIdx = xml.indexOf("</root>");
@@ -16808,13 +16867,14 @@ function parseWorkflow(taskId, xml, done) {
16808
16867
  const doc = parser.parseFromString(xml, "text/xml");
16809
16868
  let root = doc.documentElement;
16810
16869
  if (root.tagName !== "root") {
16811
- return null;
16870
+ return _workflow;
16812
16871
  }
16813
- let agents = [];
16872
+ const agents = [];
16873
+ const thought = root.getElementsByTagName("thought")[0]?.textContent || "";
16814
16874
  const workflow = {
16815
16875
  taskId: taskId,
16816
16876
  name: root.getElementsByTagName("name")[0]?.textContent || "",
16817
- thought: root.getElementsByTagName("thought")[0]?.textContent || "",
16877
+ thought: thinking ? thinking + "\n" + thought : thought,
16818
16878
  agents: agents,
16819
16879
  xml: xml,
16820
16880
  };
@@ -16847,7 +16907,7 @@ function parseWorkflow(taskId, xml, done) {
16847
16907
  throw e;
16848
16908
  }
16849
16909
  else {
16850
- return null;
16910
+ return _workflow;
16851
16911
  }
16852
16912
  }
16853
16913
  }
@@ -16925,7 +16985,7 @@ function buildAgentRootXml(agentXml, mainTaskPrompt, nodeCallback) {
16925
16985
  .replace("<task>", "<currentTask>")
16926
16986
  .replace("</task>", "</currentTask>");
16927
16987
  const xmlPrompt = `<root>${prefix}<mainTask>${mainTaskPrompt}</mainTask>${agentInnerHTML}</root>`;
16928
- return xmlPrompt.replace(/ /g, " ").replace(' </root>', '</root>');
16988
+ return xmlPrompt.replace(/ /g, " ").replace(" </root>", "</root>");
16929
16989
  }
16930
16990
  function extractAgentXmlNode(agentXml, nodeId) {
16931
16991
  const parser = new domParserExports.DOMParser();
@@ -16957,6 +17017,92 @@ function getInnerXML(node) {
16957
17017
  }
16958
17018
  return result;
16959
17019
  }
17020
+ function buildSimpleAgentWorkflow({ taskId, name, agentName, task, taskNodes, }) {
17021
+ if (!taskNodes || taskNodes.length == 0) {
17022
+ taskNodes = [task];
17023
+ }
17024
+ const workflow = {
17025
+ taskId: taskId,
17026
+ name: name,
17027
+ thought: "",
17028
+ agents: [
17029
+ {
17030
+ id: taskId + "-00",
17031
+ name: agentName,
17032
+ task: task,
17033
+ nodes: taskNodes.map((node) => {
17034
+ return {
17035
+ type: "normal",
17036
+ text: node,
17037
+ };
17038
+ }),
17039
+ xml: "",
17040
+ },
17041
+ ],
17042
+ xml: "",
17043
+ };
17044
+ workflow.taskPrompt = task;
17045
+ resetWorkflowXml(workflow);
17046
+ return workflow;
17047
+ }
17048
+ function resetWorkflowXml(workflow) {
17049
+ const agents = [];
17050
+ for (let i = 0; i < workflow.agents.length; i++) {
17051
+ const agent = workflow.agents[i];
17052
+ const nodes = agent.nodes
17053
+ .map((node) => {
17054
+ if (node.type == "forEach") {
17055
+ const forEachNodes = [];
17056
+ for (let j = 0; j < node.nodes.length; j++) {
17057
+ const _node = node.nodes[j];
17058
+ const input = _node.input ? ` input="${_node.input}"` : "";
17059
+ const output = _node.output ? ` output="${_node.output}"` : "";
17060
+ forEachNodes.push(` <node${input}${output}>${_node.text}</node>`);
17061
+ }
17062
+ return ` <forEach items="${node.items || ""}">
17063
+ ${forEachNodes.join("\n")}
17064
+ </forEach>`;
17065
+ }
17066
+ else if (node.type == "watch") {
17067
+ const watchNodes = [];
17068
+ for (let j = 0; j < node.triggerNodes.length; j++) {
17069
+ const _node = node.triggerNodes[j];
17070
+ const input = _node.input ? ` input="${_node.input}"` : "";
17071
+ const output = _node.output ? ` output="${_node.output}"` : "";
17072
+ watchNodes.push(` <node${input}${output}>${_node.text}</node>`);
17073
+ }
17074
+ return ` <watch event="${node.event || "dom"}" loop="${node.loop ? "true" : "false"}">
17075
+ <description>${node.description}</description>
17076
+ <trigger>
17077
+ ${watchNodes.join("\n")}
17078
+ </trigger>
17079
+ </watch>`;
17080
+ }
17081
+ else {
17082
+ const input = node.input ? ` input="${node.input}"` : "";
17083
+ const output = node.output ? ` output="${node.output}"` : "";
17084
+ return ` <node${input}${output}>${node.text}</node>`;
17085
+ }
17086
+ })
17087
+ .join("\n");
17088
+ const agentXml = ` <agent name="${agent.name}">
17089
+ <task>${agent.task}</task>
17090
+ <nodes>
17091
+ ${nodes}
17092
+ </nodes>
17093
+ </agent>`;
17094
+ agent.xml = agentXml;
17095
+ agents.push(agentXml);
17096
+ }
17097
+ const xml = `<root>
17098
+ <name>${workflow.name}</name>
17099
+ <thought>${workflow.thought}</thought>
17100
+ <agents>
17101
+ ${agents.join("\n")}
17102
+ </agents>
17103
+ </root>`;
17104
+ workflow.xml = xml;
17105
+ }
16960
17106
 
16961
17107
  const TOOL_NAME$5 = "task_snapshot";
16962
17108
  class TaskSnapshotTool {
@@ -17006,158 +17152,424 @@ class TaskSnapshotTool {
17006
17152
  }
17007
17153
  }
17008
17154
 
17009
- function extractUsedTool(messages, agentTools) {
17010
- let tools = [];
17011
- let toolNames = [];
17012
- for (let i = 0; i < messages.length; i++) {
17013
- let message = messages[i];
17014
- if (message.role == "tool") {
17015
- for (let j = 0; j < message.content.length; j++) {
17016
- let toolName = message.content[j].toolName;
17017
- if (toolNames.indexOf(toolName) > -1) {
17018
- continue;
17019
- }
17020
- toolNames.push(toolName);
17021
- let tool = agentTools.filter((tool) => tool.name === toolName)[0];
17022
- if (tool) {
17023
- tools.push(tool);
17024
- }
17025
- }
17026
- }
17027
- }
17028
- return tools;
17029
- }
17030
- function removeDuplicateToolUse(results) {
17031
- if (results.length <= 1 ||
17032
- results.filter((r) => r.type == "tool-call").length <= 1) {
17033
- return results;
17034
- }
17035
- let _results = [];
17036
- let tool_uniques = [];
17037
- for (let i = 0; i < results.length; i++) {
17038
- if (results[i].type === "tool-call") {
17039
- let tool = results[i];
17040
- let key = tool.toolName + tool.args;
17041
- if (tool_uniques.indexOf(key) == -1) {
17042
- _results.push(results[i]);
17043
- tool_uniques.push(key);
17044
- }
17045
- }
17046
- else {
17047
- _results.push(results[i]);
17048
- }
17155
+ async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, retry, callback) {
17156
+ await agentContext.context.checkAborted();
17157
+ if (messages.length >= config.compressThreshold && !noCompress) {
17158
+ await compressAgentMessages(agentContext, rlm, messages, tools);
17049
17159
  }
17050
- return _results;
17051
- }
17052
- async function compressAgentMessages(agentContext, rlm, messages, tools) {
17053
- if (messages.length < 10) {
17054
- return;
17160
+ if (!toolChoice) {
17161
+ // Append user dialogue
17162
+ appendUserConversation(agentContext, messages);
17055
17163
  }
17056
- // extract used tool
17057
- let usedTools = extractUsedTool(messages, tools);
17058
- let snapshotTool = new TaskSnapshotTool();
17059
- let newTools = mergeTools(usedTools, [
17060
- {
17061
- type: "function",
17062
- name: snapshotTool.name,
17063
- description: snapshotTool.description,
17064
- parameters: snapshotTool.parameters,
17065
- },
17164
+ let context = agentContext.context;
17165
+ let agentChain = agentContext.agentChain;
17166
+ let agentNode = agentChain.agent;
17167
+ let streamCallback = callback ||
17168
+ context.config.callback || {
17169
+ onMessage: async () => { },
17170
+ };
17171
+ const stepController = new AbortController();
17172
+ const signal = AbortSignal.any([
17173
+ context.controller.signal,
17174
+ stepController.signal,
17066
17175
  ]);
17067
- // handle messages
17068
- let lastToolIndex = messages.length - 1;
17069
- let newMessages = messages;
17070
- for (let r = newMessages.length - 1; r > 3; r--) {
17071
- if (newMessages[r].role == "tool") {
17072
- newMessages = newMessages.slice(0, r + 1);
17073
- lastToolIndex = r;
17074
- break;
17075
- }
17076
- }
17077
- newMessages.push({
17078
- role: "user",
17079
- content: [
17080
- {
17081
- type: "text",
17082
- text: "Please create a snapshot backup of the current task, keeping only key important information and node completion status.",
17083
- },
17084
- ],
17085
- });
17086
- // compress snapshot
17087
- let result = await callLLM(agentContext, rlm, newMessages, newTools, true, {
17088
- type: "tool",
17089
- toolName: snapshotTool.name,
17090
- });
17091
- let toolCall = result.filter((s) => s.type == "tool-call")[0];
17092
- let args = typeof toolCall.args == "string"
17093
- ? JSON.parse(toolCall.args || "{}")
17094
- : toolCall.args || {};
17095
- let toolResult = await snapshotTool.execute(args, agentContext);
17096
- let callback = agentContext.context.config.callback;
17097
- if (callback) {
17098
- await callback.onMessage({
17099
- taskId: agentContext.context.taskId,
17100
- agentName: agentContext.agent.Name,
17101
- nodeId: agentContext.agentChain.agent.id,
17102
- type: "tool_result",
17103
- toolId: toolCall.toolCallId,
17104
- toolName: toolCall.toolName,
17105
- params: args,
17106
- toolResult: toolResult,
17107
- }, agentContext);
17176
+ let request = {
17177
+ tools: tools,
17178
+ toolChoice,
17179
+ messages: messages,
17180
+ abortSignal: signal,
17181
+ };
17182
+ agentChain.agentRequest = request;
17183
+ let result;
17184
+ try {
17185
+ context.currentStepControllers.add(stepController);
17186
+ result = await rlm.callStream(request);
17108
17187
  }
17109
- // handle original messages
17110
- let firstToolIndex = 3;
17111
- for (let i = 0; i < messages.length; i++) {
17112
- if (messages[0].role == "tool") {
17113
- firstToolIndex = i;
17114
- break;
17188
+ catch (e) {
17189
+ context.currentStepControllers.delete(stepController);
17190
+ await context.checkAborted();
17191
+ if (!noCompress &&
17192
+ messages.length > 10 &&
17193
+ ((e + "").indexOf("tokens") > -1 || (e + "").indexOf("too long") > -1)) {
17194
+ await compressAgentMessages(agentContext, rlm, messages, tools);
17195
+ }
17196
+ if (!retry) {
17197
+ await sleep(200);
17198
+ return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, true, streamCallback);
17115
17199
  }
17200
+ throw e;
17116
17201
  }
17117
- // system, user, assistant, tool(first), [...], <user>, assistant, tool(last), ...
17118
- messages.splice(firstToolIndex + 1, lastToolIndex - firstToolIndex - 2, {
17119
- role: "user",
17120
- content: toolResult.content.filter((s) => s.type == "text"),
17121
- });
17122
- }
17123
- function handleLargeContextMessages(messages) {
17124
- let imageNum = 0;
17125
- let fileNum = 0;
17126
- let maxNum = config.maxDialogueImgFileNum;
17127
- let longTextTools = {};
17128
- for (let i = messages.length - 1; i >= 0; i--) {
17129
- let message = messages[i];
17130
- if (message.role == "user") {
17131
- for (let j = 0; j < message.content.length; j++) {
17132
- let content = message.content[j];
17133
- if (content.type == "image") {
17134
- if (++imageNum <= maxNum) {
17135
- break;
17202
+ let streamText = "";
17203
+ let thinkText = "";
17204
+ let toolArgsText = "";
17205
+ let streamId = uuidv4();
17206
+ let textStreamDone = false;
17207
+ let toolParts = [];
17208
+ const reader = result.stream.getReader();
17209
+ try {
17210
+ let toolPart = null;
17211
+ while (true) {
17212
+ await context.checkAborted();
17213
+ const { done, value } = await reader.read();
17214
+ if (done) {
17215
+ break;
17216
+ }
17217
+ let chunk = value;
17218
+ switch (chunk.type) {
17219
+ case "text-delta": {
17220
+ if (toolPart && !chunk.textDelta) {
17221
+ continue;
17136
17222
  }
17137
- content = {
17223
+ streamText += chunk.textDelta || "";
17224
+ await streamCallback.onMessage({
17225
+ taskId: context.taskId,
17226
+ agentName: agentNode.name,
17227
+ nodeId: agentNode.id,
17138
17228
  type: "text",
17139
- text: "[image]",
17140
- };
17141
- message.content[j] = content;
17142
- }
17143
- else if (content.type == "file") {
17144
- if (++fileNum <= maxNum) {
17145
- break;
17229
+ streamId,
17230
+ streamDone: false,
17231
+ text: streamText,
17232
+ }, agentContext);
17233
+ if (toolPart) {
17234
+ await streamCallback.onMessage({
17235
+ taskId: context.taskId,
17236
+ agentName: agentNode.name,
17237
+ nodeId: agentNode.id,
17238
+ type: "tool_use",
17239
+ toolId: toolPart.toolCallId,
17240
+ toolName: toolPart.toolName,
17241
+ params: toolPart.args || {},
17242
+ }, agentContext);
17243
+ toolPart = null;
17146
17244
  }
17147
- content = {
17148
- type: "text",
17149
- text: "[file]",
17150
- };
17151
- message.content[j] = content;
17245
+ break;
17152
17246
  }
17153
- }
17154
- }
17155
- else if (message.role == "tool") {
17156
- for (let j = 0; j < message.content.length; j++) {
17157
- let toolResult = message.content[j];
17158
- let toolContent = toolResult.content;
17159
- if (!toolContent || toolContent.length == 0) {
17160
- continue;
17247
+ case "reasoning": {
17248
+ thinkText += chunk.textDelta || "";
17249
+ await streamCallback.onMessage({
17250
+ taskId: context.taskId,
17251
+ agentName: agentNode.name,
17252
+ nodeId: agentNode.id,
17253
+ type: "thinking",
17254
+ streamId,
17255
+ streamDone: false,
17256
+ text: thinkText,
17257
+ }, agentContext);
17258
+ break;
17259
+ }
17260
+ case "tool-call-delta": {
17261
+ if (!textStreamDone) {
17262
+ textStreamDone = true;
17263
+ await streamCallback.onMessage({
17264
+ taskId: context.taskId,
17265
+ agentName: agentNode.name,
17266
+ nodeId: agentNode.id,
17267
+ type: "text",
17268
+ streamId,
17269
+ streamDone: true,
17270
+ text: streamText,
17271
+ }, agentContext);
17272
+ }
17273
+ toolArgsText += chunk.argsTextDelta || "";
17274
+ await streamCallback.onMessage({
17275
+ taskId: context.taskId,
17276
+ agentName: agentNode.name,
17277
+ nodeId: agentNode.id,
17278
+ type: "tool_streaming",
17279
+ toolId: chunk.toolCallId,
17280
+ toolName: chunk.toolName,
17281
+ paramsText: toolArgsText,
17282
+ }, agentContext);
17283
+ if (toolPart == null) {
17284
+ toolPart = {
17285
+ type: "tool-call",
17286
+ toolCallId: chunk.toolCallId,
17287
+ toolName: chunk.toolName,
17288
+ args: {},
17289
+ };
17290
+ toolParts.push(toolPart);
17291
+ }
17292
+ break;
17293
+ }
17294
+ case "tool-call": {
17295
+ toolArgsText = "";
17296
+ let args = chunk.args ? JSON.parse(chunk.args) : {};
17297
+ let message = {
17298
+ taskId: context.taskId,
17299
+ agentName: agentNode.name,
17300
+ nodeId: agentNode.id,
17301
+ type: "tool_use",
17302
+ toolId: chunk.toolCallId,
17303
+ toolName: chunk.toolName,
17304
+ params: args,
17305
+ };
17306
+ await streamCallback.onMessage(message, agentContext);
17307
+ if (toolPart == null) {
17308
+ toolParts.push({
17309
+ type: "tool-call",
17310
+ toolCallId: chunk.toolCallId,
17311
+ toolName: chunk.toolName,
17312
+ args: message.params || args,
17313
+ });
17314
+ }
17315
+ else {
17316
+ toolPart.args = message.params || args;
17317
+ toolPart = null;
17318
+ }
17319
+ break;
17320
+ }
17321
+ case "file": {
17322
+ await streamCallback.onMessage({
17323
+ taskId: context.taskId,
17324
+ agentName: agentNode.name,
17325
+ nodeId: agentNode.id,
17326
+ type: "file",
17327
+ mimeType: chunk.mimeType,
17328
+ data: chunk.data,
17329
+ }, agentContext);
17330
+ break;
17331
+ }
17332
+ case "error": {
17333
+ Log.error(`${agentNode.name} agent error: `, chunk);
17334
+ await streamCallback.onMessage({
17335
+ taskId: context.taskId,
17336
+ agentName: agentNode.name,
17337
+ nodeId: agentNode.id,
17338
+ type: "error",
17339
+ error: chunk.error,
17340
+ }, agentContext);
17341
+ throw new Error("LLM Error: " + chunk.error);
17342
+ }
17343
+ case "finish": {
17344
+ if (!textStreamDone) {
17345
+ textStreamDone = true;
17346
+ await streamCallback.onMessage({
17347
+ taskId: context.taskId,
17348
+ agentName: agentNode.name,
17349
+ nodeId: agentNode.id,
17350
+ type: "text",
17351
+ streamId,
17352
+ streamDone: true,
17353
+ text: streamText,
17354
+ }, agentContext);
17355
+ }
17356
+ if (toolPart) {
17357
+ await streamCallback.onMessage({
17358
+ taskId: context.taskId,
17359
+ agentName: agentNode.name,
17360
+ nodeId: agentNode.id,
17361
+ type: "tool_use",
17362
+ toolId: toolPart.toolCallId,
17363
+ toolName: toolPart.toolName,
17364
+ params: toolPart.args || {},
17365
+ }, agentContext);
17366
+ toolPart = null;
17367
+ }
17368
+ await streamCallback.onMessage({
17369
+ taskId: context.taskId,
17370
+ agentName: agentNode.name,
17371
+ nodeId: agentNode.id,
17372
+ type: "finish",
17373
+ finishReason: chunk.finishReason,
17374
+ usage: chunk.usage,
17375
+ }, agentContext);
17376
+ if (chunk.finishReason === "length" &&
17377
+ messages.length >= 10 &&
17378
+ !noCompress &&
17379
+ !retry) {
17380
+ await compressAgentMessages(agentContext, rlm, messages, tools);
17381
+ return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, true, streamCallback);
17382
+ }
17383
+ break;
17384
+ }
17385
+ }
17386
+ }
17387
+ }
17388
+ catch (e) {
17389
+ await context.checkAborted();
17390
+ if (!retry) {
17391
+ await sleep(200);
17392
+ return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, true, streamCallback);
17393
+ }
17394
+ throw e;
17395
+ }
17396
+ finally {
17397
+ reader.releaseLock();
17398
+ context.currentStepControllers.delete(stepController);
17399
+ }
17400
+ agentChain.agentResult = streamText;
17401
+ return streamText
17402
+ ? [
17403
+ { type: "text", text: streamText },
17404
+ ...toolParts,
17405
+ ]
17406
+ : toolParts;
17407
+ }
17408
+ function appendUserConversation(agentContext, messages) {
17409
+ const userPrompts = agentContext.context.conversation
17410
+ .splice(0, agentContext.context.conversation.length)
17411
+ .filter((s) => !!s);
17412
+ if (userPrompts.length > 0) {
17413
+ const prompt = "The user is intervening in the current task, please replan and execute according to the following instructions:\n" + userPrompts.map(s => `- ${s.trim()}`).join("\n");
17414
+ messages.push({
17415
+ role: "user",
17416
+ content: [{ type: "text", text: prompt }],
17417
+ });
17418
+ }
17419
+ }
17420
+
17421
+ function extractUsedTool(messages, agentTools) {
17422
+ let tools = [];
17423
+ let toolNames = [];
17424
+ for (let i = 0; i < messages.length; i++) {
17425
+ let message = messages[i];
17426
+ if (message.role == "tool") {
17427
+ for (let j = 0; j < message.content.length; j++) {
17428
+ let toolName = message.content[j].toolName;
17429
+ if (toolNames.indexOf(toolName) > -1) {
17430
+ continue;
17431
+ }
17432
+ toolNames.push(toolName);
17433
+ let tool = agentTools.filter((tool) => tool.name === toolName)[0];
17434
+ if (tool) {
17435
+ tools.push(tool);
17436
+ }
17437
+ }
17438
+ }
17439
+ }
17440
+ return tools;
17441
+ }
17442
+ function removeDuplicateToolUse(results) {
17443
+ if (results.length <= 1 ||
17444
+ results.filter((r) => r.type == "tool-call").length <= 1) {
17445
+ return results;
17446
+ }
17447
+ let _results = [];
17448
+ let tool_uniques = [];
17449
+ for (let i = 0; i < results.length; i++) {
17450
+ if (results[i].type === "tool-call") {
17451
+ let tool = results[i];
17452
+ let key = tool.toolName + tool.args;
17453
+ if (tool_uniques.indexOf(key) == -1) {
17454
+ _results.push(results[i]);
17455
+ tool_uniques.push(key);
17456
+ }
17457
+ }
17458
+ else {
17459
+ _results.push(results[i]);
17460
+ }
17461
+ }
17462
+ return _results;
17463
+ }
17464
+ async function compressAgentMessages(agentContext, rlm, messages, tools) {
17465
+ if (messages.length < 10) {
17466
+ return;
17467
+ }
17468
+ // extract used tool
17469
+ let usedTools = extractUsedTool(messages, tools);
17470
+ let snapshotTool = new TaskSnapshotTool();
17471
+ let newTools = mergeTools(usedTools, [
17472
+ {
17473
+ type: "function",
17474
+ name: snapshotTool.name,
17475
+ description: snapshotTool.description,
17476
+ parameters: snapshotTool.parameters,
17477
+ },
17478
+ ]);
17479
+ // handle messages
17480
+ let lastToolIndex = messages.length - 1;
17481
+ let newMessages = messages;
17482
+ for (let r = newMessages.length - 1; r > 3; r--) {
17483
+ if (newMessages[r].role == "tool") {
17484
+ newMessages = newMessages.slice(0, r + 1);
17485
+ lastToolIndex = r;
17486
+ break;
17487
+ }
17488
+ }
17489
+ newMessages.push({
17490
+ role: "user",
17491
+ content: [
17492
+ {
17493
+ type: "text",
17494
+ text: "Please create a snapshot backup of the current task, keeping only key important information and node completion status.",
17495
+ },
17496
+ ],
17497
+ });
17498
+ // compress snapshot
17499
+ let result = await callAgentLLM(agentContext, rlm, newMessages, newTools, true, {
17500
+ type: "tool",
17501
+ toolName: snapshotTool.name,
17502
+ });
17503
+ let toolCall = result.filter((s) => s.type == "tool-call")[0];
17504
+ let args = typeof toolCall.args == "string"
17505
+ ? JSON.parse(toolCall.args || "{}")
17506
+ : toolCall.args || {};
17507
+ let toolResult = await snapshotTool.execute(args, agentContext);
17508
+ let callback = agentContext.context.config.callback;
17509
+ if (callback) {
17510
+ await callback.onMessage({
17511
+ taskId: agentContext.context.taskId,
17512
+ agentName: agentContext.agent.Name,
17513
+ nodeId: agentContext.agentChain.agent.id,
17514
+ type: "tool_result",
17515
+ toolId: toolCall.toolCallId,
17516
+ toolName: toolCall.toolName,
17517
+ params: args,
17518
+ toolResult: toolResult,
17519
+ }, agentContext);
17520
+ }
17521
+ // handle original messages
17522
+ let firstToolIndex = 3;
17523
+ for (let i = 0; i < messages.length; i++) {
17524
+ if (messages[0].role == "tool") {
17525
+ firstToolIndex = i;
17526
+ break;
17527
+ }
17528
+ }
17529
+ // system, user, assistant, tool(first), [...], <user>, assistant, tool(last), ...
17530
+ messages.splice(firstToolIndex + 1, lastToolIndex - firstToolIndex - 2, {
17531
+ role: "user",
17532
+ content: toolResult.content.filter((s) => s.type == "text"),
17533
+ });
17534
+ }
17535
+ function handleLargeContextMessages(messages) {
17536
+ let imageNum = 0;
17537
+ let fileNum = 0;
17538
+ let maxNum = config.maxDialogueImgFileNum;
17539
+ let longTextTools = {};
17540
+ for (let i = messages.length - 1; i >= 0; i--) {
17541
+ let message = messages[i];
17542
+ if (message.role == "user") {
17543
+ for (let j = 0; j < message.content.length; j++) {
17544
+ let content = message.content[j];
17545
+ if (content.type == "image") {
17546
+ if (++imageNum <= maxNum) {
17547
+ break;
17548
+ }
17549
+ content = {
17550
+ type: "text",
17551
+ text: "[image]",
17552
+ };
17553
+ message.content[j] = content;
17554
+ }
17555
+ else if (content.type == "file") {
17556
+ if (++fileNum <= maxNum) {
17557
+ break;
17558
+ }
17559
+ content = {
17560
+ type: "text",
17561
+ text: "[file]",
17562
+ };
17563
+ message.content[j] = content;
17564
+ }
17565
+ }
17566
+ }
17567
+ else if (message.role == "tool") {
17568
+ for (let j = 0; j < message.content.length; j++) {
17569
+ let toolResult = message.content[j];
17570
+ let toolContent = toolResult.content;
17571
+ if (!toolContent || toolContent.length == 0) {
17572
+ continue;
17161
17573
  }
17162
17574
  for (let r = 0; r < toolContent.length; r++) {
17163
17575
  let _content = toolContent[r];
@@ -17960,21 +18372,24 @@ class Agent {
17960
18372
  mcpClient && (await mcpClient.close());
17961
18373
  }
17962
18374
  }
17963
- async runWithContext(agentContext, mcpClient, maxReactNum = 100) {
18375
+ async runWithContext(agentContext, mcpClient, maxReactNum = 100, historyMessages = []) {
17964
18376
  let loopNum = 0;
18377
+ this.agentContext = agentContext;
17965
18378
  let context = agentContext.context;
17966
18379
  let agentNode = agentContext.agentChain.agent;
17967
18380
  const tools = [...this.tools, ...this.system_auto_tools(agentNode)];
17968
- let messages = [
18381
+ const messages = [
17969
18382
  {
17970
18383
  role: "system",
17971
18384
  content: await this.buildSystemPrompt(agentContext, tools),
17972
18385
  },
18386
+ ...historyMessages,
17973
18387
  {
17974
18388
  role: "user",
17975
18389
  content: await this.buildUserPrompt(agentContext, tools),
17976
18390
  },
17977
18391
  ];
18392
+ agentContext.messages = messages;
17978
18393
  let rlm = new RetryLanguageModel(context.config.llms, this.llms);
17979
18394
  let agentTools = tools;
17980
18395
  while (loopNum < maxReactNum) {
@@ -17989,7 +18404,7 @@ class Agent {
17989
18404
  }
17990
18405
  }
17991
18406
  await this.handleMessages(agentContext, messages, tools);
17992
- let results = await callLLM(agentContext, rlm, messages, this.convertTools(agentTools), false, undefined, false, this.callback);
18407
+ let results = await callAgentLLM(agentContext, rlm, messages, this.convertTools(agentTools), false, undefined, false, this.callback);
17993
18408
  let finalResult = await this.handleCallResult(agentContext, messages, agentTools, results);
17994
18409
  if (finalResult) {
17995
18410
  return finalResult;
@@ -17999,6 +18414,10 @@ class Agent {
17999
18414
  return "Unfinished";
18000
18415
  }
18001
18416
  async handleCallResult(agentContext, messages, agentTools, results) {
18417
+ const forceStop = agentContext.variables.get("forceStop");
18418
+ if (forceStop) {
18419
+ return forceStop;
18420
+ }
18002
18421
  let text = null;
18003
18422
  let context = agentContext.context;
18004
18423
  let user_messages = [];
@@ -18231,29 +18650,6 @@ class Agent {
18231
18650
  async handleMessages(agentContext, messages, tools) {
18232
18651
  // Only keep the last image / file, large tool-text-result
18233
18652
  handleLargeContextMessages(messages);
18234
- // User dialogue
18235
- const userPrompts = agentContext.context.conversation
18236
- .splice(0, agentContext.context.conversation.length)
18237
- .filter((s) => !!s);
18238
- if (userPrompts.length > 0) {
18239
- const lastMessage = messages[messages.length - 1];
18240
- if (lastMessage.role == "user") {
18241
- for (let i = 0; i < userPrompts.length; i++) {
18242
- lastMessage.content.push({
18243
- type: "text",
18244
- text: userPrompts[i],
18245
- });
18246
- }
18247
- }
18248
- else {
18249
- messages.push({
18250
- role: "user",
18251
- content: userPrompts.map((s) => {
18252
- return { type: "text", text: s };
18253
- }),
18254
- });
18255
- }
18256
- }
18257
18653
  }
18258
18654
  async callInnerTool(fun) {
18259
18655
  let result = await fun();
@@ -18305,222 +18701,9 @@ class Agent {
18305
18701
  get McpClient() {
18306
18702
  return this.mcpClient;
18307
18703
  }
18308
- }
18309
- async function callLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, retry, callback) {
18310
- if (messages.length >= config.compressThreshold && !noCompress) {
18311
- await compressAgentMessages(agentContext, rlm, messages, tools);
18312
- }
18313
- let context = agentContext.context;
18314
- let agentChain = agentContext.agentChain;
18315
- let agentNode = agentChain.agent;
18316
- let streamCallback = callback ||
18317
- context.config.callback || {
18318
- onMessage: async () => { },
18319
- };
18320
- let request = {
18321
- tools: tools,
18322
- toolChoice,
18323
- messages: messages,
18324
- abortSignal: context.controller.signal,
18325
- };
18326
- agentChain.agentRequest = request;
18327
- let result = await rlm.callStream(request);
18328
- let streamText = "";
18329
- let thinkText = "";
18330
- let toolArgsText = "";
18331
- let streamId = uuidv4();
18332
- let textStreamDone = false;
18333
- let toolParts = [];
18334
- const reader = result.stream.getReader();
18335
- try {
18336
- let toolPart = null;
18337
- while (true) {
18338
- await context.checkAborted();
18339
- const { done, value } = await reader.read();
18340
- if (done) {
18341
- break;
18342
- }
18343
- let chunk = value;
18344
- switch (chunk.type) {
18345
- case "text-delta": {
18346
- if (toolPart && !chunk.textDelta) {
18347
- continue;
18348
- }
18349
- streamText += chunk.textDelta || "";
18350
- await streamCallback.onMessage({
18351
- taskId: context.taskId,
18352
- agentName: agentNode.name,
18353
- nodeId: agentNode.id,
18354
- type: "text",
18355
- streamId,
18356
- streamDone: false,
18357
- text: streamText,
18358
- }, agentContext);
18359
- if (toolPart) {
18360
- await streamCallback.onMessage({
18361
- taskId: context.taskId,
18362
- agentName: agentNode.name,
18363
- nodeId: agentNode.id,
18364
- type: "tool_use",
18365
- toolId: toolPart.toolCallId,
18366
- toolName: toolPart.toolName,
18367
- params: toolPart.args || {},
18368
- }, agentContext);
18369
- toolPart = null;
18370
- }
18371
- break;
18372
- }
18373
- case "reasoning": {
18374
- thinkText += chunk.textDelta || "";
18375
- await streamCallback.onMessage({
18376
- taskId: context.taskId,
18377
- agentName: agentNode.name,
18378
- nodeId: agentNode.id,
18379
- type: "thinking",
18380
- streamId,
18381
- streamDone: false,
18382
- text: thinkText,
18383
- }, agentContext);
18384
- break;
18385
- }
18386
- case "tool-call-delta": {
18387
- if (!textStreamDone) {
18388
- textStreamDone = true;
18389
- await streamCallback.onMessage({
18390
- taskId: context.taskId,
18391
- agentName: agentNode.name,
18392
- nodeId: agentNode.id,
18393
- type: "text",
18394
- streamId,
18395
- streamDone: true,
18396
- text: streamText,
18397
- }, agentContext);
18398
- }
18399
- toolArgsText += chunk.argsTextDelta || "";
18400
- await streamCallback.onMessage({
18401
- taskId: context.taskId,
18402
- agentName: agentNode.name,
18403
- nodeId: agentNode.id,
18404
- type: "tool_streaming",
18405
- toolId: chunk.toolCallId,
18406
- toolName: chunk.toolName,
18407
- paramsText: toolArgsText,
18408
- }, agentContext);
18409
- if (toolPart == null) {
18410
- toolPart = {
18411
- type: "tool-call",
18412
- toolCallId: chunk.toolCallId,
18413
- toolName: chunk.toolName,
18414
- args: {},
18415
- };
18416
- toolParts.push(toolPart);
18417
- }
18418
- break;
18419
- }
18420
- case "tool-call": {
18421
- toolArgsText = "";
18422
- let args = chunk.args ? JSON.parse(chunk.args) : {};
18423
- let message = {
18424
- taskId: context.taskId,
18425
- agentName: agentNode.name,
18426
- nodeId: agentNode.id,
18427
- type: "tool_use",
18428
- toolId: chunk.toolCallId,
18429
- toolName: chunk.toolName,
18430
- params: args,
18431
- };
18432
- await streamCallback.onMessage(message, agentContext);
18433
- if (toolPart == null) {
18434
- toolParts.push({
18435
- type: "tool-call",
18436
- toolCallId: chunk.toolCallId,
18437
- toolName: chunk.toolName,
18438
- args: message.params || args,
18439
- });
18440
- }
18441
- else {
18442
- toolPart.args = message.params || args;
18443
- toolPart = null;
18444
- }
18445
- break;
18446
- }
18447
- case "file": {
18448
- await streamCallback.onMessage({
18449
- taskId: context.taskId,
18450
- agentName: agentNode.name,
18451
- nodeId: agentNode.id,
18452
- type: "file",
18453
- mimeType: chunk.mimeType,
18454
- data: chunk.data,
18455
- }, agentContext);
18456
- break;
18457
- }
18458
- case "error": {
18459
- Log.error(`${agentNode.name} agent error: `, chunk);
18460
- await streamCallback.onMessage({
18461
- taskId: context.taskId,
18462
- agentName: agentNode.name,
18463
- nodeId: agentNode.id,
18464
- type: "error",
18465
- error: chunk.error,
18466
- }, agentContext);
18467
- throw new Error("LLM Error: " + chunk.error);
18468
- }
18469
- case "finish": {
18470
- if (!textStreamDone) {
18471
- textStreamDone = true;
18472
- await streamCallback.onMessage({
18473
- taskId: context.taskId,
18474
- agentName: agentNode.name,
18475
- nodeId: agentNode.id,
18476
- type: "text",
18477
- streamId,
18478
- streamDone: true,
18479
- text: streamText,
18480
- }, agentContext);
18481
- }
18482
- if (toolPart) {
18483
- await streamCallback.onMessage({
18484
- taskId: context.taskId,
18485
- agentName: agentNode.name,
18486
- nodeId: agentNode.id,
18487
- type: "tool_use",
18488
- toolId: toolPart.toolCallId,
18489
- toolName: toolPart.toolName,
18490
- params: toolPart.args || {},
18491
- }, agentContext);
18492
- toolPart = null;
18493
- }
18494
- await streamCallback.onMessage({
18495
- taskId: context.taskId,
18496
- agentName: agentNode.name,
18497
- nodeId: agentNode.id,
18498
- type: "finish",
18499
- finishReason: chunk.finishReason,
18500
- usage: chunk.usage,
18501
- }, agentContext);
18502
- if (chunk.finishReason === "length" &&
18503
- messages.length >= 10 &&
18504
- !noCompress &&
18505
- !retry) {
18506
- await compressAgentMessages(agentContext, rlm, messages, tools);
18507
- return callLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, true, streamCallback);
18508
- }
18509
- break;
18510
- }
18511
- }
18512
- }
18513
- }
18514
- finally {
18515
- reader.releaseLock();
18704
+ get AgentContext() {
18705
+ return this.agentContext;
18516
18706
  }
18517
- agentChain.agentResult = streamText;
18518
- return streamText
18519
- ? [
18520
- { type: "text", text: streamText },
18521
- ...toolParts,
18522
- ]
18523
- : toolParts;
18524
18707
  }
18525
18708
 
18526
18709
  const AGENT_NAME$5 = "Chat";
@@ -18555,7 +18738,9 @@ Your task is to understand the user's requirements, dynamically plan the user's
18555
18738
 
18556
18739
  ## Output Rules and Format
18557
18740
  <root>
18741
+ <!-- Task Name (Short) -->
18558
18742
  <name>Task Name</name>
18743
+ <!-- Need to break down the task into multi-agent collaboration. Please think step by step and output a detailed thought process. -->
18559
18744
  <thought>Your thought process on user demand planning</thought>
18560
18745
  <!-- Multiple Agents work together to complete the task -->
18561
18746
  <agents>
@@ -18753,21 +18938,39 @@ function getPlanUserPrompt(task_prompt, task_website, ext_prompt) {
18753
18938
  class Planner {
18754
18939
  constructor(context, taskId) {
18755
18940
  this.context = context;
18756
- this.taskId = taskId;
18757
- }
18758
- async plan(taskPrompt) {
18759
- return await this.doPlan(taskPrompt, false);
18760
- }
18761
- async replan(taskPrompt) {
18762
- return await this.doPlan(taskPrompt, true);
18941
+ this.taskId = taskId || context.taskId;
18942
+ }
18943
+ async plan(taskPrompt, saveHistory = true) {
18944
+ let taskPromptStr;
18945
+ let userPrompt;
18946
+ if (typeof taskPrompt === "string") {
18947
+ taskPromptStr = taskPrompt;
18948
+ userPrompt = {
18949
+ type: "text",
18950
+ text: getPlanUserPrompt(taskPrompt, this.context.variables.get("task_website"), this.context.variables.get("plan_ext_prompt")),
18951
+ };
18952
+ }
18953
+ else {
18954
+ userPrompt = taskPrompt;
18955
+ taskPromptStr = taskPrompt.text || "";
18956
+ }
18957
+ const messages = [
18958
+ {
18959
+ role: "system",
18960
+ content: this.context.variables.get("plan_sys_prompt") ||
18961
+ (await getPlanSystemPrompt(this.context)),
18962
+ },
18963
+ {
18964
+ role: "user",
18965
+ content: [userPrompt],
18966
+ },
18967
+ ];
18968
+ return await this.doPlan(taskPromptStr, messages, saveHistory);
18763
18969
  }
18764
- async doPlan(taskPrompt, replan = false) {
18765
- let config = this.context.config;
18766
- let chain = this.context.chain;
18767
- let rlm = new RetryLanguageModel(config.llms, config.planLlms);
18768
- let messages;
18769
- if (replan && chain.planRequest && chain.planResult) {
18770
- messages = [
18970
+ async replan(taskPrompt, saveHistory = true) {
18971
+ const chain = this.context.chain;
18972
+ if (chain.planRequest && chain.planResult) {
18973
+ const messages = [
18771
18974
  ...chain.planRequest.messages,
18772
18975
  {
18773
18976
  role: "assistant",
@@ -18778,37 +18981,28 @@ class Planner {
18778
18981
  content: [{ type: "text", text: taskPrompt }],
18779
18982
  },
18780
18983
  ];
18984
+ return await this.doPlan(taskPrompt, messages, saveHistory);
18781
18985
  }
18782
18986
  else {
18783
- messages = [
18784
- {
18785
- role: "system",
18786
- content: this.context.variables.get("plan_sys_prompt") ||
18787
- (await getPlanSystemPrompt(this.context)),
18788
- },
18789
- {
18790
- role: "user",
18791
- content: [
18792
- {
18793
- type: "text",
18794
- text: getPlanUserPrompt(taskPrompt, this.context.variables.get("task_website"), this.context.variables.get("plan_ext_prompt")),
18795
- },
18796
- ],
18797
- },
18798
- ];
18987
+ return this.plan(taskPrompt, saveHistory);
18799
18988
  }
18800
- let request = {
18989
+ }
18990
+ async doPlan(taskPrompt, messages, saveHistory) {
18991
+ const config = this.context.config;
18992
+ const rlm = new RetryLanguageModel(config.llms, config.planLlms);
18993
+ const request = {
18801
18994
  maxTokens: 4096,
18802
18995
  temperature: 0.7,
18803
18996
  messages: messages,
18804
18997
  abortSignal: this.context.controller.signal,
18805
18998
  };
18806
- let result = await rlm.callStream(request);
18999
+ const result = await rlm.callStream(request);
18807
19000
  const reader = result.stream.getReader();
18808
19001
  let streamText = "";
19002
+ let thinkingText = "";
18809
19003
  try {
18810
19004
  while (true) {
18811
- await this.context.checkAborted();
19005
+ await this.context.checkAborted(true);
18812
19006
  const { done, value } = await reader.read();
18813
19007
  if (done) {
18814
19008
  break;
@@ -18818,11 +19012,14 @@ class Planner {
18818
19012
  Log.error("Plan, LLM Error: ", chunk);
18819
19013
  throw new Error("LLM Error: " + chunk.error);
18820
19014
  }
19015
+ if (chunk.type == "reasoning") {
19016
+ thinkingText += chunk.textDelta || "";
19017
+ }
18821
19018
  if (chunk.type == "text-delta") {
18822
19019
  streamText += chunk.textDelta || "";
18823
19020
  }
18824
19021
  if (config.callback) {
18825
- let workflow = parseWorkflow(this.taskId, streamText, false);
19022
+ let workflow = parseWorkflow(this.taskId, streamText, false, thinkingText);
18826
19023
  if (workflow) {
18827
19024
  await config.callback.onMessage({
18828
19025
  taskId: this.taskId,
@@ -18837,11 +19034,16 @@ class Planner {
18837
19034
  }
18838
19035
  finally {
18839
19036
  reader.releaseLock();
18840
- Log.info("Planner result: \n" + streamText);
19037
+ if (Log.isEnableInfo()) {
19038
+ Log.info("Planner result: \n" + streamText);
19039
+ }
18841
19040
  }
18842
- chain.planRequest = request;
18843
- chain.planResult = streamText;
18844
- let workflow = parseWorkflow(this.taskId, streamText, true);
19041
+ if (saveHistory) {
19042
+ const chain = this.context.chain;
19043
+ chain.planRequest = request;
19044
+ chain.planResult = streamText;
19045
+ }
19046
+ let workflow = parseWorkflow(this.taskId, streamText, true, thinkingText);
18845
19047
  if (config.callback) {
18846
19048
  await config.callback.onMessage({
18847
19049
  taskId: this.taskId,
@@ -18851,7 +19053,12 @@ class Planner {
18851
19053
  workflow: workflow,
18852
19054
  });
18853
19055
  }
18854
- workflow.taskPrompt = taskPrompt;
19056
+ if (workflow.taskPrompt) {
19057
+ workflow.taskPrompt += "\n" + taskPrompt.trim();
19058
+ }
19059
+ else {
19060
+ workflow.taskPrompt = taskPrompt.trim();
19061
+ }
18855
19062
  return workflow;
18856
19063
  }
18857
19064
  }
@@ -18901,8 +19108,8 @@ class Eko {
18901
19108
  if (!context) {
18902
19109
  throw new Error("The task does not exist");
18903
19110
  }
18904
- if (context.paused) {
18905
- context.paused = false;
19111
+ if (context.pause) {
19112
+ context.setPause(false);
18906
19113
  }
18907
19114
  context.conversation = [];
18908
19115
  if (context.controller.signal.aborted) {
@@ -18990,7 +19197,7 @@ class Eko {
18990
19197
  abortTask(taskId, reason) {
18991
19198
  let context = this.taskMap.get(taskId);
18992
19199
  if (context) {
18993
- context.paused = false;
19200
+ context.setPause(false);
18994
19201
  this.onTaskStatus(context, "abort", reason);
18995
19202
  context.controller.abort(reason);
18996
19203
  return true;
@@ -18999,11 +19206,11 @@ class Eko {
18999
19206
  return false;
19000
19207
  }
19001
19208
  }
19002
- pauseTask(taskId, paused, reason) {
19209
+ pauseTask(taskId, pause, abortCurrentStep, reason) {
19003
19210
  let context = this.taskMap.get(taskId);
19004
19211
  if (context) {
19005
- this.onTaskStatus(context, paused ? "pause" : "resume-pause", reason);
19006
- context.paused = paused;
19212
+ this.onTaskStatus(context, pause ? "pause" : "resume-pause", reason);
19213
+ context.setPause(pause, abortCurrentStep);
19007
19214
  return true;
19008
19215
  }
19009
19216
  else {
@@ -21736,5 +21943,5 @@ class BaseBrowserScreenAgent extends BaseBrowserAgent {
21736
21943
  }
21737
21944
  }
21738
21945
 
21739
- export { Agent, AgentChain, AgentContext, BaseBrowserAgent, BaseBrowserLabelsAgent, BaseBrowserScreenAgent, BaseChatAgent, BaseComputerAgent, BaseFileAgent, BaseShellAgent, BaseTimerAgent, Chain, Context, Eko, ForeachTaskTool, HumanInteractTool, Log, RetryLanguageModel, SimpleSseMcpClient, TaskNodeStatusTool, VariableStorageTool, WatchTriggerTool, call_timeout, config, convertToolSchema, Eko as default, extract_page_content, mergeTools, toImage, uuidv4 };
21946
+ export { Agent, AgentChain, AgentContext, BaseBrowserAgent, BaseBrowserLabelsAgent, BaseBrowserScreenAgent, BaseChatAgent, BaseComputerAgent, BaseFileAgent, BaseShellAgent, BaseTimerAgent, Chain, Context, Eko, ForeachTaskTool, HumanInteractTool, Log, Planner, RetryLanguageModel, SimpleSseMcpClient, TaskNodeStatusTool, VariableStorageTool, WatchTriggerTool, buildSimpleAgentWorkflow, call_timeout, config, convertToolSchema, Eko as default, extract_page_content, mergeTools, parseWorkflow, resetWorkflowXml, toImage, uuidv4 };
21740
21947
  //# sourceMappingURL=index.esm.js.map