@smythos/sre 1.5.46 → 1.5.50
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/CHANGELOG +98 -90
- package/LICENSE +18 -18
- package/README.md +135 -135
- package/dist/bundle-analysis-lazy.html +4949 -0
- package/dist/bundle-analysis.html +4949 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/types/Components/MCPClient.class.d.ts +1 -0
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.d.ts +1 -6
- package/dist/types/utils/package-manager.utils.d.ts +26 -0
- package/package.json +1 -1
- package/src/Components/APICall/APICall.class.ts +156 -156
- package/src/Components/APICall/AccessTokenManager.ts +130 -130
- package/src/Components/APICall/ArrayBufferResponse.helper.ts +58 -58
- package/src/Components/APICall/OAuth.helper.ts +294 -294
- package/src/Components/APICall/mimeTypeCategories.ts +46 -46
- package/src/Components/APICall/parseData.ts +167 -167
- package/src/Components/APICall/parseHeaders.ts +41 -41
- package/src/Components/APICall/parseProxy.ts +68 -68
- package/src/Components/APICall/parseUrl.ts +91 -91
- package/src/Components/APIEndpoint.class.ts +234 -234
- package/src/Components/APIOutput.class.ts +58 -58
- package/src/Components/AgentPlugin.class.ts +102 -102
- package/src/Components/Async.class.ts +155 -155
- package/src/Components/Await.class.ts +90 -90
- package/src/Components/Classifier.class.ts +158 -158
- package/src/Components/Component.class.ts +132 -132
- package/src/Components/ComponentHost.class.ts +38 -38
- package/src/Components/DataSourceCleaner.class.ts +92 -92
- package/src/Components/DataSourceIndexer.class.ts +181 -181
- package/src/Components/DataSourceLookup.class.ts +161 -161
- package/src/Components/ECMASandbox.class.ts +71 -71
- package/src/Components/FEncDec.class.ts +29 -29
- package/src/Components/FHash.class.ts +33 -33
- package/src/Components/FSign.class.ts +80 -80
- package/src/Components/FSleep.class.ts +25 -25
- package/src/Components/FTimestamp.class.ts +25 -25
- package/src/Components/FileStore.class.ts +78 -78
- package/src/Components/ForEach.class.ts +97 -97
- package/src/Components/GPTPlugin.class.ts +70 -70
- package/src/Components/GenAILLM.class.ts +586 -586
- package/src/Components/HuggingFace.class.ts +314 -314
- package/src/Components/Image/imageSettings.config.ts +70 -70
- package/src/Components/ImageGenerator.class.ts +502 -502
- package/src/Components/JSONFilter.class.ts +54 -54
- package/src/Components/LLMAssistant.class.ts +213 -213
- package/src/Components/LogicAND.class.ts +28 -28
- package/src/Components/LogicAtLeast.class.ts +85 -85
- package/src/Components/LogicAtMost.class.ts +86 -86
- package/src/Components/LogicOR.class.ts +29 -29
- package/src/Components/LogicXOR.class.ts +34 -34
- package/src/Components/MCPClient.class.ts +138 -112
- package/src/Components/MemoryDeleteKeyVal.class.ts +70 -70
- package/src/Components/MemoryReadKeyVal.class.ts +66 -66
- package/src/Components/MemoryWriteKeyVal.class.ts +62 -62
- package/src/Components/MemoryWriteObject.class.ts +97 -97
- package/src/Components/MultimodalLLM.class.ts +128 -128
- package/src/Components/OpenAPI.class.ts +72 -72
- package/src/Components/PromptGenerator.class.ts +122 -122
- package/src/Components/ScrapflyWebScrape.class.ts +159 -159
- package/src/Components/ServerlessCode.class.ts +123 -123
- package/src/Components/TavilyWebSearch.class.ts +98 -98
- package/src/Components/VisionLLM.class.ts +104 -104
- package/src/Components/ZapierAction.class.ts +127 -127
- package/src/Components/index.ts +97 -97
- package/src/Core/AgentProcess.helper.ts +240 -240
- package/src/Core/Connector.class.ts +123 -123
- package/src/Core/ConnectorsService.ts +197 -197
- package/src/Core/DummyConnector.ts +49 -49
- package/src/Core/HookService.ts +105 -105
- package/src/Core/SmythRuntime.class.ts +235 -235
- package/src/Core/SystemEvents.ts +16 -16
- package/src/Core/boot.ts +56 -56
- package/src/config.ts +15 -15
- package/src/constants.ts +126 -126
- package/src/data/hugging-face.params.json +579 -579
- package/src/helpers/AWSLambdaCode.helper.ts +587 -587
- package/src/helpers/BinaryInput.helper.ts +331 -331
- package/src/helpers/Conversation.helper.ts +1119 -1119
- package/src/helpers/ECMASandbox.helper.ts +54 -54
- package/src/helpers/JsonContent.helper.ts +97 -97
- package/src/helpers/LocalCache.helper.ts +97 -97
- package/src/helpers/Log.helper.ts +274 -274
- package/src/helpers/OpenApiParser.helper.ts +150 -150
- package/src/helpers/S3Cache.helper.ts +147 -147
- package/src/helpers/SmythURI.helper.ts +5 -5
- package/src/helpers/Sysconfig.helper.ts +77 -77
- package/src/helpers/TemplateString.helper.ts +243 -243
- package/src/helpers/TypeChecker.helper.ts +329 -329
- package/src/index.ts +3 -3
- package/src/index.ts.bak +3 -3
- package/src/subsystems/AgentManager/Agent.class.ts +1114 -1114
- package/src/subsystems/AgentManager/Agent.helper.ts +3 -3
- package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +230 -230
- package/src/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.ts +66 -66
- package/src/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.ts +142 -142
- package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +39 -39
- package/src/subsystems/AgentManager/AgentData.service/index.ts +18 -18
- package/src/subsystems/AgentManager/AgentLogger.class.ts +297 -297
- package/src/subsystems/AgentManager/AgentRequest.class.ts +51 -51
- package/src/subsystems/AgentManager/AgentRuntime.class.ts +559 -559
- package/src/subsystems/AgentManager/AgentSSE.class.ts +101 -101
- package/src/subsystems/AgentManager/AgentSettings.class.ts +52 -52
- package/src/subsystems/AgentManager/Component.service/ComponentConnector.ts +32 -32
- package/src/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.ts +60 -60
- package/src/subsystems/AgentManager/Component.service/index.ts +11 -11
- package/src/subsystems/AgentManager/EmbodimentSettings.class.ts +47 -47
- package/src/subsystems/AgentManager/ForkedAgent.class.ts +154 -154
- package/src/subsystems/AgentManager/OSResourceMonitor.ts +77 -77
- package/src/subsystems/ComputeManager/Code.service/CodeConnector.ts +98 -98
- package/src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts +172 -172
- package/src/subsystems/ComputeManager/Code.service/connectors/ECMASandbox.class.ts +131 -131
- package/src/subsystems/ComputeManager/Code.service/index.ts +13 -13
- package/src/subsystems/IO/CLI.service/CLIConnector.ts +47 -47
- package/src/subsystems/IO/CLI.service/index.ts +9 -9
- package/src/subsystems/IO/Log.service/LogConnector.ts +32 -32
- package/src/subsystems/IO/Log.service/connectors/ConsoleLog.class.ts +28 -28
- package/src/subsystems/IO/Log.service/index.ts +13 -13
- package/src/subsystems/IO/NKV.service/NKVConnector.ts +43 -43
- package/src/subsystems/IO/NKV.service/connectors/NKVLocalStorage.class.ts +234 -234
- package/src/subsystems/IO/NKV.service/connectors/NKVRAM.class.ts +204 -204
- package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +182 -182
- package/src/subsystems/IO/NKV.service/index.ts +14 -14
- package/src/subsystems/IO/Router.service/RouterConnector.ts +21 -21
- package/src/subsystems/IO/Router.service/connectors/ExpressRouter.class.ts +48 -48
- package/src/subsystems/IO/Router.service/connectors/NullRouter.class.ts +40 -40
- package/src/subsystems/IO/Router.service/index.ts +11 -11
- package/src/subsystems/IO/Storage.service/SmythFS.class.ts +489 -489
- package/src/subsystems/IO/Storage.service/StorageConnector.ts +66 -66
- package/src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts +327 -327
- package/src/subsystems/IO/Storage.service/connectors/S3Storage.class.ts +482 -482
- package/src/subsystems/IO/Storage.service/index.ts +13 -13
- package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +108 -108
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +454 -454
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +384 -384
- package/src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts +421 -421
- package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +107 -107
- package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +109 -109
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +21 -21
- package/src/subsystems/IO/VectorDB.service/index.ts +14 -14
- package/src/subsystems/LLMManager/LLM.helper.ts +251 -251
- package/src/subsystems/LLMManager/LLM.inference.ts +339 -339
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +489 -489
- package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +171 -171
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +659 -659
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +400 -400
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +77 -77
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +757 -757
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +304 -304
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +250 -250
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +423 -423
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +488 -488
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +524 -524
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.ts +100 -100
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterfaceFactory.ts +81 -81
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +1145 -1145
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/constants.ts +13 -13
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/index.ts +4 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/utils.ts +11 -11
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/types.ts +32 -32
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +471 -471
- package/src/subsystems/LLMManager/LLM.service/index.ts +44 -44
- package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +300 -300
- package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +252 -252
- package/src/subsystems/LLMManager/ModelsProvider.service/index.ts +11 -11
- package/src/subsystems/LLMManager/custom-models.ts +854 -854
- package/src/subsystems/LLMManager/models.ts +2540 -2540
- package/src/subsystems/LLMManager/paramMappings.ts +69 -69
- package/src/subsystems/MemoryManager/Cache.service/CacheConnector.ts +86 -86
- package/src/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.ts +297 -297
- package/src/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.ts +201 -201
- package/src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts +252 -252
- package/src/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.ts +373 -373
- package/src/subsystems/MemoryManager/Cache.service/index.ts +15 -15
- package/src/subsystems/MemoryManager/LLMCache.ts +72 -72
- package/src/subsystems/MemoryManager/LLMContext.ts +124 -124
- package/src/subsystems/MemoryManager/LLMMemory.service/LLMMemoryConnector.ts +26 -26
- package/src/subsystems/MemoryManager/RuntimeContext.ts +266 -266
- package/src/subsystems/Security/AccessControl/ACL.class.ts +208 -208
- package/src/subsystems/Security/AccessControl/AccessCandidate.class.ts +82 -82
- package/src/subsystems/Security/AccessControl/AccessRequest.class.ts +52 -52
- package/src/subsystems/Security/Account.service/AccountConnector.ts +44 -44
- package/src/subsystems/Security/Account.service/connectors/AWSAccount.class.ts +76 -76
- package/src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts +130 -130
- package/src/subsystems/Security/Account.service/connectors/JSONFileAccount.class.ts +159 -159
- package/src/subsystems/Security/Account.service/index.ts +14 -14
- package/src/subsystems/Security/Credentials.helper.ts +62 -62
- package/src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts +38 -38
- package/src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts +53 -53
- package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +154 -154
- package/src/subsystems/Security/ManagedVault.service/index.ts +12 -12
- package/src/subsystems/Security/SecureConnector.class.ts +110 -110
- package/src/subsystems/Security/Vault.service/Vault.helper.ts +30 -30
- package/src/subsystems/Security/Vault.service/VaultConnector.ts +29 -29
- package/src/subsystems/Security/Vault.service/connectors/HashicorpVault.class.ts +46 -46
- package/src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts +221 -221
- package/src/subsystems/Security/Vault.service/connectors/NullVault.class.ts +54 -54
- package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +140 -140
- package/src/subsystems/Security/Vault.service/index.ts +12 -12
- package/src/types/ACL.types.ts +104 -104
- package/src/types/AWS.types.ts +10 -10
- package/src/types/Agent.types.ts +61 -61
- package/src/types/AgentLogger.types.ts +17 -17
- package/src/types/Cache.types.ts +1 -1
- package/src/types/Common.types.ts +2 -2
- package/src/types/LLM.types.ts +496 -496
- package/src/types/Redis.types.ts +8 -8
- package/src/types/SRE.types.ts +64 -64
- package/src/types/Security.types.ts +14 -14
- package/src/types/Storage.types.ts +5 -5
- package/src/types/VectorDB.types.ts +86 -86
- package/src/utils/base64.utils.ts +275 -275
- package/src/utils/cli.utils.ts +68 -68
- package/src/utils/data.utils.ts +322 -322
- package/src/utils/date-time.utils.ts +22 -22
- package/src/utils/general.utils.ts +238 -238
- package/src/utils/index.ts +12 -12
- package/src/utils/lazy-client.ts +261 -261
- package/src/utils/numbers.utils.ts +13 -13
- package/src/utils/oauth.utils.ts +35 -35
- package/src/utils/string.utils.ts +414 -414
- package/src/utils/url.utils.ts +19 -19
- package/src/utils/validation.utils.ts +74 -74
- package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.d.ts +0 -39
|
@@ -1,559 +1,559 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { Agent } from './Agent.class';
|
|
4
|
-
import { Component } from '@sre/Components/Component.class';
|
|
5
|
-
|
|
6
|
-
import { Logger } from '@sre/helpers/Log.helper';
|
|
7
|
-
import { uid } from '@sre/utils';
|
|
8
|
-
import { RuntimeContext } from '@sre/MemoryManager/RuntimeContext';
|
|
9
|
-
import { LLMCache } from '@sre/MemoryManager/LLMCache';
|
|
10
|
-
import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
|
|
11
|
-
|
|
12
|
-
const console = Logger('AgentRuntime');
|
|
13
|
-
const AgentRuntimeUnavailable = new Proxy(
|
|
14
|
-
{},
|
|
15
|
-
{
|
|
16
|
-
get: function (target, prop, receiver) {
|
|
17
|
-
// Check if the property being accessed is a function
|
|
18
|
-
if (typeof target[prop] === 'function') {
|
|
19
|
-
return target[prop];
|
|
20
|
-
} else {
|
|
21
|
-
// Return a function that logs "unavailable"
|
|
22
|
-
return function () {
|
|
23
|
-
console.warn(`AgentRuntime Unavailable tried to call : ${prop.toString()}`);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
);
|
|
29
|
-
export class AgentRuntime {
|
|
30
|
-
private static processResults: any = {};
|
|
31
|
-
private static tagsData = {};
|
|
32
|
-
public static dummy = AgentRuntimeUnavailable;
|
|
33
|
-
|
|
34
|
-
private agentContext: RuntimeContext;
|
|
35
|
-
public llmCache: LLMCache;
|
|
36
|
-
//private ctxFile: string = '';
|
|
37
|
-
private xDebugRun: string | undefined = '';
|
|
38
|
-
private xDebugInject: string | undefined = '';
|
|
39
|
-
private xDebugRead: string | undefined = '';
|
|
40
|
-
private xDebugStop: string | undefined = '';
|
|
41
|
-
private xDebugPendingInject: any = null;
|
|
42
|
-
private xMockDataInject: any = null;
|
|
43
|
-
public xDebugId: string | undefined = '';
|
|
44
|
-
|
|
45
|
-
private xDebugCmd: string | undefined = '';
|
|
46
|
-
private _debugActive = false;
|
|
47
|
-
private _runtimeFileReady = false;
|
|
48
|
-
public sessionClosed = false;
|
|
49
|
-
|
|
50
|
-
private reqTagOwner = false;
|
|
51
|
-
|
|
52
|
-
//reqTag is used to identify the current running workflow including nested calls, it allows us to identify circular calls
|
|
53
|
-
public reqTag: any;
|
|
54
|
-
public processID: any; //this identifies the current processID, a process ID is the full set of runCycles that is executed by the agent.
|
|
55
|
-
public workflowReqId: any; //this identifies the current running workflow. a workflow starts when and agent endpoint is called, or a debug session is initiated, and ends when no more steps can be executed.
|
|
56
|
-
|
|
57
|
-
public alwaysActiveComponents: any = {};
|
|
58
|
-
public exclusiveComponents: any = {};
|
|
59
|
-
|
|
60
|
-
private checkRuntimeContext: any = null;
|
|
61
|
-
|
|
62
|
-
public get circularLimitReached() {
|
|
63
|
-
return this.agentContext?.circularLimitReached || false;
|
|
64
|
-
}
|
|
65
|
-
public set circularLimitReached(value) {
|
|
66
|
-
if (this.agentContext) this.agentContext.circularLimitReached = value;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public get debug() {
|
|
70
|
-
return this._debugActive;
|
|
71
|
-
}
|
|
72
|
-
public get curStep() {
|
|
73
|
-
return this.agentContext?.step || 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
constructor(public agent: Agent) {
|
|
77
|
-
this.reqTag = agent.agentRequest.header('X-REQUEST-TAG');
|
|
78
|
-
const isNestedProcess: boolean = !!this.reqTag;
|
|
79
|
-
|
|
80
|
-
if (!this.reqTag) {
|
|
81
|
-
//tagged request should not be run in debug mode, this comes from a parent agent
|
|
82
|
-
this.xDebugStop = agent.agentRequest.header('X-DEBUG-STOP');
|
|
83
|
-
this.xDebugRun = agent.agentRequest.header('X-DEBUG-RUN'); //send this as header to create a session and attach it
|
|
84
|
-
this.xDebugInject = agent.agentRequest.header('X-DEBUG-INJ');
|
|
85
|
-
this.xDebugRead = agent.agentRequest.header('X-DEBUG-READ');
|
|
86
|
-
this.reqTag = 'xTAG-' + uid(); //if request tag is not set, set a new value, this will be used to tag nested agent calls
|
|
87
|
-
this.reqTagOwner = true;
|
|
88
|
-
} else {
|
|
89
|
-
this.xDebugStop = undefined;
|
|
90
|
-
this.xDebugRun = undefined;
|
|
91
|
-
this.xDebugInject = undefined;
|
|
92
|
-
this.xDebugRead = undefined;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
this.xDebugId = this.xDebugStop || this.xDebugRun || this.xDebugRead;
|
|
96
|
-
|
|
97
|
-
//if (req.body) {
|
|
98
|
-
if (!this.xDebugId && agent.agentRequest.body) {
|
|
99
|
-
if (this.xDebugInject != undefined && this.xDebugInject != null) {
|
|
100
|
-
this.xDebugPendingInject = agent.agentRequest.body;
|
|
101
|
-
this.xDebugRun = this.xDebugInject || 'inj-' + uid();
|
|
102
|
-
} else {
|
|
103
|
-
if (this.xDebugRun == '') {
|
|
104
|
-
this.xDebugRun = 'dbg-' + uid(); //generate a random debug id
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
this.xDebugId = this.xDebugRun;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (agent.agentRequest.header('X-MOCK-DATA-INJ') !== undefined) {
|
|
111
|
-
this.xMockDataInject = agent.agentRequest.body;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
this.processID = this.xDebugId;
|
|
115
|
-
|
|
116
|
-
if (!this.xDebugId) {
|
|
117
|
-
//if it's not a debug session, processID is unique per request
|
|
118
|
-
this.xDebugId = agent.sessionId;
|
|
119
|
-
this.processID = this.reqTag;
|
|
120
|
-
}
|
|
121
|
-
if (isNestedProcess) {
|
|
122
|
-
// Need to make processID unique to run same sub-agents multiple times in parallel
|
|
123
|
-
this.processID += `:${Math.floor(1000 + Math.random() * 9000)}`;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
//we need a way to identify current running workflow in a unique way
|
|
127
|
-
//=> In debug mode, xDebugRun holds the debug sessionID which is unique per workflow run
|
|
128
|
-
// if the debug session is stopped, xDebugStop holds the sessionID
|
|
129
|
-
// Note : We can't use reqTag in debug mode because it changes every time a new debug step is executed
|
|
130
|
-
//
|
|
131
|
-
//=> In normal mode, reqTag is unique per workflow run
|
|
132
|
-
this.workflowReqId = this.xDebugRun || this.xDebugStop || this.reqTag;
|
|
133
|
-
|
|
134
|
-
//tagsData can be updated from external integrations (eg. Chatbot, API Endpoint, etc.)
|
|
135
|
-
if (!AgentRuntime.tagsData[this.reqTag]) AgentRuntime.tagsData[this.reqTag] = {};
|
|
136
|
-
if (!AgentRuntime.processResults[this.processID])
|
|
137
|
-
AgentRuntime.processResults[this.processID] = {
|
|
138
|
-
timestamp: Date.now(),
|
|
139
|
-
errorResults: [],
|
|
140
|
-
sessionResults: [],
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
this.agentContext = new RuntimeContext(this);
|
|
144
|
-
this.agentContext.on('ready', () => {
|
|
145
|
-
this.alwaysActiveComponents = {};
|
|
146
|
-
this.exclusiveComponents = {};
|
|
147
|
-
for (let component of this.agent.data.components) {
|
|
148
|
-
const cpt: Component = this.agent.ComponentInstances[component.name];
|
|
149
|
-
if (!cpt) {
|
|
150
|
-
console.warn(`Component ${component.name} Exists in agent but has no implementation`, AccessCandidate.agent(this.agent.id));
|
|
151
|
-
continue;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (cpt.alwaysActive) {
|
|
155
|
-
this.alwaysActiveComponents[component.id] = cpt;
|
|
156
|
-
this.updateComponent(component.id, { active: true, alwaysActive: true });
|
|
157
|
-
const runtimeData = { ...this.getRuntimeData(component.id) };
|
|
158
|
-
this.saveRuntimeComponentData(component.id, runtimeData);
|
|
159
|
-
}
|
|
160
|
-
if (cpt.exclusive) {
|
|
161
|
-
this.exclusiveComponents[component.id] = cpt;
|
|
162
|
-
this.updateComponent(component.id, { exclusive: true });
|
|
163
|
-
const runtimeData = { ...this.getRuntimeData(component.id) };
|
|
164
|
-
this.saveRuntimeComponentData(component.id, runtimeData);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
//if xDebugId is equal to agent session, it means that the debugging features are not active
|
|
170
|
-
this._debugActive = this.xDebugId != agent.sessionId;
|
|
171
|
-
|
|
172
|
-
const xCacheId = agent.agentRequest.header('X-CACHE-ID') || '';
|
|
173
|
-
this.llmCache = new LLMCache(AccessCandidate.agent(this.agent.id), xCacheId);
|
|
174
|
-
//this.xCacheId =
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
public async ready() {
|
|
178
|
-
return this.agentContext.ready();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
public destroy() {
|
|
182
|
-
this.sessionClosed = true;
|
|
183
|
-
this.sync();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
public incTag(componentId) {
|
|
187
|
-
if (!AgentRuntime.tagsData[this.reqTag][componentId]) AgentRuntime.tagsData[this.reqTag][componentId] = 0;
|
|
188
|
-
AgentRuntime.tagsData[this.reqTag][componentId]++;
|
|
189
|
-
|
|
190
|
-
// console.log(
|
|
191
|
-
// `incTag agentId=${this.agent.id} componentId=${componentId} tag=${this.reqTag} ==> ${AgentRuntime.tagsData[this.reqTag][componentId]}`,
|
|
192
|
-
// );
|
|
193
|
-
//console.log('incTag tagsData', tagsData);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
public async sync() {
|
|
197
|
-
//if (!this.ctxFile) return;
|
|
198
|
-
|
|
199
|
-
const deleteTag = (this.reqTagOwner && this.sessionClosed) || this.circularLimitReached;
|
|
200
|
-
if (deleteTag) {
|
|
201
|
-
delete AgentRuntime.tagsData[this.reqTag];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
this.agentContext.sync();
|
|
205
|
-
}
|
|
206
|
-
public getWaitingComponents() {
|
|
207
|
-
const ctxData = this.agentContext;
|
|
208
|
-
const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
209
|
-
const waitingComponents: any = dbgComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);
|
|
210
|
-
return waitingComponents;
|
|
211
|
-
}
|
|
212
|
-
public getExclusiveActiveComponents() {
|
|
213
|
-
const ctxData = this.agentContext;
|
|
214
|
-
const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
215
|
-
const exclusiveActiveComponents: any = dbgComponents.filter((c: any) => c?.ctx?.exclusive == true);
|
|
216
|
-
return exclusiveActiveComponents;
|
|
217
|
-
}
|
|
218
|
-
public readState(stateId: string, deltaOnly = false) {
|
|
219
|
-
//if (!this._debugActive || !this.xDebugRead) return null;
|
|
220
|
-
if (!this._debugActive || !stateId) return null;
|
|
221
|
-
|
|
222
|
-
//this.checkRuntimeContext();
|
|
223
|
-
const runtime = this;
|
|
224
|
-
const agent = this.agent;
|
|
225
|
-
|
|
226
|
-
const ctxData = runtime.agentContext;
|
|
227
|
-
const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);
|
|
228
|
-
|
|
229
|
-
//first try to find exclusive active components
|
|
230
|
-
let dbgActiveComponents: any;
|
|
231
|
-
dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);
|
|
232
|
-
//if no exclusive active components, find all active components
|
|
233
|
-
if (!dbgActiveComponents || dbgActiveComponents.length == 0)
|
|
234
|
-
dbgActiveComponents = dbgAllComponents.filter(
|
|
235
|
-
(c: any) =>
|
|
236
|
-
c?.ctx?.active == true ||
|
|
237
|
-
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
238
|
-
);
|
|
239
|
-
//find waiting components that was not previously run
|
|
240
|
-
const dbgActiveWaitingComponents: any = dbgAllComponents.filter(
|
|
241
|
-
(c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
const dbgActiveReadyComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);
|
|
245
|
-
|
|
246
|
-
let state = {};
|
|
247
|
-
for (let dbgComponent of dbgAllComponents) {
|
|
248
|
-
state[dbgComponent.id] = dbgComponent.ctx;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
//let dbgSession: any = runtime.xDebugRead;
|
|
252
|
-
let dbgSession: any = stateId;
|
|
253
|
-
|
|
254
|
-
// let alwaysActiveComponents = 0;
|
|
255
|
-
// for (let activeCpt of dbgActiveComponents) {
|
|
256
|
-
// if (this.agent.alwaysActiveComponents[activeCpt.id]) alwaysActiveComponents++;
|
|
257
|
-
// }
|
|
258
|
-
|
|
259
|
-
if (!dbgActiveComponents || dbgActiveComponents.length == 0 /*|| dbgActiveComponents.length == alwaysActiveComponents*/) {
|
|
260
|
-
dbgSession = null;
|
|
261
|
-
runtime.sessionClosed = true;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter(
|
|
265
|
-
(c: any) => c?.ctx?.active == true && !c?.ctx?.alwaysActive
|
|
266
|
-
);
|
|
267
|
-
const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(
|
|
268
|
-
(c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
if (remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/) {
|
|
272
|
-
runtime.sessionClosed = true;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (runtime.circularLimitReached) {
|
|
276
|
-
const circularLimitData = runtime.checkCircularLimit();
|
|
277
|
-
const error = `Circular Calls Limit Reached on ${circularLimitData}. Current agent circular limit is ${agent.circularLimit}`;
|
|
278
|
-
runtime.sessionClosed = true;
|
|
279
|
-
return { state, dbgSession, sessionClosed: runtime.sessionClosed, error };
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const step = this.curStep >= 1 ? this.curStep - 1 : 0; //current state was executed in previous step
|
|
283
|
-
|
|
284
|
-
if (deltaOnly) {
|
|
285
|
-
const delta = {};
|
|
286
|
-
for (let cptId in state) {
|
|
287
|
-
const cpt = state[cptId];
|
|
288
|
-
|
|
289
|
-
//workaround, here we are supposed to test component steps that are equalt to current step
|
|
290
|
-
//but due to an inconsistency, the Async component has sometimes a step greater than the current step
|
|
291
|
-
if (cpt.step >= step) delta[cptId] = cpt;
|
|
292
|
-
//FIXME : identify the root cause of this issue and replace >= with ==
|
|
293
|
-
}
|
|
294
|
-
//return { state: delta, dbgSession, sessionClosed: runtime.sessionClosed, step };
|
|
295
|
-
state = delta;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return { state, dbgSession, sessionClosed: runtime.sessionClosed, step };
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* This method is called by the agent to run a process cycle, it will run all active components and return the results
|
|
303
|
-
* The function is called multiple times until all components are executed and no more active components are available
|
|
304
|
-
* @returns
|
|
305
|
-
*/
|
|
306
|
-
public async runCycle() {
|
|
307
|
-
console.debug(
|
|
308
|
-
`runCycle agentId=${this.agent.id} wfReqId=${this.workflowReqId} reqTag=${this.reqTag} session=${this.xDebugRun} cycleId=${this.processID}`,
|
|
309
|
-
AccessCandidate.agent(this.agent.id)
|
|
310
|
-
);
|
|
311
|
-
//this.checkRuntimeContext();
|
|
312
|
-
|
|
313
|
-
const runtime = this;
|
|
314
|
-
const agent = this.agent;
|
|
315
|
-
const ctxData = runtime.agentContext;
|
|
316
|
-
const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);
|
|
317
|
-
|
|
318
|
-
//first try to find exclusive active components
|
|
319
|
-
let dbgActiveComponents: any;
|
|
320
|
-
dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);
|
|
321
|
-
//if no exclusive active components, find all active components
|
|
322
|
-
if (!dbgActiveComponents || dbgActiveComponents.length == 0)
|
|
323
|
-
dbgActiveComponents = dbgAllComponents.filter(
|
|
324
|
-
(c: any) =>
|
|
325
|
-
c?.ctx?.active == true ||
|
|
326
|
-
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
327
|
-
);
|
|
328
|
-
//find waiting components that was not previously run
|
|
329
|
-
const dbgActiveWaitingComponents: any = dbgAllComponents.filter(
|
|
330
|
-
(c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined
|
|
331
|
-
);
|
|
332
|
-
const dbgActiveReadyComponents: any = dbgAllComponents.filter(
|
|
333
|
-
(c: any) =>
|
|
334
|
-
(c?.ctx?.active == true && !c?.ctx?.status) ||
|
|
335
|
-
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
336
|
-
);
|
|
337
|
-
//const dbgActiveReadyComponents: any = dbgActiveComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);
|
|
338
|
-
|
|
339
|
-
let step: any;
|
|
340
|
-
|
|
341
|
-
if (!dbgActiveComponents || dbgActiveComponents.length == 0) {
|
|
342
|
-
runtime.sessionClosed = true;
|
|
343
|
-
step = {
|
|
344
|
-
state: { sessionClosed: true },
|
|
345
|
-
dbgSession: null,
|
|
346
|
-
//expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,
|
|
347
|
-
expiredDbgSession: runtime.xDebugId,
|
|
348
|
-
sessionClosed: true,
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (!step && dbgActiveComponents.length == dbgActiveWaitingComponents.length && ctxData.sessionResult) {
|
|
353
|
-
runtime.sessionClosed = true;
|
|
354
|
-
step = {
|
|
355
|
-
state: { sessionClosed: true },
|
|
356
|
-
dbgSession: null,
|
|
357
|
-
//expiredDbgSession: runtime.xDebugRun,
|
|
358
|
-
expiredDbgSession: runtime.xDebugId,
|
|
359
|
-
sessionClosed: true,
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
if (!step && dbgActiveReadyComponents.length > 0) {
|
|
363
|
-
const promises: any = [];
|
|
364
|
-
|
|
365
|
-
for (let dbgComponent of dbgActiveReadyComponents) {
|
|
366
|
-
const injectInput = runtime.xDebugPendingInject ? dbgComponent.ctx.input : undefined;
|
|
367
|
-
|
|
368
|
-
promises.push(agent.callComponent(dbgComponent.ctx.sourceId, dbgComponent.id, injectInput));
|
|
369
|
-
}
|
|
370
|
-
const dbgResults = await Promise.all(promises);
|
|
371
|
-
const state = dbgResults.length == 1 ? dbgResults[0] : dbgResults;
|
|
372
|
-
|
|
373
|
-
runtime.xDebugPendingInject = null;
|
|
374
|
-
|
|
375
|
-
const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
376
|
-
const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(
|
|
377
|
-
(c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0
|
|
378
|
-
);
|
|
379
|
-
const dbgActiveWaitingComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);
|
|
380
|
-
|
|
381
|
-
if (dbgActiveWaitingComponents.length == remainingActiveComponents.length) {
|
|
382
|
-
ctxData.sessionResult = true;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
//capture results
|
|
386
|
-
let sessionResults = dbgResults.flat().filter(
|
|
387
|
-
(e) =>
|
|
388
|
-
e.id &&
|
|
389
|
-
e.result &&
|
|
390
|
-
!e.result._missing_inputs &&
|
|
391
|
-
//check if this is the last component in the chain
|
|
392
|
-
!agent.connections.find((c) => c.sourceId == e.id)
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
let errorResults = dbgResults.flat().filter((e) => e.id && (e.error || e.result?._error));
|
|
396
|
-
|
|
397
|
-
//also filter out erroneous components that are children of a loop
|
|
398
|
-
//otherwise, errors inside a loop will be reported as session results and can lead to wrong results or generated noise in the final agent output
|
|
399
|
-
errorResults = errorResults.filter((e) => {
|
|
400
|
-
return !ctxData?.components?.[e.id]?.ctx?.runtimeData?._ChildLoopData;
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
if (ctxData.sessionResult && sessionResults.length == 0 && runtime.sessionClosed) {
|
|
404
|
-
//no result ? check if we have errors
|
|
405
|
-
sessionResults = errorResults;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
ctxData.sessionResults = sessionResults;
|
|
409
|
-
step = {
|
|
410
|
-
state,
|
|
411
|
-
dbgSession: runtime.xDebugRun,
|
|
412
|
-
sessionResult: runtime.agentContext.sessionResult,
|
|
413
|
-
sessionResults: runtime.agentContext.sessionResults,
|
|
414
|
-
errorResults,
|
|
415
|
-
sessionClosed: remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/,
|
|
416
|
-
};
|
|
417
|
-
} else {
|
|
418
|
-
runtime.sessionClosed = true;
|
|
419
|
-
//return { sessionClosed: true };
|
|
420
|
-
step = {
|
|
421
|
-
state: { sessionClosed: true },
|
|
422
|
-
dbgSession: null,
|
|
423
|
-
//expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,
|
|
424
|
-
expiredDbgSession: runtime.xDebugId,
|
|
425
|
-
sessionClosed: true,
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
this.checkCircularLimit();
|
|
430
|
-
if (step.sessionResults) {
|
|
431
|
-
AgentRuntime.processResults[this.processID].sessionResults.push(step.sessionResults);
|
|
432
|
-
}
|
|
433
|
-
if (step.errorResults) {
|
|
434
|
-
AgentRuntime.processResults[this.processID].errorResults.push(step.errorResults);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (step?.sessionClosed || this.circularLimitReached) {
|
|
438
|
-
const finalResult = this.processResults();
|
|
439
|
-
step.finalResult = finalResult;
|
|
440
|
-
runtime.sessionClosed = true;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
this.incStep();
|
|
444
|
-
this.sync();
|
|
445
|
-
return step;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
private processResults() {
|
|
449
|
-
//this.checkCircularLimit();
|
|
450
|
-
let result: any = { error: 'Error processing results' };
|
|
451
|
-
const sessionResults = AgentRuntime.processResults[this.processID].sessionResults;
|
|
452
|
-
const errorResults = AgentRuntime.processResults[this.processID].errorResults;
|
|
453
|
-
if (this.circularLimitReached) {
|
|
454
|
-
const circularLimitData = this.circularLimitReached;
|
|
455
|
-
result = { error: `Circular Calls Limit Reached on ${circularLimitData}. Current circular limit is ${this.agent.circularLimit}` };
|
|
456
|
-
} else {
|
|
457
|
-
let state = [sessionResults, errorResults].flat(Infinity);
|
|
458
|
-
if (!state || state.length == 0) state = errorResults.flat(Infinity);
|
|
459
|
-
|
|
460
|
-
//post process run cycle results
|
|
461
|
-
//deduplicating redundant entries
|
|
462
|
-
|
|
463
|
-
const data = state
|
|
464
|
-
.reduce(
|
|
465
|
-
(acc, current) => {
|
|
466
|
-
if (!acc.seen[current.id]) {
|
|
467
|
-
acc.result.push(current);
|
|
468
|
-
acc.seen[current.id] = true;
|
|
469
|
-
}
|
|
470
|
-
return acc;
|
|
471
|
-
},
|
|
472
|
-
{ seen: {}, result: [] }
|
|
473
|
-
)
|
|
474
|
-
.result.filter((e) => !e.result?._exclude);
|
|
475
|
-
|
|
476
|
-
//data.forEach((d: any) => delete d?.result?._debug);
|
|
477
|
-
|
|
478
|
-
result = data;
|
|
479
|
-
/////////////
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
//cleanup
|
|
483
|
-
delete AgentRuntime.processResults[this.processID];
|
|
484
|
-
|
|
485
|
-
this.sync();
|
|
486
|
-
return result;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
public checkCircularLimit() {
|
|
490
|
-
if (this.circularLimitReached) return this.agentContext.circularLimitReached;
|
|
491
|
-
for (let componentId in AgentRuntime.tagsData[this.reqTag]) {
|
|
492
|
-
if (AgentRuntime.tagsData[this.reqTag][componentId] > this.agent.circularLimit) {
|
|
493
|
-
this.sessionClosed = true;
|
|
494
|
-
this.agentContext.circularLimitReached = componentId;
|
|
495
|
-
return componentId;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
return false;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
public async injectDebugOutput(componentId: string) {
|
|
502
|
-
let component: {
|
|
503
|
-
ctx?: Record<string, any>;
|
|
504
|
-
} = {};
|
|
505
|
-
|
|
506
|
-
if (this.xDebugPendingInject) {
|
|
507
|
-
component = this.xDebugPendingInject?.find((c: any) => c.id == componentId);
|
|
508
|
-
} else if (this.xMockDataInject) {
|
|
509
|
-
component = this.xMockDataInject?.find((c: any) => c.id == componentId);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (component?.ctx?.output) {
|
|
513
|
-
//if all outputs values are empty, we don't inject
|
|
514
|
-
let allEmpty = true;
|
|
515
|
-
for (let key in component.ctx.output) {
|
|
516
|
-
if (component.ctx.output[key] != '') {
|
|
517
|
-
allEmpty = false;
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
if (allEmpty) return null;
|
|
522
|
-
|
|
523
|
-
return component.ctx.output;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
public getRuntimeData(componentId) {
|
|
527
|
-
const componentData = this.getComponentData(componentId);
|
|
528
|
-
if (!componentData) return {};
|
|
529
|
-
const rData = componentData.runtimeData || {};
|
|
530
|
-
|
|
531
|
-
return rData;
|
|
532
|
-
}
|
|
533
|
-
public updateRuntimeData(componentId, data) {
|
|
534
|
-
const componentData = this.getComponentData(componentId);
|
|
535
|
-
if (!componentData) return;
|
|
536
|
-
componentData.runtimeData = { ...componentData.runtimeData, ...data };
|
|
537
|
-
|
|
538
|
-
this.sync();
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
public saveRuntimeComponentData(componentId, data) {
|
|
542
|
-
this.updateComponent(componentId, { runtimeData: data });
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
public incStep() {
|
|
546
|
-
this.agentContext.incStep();
|
|
547
|
-
}
|
|
548
|
-
public updateComponent(componentId: string, data: any) {
|
|
549
|
-
this.agentContext.updateComponent(componentId, data);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
public resetComponent(componentId: string) {
|
|
553
|
-
this.agentContext.resetComponent(componentId);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
public getComponentData(componentId: string) {
|
|
557
|
-
return this.agentContext.getComponentData(componentId);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { Agent } from './Agent.class';
|
|
4
|
+
import { Component } from '@sre/Components/Component.class';
|
|
5
|
+
|
|
6
|
+
import { Logger } from '@sre/helpers/Log.helper';
|
|
7
|
+
import { uid } from '@sre/utils';
|
|
8
|
+
import { RuntimeContext } from '@sre/MemoryManager/RuntimeContext';
|
|
9
|
+
import { LLMCache } from '@sre/MemoryManager/LLMCache';
|
|
10
|
+
import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
|
|
11
|
+
|
|
12
|
+
const console = Logger('AgentRuntime');
|
|
13
|
+
const AgentRuntimeUnavailable = new Proxy(
|
|
14
|
+
{},
|
|
15
|
+
{
|
|
16
|
+
get: function (target, prop, receiver) {
|
|
17
|
+
// Check if the property being accessed is a function
|
|
18
|
+
if (typeof target[prop] === 'function') {
|
|
19
|
+
return target[prop];
|
|
20
|
+
} else {
|
|
21
|
+
// Return a function that logs "unavailable"
|
|
22
|
+
return function () {
|
|
23
|
+
console.warn(`AgentRuntime Unavailable tried to call : ${prop.toString()}`);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
export class AgentRuntime {
|
|
30
|
+
private static processResults: any = {};
|
|
31
|
+
private static tagsData = {};
|
|
32
|
+
public static dummy = AgentRuntimeUnavailable;
|
|
33
|
+
|
|
34
|
+
private agentContext: RuntimeContext;
|
|
35
|
+
public llmCache: LLMCache;
|
|
36
|
+
//private ctxFile: string = '';
|
|
37
|
+
private xDebugRun: string | undefined = '';
|
|
38
|
+
private xDebugInject: string | undefined = '';
|
|
39
|
+
private xDebugRead: string | undefined = '';
|
|
40
|
+
private xDebugStop: string | undefined = '';
|
|
41
|
+
private xDebugPendingInject: any = null;
|
|
42
|
+
private xMockDataInject: any = null;
|
|
43
|
+
public xDebugId: string | undefined = '';
|
|
44
|
+
|
|
45
|
+
private xDebugCmd: string | undefined = '';
|
|
46
|
+
private _debugActive = false;
|
|
47
|
+
private _runtimeFileReady = false;
|
|
48
|
+
public sessionClosed = false;
|
|
49
|
+
|
|
50
|
+
private reqTagOwner = false;
|
|
51
|
+
|
|
52
|
+
//reqTag is used to identify the current running workflow including nested calls, it allows us to identify circular calls
|
|
53
|
+
public reqTag: any;
|
|
54
|
+
public processID: any; //this identifies the current processID, a process ID is the full set of runCycles that is executed by the agent.
|
|
55
|
+
public workflowReqId: any; //this identifies the current running workflow. a workflow starts when and agent endpoint is called, or a debug session is initiated, and ends when no more steps can be executed.
|
|
56
|
+
|
|
57
|
+
public alwaysActiveComponents: any = {};
|
|
58
|
+
public exclusiveComponents: any = {};
|
|
59
|
+
|
|
60
|
+
private checkRuntimeContext: any = null;
|
|
61
|
+
|
|
62
|
+
public get circularLimitReached() {
|
|
63
|
+
return this.agentContext?.circularLimitReached || false;
|
|
64
|
+
}
|
|
65
|
+
public set circularLimitReached(value) {
|
|
66
|
+
if (this.agentContext) this.agentContext.circularLimitReached = value;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public get debug() {
|
|
70
|
+
return this._debugActive;
|
|
71
|
+
}
|
|
72
|
+
public get curStep() {
|
|
73
|
+
return this.agentContext?.step || 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
constructor(public agent: Agent) {
|
|
77
|
+
this.reqTag = agent.agentRequest.header('X-REQUEST-TAG');
|
|
78
|
+
const isNestedProcess: boolean = !!this.reqTag;
|
|
79
|
+
|
|
80
|
+
if (!this.reqTag) {
|
|
81
|
+
//tagged request should not be run in debug mode, this comes from a parent agent
|
|
82
|
+
this.xDebugStop = agent.agentRequest.header('X-DEBUG-STOP');
|
|
83
|
+
this.xDebugRun = agent.agentRequest.header('X-DEBUG-RUN'); //send this as header to create a session and attach it
|
|
84
|
+
this.xDebugInject = agent.agentRequest.header('X-DEBUG-INJ');
|
|
85
|
+
this.xDebugRead = agent.agentRequest.header('X-DEBUG-READ');
|
|
86
|
+
this.reqTag = 'xTAG-' + uid(); //if request tag is not set, set a new value, this will be used to tag nested agent calls
|
|
87
|
+
this.reqTagOwner = true;
|
|
88
|
+
} else {
|
|
89
|
+
this.xDebugStop = undefined;
|
|
90
|
+
this.xDebugRun = undefined;
|
|
91
|
+
this.xDebugInject = undefined;
|
|
92
|
+
this.xDebugRead = undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.xDebugId = this.xDebugStop || this.xDebugRun || this.xDebugRead;
|
|
96
|
+
|
|
97
|
+
//if (req.body) {
|
|
98
|
+
if (!this.xDebugId && agent.agentRequest.body) {
|
|
99
|
+
if (this.xDebugInject != undefined && this.xDebugInject != null) {
|
|
100
|
+
this.xDebugPendingInject = agent.agentRequest.body;
|
|
101
|
+
this.xDebugRun = this.xDebugInject || 'inj-' + uid();
|
|
102
|
+
} else {
|
|
103
|
+
if (this.xDebugRun == '') {
|
|
104
|
+
this.xDebugRun = 'dbg-' + uid(); //generate a random debug id
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.xDebugId = this.xDebugRun;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (agent.agentRequest.header('X-MOCK-DATA-INJ') !== undefined) {
|
|
111
|
+
this.xMockDataInject = agent.agentRequest.body;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.processID = this.xDebugId;
|
|
115
|
+
|
|
116
|
+
if (!this.xDebugId) {
|
|
117
|
+
//if it's not a debug session, processID is unique per request
|
|
118
|
+
this.xDebugId = agent.sessionId;
|
|
119
|
+
this.processID = this.reqTag;
|
|
120
|
+
}
|
|
121
|
+
if (isNestedProcess) {
|
|
122
|
+
// Need to make processID unique to run same sub-agents multiple times in parallel
|
|
123
|
+
this.processID += `:${Math.floor(1000 + Math.random() * 9000)}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
//we need a way to identify current running workflow in a unique way
|
|
127
|
+
//=> In debug mode, xDebugRun holds the debug sessionID which is unique per workflow run
|
|
128
|
+
// if the debug session is stopped, xDebugStop holds the sessionID
|
|
129
|
+
// Note : We can't use reqTag in debug mode because it changes every time a new debug step is executed
|
|
130
|
+
//
|
|
131
|
+
//=> In normal mode, reqTag is unique per workflow run
|
|
132
|
+
this.workflowReqId = this.xDebugRun || this.xDebugStop || this.reqTag;
|
|
133
|
+
|
|
134
|
+
//tagsData can be updated from external integrations (eg. Chatbot, API Endpoint, etc.)
|
|
135
|
+
if (!AgentRuntime.tagsData[this.reqTag]) AgentRuntime.tagsData[this.reqTag] = {};
|
|
136
|
+
if (!AgentRuntime.processResults[this.processID])
|
|
137
|
+
AgentRuntime.processResults[this.processID] = {
|
|
138
|
+
timestamp: Date.now(),
|
|
139
|
+
errorResults: [],
|
|
140
|
+
sessionResults: [],
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
this.agentContext = new RuntimeContext(this);
|
|
144
|
+
this.agentContext.on('ready', () => {
|
|
145
|
+
this.alwaysActiveComponents = {};
|
|
146
|
+
this.exclusiveComponents = {};
|
|
147
|
+
for (let component of this.agent.data.components) {
|
|
148
|
+
const cpt: Component = this.agent.ComponentInstances[component.name];
|
|
149
|
+
if (!cpt) {
|
|
150
|
+
console.warn(`Component ${component.name} Exists in agent but has no implementation`, AccessCandidate.agent(this.agent.id));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (cpt.alwaysActive) {
|
|
155
|
+
this.alwaysActiveComponents[component.id] = cpt;
|
|
156
|
+
this.updateComponent(component.id, { active: true, alwaysActive: true });
|
|
157
|
+
const runtimeData = { ...this.getRuntimeData(component.id) };
|
|
158
|
+
this.saveRuntimeComponentData(component.id, runtimeData);
|
|
159
|
+
}
|
|
160
|
+
if (cpt.exclusive) {
|
|
161
|
+
this.exclusiveComponents[component.id] = cpt;
|
|
162
|
+
this.updateComponent(component.id, { exclusive: true });
|
|
163
|
+
const runtimeData = { ...this.getRuntimeData(component.id) };
|
|
164
|
+
this.saveRuntimeComponentData(component.id, runtimeData);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
//if xDebugId is equal to agent session, it means that the debugging features are not active
|
|
170
|
+
this._debugActive = this.xDebugId != agent.sessionId;
|
|
171
|
+
|
|
172
|
+
const xCacheId = agent.agentRequest.header('X-CACHE-ID') || '';
|
|
173
|
+
this.llmCache = new LLMCache(AccessCandidate.agent(this.agent.id), xCacheId);
|
|
174
|
+
//this.xCacheId =
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public async ready() {
|
|
178
|
+
return this.agentContext.ready();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
public destroy() {
|
|
182
|
+
this.sessionClosed = true;
|
|
183
|
+
this.sync();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
public incTag(componentId) {
|
|
187
|
+
if (!AgentRuntime.tagsData[this.reqTag][componentId]) AgentRuntime.tagsData[this.reqTag][componentId] = 0;
|
|
188
|
+
AgentRuntime.tagsData[this.reqTag][componentId]++;
|
|
189
|
+
|
|
190
|
+
// console.log(
|
|
191
|
+
// `incTag agentId=${this.agent.id} componentId=${componentId} tag=${this.reqTag} ==> ${AgentRuntime.tagsData[this.reqTag][componentId]}`,
|
|
192
|
+
// );
|
|
193
|
+
//console.log('incTag tagsData', tagsData);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public async sync() {
|
|
197
|
+
//if (!this.ctxFile) return;
|
|
198
|
+
|
|
199
|
+
const deleteTag = (this.reqTagOwner && this.sessionClosed) || this.circularLimitReached;
|
|
200
|
+
if (deleteTag) {
|
|
201
|
+
delete AgentRuntime.tagsData[this.reqTag];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.agentContext.sync();
|
|
205
|
+
}
|
|
206
|
+
public getWaitingComponents() {
|
|
207
|
+
const ctxData = this.agentContext;
|
|
208
|
+
const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
209
|
+
const waitingComponents: any = dbgComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);
|
|
210
|
+
return waitingComponents;
|
|
211
|
+
}
|
|
212
|
+
public getExclusiveActiveComponents() {
|
|
213
|
+
const ctxData = this.agentContext;
|
|
214
|
+
const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
215
|
+
const exclusiveActiveComponents: any = dbgComponents.filter((c: any) => c?.ctx?.exclusive == true);
|
|
216
|
+
return exclusiveActiveComponents;
|
|
217
|
+
}
|
|
218
|
+
public readState(stateId: string, deltaOnly = false) {
|
|
219
|
+
//if (!this._debugActive || !this.xDebugRead) return null;
|
|
220
|
+
if (!this._debugActive || !stateId) return null;
|
|
221
|
+
|
|
222
|
+
//this.checkRuntimeContext();
|
|
223
|
+
const runtime = this;
|
|
224
|
+
const agent = this.agent;
|
|
225
|
+
|
|
226
|
+
const ctxData = runtime.agentContext;
|
|
227
|
+
const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);
|
|
228
|
+
|
|
229
|
+
//first try to find exclusive active components
|
|
230
|
+
let dbgActiveComponents: any;
|
|
231
|
+
dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);
|
|
232
|
+
//if no exclusive active components, find all active components
|
|
233
|
+
if (!dbgActiveComponents || dbgActiveComponents.length == 0)
|
|
234
|
+
dbgActiveComponents = dbgAllComponents.filter(
|
|
235
|
+
(c: any) =>
|
|
236
|
+
c?.ctx?.active == true ||
|
|
237
|
+
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
238
|
+
);
|
|
239
|
+
//find waiting components that was not previously run
|
|
240
|
+
const dbgActiveWaitingComponents: any = dbgAllComponents.filter(
|
|
241
|
+
(c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
const dbgActiveReadyComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);
|
|
245
|
+
|
|
246
|
+
let state = {};
|
|
247
|
+
for (let dbgComponent of dbgAllComponents) {
|
|
248
|
+
state[dbgComponent.id] = dbgComponent.ctx;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
//let dbgSession: any = runtime.xDebugRead;
|
|
252
|
+
let dbgSession: any = stateId;
|
|
253
|
+
|
|
254
|
+
// let alwaysActiveComponents = 0;
|
|
255
|
+
// for (let activeCpt of dbgActiveComponents) {
|
|
256
|
+
// if (this.agent.alwaysActiveComponents[activeCpt.id]) alwaysActiveComponents++;
|
|
257
|
+
// }
|
|
258
|
+
|
|
259
|
+
if (!dbgActiveComponents || dbgActiveComponents.length == 0 /*|| dbgActiveComponents.length == alwaysActiveComponents*/) {
|
|
260
|
+
dbgSession = null;
|
|
261
|
+
runtime.sessionClosed = true;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter(
|
|
265
|
+
(c: any) => c?.ctx?.active == true && !c?.ctx?.alwaysActive
|
|
266
|
+
);
|
|
267
|
+
const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(
|
|
268
|
+
(c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
if (remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/) {
|
|
272
|
+
runtime.sessionClosed = true;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (runtime.circularLimitReached) {
|
|
276
|
+
const circularLimitData = runtime.checkCircularLimit();
|
|
277
|
+
const error = `Circular Calls Limit Reached on ${circularLimitData}. Current agent circular limit is ${agent.circularLimit}`;
|
|
278
|
+
runtime.sessionClosed = true;
|
|
279
|
+
return { state, dbgSession, sessionClosed: runtime.sessionClosed, error };
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const step = this.curStep >= 1 ? this.curStep - 1 : 0; //current state was executed in previous step
|
|
283
|
+
|
|
284
|
+
if (deltaOnly) {
|
|
285
|
+
const delta = {};
|
|
286
|
+
for (let cptId in state) {
|
|
287
|
+
const cpt = state[cptId];
|
|
288
|
+
|
|
289
|
+
//workaround, here we are supposed to test component steps that are equalt to current step
|
|
290
|
+
//but due to an inconsistency, the Async component has sometimes a step greater than the current step
|
|
291
|
+
if (cpt.step >= step) delta[cptId] = cpt;
|
|
292
|
+
//FIXME : identify the root cause of this issue and replace >= with ==
|
|
293
|
+
}
|
|
294
|
+
//return { state: delta, dbgSession, sessionClosed: runtime.sessionClosed, step };
|
|
295
|
+
state = delta;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return { state, dbgSession, sessionClosed: runtime.sessionClosed, step };
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* This method is called by the agent to run a process cycle, it will run all active components and return the results
|
|
303
|
+
* The function is called multiple times until all components are executed and no more active components are available
|
|
304
|
+
* @returns
|
|
305
|
+
*/
|
|
306
|
+
public async runCycle() {
|
|
307
|
+
console.debug(
|
|
308
|
+
`runCycle agentId=${this.agent.id} wfReqId=${this.workflowReqId} reqTag=${this.reqTag} session=${this.xDebugRun} cycleId=${this.processID}`,
|
|
309
|
+
AccessCandidate.agent(this.agent.id)
|
|
310
|
+
);
|
|
311
|
+
//this.checkRuntimeContext();
|
|
312
|
+
|
|
313
|
+
const runtime = this;
|
|
314
|
+
const agent = this.agent;
|
|
315
|
+
const ctxData = runtime.agentContext;
|
|
316
|
+
const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);
|
|
317
|
+
|
|
318
|
+
//first try to find exclusive active components
|
|
319
|
+
let dbgActiveComponents: any;
|
|
320
|
+
dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);
|
|
321
|
+
//if no exclusive active components, find all active components
|
|
322
|
+
if (!dbgActiveComponents || dbgActiveComponents.length == 0)
|
|
323
|
+
dbgActiveComponents = dbgAllComponents.filter(
|
|
324
|
+
(c: any) =>
|
|
325
|
+
c?.ctx?.active == true ||
|
|
326
|
+
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
327
|
+
);
|
|
328
|
+
//find waiting components that was not previously run
|
|
329
|
+
const dbgActiveWaitingComponents: any = dbgAllComponents.filter(
|
|
330
|
+
(c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined
|
|
331
|
+
);
|
|
332
|
+
const dbgActiveReadyComponents: any = dbgAllComponents.filter(
|
|
333
|
+
(c: any) =>
|
|
334
|
+
(c?.ctx?.active == true && !c?.ctx?.status) ||
|
|
335
|
+
(!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0)
|
|
336
|
+
);
|
|
337
|
+
//const dbgActiveReadyComponents: any = dbgActiveComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);
|
|
338
|
+
|
|
339
|
+
let step: any;
|
|
340
|
+
|
|
341
|
+
if (!dbgActiveComponents || dbgActiveComponents.length == 0) {
|
|
342
|
+
runtime.sessionClosed = true;
|
|
343
|
+
step = {
|
|
344
|
+
state: { sessionClosed: true },
|
|
345
|
+
dbgSession: null,
|
|
346
|
+
//expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,
|
|
347
|
+
expiredDbgSession: runtime.xDebugId,
|
|
348
|
+
sessionClosed: true,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (!step && dbgActiveComponents.length == dbgActiveWaitingComponents.length && ctxData.sessionResult) {
|
|
353
|
+
runtime.sessionClosed = true;
|
|
354
|
+
step = {
|
|
355
|
+
state: { sessionClosed: true },
|
|
356
|
+
dbgSession: null,
|
|
357
|
+
//expiredDbgSession: runtime.xDebugRun,
|
|
358
|
+
expiredDbgSession: runtime.xDebugId,
|
|
359
|
+
sessionClosed: true,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
if (!step && dbgActiveReadyComponents.length > 0) {
|
|
363
|
+
const promises: any = [];
|
|
364
|
+
|
|
365
|
+
for (let dbgComponent of dbgActiveReadyComponents) {
|
|
366
|
+
const injectInput = runtime.xDebugPendingInject ? dbgComponent.ctx.input : undefined;
|
|
367
|
+
|
|
368
|
+
promises.push(agent.callComponent(dbgComponent.ctx.sourceId, dbgComponent.id, injectInput));
|
|
369
|
+
}
|
|
370
|
+
const dbgResults = await Promise.all(promises);
|
|
371
|
+
const state = dbgResults.length == 1 ? dbgResults[0] : dbgResults;
|
|
372
|
+
|
|
373
|
+
runtime.xDebugPendingInject = null;
|
|
374
|
+
|
|
375
|
+
const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);
|
|
376
|
+
const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(
|
|
377
|
+
(c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0
|
|
378
|
+
);
|
|
379
|
+
const dbgActiveWaitingComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);
|
|
380
|
+
|
|
381
|
+
if (dbgActiveWaitingComponents.length == remainingActiveComponents.length) {
|
|
382
|
+
ctxData.sessionResult = true;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
//capture results
|
|
386
|
+
let sessionResults = dbgResults.flat().filter(
|
|
387
|
+
(e) =>
|
|
388
|
+
e.id &&
|
|
389
|
+
e.result &&
|
|
390
|
+
!e.result._missing_inputs &&
|
|
391
|
+
//check if this is the last component in the chain
|
|
392
|
+
!agent.connections.find((c) => c.sourceId == e.id)
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
let errorResults = dbgResults.flat().filter((e) => e.id && (e.error || e.result?._error));
|
|
396
|
+
|
|
397
|
+
//also filter out erroneous components that are children of a loop
|
|
398
|
+
//otherwise, errors inside a loop will be reported as session results and can lead to wrong results or generated noise in the final agent output
|
|
399
|
+
errorResults = errorResults.filter((e) => {
|
|
400
|
+
return !ctxData?.components?.[e.id]?.ctx?.runtimeData?._ChildLoopData;
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
if (ctxData.sessionResult && sessionResults.length == 0 && runtime.sessionClosed) {
|
|
404
|
+
//no result ? check if we have errors
|
|
405
|
+
sessionResults = errorResults;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
ctxData.sessionResults = sessionResults;
|
|
409
|
+
step = {
|
|
410
|
+
state,
|
|
411
|
+
dbgSession: runtime.xDebugRun,
|
|
412
|
+
sessionResult: runtime.agentContext.sessionResult,
|
|
413
|
+
sessionResults: runtime.agentContext.sessionResults,
|
|
414
|
+
errorResults,
|
|
415
|
+
sessionClosed: remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/,
|
|
416
|
+
};
|
|
417
|
+
} else {
|
|
418
|
+
runtime.sessionClosed = true;
|
|
419
|
+
//return { sessionClosed: true };
|
|
420
|
+
step = {
|
|
421
|
+
state: { sessionClosed: true },
|
|
422
|
+
dbgSession: null,
|
|
423
|
+
//expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,
|
|
424
|
+
expiredDbgSession: runtime.xDebugId,
|
|
425
|
+
sessionClosed: true,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.checkCircularLimit();
|
|
430
|
+
if (step.sessionResults) {
|
|
431
|
+
AgentRuntime.processResults[this.processID].sessionResults.push(step.sessionResults);
|
|
432
|
+
}
|
|
433
|
+
if (step.errorResults) {
|
|
434
|
+
AgentRuntime.processResults[this.processID].errorResults.push(step.errorResults);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (step?.sessionClosed || this.circularLimitReached) {
|
|
438
|
+
const finalResult = this.processResults();
|
|
439
|
+
step.finalResult = finalResult;
|
|
440
|
+
runtime.sessionClosed = true;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
this.incStep();
|
|
444
|
+
this.sync();
|
|
445
|
+
return step;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private processResults() {
|
|
449
|
+
//this.checkCircularLimit();
|
|
450
|
+
let result: any = { error: 'Error processing results' };
|
|
451
|
+
const sessionResults = AgentRuntime.processResults[this.processID].sessionResults;
|
|
452
|
+
const errorResults = AgentRuntime.processResults[this.processID].errorResults;
|
|
453
|
+
if (this.circularLimitReached) {
|
|
454
|
+
const circularLimitData = this.circularLimitReached;
|
|
455
|
+
result = { error: `Circular Calls Limit Reached on ${circularLimitData}. Current circular limit is ${this.agent.circularLimit}` };
|
|
456
|
+
} else {
|
|
457
|
+
let state = [sessionResults, errorResults].flat(Infinity);
|
|
458
|
+
if (!state || state.length == 0) state = errorResults.flat(Infinity);
|
|
459
|
+
|
|
460
|
+
//post process run cycle results
|
|
461
|
+
//deduplicating redundant entries
|
|
462
|
+
|
|
463
|
+
const data = state
|
|
464
|
+
.reduce(
|
|
465
|
+
(acc, current) => {
|
|
466
|
+
if (!acc.seen[current.id]) {
|
|
467
|
+
acc.result.push(current);
|
|
468
|
+
acc.seen[current.id] = true;
|
|
469
|
+
}
|
|
470
|
+
return acc;
|
|
471
|
+
},
|
|
472
|
+
{ seen: {}, result: [] }
|
|
473
|
+
)
|
|
474
|
+
.result.filter((e) => !e.result?._exclude);
|
|
475
|
+
|
|
476
|
+
//data.forEach((d: any) => delete d?.result?._debug);
|
|
477
|
+
|
|
478
|
+
result = data;
|
|
479
|
+
/////////////
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
//cleanup
|
|
483
|
+
delete AgentRuntime.processResults[this.processID];
|
|
484
|
+
|
|
485
|
+
this.sync();
|
|
486
|
+
return result;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
public checkCircularLimit() {
|
|
490
|
+
if (this.circularLimitReached) return this.agentContext.circularLimitReached;
|
|
491
|
+
for (let componentId in AgentRuntime.tagsData[this.reqTag]) {
|
|
492
|
+
if (AgentRuntime.tagsData[this.reqTag][componentId] > this.agent.circularLimit) {
|
|
493
|
+
this.sessionClosed = true;
|
|
494
|
+
this.agentContext.circularLimitReached = componentId;
|
|
495
|
+
return componentId;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
public async injectDebugOutput(componentId: string) {
|
|
502
|
+
let component: {
|
|
503
|
+
ctx?: Record<string, any>;
|
|
504
|
+
} = {};
|
|
505
|
+
|
|
506
|
+
if (this.xDebugPendingInject) {
|
|
507
|
+
component = this.xDebugPendingInject?.find((c: any) => c.id == componentId);
|
|
508
|
+
} else if (this.xMockDataInject) {
|
|
509
|
+
component = this.xMockDataInject?.find((c: any) => c.id == componentId);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (component?.ctx?.output) {
|
|
513
|
+
//if all outputs values are empty, we don't inject
|
|
514
|
+
let allEmpty = true;
|
|
515
|
+
for (let key in component.ctx.output) {
|
|
516
|
+
if (component.ctx.output[key] != '') {
|
|
517
|
+
allEmpty = false;
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (allEmpty) return null;
|
|
522
|
+
|
|
523
|
+
return component.ctx.output;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
public getRuntimeData(componentId) {
|
|
527
|
+
const componentData = this.getComponentData(componentId);
|
|
528
|
+
if (!componentData) return {};
|
|
529
|
+
const rData = componentData.runtimeData || {};
|
|
530
|
+
|
|
531
|
+
return rData;
|
|
532
|
+
}
|
|
533
|
+
public updateRuntimeData(componentId, data) {
|
|
534
|
+
const componentData = this.getComponentData(componentId);
|
|
535
|
+
if (!componentData) return;
|
|
536
|
+
componentData.runtimeData = { ...componentData.runtimeData, ...data };
|
|
537
|
+
|
|
538
|
+
this.sync();
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
public saveRuntimeComponentData(componentId, data) {
|
|
542
|
+
this.updateComponent(componentId, { runtimeData: data });
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
public incStep() {
|
|
546
|
+
this.agentContext.incStep();
|
|
547
|
+
}
|
|
548
|
+
public updateComponent(componentId: string, data: any) {
|
|
549
|
+
this.agentContext.updateComponent(componentId, data);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
public resetComponent(componentId: string) {
|
|
553
|
+
this.agentContext.resetComponent(componentId);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
public getComponentData(componentId: string) {
|
|
557
|
+
return this.agentContext.getComponentData(componentId);
|
|
558
|
+
}
|
|
559
|
+
}
|