@eko-ai/eko 2.1.8 → 2.1.9-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/agent/base.d.ts +3 -1
- package/dist/agent/base.d.ts.map +1 -1
- package/dist/agent/browser/browser_labels.d.ts +2 -2
- package/dist/agent/browser/browser_labels.d.ts.map +1 -1
- package/dist/agent/index.d.ts +1 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/llm.d.ts +2 -2
- package/dist/agent/llm.d.ts.map +1 -1
- package/dist/common/tree.d.ts +3 -0
- package/dist/common/tree.d.ts.map +1 -0
- package/dist/common/utils.d.ts +2 -2
- package/dist/common/utils.d.ts.map +1 -1
- package/dist/common/xml.d.ts.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/core/context.d.ts +1 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/plan.d.ts +5 -4
- package/dist/core/plan.d.ts.map +1 -1
- package/dist/index.cjs.js +444 -130
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +444 -130
- package/dist/index.esm.js.map +1 -1
- package/dist/llm/index.d.ts +2 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/prompt/plan.d.ts.map +1 -1
- package/dist/types/core.types.d.ts +16 -0
- package/dist/types/core.types.d.ts.map +1 -1
- package/dist/types/llm.types.d.ts +3 -1
- package/dist/types/llm.types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -9,6 +9,8 @@ const config = {
|
|
|
9
9
|
platform: "mac",
|
|
10
10
|
maxReactNum: 500,
|
|
11
11
|
maxTokens: 16000,
|
|
12
|
+
maxRetryNum: 3,
|
|
13
|
+
agentParallel: false,
|
|
12
14
|
compressThreshold: 80,
|
|
13
15
|
largeTextLength: 5000,
|
|
14
16
|
fileTextMaxLength: 20000,
|
|
@@ -323,6 +325,8 @@ function fixXmlTag(code) {
|
|
|
323
325
|
code += '""';
|
|
324
326
|
}
|
|
325
327
|
else if (endStr == "name" ||
|
|
328
|
+
endStr == "id" ||
|
|
329
|
+
endStr == "dependsOn" ||
|
|
326
330
|
endStr == "input" ||
|
|
327
331
|
endStr == "output" ||
|
|
328
332
|
endStr == "items" ||
|
|
@@ -388,13 +392,13 @@ class Context {
|
|
|
388
392
|
this.variables = new Map();
|
|
389
393
|
this.controller = new AbortController();
|
|
390
394
|
}
|
|
391
|
-
async checkAborted() {
|
|
395
|
+
async checkAborted(noCheckPause) {
|
|
392
396
|
if (this.controller.signal.aborted) {
|
|
393
397
|
const error = new Error("Operation was interrupted");
|
|
394
398
|
error.name = "AbortError";
|
|
395
399
|
throw error;
|
|
396
400
|
}
|
|
397
|
-
while (this.pauseStatus > 0) {
|
|
401
|
+
while (this.pauseStatus > 0 && !noCheckPause) {
|
|
398
402
|
await sleep(500);
|
|
399
403
|
if (this.pauseStatus == 2) {
|
|
400
404
|
this.currentStepControllers.forEach((c) => {
|
|
@@ -14157,10 +14161,11 @@ createOpenRouter({
|
|
|
14157
14161
|
});
|
|
14158
14162
|
|
|
14159
14163
|
class RetryLanguageModel {
|
|
14160
|
-
constructor(llms, names, stream_first_timeout) {
|
|
14164
|
+
constructor(llms, names, stream_first_timeout, stream_token_timeout) {
|
|
14161
14165
|
this.llms = llms;
|
|
14162
14166
|
this.names = names || [];
|
|
14163
14167
|
this.stream_first_timeout = stream_first_timeout || 30000;
|
|
14168
|
+
this.stream_token_timeout = stream_token_timeout || 180000;
|
|
14164
14169
|
if (this.names.indexOf("default") == -1) {
|
|
14165
14170
|
this.names.push("default");
|
|
14166
14171
|
}
|
|
@@ -14178,6 +14183,7 @@ class RetryLanguageModel {
|
|
|
14178
14183
|
temperature: request.temperature,
|
|
14179
14184
|
topP: request.topP,
|
|
14180
14185
|
topK: request.topK,
|
|
14186
|
+
stopSequences: request.stopSequences,
|
|
14181
14187
|
abortSignal: request.abortSignal,
|
|
14182
14188
|
});
|
|
14183
14189
|
}
|
|
@@ -14188,25 +14194,29 @@ class RetryLanguageModel {
|
|
|
14188
14194
|
let lastError;
|
|
14189
14195
|
for (let i = 0; i < names.length; i++) {
|
|
14190
14196
|
const name = names[i];
|
|
14197
|
+
const llmConfig = this.llms[name];
|
|
14191
14198
|
const llm = await this.getLLM(name);
|
|
14192
14199
|
if (!llm) {
|
|
14193
14200
|
continue;
|
|
14194
14201
|
}
|
|
14195
14202
|
if (!maxTokens) {
|
|
14196
|
-
options.maxTokens =
|
|
14197
|
-
this.llms[name].config?.maxTokens || config.maxTokens;
|
|
14203
|
+
options.maxTokens = llmConfig.config?.maxTokens || config.maxTokens;
|
|
14198
14204
|
}
|
|
14199
14205
|
if (!providerMetadata) {
|
|
14200
14206
|
options.providerMetadata = {};
|
|
14201
|
-
options.providerMetadata[llm.provider] =
|
|
14207
|
+
options.providerMetadata[llm.provider] = llmConfig.options || {};
|
|
14208
|
+
}
|
|
14209
|
+
let _options = options;
|
|
14210
|
+
if (llmConfig.handler) {
|
|
14211
|
+
_options = await llmConfig.handler(_options);
|
|
14202
14212
|
}
|
|
14203
14213
|
try {
|
|
14204
|
-
let result = (await llm.doGenerate(
|
|
14214
|
+
let result = (await llm.doGenerate(_options));
|
|
14205
14215
|
if (Log.isEnableDebug()) {
|
|
14206
14216
|
Log.debug(`LLM nonstream body, name: ${name} => `, result.request?.body);
|
|
14207
14217
|
}
|
|
14208
14218
|
result.llm = name;
|
|
14209
|
-
result.llmConfig =
|
|
14219
|
+
result.llmConfig = llmConfig;
|
|
14210
14220
|
return result;
|
|
14211
14221
|
}
|
|
14212
14222
|
catch (e) {
|
|
@@ -14216,8 +14226,8 @@ class RetryLanguageModel {
|
|
|
14216
14226
|
lastError = e;
|
|
14217
14227
|
if (Log.isEnableInfo()) {
|
|
14218
14228
|
Log.info(`LLM nonstream request, name: ${name} => `, {
|
|
14219
|
-
tools:
|
|
14220
|
-
messages:
|
|
14229
|
+
tools: _options.mode?.tools,
|
|
14230
|
+
messages: _options.prompt,
|
|
14221
14231
|
});
|
|
14222
14232
|
}
|
|
14223
14233
|
Log.error(`LLM error, name: ${name} => `, e);
|
|
@@ -14238,6 +14248,7 @@ class RetryLanguageModel {
|
|
|
14238
14248
|
temperature: request.temperature,
|
|
14239
14249
|
topP: request.topP,
|
|
14240
14250
|
topK: request.topK,
|
|
14251
|
+
stopSequences: request.stopSequences,
|
|
14241
14252
|
abortSignal: request.abortSignal,
|
|
14242
14253
|
});
|
|
14243
14254
|
}
|
|
@@ -14248,24 +14259,28 @@ class RetryLanguageModel {
|
|
|
14248
14259
|
let lastError;
|
|
14249
14260
|
for (let i = 0; i < names.length; i++) {
|
|
14250
14261
|
const name = names[i];
|
|
14262
|
+
const llmConfig = this.llms[name];
|
|
14251
14263
|
const llm = await this.getLLM(name);
|
|
14252
14264
|
if (!llm) {
|
|
14253
14265
|
continue;
|
|
14254
14266
|
}
|
|
14255
14267
|
if (!maxTokens) {
|
|
14256
|
-
options.maxTokens =
|
|
14257
|
-
this.llms[name].config?.maxTokens || config.maxTokens;
|
|
14268
|
+
options.maxTokens = llmConfig.config?.maxTokens || config.maxTokens;
|
|
14258
14269
|
}
|
|
14259
14270
|
if (!providerMetadata) {
|
|
14260
14271
|
options.providerMetadata = {};
|
|
14261
|
-
options.providerMetadata[llm.provider] =
|
|
14272
|
+
options.providerMetadata[llm.provider] = llmConfig.options || {};
|
|
14273
|
+
}
|
|
14274
|
+
let _options = options;
|
|
14275
|
+
if (llmConfig.handler) {
|
|
14276
|
+
_options = await llmConfig.handler(_options);
|
|
14262
14277
|
}
|
|
14263
14278
|
try {
|
|
14264
14279
|
const controller = new AbortController();
|
|
14265
|
-
const signal =
|
|
14266
|
-
? AbortSignal.any([
|
|
14280
|
+
const signal = _options.abortSignal
|
|
14281
|
+
? AbortSignal.any([_options.abortSignal, controller.signal])
|
|
14267
14282
|
: controller.signal;
|
|
14268
|
-
const result = (await call_timeout(async () => await llm.doStream({ ...
|
|
14283
|
+
const result = (await call_timeout(async () => await llm.doStream({ ..._options, abortSignal: signal }), this.stream_first_timeout, (e) => {
|
|
14269
14284
|
controller.abort();
|
|
14270
14285
|
}));
|
|
14271
14286
|
const stream = result.stream;
|
|
@@ -14290,8 +14305,8 @@ class RetryLanguageModel {
|
|
|
14290
14305
|
continue;
|
|
14291
14306
|
}
|
|
14292
14307
|
result.llm = name;
|
|
14293
|
-
result.llmConfig =
|
|
14294
|
-
result.stream = this.streamWrapper([chunk], reader);
|
|
14308
|
+
result.llmConfig = llmConfig;
|
|
14309
|
+
result.stream = this.streamWrapper([chunk], reader, controller);
|
|
14295
14310
|
return result;
|
|
14296
14311
|
}
|
|
14297
14312
|
catch (e) {
|
|
@@ -14301,8 +14316,8 @@ class RetryLanguageModel {
|
|
|
14301
14316
|
lastError = e;
|
|
14302
14317
|
if (Log.isEnableInfo()) {
|
|
14303
14318
|
Log.info(`LLM stream request, name: ${name} => `, {
|
|
14304
|
-
tools:
|
|
14305
|
-
messages:
|
|
14319
|
+
tools: _options.mode?.tools,
|
|
14320
|
+
messages: _options.prompt,
|
|
14306
14321
|
});
|
|
14307
14322
|
}
|
|
14308
14323
|
Log.error(`LLM error, name: ${name} => `, e);
|
|
@@ -14383,7 +14398,8 @@ class RetryLanguageModel {
|
|
|
14383
14398
|
return llm.provider.languageModel(llm.model);
|
|
14384
14399
|
}
|
|
14385
14400
|
}
|
|
14386
|
-
streamWrapper(parts, reader) {
|
|
14401
|
+
streamWrapper(parts, reader, abortController) {
|
|
14402
|
+
let timer = null;
|
|
14387
14403
|
return new ReadableStream({
|
|
14388
14404
|
start: (controller) => {
|
|
14389
14405
|
if (parts != null && parts.length > 0) {
|
|
@@ -14393,7 +14409,11 @@ class RetryLanguageModel {
|
|
|
14393
14409
|
}
|
|
14394
14410
|
},
|
|
14395
14411
|
pull: async (controller) => {
|
|
14412
|
+
timer = setTimeout(() => {
|
|
14413
|
+
abortController.abort("Streaming request timeout");
|
|
14414
|
+
}, this.stream_token_timeout);
|
|
14396
14415
|
const { done, value } = await reader.read();
|
|
14416
|
+
clearTimeout(timer);
|
|
14397
14417
|
if (done) {
|
|
14398
14418
|
controller.close();
|
|
14399
14419
|
reader.releaseLock();
|
|
@@ -14402,6 +14422,7 @@ class RetryLanguageModel {
|
|
|
14402
14422
|
controller.enqueue(value);
|
|
14403
14423
|
},
|
|
14404
14424
|
cancel: (reason) => {
|
|
14425
|
+
timer && clearTimeout(timer);
|
|
14405
14426
|
reader.cancel(reason);
|
|
14406
14427
|
},
|
|
14407
14428
|
});
|
|
@@ -16859,6 +16880,159 @@ function requireDomParser () {
|
|
|
16859
16880
|
|
|
16860
16881
|
var domParserExports = requireDomParser();
|
|
16861
16882
|
|
|
16883
|
+
function buildAgentTree(agents) {
|
|
16884
|
+
// Detect and handle circular dependencies
|
|
16885
|
+
const safeAgents = detectAndBreakCycles(agents);
|
|
16886
|
+
if (safeAgents.length === 0) {
|
|
16887
|
+
throw new Error("No executable agent");
|
|
16888
|
+
}
|
|
16889
|
+
// Establish dependency relationship mapping
|
|
16890
|
+
const agentMap = new Map();
|
|
16891
|
+
const dependents = new Map();
|
|
16892
|
+
for (const agent of safeAgents) {
|
|
16893
|
+
agentMap.set(agent.id, agent);
|
|
16894
|
+
dependents.set(agent.id, []);
|
|
16895
|
+
}
|
|
16896
|
+
for (const agent of safeAgents) {
|
|
16897
|
+
for (const depId of agent.dependsOn) {
|
|
16898
|
+
if (dependents.has(depId)) {
|
|
16899
|
+
dependents.get(depId).push(agent);
|
|
16900
|
+
}
|
|
16901
|
+
}
|
|
16902
|
+
}
|
|
16903
|
+
let entryAgents = safeAgents.filter((agent) => agent.dependsOn.length === 0);
|
|
16904
|
+
if (entryAgents.length === 0) {
|
|
16905
|
+
entryAgents = safeAgents.filter((agent) => agent.dependsOn.length == 1 && agent.dependsOn[0].endsWith("00"));
|
|
16906
|
+
}
|
|
16907
|
+
const processedAgents = new Set();
|
|
16908
|
+
function buildNodeRecursive(currentAgents) {
|
|
16909
|
+
if (currentAgents.length === 0) {
|
|
16910
|
+
return undefined;
|
|
16911
|
+
}
|
|
16912
|
+
for (const agent of currentAgents) {
|
|
16913
|
+
processedAgents.add(agent.id);
|
|
16914
|
+
}
|
|
16915
|
+
const nextLevelAgents = [];
|
|
16916
|
+
const nextLevelSet = new Set();
|
|
16917
|
+
for (const agent of currentAgents) {
|
|
16918
|
+
const dependentAgents = dependents.get(agent.id) || [];
|
|
16919
|
+
for (const dependentAgent of dependentAgents) {
|
|
16920
|
+
const allDependenciesProcessed = dependentAgent.dependsOn.every((depId) => processedAgents.has(depId));
|
|
16921
|
+
if (allDependenciesProcessed && !nextLevelSet.has(dependentAgent.id)) {
|
|
16922
|
+
nextLevelAgents.push(dependentAgent);
|
|
16923
|
+
nextLevelSet.add(dependentAgent.id);
|
|
16924
|
+
}
|
|
16925
|
+
}
|
|
16926
|
+
}
|
|
16927
|
+
const nextNode = buildNodeRecursive(nextLevelAgents);
|
|
16928
|
+
if (currentAgents.length === 1) {
|
|
16929
|
+
return {
|
|
16930
|
+
type: "normal",
|
|
16931
|
+
agent: currentAgents[0],
|
|
16932
|
+
nextAgent: nextNode,
|
|
16933
|
+
};
|
|
16934
|
+
}
|
|
16935
|
+
else {
|
|
16936
|
+
const parallelNodes = currentAgents.map((agent) => ({
|
|
16937
|
+
type: "normal",
|
|
16938
|
+
agent: agent,
|
|
16939
|
+
nextAgent: undefined,
|
|
16940
|
+
}));
|
|
16941
|
+
return {
|
|
16942
|
+
type: "parallel",
|
|
16943
|
+
agents: parallelNodes,
|
|
16944
|
+
nextAgent: nextNode,
|
|
16945
|
+
};
|
|
16946
|
+
}
|
|
16947
|
+
}
|
|
16948
|
+
const rootNode = buildNodeRecursive(entryAgents);
|
|
16949
|
+
if (!rootNode) {
|
|
16950
|
+
throw new Error("Unable to build execution tree");
|
|
16951
|
+
}
|
|
16952
|
+
return rootNode;
|
|
16953
|
+
}
|
|
16954
|
+
function detectAndBreakCycles(agents) {
|
|
16955
|
+
// Detect cyclic dependencies and return a safe dependency relationship
|
|
16956
|
+
// Use topological sorting algorithm to detect cycles, if a cycle is found, break some dependencies.
|
|
16957
|
+
const agentMap = new Map();
|
|
16958
|
+
const inDegree = new Map();
|
|
16959
|
+
const adjList = new Map();
|
|
16960
|
+
for (const agent of agents) {
|
|
16961
|
+
agentMap.set(agent.id, agent);
|
|
16962
|
+
inDegree.set(agent.id, 0);
|
|
16963
|
+
adjList.set(agent.id, []);
|
|
16964
|
+
}
|
|
16965
|
+
for (const agent of agents) {
|
|
16966
|
+
for (const depId of agent.dependsOn) {
|
|
16967
|
+
if (agentMap.has(depId)) {
|
|
16968
|
+
// depId -> agent.id indicates that the agent depends on depId.
|
|
16969
|
+
adjList.get(depId).push(agent.id);
|
|
16970
|
+
inDegree.set(agent.id, inDegree.get(agent.id) + 1);
|
|
16971
|
+
}
|
|
16972
|
+
}
|
|
16973
|
+
}
|
|
16974
|
+
// Topological Sorting Detects Cycles
|
|
16975
|
+
const queue = [];
|
|
16976
|
+
const processedCount = new Map();
|
|
16977
|
+
for (const [agentId, degree] of inDegree.entries()) {
|
|
16978
|
+
if (degree === 0) {
|
|
16979
|
+
queue.push(agentId);
|
|
16980
|
+
}
|
|
16981
|
+
processedCount.set(agentId, 0);
|
|
16982
|
+
}
|
|
16983
|
+
let processedNodes = 0;
|
|
16984
|
+
while (queue.length > 0) {
|
|
16985
|
+
const currentId = queue.shift();
|
|
16986
|
+
processedNodes++;
|
|
16987
|
+
for (const neighborId of adjList.get(currentId)) {
|
|
16988
|
+
const newInDegree = inDegree.get(neighborId) - 1;
|
|
16989
|
+
inDegree.set(neighborId, newInDegree);
|
|
16990
|
+
if (newInDegree === 0) {
|
|
16991
|
+
queue.push(neighborId);
|
|
16992
|
+
}
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
if (processedNodes < agents.length) {
|
|
16996
|
+
console.warn("Detected a circular dependency, automatically disconnecting the circular link...");
|
|
16997
|
+
const cyclicNodes = new Set();
|
|
16998
|
+
for (const [agentId, degree] of inDegree.entries()) {
|
|
16999
|
+
if (degree > 0) {
|
|
17000
|
+
cyclicNodes.add(agentId);
|
|
17001
|
+
}
|
|
17002
|
+
}
|
|
17003
|
+
const fixedAgents = [];
|
|
17004
|
+
for (const agent of agents) {
|
|
17005
|
+
if (cyclicNodes.has(agent.id)) {
|
|
17006
|
+
const filteredDependsOn = agent.dependsOn.filter((depId) => !cyclicNodes.has(depId) || !agentMap.has(depId));
|
|
17007
|
+
// Preserve the shortest path dependency
|
|
17008
|
+
if (filteredDependsOn.length === 0 && agent.dependsOn.length > 0) {
|
|
17009
|
+
const firstValidDep = agent.dependsOn.find((depId) => agentMap.has(depId));
|
|
17010
|
+
if (firstValidDep && !cyclicNodes.has(firstValidDep)) {
|
|
17011
|
+
filteredDependsOn.push(firstValidDep);
|
|
17012
|
+
}
|
|
17013
|
+
}
|
|
17014
|
+
agent.dependsOn = filteredDependsOn;
|
|
17015
|
+
fixedAgents.push(agent);
|
|
17016
|
+
if (filteredDependsOn.length !== agent.dependsOn.length) {
|
|
17017
|
+
console.warn(`The partial cyclic dependency of agent ${agent.id} has been disconnected.`);
|
|
17018
|
+
}
|
|
17019
|
+
}
|
|
17020
|
+
else {
|
|
17021
|
+
// Non-cyclic node, filter out non-existent dependencies
|
|
17022
|
+
const validDependsOn = agent.dependsOn.filter((depId) => agentMap.has(depId));
|
|
17023
|
+
agent.dependsOn = validDependsOn;
|
|
17024
|
+
fixedAgents.push(agent);
|
|
17025
|
+
}
|
|
17026
|
+
}
|
|
17027
|
+
return fixedAgents;
|
|
17028
|
+
}
|
|
17029
|
+
// No loops, just need to filter out non-existent dependencies
|
|
17030
|
+
return agents.map((agent) => {
|
|
17031
|
+
agent.dependsOn = agent.dependsOn.filter((depId) => agentMap.has(depId));
|
|
17032
|
+
return agent;
|
|
17033
|
+
});
|
|
17034
|
+
}
|
|
17035
|
+
|
|
16862
17036
|
function parseWorkflow(taskId, xml, done, thinking) {
|
|
16863
17037
|
let _workflow = null;
|
|
16864
17038
|
try {
|
|
@@ -16906,12 +17080,17 @@ function parseWorkflow(taskId, xml, done, thinking) {
|
|
|
16906
17080
|
if (!name) {
|
|
16907
17081
|
break;
|
|
16908
17082
|
}
|
|
17083
|
+
let index = agentNode.getAttribute("id") || i;
|
|
17084
|
+
let dependsOn = agentNode.getAttribute("dependsOn") || "";
|
|
16909
17085
|
let nodes = [];
|
|
16910
17086
|
let agent = {
|
|
16911
17087
|
name: name,
|
|
16912
|
-
id: taskId
|
|
17088
|
+
id: getAgentId(taskId, index),
|
|
17089
|
+
dependsOn: dependsOn.split(",").filter(idx => idx.trim() != "").map(idx => getAgentId(taskId, idx)),
|
|
16913
17090
|
task: agentNode.getElementsByTagName("task")[0]?.textContent || "",
|
|
16914
17091
|
nodes: nodes,
|
|
17092
|
+
status: "init",
|
|
17093
|
+
parallel: undefined,
|
|
16915
17094
|
xml: agentNode.toString(),
|
|
16916
17095
|
};
|
|
16917
17096
|
let xmlNodes = agentNode.getElementsByTagName("nodes");
|
|
@@ -16920,6 +17099,25 @@ function parseWorkflow(taskId, xml, done, thinking) {
|
|
|
16920
17099
|
}
|
|
16921
17100
|
agents.push(agent);
|
|
16922
17101
|
}
|
|
17102
|
+
if (done) {
|
|
17103
|
+
let agentTree = buildAgentTree(workflow.agents);
|
|
17104
|
+
while (true) {
|
|
17105
|
+
if (agentTree.type === "normal") {
|
|
17106
|
+
agentTree.agent.parallel = false;
|
|
17107
|
+
}
|
|
17108
|
+
else {
|
|
17109
|
+
const parallelAgents = agentTree.agents;
|
|
17110
|
+
for (let i = 0; i < parallelAgents.length; i++) {
|
|
17111
|
+
const agentNode = parallelAgents[i];
|
|
17112
|
+
agentNode.agent.parallel = true;
|
|
17113
|
+
}
|
|
17114
|
+
}
|
|
17115
|
+
if (!agentTree.nextAgent) {
|
|
17116
|
+
break;
|
|
17117
|
+
}
|
|
17118
|
+
agentTree = agentTree.nextAgent;
|
|
17119
|
+
}
|
|
17120
|
+
}
|
|
16923
17121
|
return workflow;
|
|
16924
17122
|
}
|
|
16925
17123
|
catch (e) {
|
|
@@ -16931,6 +17129,9 @@ function parseWorkflow(taskId, xml, done, thinking) {
|
|
|
16931
17129
|
}
|
|
16932
17130
|
}
|
|
16933
17131
|
}
|
|
17132
|
+
function getAgentId(taskId, index) {
|
|
17133
|
+
return taskId + "-" + (+index < 10 ? "0" + index : index);
|
|
17134
|
+
}
|
|
16934
17135
|
function parseWorkflowNodes(nodes, xmlNodes) {
|
|
16935
17136
|
for (let i = 0; i < xmlNodes.length; i++) {
|
|
16936
17137
|
if (xmlNodes[i].nodeType !== 1) {
|
|
@@ -17048,6 +17249,7 @@ function buildSimpleAgentWorkflow({ taskId, name, agentName, task, taskNodes, })
|
|
|
17048
17249
|
agents: [
|
|
17049
17250
|
{
|
|
17050
17251
|
id: taskId + "-00",
|
|
17252
|
+
dependsOn: [],
|
|
17051
17253
|
name: agentName,
|
|
17052
17254
|
task: task,
|
|
17053
17255
|
nodes: taskNodes.map((node) => {
|
|
@@ -17056,6 +17258,8 @@ function buildSimpleAgentWorkflow({ taskId, name, agentName, task, taskNodes, })
|
|
|
17056
17258
|
text: node,
|
|
17057
17259
|
};
|
|
17058
17260
|
}),
|
|
17261
|
+
status: "init",
|
|
17262
|
+
parallel: false,
|
|
17059
17263
|
xml: "",
|
|
17060
17264
|
},
|
|
17061
17265
|
],
|
|
@@ -17069,6 +17273,7 @@ function resetWorkflowXml(workflow) {
|
|
|
17069
17273
|
const agents = [];
|
|
17070
17274
|
for (let i = 0; i < workflow.agents.length; i++) {
|
|
17071
17275
|
const agent = workflow.agents[i];
|
|
17276
|
+
const agentDependsAttr = ` id="${i}" dependsOn="${(agent.dependsOn || []).filter(s => parseInt(s.split("-")[s.split("-").length - 1])).join(",")}"`;
|
|
17072
17277
|
const nodes = agent.nodes
|
|
17073
17278
|
.map((node) => {
|
|
17074
17279
|
if (node.type == "forEach") {
|
|
@@ -17105,7 +17310,7 @@ ${watchNodes.join("\n")}
|
|
|
17105
17310
|
}
|
|
17106
17311
|
})
|
|
17107
17312
|
.join("\n");
|
|
17108
|
-
const agentXml = ` <agent name="${agent.name}">
|
|
17313
|
+
const agentXml = ` <agent name="${agent.name}"${agentDependsAttr}>
|
|
17109
17314
|
<task>${agent.task}</task>
|
|
17110
17315
|
<nodes>
|
|
17111
17316
|
${nodes}
|
|
@@ -17172,7 +17377,7 @@ class TaskSnapshotTool {
|
|
|
17172
17377
|
}
|
|
17173
17378
|
}
|
|
17174
17379
|
|
|
17175
|
-
async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice,
|
|
17380
|
+
async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, retryNum = 0, callback, requestHandler) {
|
|
17176
17381
|
await agentContext.context.checkAborted();
|
|
17177
17382
|
if (messages.length >= config.compressThreshold && !noCompress) {
|
|
17178
17383
|
await compressAgentMessages(agentContext, rlm, messages, tools);
|
|
@@ -17199,6 +17404,7 @@ async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, tool
|
|
|
17199
17404
|
messages: messages,
|
|
17200
17405
|
abortSignal: signal,
|
|
17201
17406
|
};
|
|
17407
|
+
requestHandler && requestHandler(request);
|
|
17202
17408
|
agentChain.agentRequest = request;
|
|
17203
17409
|
let result;
|
|
17204
17410
|
try {
|
|
@@ -17209,13 +17415,13 @@ async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, tool
|
|
|
17209
17415
|
context.currentStepControllers.delete(stepController);
|
|
17210
17416
|
await context.checkAborted();
|
|
17211
17417
|
if (!noCompress &&
|
|
17212
|
-
messages.length
|
|
17418
|
+
messages.length >= 5 &&
|
|
17213
17419
|
((e + "").indexOf("tokens") > -1 || (e + "").indexOf("too long") > -1)) {
|
|
17214
17420
|
await compressAgentMessages(agentContext, rlm, messages, tools);
|
|
17215
17421
|
}
|
|
17216
|
-
if (
|
|
17217
|
-
await sleep(200);
|
|
17218
|
-
return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice,
|
|
17422
|
+
if (retryNum < config.maxRetryNum) {
|
|
17423
|
+
await sleep(200 * (retryNum + 1) * (retryNum + 1));
|
|
17424
|
+
return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, ++retryNum, streamCallback);
|
|
17219
17425
|
}
|
|
17220
17426
|
throw e;
|
|
17221
17427
|
}
|
|
@@ -17394,11 +17600,11 @@ async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, tool
|
|
|
17394
17600
|
usage: chunk.usage,
|
|
17395
17601
|
}, agentContext);
|
|
17396
17602
|
if (chunk.finishReason === "length" &&
|
|
17397
|
-
messages.length >=
|
|
17603
|
+
messages.length >= 5 &&
|
|
17398
17604
|
!noCompress &&
|
|
17399
|
-
|
|
17605
|
+
retryNum < config.maxRetryNum) {
|
|
17400
17606
|
await compressAgentMessages(agentContext, rlm, messages, tools);
|
|
17401
|
-
return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice,
|
|
17607
|
+
return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, ++retryNum, streamCallback);
|
|
17402
17608
|
}
|
|
17403
17609
|
break;
|
|
17404
17610
|
}
|
|
@@ -17407,8 +17613,9 @@ async function callAgentLLM(agentContext, rlm, messages, tools, noCompress, tool
|
|
|
17407
17613
|
}
|
|
17408
17614
|
catch (e) {
|
|
17409
17615
|
await context.checkAborted();
|
|
17410
|
-
if (
|
|
17411
|
-
|
|
17616
|
+
if (retryNum < config.maxRetryNum) {
|
|
17617
|
+
await sleep(200 * (retryNum + 1) * (retryNum + 1));
|
|
17618
|
+
return callAgentLLM(agentContext, rlm, messages, tools, noCompress, toolChoice, ++retryNum, streamCallback);
|
|
17412
17619
|
}
|
|
17413
17620
|
throw e;
|
|
17414
17621
|
}
|
|
@@ -17429,7 +17636,8 @@ function appendUserConversation(agentContext, messages) {
|
|
|
17429
17636
|
.splice(0, agentContext.context.conversation.length)
|
|
17430
17637
|
.filter((s) => !!s);
|
|
17431
17638
|
if (userPrompts.length > 0) {
|
|
17432
|
-
const prompt = "The user is intervening in the current task
|
|
17639
|
+
const prompt = "The user is intervening in the current task, please replan and execute according to the following instructions:\n" +
|
|
17640
|
+
userPrompts.map((s) => `- ${s.trim()}`).join("\n");
|
|
17433
17641
|
messages.push({
|
|
17434
17642
|
role: "user",
|
|
17435
17643
|
content: [{ type: "text", text: prompt }],
|
|
@@ -17481,9 +17689,17 @@ function removeDuplicateToolUse(results) {
|
|
|
17481
17689
|
return _results;
|
|
17482
17690
|
}
|
|
17483
17691
|
async function compressAgentMessages(agentContext, rlm, messages, tools) {
|
|
17484
|
-
if (messages.length <
|
|
17692
|
+
if (messages.length < 5) {
|
|
17485
17693
|
return;
|
|
17486
17694
|
}
|
|
17695
|
+
try {
|
|
17696
|
+
doCompressAgentMessages(agentContext, rlm, messages, tools);
|
|
17697
|
+
}
|
|
17698
|
+
catch (e) {
|
|
17699
|
+
Log.error("Error compressing agent messages:", e);
|
|
17700
|
+
}
|
|
17701
|
+
}
|
|
17702
|
+
async function doCompressAgentMessages(agentContext, rlm, messages, tools) {
|
|
17487
17703
|
// extract used tool
|
|
17488
17704
|
let usedTools = extractUsedTool(messages, tools);
|
|
17489
17705
|
let snapshotTool = new TaskSnapshotTool();
|
|
@@ -17605,7 +17821,8 @@ function handleLargeContextMessages(messages) {
|
|
|
17605
17821
|
}
|
|
17606
17822
|
for (let r = 0; r < toolContent.length; r++) {
|
|
17607
17823
|
let _content = toolContent[r];
|
|
17608
|
-
if (_content.type == "text" &&
|
|
17824
|
+
if (_content.type == "text" &&
|
|
17825
|
+
_content.text?.length > config.largeTextLength) {
|
|
17609
17826
|
if (!longTextTools[toolResult.toolName]) {
|
|
17610
17827
|
longTextTools[toolResult.toolName] = 1;
|
|
17611
17828
|
break;
|
|
@@ -18378,6 +18595,7 @@ class Agent {
|
|
|
18378
18595
|
this.llms = params.llms;
|
|
18379
18596
|
this.mcpClient = params.mcpClient;
|
|
18380
18597
|
this.planDescription = params.planDescription;
|
|
18598
|
+
this.requestHandler = params.requestHandler;
|
|
18381
18599
|
}
|
|
18382
18600
|
async run(context, agentChain) {
|
|
18383
18601
|
let mcpClient = this.mcpClient || context.config.defaultMcpClient;
|
|
@@ -18423,7 +18641,7 @@ class Agent {
|
|
|
18423
18641
|
}
|
|
18424
18642
|
}
|
|
18425
18643
|
await this.handleMessages(agentContext, messages, tools);
|
|
18426
|
-
let results = await callAgentLLM(agentContext, rlm, messages, this.convertTools(agentTools), false, undefined,
|
|
18644
|
+
let results = await callAgentLLM(agentContext, rlm, messages, this.convertTools(agentTools), false, undefined, 0, this.callback, this.requestHandler);
|
|
18427
18645
|
let finalResult = await this.handleCallResult(agentContext, messages, agentTools, results);
|
|
18428
18646
|
if (finalResult) {
|
|
18429
18647
|
return finalResult;
|
|
@@ -18433,6 +18651,10 @@ class Agent {
|
|
|
18433
18651
|
return "Unfinished";
|
|
18434
18652
|
}
|
|
18435
18653
|
async handleCallResult(agentContext, messages, agentTools, results) {
|
|
18654
|
+
const forceStop = agentContext.variables.get("forceStop");
|
|
18655
|
+
if (forceStop) {
|
|
18656
|
+
return forceStop;
|
|
18657
|
+
}
|
|
18436
18658
|
let text = null;
|
|
18437
18659
|
let context = agentContext.context;
|
|
18438
18660
|
let user_messages = [];
|
|
@@ -18721,11 +18943,11 @@ class Agent {
|
|
|
18721
18943
|
}
|
|
18722
18944
|
}
|
|
18723
18945
|
|
|
18724
|
-
const AGENT_NAME$
|
|
18946
|
+
const AGENT_NAME$4 = "Chat";
|
|
18725
18947
|
class BaseChatAgent extends Agent {
|
|
18726
18948
|
constructor(llms, ext_tools, mcpClient) {
|
|
18727
18949
|
super({
|
|
18728
|
-
name: AGENT_NAME$
|
|
18950
|
+
name: AGENT_NAME$4,
|
|
18729
18951
|
description: "You are a helpful assistant.",
|
|
18730
18952
|
tools: ext_tools || [],
|
|
18731
18953
|
llms: llms,
|
|
@@ -18759,8 +18981,13 @@ Your task is to understand the user's requirements, dynamically plan the user's
|
|
|
18759
18981
|
<thought>Your thought process on user demand planning</thought>
|
|
18760
18982
|
<!-- Multiple Agents work together to complete the task -->
|
|
18761
18983
|
<agents>
|
|
18762
|
-
<!--
|
|
18763
|
-
|
|
18984
|
+
<!--
|
|
18985
|
+
Multi-Agent supports parallelism, coordinating parallel tasks through dependencies, and passing dependent context information through node variables.
|
|
18986
|
+
name: The name of the Agent, where the name can only be an available name in the Agent list.
|
|
18987
|
+
id: Use subscript order as ID for dependency relationships between multiple agents.
|
|
18988
|
+
dependsOn: The IDs of agents that the current agent depends on, separated by commas when there are multiple dependencies.
|
|
18989
|
+
-->
|
|
18990
|
+
<agent name="Agent name" id="0" dependsOn="">
|
|
18764
18991
|
<!-- The current Agent needs to complete the task -->
|
|
18765
18992
|
<task>current agent task</task>
|
|
18766
18993
|
<nodes>
|
|
@@ -18782,6 +19009,22 @@ Your task is to understand the user's requirements, dynamically plan the user's
|
|
|
18782
19009
|
</watch>
|
|
18783
19010
|
</nodes>
|
|
18784
19011
|
</agent>
|
|
19012
|
+
<!--
|
|
19013
|
+
Multi-agent Collaboration Dependency Example:
|
|
19014
|
+
|
|
19015
|
+
Execution Flow:
|
|
19016
|
+
1. Agent 0: Initial agent with no dependencies (executes first)
|
|
19017
|
+
2. Agent 1: Depends on Agent 0 completion (executes after Agent 0)
|
|
19018
|
+
3. Agent 2 & 3: Both depend on Agent 1 completion (execute in parallel after Agent 1)
|
|
19019
|
+
4. Agent 4: Depends on both Agent 2 and Agent 3 completion (executes last)
|
|
19020
|
+
|
|
19021
|
+
Dependency Chain: Agent 0 → Agent 1 → (Agent 2 ∥ Agent 3) → Agent 4
|
|
19022
|
+
-->
|
|
19023
|
+
<agent name="Agent name" id="0" dependsOn="">...</agent>
|
|
19024
|
+
<agent name="Agent name" id="1" dependsOn="0">...</agent>
|
|
19025
|
+
<agent name="Agent name" id="2" dependsOn="1">...</agent>
|
|
19026
|
+
<agent name="Agent name" id="3" dependsOn="1">...</agent>
|
|
19027
|
+
<agent name="Agent name" id="4" dependsOn="2,3">...</agent>
|
|
18785
19028
|
</agents>
|
|
18786
19029
|
</root>
|
|
18787
19030
|
|
|
@@ -18794,7 +19037,7 @@ Output result:
|
|
|
18794
19037
|
<thought>Alright, the user wrote "hello". That's pretty straightforward. I need to respond in a friendly and welcoming manner.</thought>
|
|
18795
19038
|
<agents>
|
|
18796
19039
|
<!-- Chat agents can exist without the <task> and <nodes> nodes. -->
|
|
18797
|
-
<agent name="Chat"></agent>
|
|
19040
|
+
<agent name="Chat" id="0" dependsOn=""></agent>
|
|
18798
19041
|
</agents>
|
|
18799
19042
|
</root>`;
|
|
18800
19043
|
const PLAN_EXAMPLE_LIST = [
|
|
@@ -18804,7 +19047,7 @@ Output result:
|
|
|
18804
19047
|
<name>Submit resume</name>
|
|
18805
19048
|
<thought>OK, now the user requests me to create a workflow that involves opening the Boss Zhipin website, finding 10 operation positions in Chengdu, and sending personal resumes to the recruiters based on the job information.</thought>
|
|
18806
19049
|
<agents>
|
|
18807
|
-
<agent name="Browser">
|
|
19050
|
+
<agent name="Browser" id="0" dependsOn="">
|
|
18808
19051
|
<task>Open Boss Zhipin, find 10 operation positions in Chengdu, and send a personal introduction to the recruiters based on the page information.</task>
|
|
18809
19052
|
<nodes>
|
|
18810
19053
|
<node>Open Boss Zhipin, enter the job search page</node>
|
|
@@ -18824,7 +19067,7 @@ Output result:
|
|
|
18824
19067
|
<name>Latest AI News</name>
|
|
18825
19068
|
<thought>OK, users need to collect the latest AI news, summarize it, and send it to a WeChat group named "AI news information" This requires automation, including the steps of data collection, processing, and distribution.</thought>
|
|
18826
19069
|
<agents>
|
|
18827
|
-
<agent name="Browser">
|
|
19070
|
+
<agent name="Browser" id="0" dependsOn="">
|
|
18828
19071
|
<task>Search for the latest updates on AI</task>
|
|
18829
19072
|
<nodes>
|
|
18830
19073
|
<node>Open Google</node>
|
|
@@ -18835,7 +19078,7 @@ Output result:
|
|
|
18835
19078
|
<node output="summaryInfo">Summarize search information</node>
|
|
18836
19079
|
</nodes>
|
|
18837
19080
|
</agent>
|
|
18838
|
-
<agent name="Computer">
|
|
19081
|
+
<agent name="Computer" id="1" dependsOn="0">
|
|
18839
19082
|
<task>Send a message to the WeChat group chat "AI news information"</task>
|
|
18840
19083
|
<nodes>
|
|
18841
19084
|
<node>Open WeChat</node>
|
|
@@ -18851,7 +19094,7 @@ Output result:
|
|
|
18851
19094
|
<name>Statistics of Google Team Developers' Geographic Distribution</name>
|
|
18852
19095
|
<thought>Okay, I need to first visit GitHub, then find Google's organization page on GitHub, extract the team member list, and individually visit each developer's homepage to obtain location information for each developer. This requires using a browser to complete all operations.</thought>
|
|
18853
19096
|
<agents>
|
|
18854
|
-
<agent name="Browser">
|
|
19097
|
+
<agent name="Browser" id="0" dependsOn="">
|
|
18855
19098
|
<task>Visit Google GitHub Organization Page and Analyze Developer Geographic Distribution</task>
|
|
18856
19099
|
<nodes>
|
|
18857
19100
|
<node>Visit https://github.com/google</node>
|
|
@@ -18873,7 +19116,7 @@ Output result:
|
|
|
18873
19116
|
<name>Automatic reply to Discord messages</name>
|
|
18874
19117
|
<thought>OK, monitor the chat messages in Discord group A and automatically reply.</thought>
|
|
18875
19118
|
<agents>
|
|
18876
|
-
<agent name="Browser">
|
|
19119
|
+
<agent name="Browser" id="0" dependsOn="">
|
|
18877
19120
|
<task>Open Group A in Discord</task>
|
|
18878
19121
|
<nodes>
|
|
18879
19122
|
<node>Open Discord page</node>
|
|
@@ -18888,6 +19131,59 @@ Output result:
|
|
|
18888
19131
|
</nodes>
|
|
18889
19132
|
</agent>
|
|
18890
19133
|
</agents>
|
|
19134
|
+
</root>`,
|
|
19135
|
+
`User: Search for information about "fellou," compile the results into a summary profile, then share it across social media platforms including Twitter, Facebook, and Reddit. Finally, export the platform sharing operation results to an Excel file.
|
|
19136
|
+
Output result:
|
|
19137
|
+
<root>
|
|
19138
|
+
<name>Fellou Research and Social Media Campaign</name>
|
|
19139
|
+
<thought>The user wants me to research information about 'Fellou', create a summary profile, share it on multiple social media platforms (Twitter, Facebook, Reddit), and then compile the results into an Excel file. This requires multiple agents working together: Browser for research, Browser for social media posting (Twitter, Facebook, and Reddit in parallel), and File for creating the Excel export. I need to break this down into sequential steps with proper variable passing between agents.</thought>
|
|
19140
|
+
<agents>
|
|
19141
|
+
<agent name="Browser" id="0" dependsOn="">
|
|
19142
|
+
<task>Research comprehensive information about 'Fellou'</task>
|
|
19143
|
+
<nodes>
|
|
19144
|
+
<node>Search for the latest information about 'Fellou' - its identity, purpose, and core features</node>
|
|
19145
|
+
<node>Search for Fellou's functionalities, capabilities, and technical specifications</node>
|
|
19146
|
+
<node>Search for recent news, updates, announcements, and developments related to Fellou</node>
|
|
19147
|
+
<node>Search for user reviews, feedback, and community discussions about Fellou</node>
|
|
19148
|
+
<node>Search for Fellou's market position, competitors, and industry context</node>
|
|
19149
|
+
<node output="researchData">Compile all research findings into a comprehensive summary profile</node>
|
|
19150
|
+
</nodes>
|
|
19151
|
+
</agent>
|
|
19152
|
+
<agent name="Browser" id="1" dependsOn="0">
|
|
19153
|
+
<task>Share Fellou's summary and collected interaction data on Twitter/X</task>
|
|
19154
|
+
<nodes>
|
|
19155
|
+
<node>Navigate to Twitter/X platform</node>
|
|
19156
|
+
<node input="researchData">Create and post Twitter-optimized content about Fellou (within character limits, using hashtags)</node>
|
|
19157
|
+
<node output="twitterResults">Capture Twitter post URL and initial engagement metrics</node>
|
|
19158
|
+
</nodes>
|
|
19159
|
+
</agent>
|
|
19160
|
+
<agent name="Browser" id="2" dependsOn="0">
|
|
19161
|
+
<task>Share Fellou's summary and collected interaction data on Facebook</task>
|
|
19162
|
+
<nodes>
|
|
19163
|
+
<node>Navigate to Facebook platform</node>
|
|
19164
|
+
<node input="researchData">Create and post Facebook-optimized content about Fellou (longer format, engaging description)</node>
|
|
19165
|
+
<node output="facebookResults">Capture Facebook post URL and initial engagement metrics</node>
|
|
19166
|
+
</nodes>
|
|
19167
|
+
</agent>
|
|
19168
|
+
<agent name="Browser" id="3" dependsOn="0">
|
|
19169
|
+
<task>Share Fellou's summary and collected interaction data on Reddit</task>
|
|
19170
|
+
<nodes>
|
|
19171
|
+
<node>Navigate to Reddit platform</node>
|
|
19172
|
+
<node input="researchData">Find appropriate subreddit and create Reddit-optimized post about Fellou (community-focused, informative)</node>
|
|
19173
|
+
<node output="redditResults">Capture Reddit post URL and initial engagement metrics</node>
|
|
19174
|
+
</nodes>
|
|
19175
|
+
</agent>
|
|
19176
|
+
<agent name="File" id="4" dependsOn="1,2,3">
|
|
19177
|
+
<task>Compile social media results into Excel file</task>
|
|
19178
|
+
<nodes>
|
|
19179
|
+
<node input="twitterResults,facebookResults,redditResults">Create Excel file with social media campaign results</node>
|
|
19180
|
+
<node>Include columns for Platform, Post URL, Content Summary, Timestamp, Initial Likes/Shares/Comments</node>
|
|
19181
|
+
<node>Format the Excel file with proper headers and styling</node>
|
|
19182
|
+
<node>Save the file as 'Fellou_Social_Media_Campaign_Results.xlsx'</node>
|
|
19183
|
+
</nodes>
|
|
19184
|
+
</agent>
|
|
19185
|
+
</agents>
|
|
19186
|
+
</agents>
|
|
18891
19187
|
</root>`,
|
|
18892
19188
|
];
|
|
18893
19189
|
const PLAN_USER_TEMPLATE = `
|
|
@@ -18918,7 +19214,7 @@ async function getPlanSystemPrompt(context) {
|
|
|
18918
19214
|
"\n</agent>\n\n";
|
|
18919
19215
|
}
|
|
18920
19216
|
let plan_example_list = context.variables.get("plan_example_list") || PLAN_EXAMPLE_LIST;
|
|
18921
|
-
let hasChatAgent = context.agents.filter((a) => a.Name == AGENT_NAME$
|
|
19217
|
+
let hasChatAgent = context.agents.filter((a) => a.Name == AGENT_NAME$4).length > 0;
|
|
18922
19218
|
let example_prompt = "";
|
|
18923
19219
|
const example_list = hasChatAgent
|
|
18924
19220
|
? [PLAN_CHAT_EXAMPLE, ...plan_example_list]
|
|
@@ -18951,9 +19247,10 @@ function getPlanUserPrompt(task_prompt, task_website, ext_prompt) {
|
|
|
18951
19247
|
}
|
|
18952
19248
|
|
|
18953
19249
|
class Planner {
|
|
18954
|
-
constructor(context,
|
|
19250
|
+
constructor(context, callback) {
|
|
18955
19251
|
this.context = context;
|
|
18956
|
-
this.taskId =
|
|
19252
|
+
this.taskId = context.taskId;
|
|
19253
|
+
this.callback = callback || context.config.callback;
|
|
18957
19254
|
}
|
|
18958
19255
|
async plan(taskPrompt, saveHistory = true) {
|
|
18959
19256
|
let taskPromptStr;
|
|
@@ -19017,7 +19314,7 @@ class Planner {
|
|
|
19017
19314
|
let thinkingText = "";
|
|
19018
19315
|
try {
|
|
19019
19316
|
while (true) {
|
|
19020
|
-
await this.context.checkAborted();
|
|
19317
|
+
await this.context.checkAborted(true);
|
|
19021
19318
|
const { done, value } = await reader.read();
|
|
19022
19319
|
if (done) {
|
|
19023
19320
|
break;
|
|
@@ -19033,10 +19330,10 @@ class Planner {
|
|
|
19033
19330
|
if (chunk.type == "text-delta") {
|
|
19034
19331
|
streamText += chunk.textDelta || "";
|
|
19035
19332
|
}
|
|
19036
|
-
if (
|
|
19333
|
+
if (this.callback) {
|
|
19037
19334
|
let workflow = parseWorkflow(this.taskId, streamText, false, thinkingText);
|
|
19038
19335
|
if (workflow) {
|
|
19039
|
-
await
|
|
19336
|
+
await this.callback.onMessage({
|
|
19040
19337
|
taskId: this.taskId,
|
|
19041
19338
|
agentName: "Planer",
|
|
19042
19339
|
type: "workflow",
|
|
@@ -19059,8 +19356,8 @@ class Planner {
|
|
|
19059
19356
|
chain.planResult = streamText;
|
|
19060
19357
|
}
|
|
19061
19358
|
let workflow = parseWorkflow(this.taskId, streamText, true, thinkingText);
|
|
19062
|
-
if (
|
|
19063
|
-
await
|
|
19359
|
+
if (this.callback) {
|
|
19360
|
+
await this.callback.onMessage({
|
|
19064
19361
|
taskId: this.taskId,
|
|
19065
19362
|
agentName: "Planer",
|
|
19066
19363
|
type: "workflow",
|
|
@@ -19085,18 +19382,18 @@ class Eko {
|
|
|
19085
19382
|
}
|
|
19086
19383
|
async generate(taskPrompt, taskId = uuidv4(), contextParams) {
|
|
19087
19384
|
const agents = [...(this.config.agents || [])];
|
|
19088
|
-
|
|
19089
|
-
|
|
19385
|
+
const chain = new Chain(taskPrompt);
|
|
19386
|
+
const context = new Context(taskId, this.config, agents, chain);
|
|
19090
19387
|
if (contextParams) {
|
|
19091
19388
|
Object.keys(contextParams).forEach((key) => context.variables.set(key, contextParams[key]));
|
|
19092
19389
|
}
|
|
19093
19390
|
try {
|
|
19094
19391
|
this.taskMap.set(taskId, context);
|
|
19095
19392
|
if (this.config.a2aClient) {
|
|
19096
|
-
|
|
19393
|
+
const a2aList = await this.config.a2aClient.listAgents(taskPrompt);
|
|
19097
19394
|
context.agents = mergeAgents(context.agents, a2aList);
|
|
19098
19395
|
}
|
|
19099
|
-
|
|
19396
|
+
const planner = new Planner(context);
|
|
19100
19397
|
context.workflow = await planner.plan(taskPrompt);
|
|
19101
19398
|
return context.workflow;
|
|
19102
19399
|
}
|
|
@@ -19106,20 +19403,20 @@ class Eko {
|
|
|
19106
19403
|
}
|
|
19107
19404
|
}
|
|
19108
19405
|
async modify(taskId, modifyTaskPrompt) {
|
|
19109
|
-
|
|
19406
|
+
const context = this.taskMap.get(taskId);
|
|
19110
19407
|
if (!context) {
|
|
19111
19408
|
return await this.generate(modifyTaskPrompt, taskId);
|
|
19112
19409
|
}
|
|
19113
19410
|
if (this.config.a2aClient) {
|
|
19114
|
-
|
|
19411
|
+
const a2aList = await this.config.a2aClient.listAgents(modifyTaskPrompt);
|
|
19115
19412
|
context.agents = mergeAgents(context.agents, a2aList);
|
|
19116
19413
|
}
|
|
19117
|
-
|
|
19414
|
+
const planner = new Planner(context);
|
|
19118
19415
|
context.workflow = await planner.replan(modifyTaskPrompt);
|
|
19119
19416
|
return context.workflow;
|
|
19120
19417
|
}
|
|
19121
19418
|
async execute(taskId) {
|
|
19122
|
-
|
|
19419
|
+
const context = this.getTask(taskId);
|
|
19123
19420
|
if (!context) {
|
|
19124
19421
|
throw new Error("The task does not exist");
|
|
19125
19422
|
}
|
|
@@ -19149,10 +19446,10 @@ class Eko {
|
|
|
19149
19446
|
}
|
|
19150
19447
|
async initContext(workflow, contextParams) {
|
|
19151
19448
|
const agents = this.config.agents || [];
|
|
19152
|
-
|
|
19153
|
-
|
|
19449
|
+
const chain = new Chain(workflow.taskPrompt || workflow.name);
|
|
19450
|
+
const context = new Context(workflow.taskId, this.config, agents, chain);
|
|
19154
19451
|
if (this.config.a2aClient) {
|
|
19155
|
-
|
|
19452
|
+
const a2aList = await this.config.a2aClient.listAgents(workflow.taskPrompt || workflow.name);
|
|
19156
19453
|
context.agents = mergeAgents(context.agents, a2aList);
|
|
19157
19454
|
}
|
|
19158
19455
|
if (contextParams) {
|
|
@@ -19163,30 +19460,88 @@ class Eko {
|
|
|
19163
19460
|
return context;
|
|
19164
19461
|
}
|
|
19165
19462
|
async doRunWorkflow(context) {
|
|
19166
|
-
|
|
19167
|
-
|
|
19463
|
+
const agents = context.agents;
|
|
19464
|
+
const workflow = context.workflow;
|
|
19168
19465
|
if (!workflow || workflow.agents.length == 0) {
|
|
19169
19466
|
throw new Error("Workflow error");
|
|
19170
19467
|
}
|
|
19171
|
-
|
|
19468
|
+
const agentNameMap = agents.reduce((map, item) => {
|
|
19172
19469
|
map[item.Name] = item;
|
|
19173
19470
|
return map;
|
|
19174
19471
|
}, {});
|
|
19175
|
-
let
|
|
19176
|
-
|
|
19472
|
+
let agentTree = buildAgentTree(workflow.agents);
|
|
19473
|
+
const results = [];
|
|
19474
|
+
while (true) {
|
|
19177
19475
|
await context.checkAborted();
|
|
19178
|
-
|
|
19179
|
-
|
|
19180
|
-
|
|
19181
|
-
|
|
19182
|
-
|
|
19183
|
-
|
|
19184
|
-
|
|
19185
|
-
|
|
19186
|
-
|
|
19187
|
-
|
|
19476
|
+
if (agentTree.type === "normal") {
|
|
19477
|
+
// normal agent
|
|
19478
|
+
const agent = agentNameMap[agentTree.agent.name];
|
|
19479
|
+
if (!agent) {
|
|
19480
|
+
throw new Error("Unknown Agent: " + agentTree.agent.name);
|
|
19481
|
+
}
|
|
19482
|
+
const agentNode = agentTree.agent;
|
|
19483
|
+
const agentChain = new AgentChain(agentNode);
|
|
19484
|
+
context.chain.push(agentChain);
|
|
19485
|
+
try {
|
|
19486
|
+
agentNode.status = "running";
|
|
19487
|
+
agentTree.result = await agent.run(context, agentChain);
|
|
19488
|
+
agentNode.status = "done";
|
|
19489
|
+
results.push(agentTree.result);
|
|
19490
|
+
}
|
|
19491
|
+
catch (e) {
|
|
19492
|
+
agentNode.status = "error";
|
|
19493
|
+
throw e;
|
|
19494
|
+
}
|
|
19495
|
+
}
|
|
19496
|
+
else {
|
|
19497
|
+
// parallel agent
|
|
19498
|
+
const parallelAgents = agentTree.agents;
|
|
19499
|
+
const doRunAgent = async (agentNode, index) => {
|
|
19500
|
+
const agent = agentNameMap[agentNode.agent.name];
|
|
19501
|
+
if (!agent) {
|
|
19502
|
+
throw new Error("Unknown Agent: " + agentNode.agent.name);
|
|
19503
|
+
}
|
|
19504
|
+
const agentChain = new AgentChain(agentNode.agent);
|
|
19505
|
+
try {
|
|
19506
|
+
agentNode.agent.status = "running";
|
|
19507
|
+
agentNode.result = await agent.run(context, agentChain);
|
|
19508
|
+
agentNode.agent.status = "done";
|
|
19509
|
+
}
|
|
19510
|
+
catch (e) {
|
|
19511
|
+
agentNode.agent.status = "error";
|
|
19512
|
+
throw e;
|
|
19513
|
+
}
|
|
19514
|
+
return { result: agentNode.result, agentChain, index };
|
|
19515
|
+
};
|
|
19516
|
+
let agent_results = [];
|
|
19517
|
+
let agentParallel = context.variables.get("agentParallel");
|
|
19518
|
+
if (agentParallel === undefined) {
|
|
19519
|
+
agentParallel = config.agentParallel;
|
|
19520
|
+
}
|
|
19521
|
+
if (agentParallel) {
|
|
19522
|
+
// parallel execution
|
|
19523
|
+
const parallelResults = await Promise.all(parallelAgents.map((agent, index) => doRunAgent(agent, index)));
|
|
19524
|
+
parallelResults.sort((a, b) => a.index - b.index);
|
|
19525
|
+
parallelResults.forEach(({ agentChain }) => {
|
|
19526
|
+
context.chain.push(agentChain);
|
|
19527
|
+
});
|
|
19528
|
+
agent_results = parallelResults.map(({ result }) => result);
|
|
19529
|
+
}
|
|
19530
|
+
else {
|
|
19531
|
+
// serial execution
|
|
19532
|
+
for (let i = 0; i < parallelAgents.length; i++) {
|
|
19533
|
+
const { result, agentChain } = await doRunAgent(parallelAgents[i], i);
|
|
19534
|
+
context.chain.push(agentChain);
|
|
19535
|
+
agent_results.push(result);
|
|
19536
|
+
}
|
|
19537
|
+
}
|
|
19538
|
+
results.push(agent_results.join("\n\n"));
|
|
19539
|
+
}
|
|
19540
|
+
context.conversation.splice(0, context.conversation.length);
|
|
19541
|
+
if (!agentTree.nextAgent) {
|
|
19188
19542
|
break;
|
|
19189
19543
|
}
|
|
19544
|
+
agentTree = agentTree.nextAgent;
|
|
19190
19545
|
}
|
|
19191
19546
|
return {
|
|
19192
19547
|
success: true,
|
|
@@ -19222,7 +19577,7 @@ class Eko {
|
|
|
19222
19577
|
}
|
|
19223
19578
|
}
|
|
19224
19579
|
pauseTask(taskId, pause, abortCurrentStep, reason) {
|
|
19225
|
-
|
|
19580
|
+
const context = this.taskMap.get(taskId);
|
|
19226
19581
|
if (context) {
|
|
19227
19582
|
this.onTaskStatus(context, pause ? "pause" : "resume-pause", reason);
|
|
19228
19583
|
context.setPause(pause, abortCurrentStep);
|
|
@@ -19233,7 +19588,7 @@ class Eko {
|
|
|
19233
19588
|
}
|
|
19234
19589
|
}
|
|
19235
19590
|
chatTask(taskId, userPrompt) {
|
|
19236
|
-
|
|
19591
|
+
const context = this.taskMap.get(taskId);
|
|
19237
19592
|
if (context) {
|
|
19238
19593
|
context.conversation.push(userPrompt);
|
|
19239
19594
|
return context.conversation;
|
|
@@ -19476,7 +19831,7 @@ function parseChunk(chunk) {
|
|
|
19476
19831
|
return chunk_obj;
|
|
19477
19832
|
}
|
|
19478
19833
|
|
|
19479
|
-
const AGENT_NAME$
|
|
19834
|
+
const AGENT_NAME$3 = "File";
|
|
19480
19835
|
class BaseFileAgent extends Agent {
|
|
19481
19836
|
constructor(work_path, llms, ext_tools, mcpClient, planDescription) {
|
|
19482
19837
|
const _tools_ = [];
|
|
@@ -19484,7 +19839,7 @@ class BaseFileAgent extends Agent {
|
|
|
19484
19839
|
? `Your default working path is: ${work_path}`
|
|
19485
19840
|
: "";
|
|
19486
19841
|
super({
|
|
19487
|
-
name: AGENT_NAME$
|
|
19842
|
+
name: AGENT_NAME$3,
|
|
19488
19843
|
description: `You are a file agent, handling file-related tasks such as creating, finding, reading, modifying files, etc.${prompt}`,
|
|
19489
19844
|
tools: _tools_,
|
|
19490
19845
|
llms: llms,
|
|
@@ -19636,7 +19991,7 @@ class BaseFileAgent extends Agent {
|
|
|
19636
19991
|
},
|
|
19637
19992
|
glob: {
|
|
19638
19993
|
type: "string",
|
|
19639
|
-
description: "Filename pattern using glob syntax wildcards",
|
|
19994
|
+
description: "Filename pattern using glob syntax wildcards, Example: **/*.txt",
|
|
19640
19995
|
},
|
|
19641
19996
|
},
|
|
19642
19997
|
required: ["path", "glob"],
|
|
@@ -19649,12 +20004,12 @@ class BaseFileAgent extends Agent {
|
|
|
19649
20004
|
}
|
|
19650
20005
|
}
|
|
19651
20006
|
|
|
19652
|
-
const AGENT_NAME$
|
|
20007
|
+
const AGENT_NAME$2 = "Shell";
|
|
19653
20008
|
class BaseShellAgent extends Agent {
|
|
19654
20009
|
constructor(llms, ext_tools, mcpClient, planDescription) {
|
|
19655
20010
|
const _tools_ = [];
|
|
19656
20011
|
super({
|
|
19657
|
-
name: AGENT_NAME$
|
|
20012
|
+
name: AGENT_NAME$2,
|
|
19658
20013
|
description: `Run commands in a bash shell,
|
|
19659
20014
|
* You must first call create_session to create a new session when using it for the first time.
|
|
19660
20015
|
* Please execute delete commands with caution, and never perform dangerous operations like \`rm -rf /\`.
|
|
@@ -19731,47 +20086,6 @@ class BaseShellAgent extends Agent {
|
|
|
19731
20086
|
}
|
|
19732
20087
|
}
|
|
19733
20088
|
|
|
19734
|
-
const AGENT_NAME$2 = "Timer";
|
|
19735
|
-
class BaseTimerAgent extends Agent {
|
|
19736
|
-
constructor(llms, ext_tools, mcpClient) {
|
|
19737
|
-
super({
|
|
19738
|
-
name: AGENT_NAME$2,
|
|
19739
|
-
description: "You are a scheduled task scheduling agent.",
|
|
19740
|
-
tools: ext_tools || [],
|
|
19741
|
-
llms: llms,
|
|
19742
|
-
mcpClient: mcpClient,
|
|
19743
|
-
});
|
|
19744
|
-
this.addTool(this.schedule_tool());
|
|
19745
|
-
}
|
|
19746
|
-
schedule_tool() {
|
|
19747
|
-
return {
|
|
19748
|
-
name: "task_schedule",
|
|
19749
|
-
description: "Task scheduled trigger, the task is triggered at a scheduled time and will automatically create a scheduled task for execution.",
|
|
19750
|
-
parameters: {
|
|
19751
|
-
type: "object",
|
|
19752
|
-
properties: {
|
|
19753
|
-
trigger_description: {
|
|
19754
|
-
type: "string",
|
|
19755
|
-
description: "Trigger time description.",
|
|
19756
|
-
},
|
|
19757
|
-
task_description: {
|
|
19758
|
-
type: "string",
|
|
19759
|
-
description: "Main task description, excluding trigger time.",
|
|
19760
|
-
},
|
|
19761
|
-
cron: {
|
|
19762
|
-
type: "string",
|
|
19763
|
-
description: "The cron expression of the trigger, for example, '0 9 * * *' indicates that it triggers at 9 a.m. every day.",
|
|
19764
|
-
},
|
|
19765
|
-
},
|
|
19766
|
-
required: ["cron"],
|
|
19767
|
-
},
|
|
19768
|
-
execute: async (args, agentContext) => {
|
|
19769
|
-
return await this.callInnerTool(() => this.task_schedule(agentContext, args.trigger_description, args.task_description, args.cron));
|
|
19770
|
-
},
|
|
19771
|
-
};
|
|
19772
|
-
}
|
|
19773
|
-
}
|
|
19774
|
-
|
|
19775
20089
|
const AGENT_NAME$1 = "Computer";
|
|
19776
20090
|
class BaseComputerAgent extends Agent {
|
|
19777
20091
|
constructor(llms, ext_tools, mcpClient, keyboardKeys) {
|
|
@@ -21968,7 +22282,6 @@ exports.BaseChatAgent = BaseChatAgent;
|
|
|
21968
22282
|
exports.BaseComputerAgent = BaseComputerAgent;
|
|
21969
22283
|
exports.BaseFileAgent = BaseFileAgent;
|
|
21970
22284
|
exports.BaseShellAgent = BaseShellAgent;
|
|
21971
|
-
exports.BaseTimerAgent = BaseTimerAgent;
|
|
21972
22285
|
exports.Chain = Chain;
|
|
21973
22286
|
exports.Context = Context;
|
|
21974
22287
|
exports.Eko = Eko;
|
|
@@ -21981,6 +22294,7 @@ exports.SimpleSseMcpClient = SimpleSseMcpClient;
|
|
|
21981
22294
|
exports.TaskNodeStatusTool = TaskNodeStatusTool;
|
|
21982
22295
|
exports.VariableStorageTool = VariableStorageTool;
|
|
21983
22296
|
exports.WatchTriggerTool = WatchTriggerTool;
|
|
22297
|
+
exports.buildAgentTree = buildAgentTree;
|
|
21984
22298
|
exports.buildSimpleAgentWorkflow = buildSimpleAgentWorkflow;
|
|
21985
22299
|
exports.call_timeout = call_timeout;
|
|
21986
22300
|
exports.config = config;
|