@memberjunction/ai-agents 2.50.0 → 2.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,113 +1,236 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseAgent = void 0;
4
+ const core_1 = require("@memberjunction/core");
4
5
  const ai_prompts_1 = require("@memberjunction/ai-prompts");
5
- const base_agent_type_1 = require("./base-agent-type");
6
+ const base_agent_type_1 = require("./agent-types/base-agent-type");
6
7
  const global_1 = require("@memberjunction/global");
7
8
  const aiengine_1 = require("@memberjunction/aiengine");
8
9
  const actions_1 = require("@memberjunction/actions");
10
+ const AgentRunner_1 = require("./AgentRunner");
9
11
  class BaseAgent {
10
12
  constructor() {
11
13
  this._promptRunner = new ai_prompts_1.AIPromptRunner();
14
+ this._metadata = new core_1.Metadata();
15
+ this._runContext = null;
16
+ this._agentRun = null;
17
+ this._executionChain = [];
18
+ this._allProgressSteps = [];
19
+ this._subAgentRuns = [];
20
+ }
21
+ async getAgentRunSteps(contextUser) {
22
+ if (!this._agentRun)
23
+ return [];
24
+ const md = new core_1.Metadata();
25
+ const rv = new core_1.RunView();
26
+ const result = await rv.RunView({
27
+ EntityName: 'MJ: AI Agent Run Steps',
28
+ ExtraFilter: `AgentRunID = '${this._agentRun.ID}'`,
29
+ OrderBy: 'StepNumber',
30
+ ResultType: 'entity_object'
31
+ }, contextUser);
32
+ return result.Success ? result.Results : [];
33
+ }
34
+ wrapProgressCallback(originalCallback) {
35
+ if (!originalCallback)
36
+ return undefined;
37
+ return (progress) => {
38
+ this._allProgressSteps.push({
39
+ ...progress,
40
+ timestamp: new Date(),
41
+ agentHierarchy: this._runContext?.agentHierarchy || [],
42
+ depth: this._runContext?.depth || 0
43
+ });
44
+ originalCallback(progress);
45
+ };
12
46
  }
13
47
  async Execute(params) {
14
48
  try {
15
- await aiengine_1.AIEngine.Instance.Config(false, params.contextUser);
16
- await actions_1.ActionEngineServer.Instance.Config(false, params.contextUser);
17
- const engine = aiengine_1.AIEngine.Instance;
18
- if (params.agent.Status !== 'Active') {
19
- return {
20
- nextStep: 'failed',
21
- errorMessage: `Agent '${params.agent.Name}' is not active. Current status: ${params.agent.Status}`
22
- };
23
- }
24
- const agentType = engine.AgentTypes.find(at => at.ID === params.agent.TypeID);
25
- if (!agentType) {
26
- return {
27
- nextStep: 'failed',
28
- errorMessage: `Agent type not found for ID: ${params.agent.TypeID}`
29
- };
30
- }
31
- const systemPrompt = engine.Prompts.find(p => p.ID === agentType.SystemPromptID);
32
- if (!systemPrompt) {
33
- return {
34
- nextStep: 'failed',
35
- errorMessage: `System prompt not found for agent type: ${agentType.Name}`
36
- };
37
- }
38
- const agentPrompt = engine.AgentPrompts
39
- .filter(ap => ap.AgentID === params.agent.ID && ap.Status === 'Active')
40
- .sort((a, b) => a.ExecutionOrder - b.ExecutionOrder)[0];
41
- if (!agentPrompt) {
42
- return {
43
- nextStep: 'failed',
44
- errorMessage: `No prompts configured for agent: ${params.agent.Name}`
45
- };
49
+ const wrappedParams = {
50
+ ...params,
51
+ onProgress: this.wrapProgressCallback(params.onProgress)
52
+ };
53
+ if (params.cancellationToken?.aborted) {
54
+ return await this.createCancelledResult('Cancelled before execution started', params.contextUser);
46
55
  }
47
- const childPrompt = engine.Prompts.find(p => p.ID === agentPrompt.PromptID);
48
- if (!childPrompt) {
49
- return {
50
- nextStep: 'failed',
51
- errorMessage: `Child prompt not found for ID: ${agentPrompt.PromptID}`
52
- };
56
+ wrappedParams.onProgress?.({
57
+ step: 'initialization',
58
+ percentage: 0,
59
+ message: this.formatHierarchicalMessage(`Initializing ${params.agent.Name} agent and preparing execution environment`)
60
+ });
61
+ await this.initializeAgentRun(wrappedParams);
62
+ await this.initializeEngines(params.contextUser);
63
+ if (params.cancellationToken?.aborted) {
64
+ return await this.createCancelledResult('Cancelled during initialization', params.contextUser);
53
65
  }
54
- const contextData = await this.gatherContextData(params.agent, params.contextUser);
55
- const promptParams = new ai_prompts_1.AIPromptParams();
56
- promptParams.prompt = systemPrompt;
57
- promptParams.data = contextData;
58
- promptParams.contextUser = params.contextUser;
59
- promptParams.conversationMessages = params.conversationMessages;
60
- promptParams.templateMessageRole = 'system';
61
- if (!agentType.AgentPromptPlaceholder) {
62
- const errorMsg = `Agent type '${agentType.Name}' does not have AgentPromptPlaceholder configured. This field is required to properly inject agent prompt results into the system prompt template.`;
63
- console.error(errorMsg);
64
- return {
65
- nextStep: 'failed',
66
- errorMessage: errorMsg
67
- };
66
+ wrappedParams.onProgress?.({
67
+ step: 'validation',
68
+ percentage: 10,
69
+ message: this.formatHierarchicalMessage('Validating agent configuration and loading prompts')
70
+ });
71
+ const validationResult = await this.validateAgentWithTracking(params.agent, params.contextUser);
72
+ if (validationResult)
73
+ return validationResult;
74
+ const config = await this.loadAgentConfiguration(params.agent);
75
+ if (!config.success) {
76
+ return await this.createFailureResult(config.errorMessage || 'Failed to load agent configuration', params.contextUser);
68
77
  }
69
- promptParams.childPrompts = [
70
- new ai_prompts_1.ChildPromptParam({
71
- prompt: childPrompt,
72
- data: contextData,
73
- contextUser: params.contextUser,
74
- conversationMessages: params.conversationMessages,
75
- templateMessageRole: 'user'
76
- }, agentType.AgentPromptPlaceholder)
77
- ];
78
- const result = await this._promptRunner.ExecutePrompt(promptParams);
79
- if (!result.success) {
80
- return {
81
- nextStep: 'failed',
82
- errorMessage: result.errorMessage,
83
- rawResult: result.rawResult
84
- };
78
+ let continueExecution = true;
79
+ let currentNextStep = null;
80
+ let finalReturnValue = undefined;
81
+ let stepCount = 0;
82
+ while (continueExecution) {
83
+ if (params.cancellationToken?.aborted) {
84
+ return await this.createCancelledResult('Cancelled during execution', params.contextUser);
85
+ }
86
+ const stepResult = await this.executeNextStep(wrappedParams, config, currentNextStep);
87
+ stepCount++;
88
+ if (stepResult.terminate) {
89
+ continueExecution = false;
90
+ finalReturnValue = stepResult.returnValue;
91
+ }
92
+ else {
93
+ currentNextStep = stepResult.nextStep;
94
+ }
85
95
  }
86
- let agentTypeInstance;
87
- try {
88
- agentTypeInstance = await this.getAgentTypeInstance(agentType);
89
- }
90
- catch (error) {
91
- return {
92
- nextStep: 'failed',
93
- errorMessage: error.message
94
- };
96
+ wrappedParams.onProgress?.({
97
+ step: 'finalization',
98
+ percentage: 95,
99
+ message: this.formatHierarchicalMessage('Finalizing agent execution')
100
+ });
101
+ return await this.finalizeAgentRun(finalReturnValue?.step || 'success', finalReturnValue, params.contextUser);
102
+ }
103
+ catch (error) {
104
+ if (params.cancellationToken?.aborted) {
105
+ return await this.createCancelledResult('Cancelled due to error during execution', params.contextUser);
95
106
  }
96
- const nextStep = await agentTypeInstance.DetermineNextStep(result);
107
+ return await this.createFailureResult(error.message, params.contextUser);
108
+ }
109
+ }
110
+ async initializeEngines(contextUser) {
111
+ await aiengine_1.AIEngine.Instance.Config(false, contextUser);
112
+ await actions_1.ActionEngineServer.Instance.Config(false, contextUser);
113
+ }
114
+ async validateAgent(agent) {
115
+ if (agent.Status !== 'Active') {
97
116
  return {
98
- nextStep: nextStep.step,
99
- returnValue: nextStep.returnValue || result.result,
100
- rawResult: result.rawResult
117
+ success: false,
118
+ finalStep: 'failed',
119
+ errorMessage: `Agent '${agent.Name}' is not active. Current status: ${agent.Status}`,
120
+ agentRun: this._agentRun,
121
+ executionTree: []
101
122
  };
102
123
  }
124
+ return null;
125
+ }
126
+ async loadAgentConfiguration(agent) {
127
+ const engine = aiengine_1.AIEngine.Instance;
128
+ const agentType = engine.AgentTypes.find(at => at.ID === agent.TypeID);
129
+ if (!agentType) {
130
+ return {
131
+ success: false,
132
+ errorMessage: `Agent type not found for ID: ${agent.TypeID}`
133
+ };
134
+ }
135
+ const systemPrompt = engine.Prompts.find(p => p.ID === agentType.SystemPromptID);
136
+ if (!systemPrompt) {
137
+ return {
138
+ success: false,
139
+ errorMessage: `System prompt not found for agent type: ${agentType.Name}`
140
+ };
141
+ }
142
+ const agentPrompt = engine.AgentPrompts
143
+ .filter(ap => ap.AgentID === agent.ID && ap.Status === 'Active')
144
+ .sort((a, b) => a.ExecutionOrder - b.ExecutionOrder)[0];
145
+ if (!agentPrompt) {
146
+ return {
147
+ success: false,
148
+ errorMessage: `No prompts configured for agent: ${agent.Name}`
149
+ };
150
+ }
151
+ const childPrompt = engine.Prompts.find(p => p.ID === agentPrompt.PromptID);
152
+ if (!childPrompt) {
153
+ return {
154
+ success: false,
155
+ errorMessage: `Child prompt not found for ID: ${agentPrompt.PromptID}`
156
+ };
157
+ }
158
+ if (!agentType.AgentPromptPlaceholder) {
159
+ return {
160
+ success: false,
161
+ errorMessage: `Agent type '${agentType.Name}' does not have AgentPromptPlaceholder configured.`
162
+ };
163
+ }
164
+ return {
165
+ success: true,
166
+ agentType,
167
+ systemPrompt,
168
+ childPrompt
169
+ };
170
+ }
171
+ async preparePromptParams(agentType, systemPrompt, childPrompt, params) {
172
+ const contextData = await this.gatherContextData(params.agent, params.contextUser);
173
+ const promptParams = new ai_prompts_1.AIPromptParams();
174
+ promptParams.prompt = systemPrompt;
175
+ promptParams.data = contextData;
176
+ promptParams.contextUser = params.contextUser;
177
+ promptParams.conversationMessages = params.conversationMessages;
178
+ promptParams.templateMessageRole = 'system';
179
+ promptParams.childPrompts = [
180
+ new ai_prompts_1.ChildPromptParam({
181
+ prompt: childPrompt,
182
+ data: contextData,
183
+ contextUser: params.contextUser,
184
+ conversationMessages: params.conversationMessages,
185
+ templateMessageRole: 'user'
186
+ }, agentType.AgentPromptPlaceholder)
187
+ ];
188
+ return promptParams;
189
+ }
190
+ async executePrompt(promptParams) {
191
+ return await this._promptRunner.ExecutePrompt(promptParams);
192
+ }
193
+ async processNextStep(params, agentType, promptResult) {
194
+ let agentTypeInstance;
195
+ try {
196
+ agentTypeInstance = await this.getAgentTypeInstance(agentType);
197
+ }
103
198
  catch (error) {
104
199
  return {
105
- nextStep: 'failed',
106
- errorMessage: error.message,
200
+ step: 'failed',
201
+ errorMessage: error.message
107
202
  };
108
203
  }
204
+ const nextStep = await agentTypeInstance.DetermineNextStep(promptResult);
205
+ return nextStep;
206
+ }
207
+ createActionResultMessage(actions, results) {
208
+ const resultSummary = actions.map((action, index) => {
209
+ const result = results[index];
210
+ const outputParams = result.Params?.filter((p) => p.Type === 'Output' || p.Type === 'Both') || [];
211
+ return {
212
+ actionName: action.name,
213
+ success: result.Success,
214
+ resultCode: result.Result?.Code || 'N/A',
215
+ message: result.Message || null,
216
+ outputs: outputParams.reduce((acc, param) => {
217
+ acc[param.Name] = param.Value;
218
+ return acc;
219
+ }, {})
220
+ };
221
+ });
222
+ return {
223
+ role: 'user',
224
+ content: `Action results:\n${JSON.stringify(resultSummary, null, 2)}`
225
+ };
226
+ }
227
+ createSubAgentResultMessage(subAgent, result) {
228
+ return {
229
+ role: 'user',
230
+ content: `Sub-agent '${subAgent.name}' result:\n${typeof result === 'string' ? result : JSON.stringify(result, null, 2)}`
231
+ };
109
232
  }
110
- async gatherContextData(agent, contextUser) {
233
+ async gatherContextData(agent, _contextUser) {
111
234
  try {
112
235
  const engine = aiengine_1.AIEngine.Instance;
113
236
  const subAgents = engine.Agents.filter(a => a.ParentID === agent.ID)
@@ -119,21 +242,9 @@ class BaseAgent {
119
242
  agentName: agent.Name,
120
243
  agentDescription: agent.Description,
121
244
  subAgentCount: subAgents.length,
122
- subAgentDetails: JSON.stringify(subAgents.map(sa => {
123
- return {
124
- ID: sa.ID,
125
- Name: sa.Name,
126
- Description: sa.Description
127
- };
128
- }), null, 2),
245
+ subAgentDetails: this.formatSubAgentDetails(subAgents),
129
246
  actionCount: actions.length,
130
- actionDetails: JSON.stringify(activeActions.map(action => {
131
- return {
132
- ID: action.ID,
133
- Name: action.Name,
134
- Description: action.Description,
135
- };
136
- }), null, 2),
247
+ actionDetails: this.formatActionDetails(activeActions),
137
248
  };
138
249
  return contextData;
139
250
  }
@@ -151,6 +262,894 @@ class BaseAgent {
151
262
  }
152
263
  return instance;
153
264
  }
265
+ async ExecuteActions(params, actions, contextUser) {
266
+ try {
267
+ const actionEngine = actions_1.ActionEngineServer.Instance;
268
+ const actionPromises = actions.map(async (action) => {
269
+ if (!action.id) {
270
+ throw new Error(`Action ID is required for action: ${action.name || 'unknown'}`);
271
+ }
272
+ const actionEntity = actionEngine.Actions.find(a => a.ID === action.id);
273
+ if (!actionEntity) {
274
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
275
+ if (!uuidRegex.test(action.id)) {
276
+ throw new Error(`${action.id} is not a valid UUID and must be a UUID representing the Action ID`);
277
+ }
278
+ else {
279
+ throw new Error(`Action with ID ${action.id} not found in the action table`);
280
+ }
281
+ }
282
+ const actionParams = Object.entries(action.params || {}).map(([key, value]) => ({
283
+ Name: key,
284
+ Value: value,
285
+ Type: 'Input'
286
+ }));
287
+ const result = await actionEngine.RunAction({
288
+ Action: actionEntity,
289
+ Params: actionParams,
290
+ ContextUser: contextUser,
291
+ Filters: [],
292
+ SkipActionLog: false,
293
+ Context: params.context
294
+ });
295
+ if (!result.Success) {
296
+ throw new Error(`Action '${action.name}' failed: ${result.Message || 'Unknown error'}`);
297
+ }
298
+ return result;
299
+ });
300
+ return await Promise.all(actionPromises);
301
+ }
302
+ catch (error) {
303
+ throw new Error(`Error executing actions: ${error.message}`);
304
+ }
305
+ }
306
+ async ExecuteSubAgent(params, subAgentRequest) {
307
+ try {
308
+ const engine = aiengine_1.AIEngine.Instance;
309
+ if (!subAgentRequest.id) {
310
+ throw new Error('Sub-agent ID is required');
311
+ }
312
+ const subAgent = engine.Agents.find(a => a.ID === subAgentRequest.id);
313
+ if (!subAgent) {
314
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
315
+ if (!uuidRegex.test(subAgentRequest.id)) {
316
+ throw new Error(`${subAgentRequest.id} is not a valid UUID and must be a UUID representing the Agent ID`);
317
+ }
318
+ else {
319
+ throw new Error(`Sub-agent with ID ${subAgentRequest.id} not found in the agent table`);
320
+ }
321
+ }
322
+ const runner = new AgentRunner_1.AgentRunner();
323
+ const subAgentMessages = [
324
+ ...params.conversationMessages,
325
+ {
326
+ role: 'user',
327
+ content: subAgentRequest.message
328
+ }
329
+ ];
330
+ const result = await runner.RunAgent({
331
+ agent: subAgent,
332
+ conversationMessages: subAgentMessages,
333
+ contextUser: params.contextUser,
334
+ cancellationToken: params.cancellationToken,
335
+ onProgress: params.onProgress,
336
+ onStreaming: params.onStreaming,
337
+ parentAgentHierarchy: this._runContext?.agentHierarchy,
338
+ parentDepth: this._runContext?.depth,
339
+ context: params.context
340
+ });
341
+ if (!result.success) {
342
+ throw new Error(`Sub-agent '${subAgentRequest.name}' failed: ${result.errorMessage || 'Unknown error'}`);
343
+ }
344
+ return result;
345
+ }
346
+ catch (error) {
347
+ throw new Error(`Error executing sub-agent: ${error.message}`);
348
+ }
349
+ }
350
+ formatSubAgentDetails(subAgents) {
351
+ return JSON.stringify(subAgents.map(sa => ({
352
+ ID: sa.ID,
353
+ Name: sa.Name,
354
+ Description: sa.Description,
355
+ Type: sa.TypeID ? this.getAgentTypeName(sa.TypeID) : 'Unknown',
356
+ Status: sa.Status,
357
+ ExecutionMode: sa.ExecutionMode,
358
+ ExecutionOrder: sa.ExecutionOrder
359
+ })), null, 2);
360
+ }
361
+ formatActionDetails(actions) {
362
+ return JSON.stringify(actions.map(action => ({
363
+ ID: action.ID,
364
+ Name: action.Name,
365
+ Description: action.Description,
366
+ Parameters: {
367
+ Input: action.Params
368
+ .filter(p => p.Type.trim().toLowerCase() === 'input' || p.Type.trim().toLowerCase() === 'both')
369
+ .map(param => this.formatActionParameter(param)),
370
+ Output: action.Params
371
+ .filter(p => p.Type.trim().toLowerCase() === 'output' || p.Type.trim().toLowerCase() === 'both')
372
+ .map(param => this.formatActionParameter(param))
373
+ },
374
+ ResultCodes: action.ResultCodes.map(rc => ({
375
+ Code: rc.ResultCode,
376
+ IsSuccess: rc.IsSuccess,
377
+ Description: rc.Description || 'No description provided',
378
+ Usage: this.inferResultCodeUsage(rc.ResultCode, rc.IsSuccess)
379
+ })),
380
+ Category: action.CategoryID ? this.getActionCategoryName(action.CategoryID) : null,
381
+ Status: action.Status
382
+ })), null, 2);
383
+ }
384
+ formatActionParameter(param) {
385
+ return {
386
+ Name: param.Name,
387
+ Type: param.Type,
388
+ IsRequired: param.IsRequired,
389
+ IsArray: param.IsArray,
390
+ DefaultValue: param.DefaultValue,
391
+ Description: param.Description,
392
+ ValueType: param.ValueType
393
+ };
394
+ }
395
+ getAgentTypeName(typeID) {
396
+ const agentType = aiengine_1.AIEngine.Instance.AgentTypes.find(at => at.ID === typeID);
397
+ return agentType?.Name || 'Unknown';
398
+ }
399
+ getValueListItems(valueListID) {
400
+ return null;
401
+ }
402
+ getActionCategoryName(categoryID) {
403
+ return 'General';
404
+ }
405
+ inferResultCodeUsage(resultCode, isSuccess) {
406
+ if (resultCode === 'SUCCESS') {
407
+ return 'Returned when the action completes successfully';
408
+ }
409
+ else if (resultCode === 'FAILED') {
410
+ return 'Generic failure - check error message for details';
411
+ }
412
+ else if (resultCode.includes('MISSING_PARAMETERS')) {
413
+ return 'Returned when required parameters are not provided';
414
+ }
415
+ else if (resultCode.includes('INVALID')) {
416
+ return 'Returned when input validation fails';
417
+ }
418
+ else if (resultCode.includes('NOT_FOUND')) {
419
+ return 'Returned when the requested resource cannot be found';
420
+ }
421
+ else if (resultCode.includes('TIMEOUT')) {
422
+ return 'Returned when the operation times out';
423
+ }
424
+ else if (resultCode.includes('PERMISSION') || resultCode.includes('UNAUTHORIZED')) {
425
+ return 'Returned when permission is denied';
426
+ }
427
+ else {
428
+ return isSuccess
429
+ ? 'Specific success condition - see description'
430
+ : 'Specific error condition - see description';
431
+ }
432
+ }
433
+ async initializeAgentRun(params) {
434
+ this._agentRun = await this._metadata.GetEntityObject('MJ: AI Agent Runs', params.contextUser);
435
+ this._agentRun.AgentID = params.agent.ID;
436
+ this._agentRun.Status = 'Running';
437
+ this._agentRun.StartedAt = new Date();
438
+ this._agentRun.UserID = params.contextUser?.ID || null;
439
+ this._agentRun.ParentRunID = null;
440
+ if (!await this._agentRun.Save()) {
441
+ throw new Error('Failed to create agent run record');
442
+ }
443
+ this._runContext = {
444
+ currentStepIndex: 0,
445
+ parentRunStack: [],
446
+ agentHierarchy: params.parentAgentHierarchy
447
+ ? [...params.parentAgentHierarchy, params.agent.Name || 'Unknown Agent']
448
+ : [params.agent.Name || 'Unknown Agent'],
449
+ depth: params.parentDepth !== undefined ? params.parentDepth + 1 : 0,
450
+ conversationId: undefined,
451
+ userId: params.contextUser?.ID,
452
+ agentState: {}
453
+ };
454
+ this._executionChain = [];
455
+ this._allProgressSteps = [];
456
+ }
457
+ async validateAgentWithTracking(agent, contextUser) {
458
+ const startTime = new Date();
459
+ try {
460
+ const validationResult = await this.validateAgent(agent);
461
+ if (validationResult) {
462
+ const stepEntity = await this.createStepEntity('validation', 'Agent Validation', contextUser);
463
+ const executionResult = {
464
+ type: 'validation',
465
+ validationTarget: 'agent configuration',
466
+ result: { valid: false, errors: [validationResult.errorMessage || 'Validation failed'] }
467
+ };
468
+ const nextStepDecision = {
469
+ decision: 'failed',
470
+ reasoning: 'Agent validation failed',
471
+ nextStepDetails: { type: 'complete' }
472
+ };
473
+ this._executionChain.push({
474
+ stepEntity,
475
+ executionType: 'validation',
476
+ executionResult,
477
+ nextStepDecision,
478
+ startTime,
479
+ endTime: new Date(),
480
+ durationMs: new Date().getTime() - startTime.getTime()
481
+ });
482
+ await this.finalizeStepEntity(stepEntity, false, validationResult.errorMessage);
483
+ return await this.createFailureResult(validationResult.errorMessage || 'Validation failed', contextUser);
484
+ }
485
+ const stepEntity = await this.createStepEntity('validation', 'Agent Validation', contextUser);
486
+ const executionResult = {
487
+ type: 'validation',
488
+ validationTarget: 'agent configuration',
489
+ result: { valid: true }
490
+ };
491
+ const nextStepDecision = {
492
+ decision: 'success',
493
+ reasoning: 'Agent validation passed',
494
+ nextStepDetails: { type: 'prompt', promptId: agent.ID, promptName: 'Initial Prompt' }
495
+ };
496
+ this._executionChain.push({
497
+ stepEntity,
498
+ executionType: 'validation',
499
+ executionResult,
500
+ nextStepDecision,
501
+ startTime,
502
+ endTime: new Date(),
503
+ durationMs: new Date().getTime() - startTime.getTime()
504
+ });
505
+ await this.finalizeStepEntity(stepEntity, true);
506
+ return null;
507
+ }
508
+ catch (error) {
509
+ return await this.createFailureResult(`Validation error: ${error.message}`, contextUser);
510
+ }
511
+ }
512
+ async createStepEntity(stepType, stepName, contextUser, targetId, inputData) {
513
+ const stepEntity = await this._metadata.GetEntityObject('MJ: AI Agent Run Steps', contextUser);
514
+ stepEntity.AgentRunID = this._agentRun.ID;
515
+ stepEntity.StepNumber = this._runContext.currentStepIndex + 1;
516
+ stepEntity.StepType = stepType;
517
+ stepEntity.StepName = this.formatHierarchicalMessage(stepName);
518
+ stepEntity.TargetID = targetId || null;
519
+ stepEntity.Status = 'Running';
520
+ stepEntity.StartedAt = new Date();
521
+ if (inputData) {
522
+ stepEntity.InputData = JSON.stringify({
523
+ ...inputData,
524
+ context: {
525
+ agentHierarchy: this._runContext.agentHierarchy,
526
+ depth: this._runContext.depth,
527
+ stepNumber: stepEntity.StepNumber
528
+ }
529
+ });
530
+ }
531
+ if (!await stepEntity.Save()) {
532
+ throw new Error(`Failed to create agent run step record: ${JSON.stringify(stepEntity.LatestResult)}`);
533
+ }
534
+ this._runContext.currentStepIndex++;
535
+ return stepEntity;
536
+ }
537
+ async finalizeStepEntity(stepEntity, success, errorMessage, outputData) {
538
+ stepEntity.Status = success ? 'Completed' : 'Failed';
539
+ stepEntity.CompletedAt = new Date();
540
+ stepEntity.Success = success;
541
+ stepEntity.ErrorMessage = errorMessage || null;
542
+ if (outputData) {
543
+ stepEntity.OutputData = JSON.stringify({
544
+ ...outputData,
545
+ context: {
546
+ success,
547
+ durationMs: stepEntity.CompletedAt.getTime() - stepEntity.StartedAt.getTime(),
548
+ errorMessage
549
+ }
550
+ });
551
+ }
552
+ if (!await stepEntity.Save()) {
553
+ console.error('Failed to update agent run step record');
554
+ }
555
+ }
556
+ formatHierarchicalMessage(baseMessage) {
557
+ if (this._runContext && this._runContext.depth > 0) {
558
+ const breadcrumb = this._runContext.agentHierarchy
559
+ .slice(1)
560
+ .join(' → ');
561
+ return breadcrumb ? `${breadcrumb}: ${baseMessage}` : baseMessage;
562
+ }
563
+ return baseMessage;
564
+ }
565
+ async executeNextStep(params, config, previousDecision) {
566
+ if (!previousDecision) {
567
+ return await this.executePromptStep(params, config);
568
+ }
569
+ switch (previousDecision.step) {
570
+ case 'retry':
571
+ return await this.executePromptStep(params, config, previousDecision);
572
+ case 'sub-agent':
573
+ return await this.executeSubAgentStep(params, previousDecision.subAgent);
574
+ case 'actions':
575
+ return await this.executeActionsStep(params, previousDecision.actions);
576
+ case 'chat':
577
+ return await this.executeChatStep(params, previousDecision.userMessage);
578
+ case 'success':
579
+ case 'failed':
580
+ return { terminate: true, returnValue: previousDecision.returnValue };
581
+ default:
582
+ throw new Error(`Unsupported next step: ${previousDecision.step}`);
583
+ }
584
+ }
585
+ async executePromptStep(params, config, retryContext) {
586
+ const startTime = new Date();
587
+ const inputData = {
588
+ promptId: config.childPrompt?.ID,
589
+ promptName: config.childPrompt?.Name,
590
+ isRetry: !!retryContext,
591
+ retryContext: retryContext ? {
592
+ reason: retryContext.retryReason,
593
+ instructions: retryContext.retryInstructions
594
+ } : undefined,
595
+ conversationMessages: params.conversationMessages,
596
+ agentState: this._runContext?.agentState
597
+ };
598
+ const stepEntity = await this.createStepEntity('prompt', 'Execute Agent Prompt', params.contextUser, config.childPrompt?.ID, inputData);
599
+ try {
600
+ const isRetry = !!retryContext;
601
+ const promptMessage = isRetry
602
+ ? `Re-executing agent prompt with additional context from ${retryContext.retryReason || 'previous actions'}`
603
+ : `Executing agent's initial prompt to analyze your request`;
604
+ params.onProgress?.({
605
+ step: 'prompt_execution',
606
+ percentage: 30,
607
+ message: this.formatHierarchicalMessage(promptMessage),
608
+ metadata: {
609
+ promptId: config.childPrompt?.ID,
610
+ isRetry,
611
+ promptName: config.childPrompt?.Name
612
+ }
613
+ });
614
+ const promptParams = await this.preparePromptParams(config.agentType, config.systemPrompt, config.childPrompt, params);
615
+ promptParams.cancellationToken = params.cancellationToken;
616
+ promptParams.onStreaming = params.onStreaming ? (chunk) => {
617
+ params.onStreaming({
618
+ ...chunk,
619
+ stepType: 'prompt',
620
+ stepEntityId: stepEntity.ID
621
+ });
622
+ } : undefined;
623
+ const promptResult = await this.executePrompt(promptParams);
624
+ if (params.cancellationToken?.aborted) {
625
+ await this.finalizeStepEntity(stepEntity, false, 'Cancelled during prompt execution');
626
+ return { terminate: true, returnValue: await this.createCancelledResult('Cancelled during prompt execution', params.contextUser) };
627
+ }
628
+ const executionResult = {
629
+ type: 'prompt',
630
+ promptId: config.childPrompt.ID,
631
+ promptName: config.childPrompt.Name,
632
+ result: promptResult
633
+ };
634
+ params.onProgress?.({
635
+ step: 'decision_processing',
636
+ percentage: 70,
637
+ message: this.formatHierarchicalMessage('Analyzing response and determining next steps')
638
+ });
639
+ const nextStep = await this.processNextStep(params, config.agentType, promptResult);
640
+ const nextStepDecision = {
641
+ decision: nextStep.step,
642
+ reasoning: this.getNextStepReasoning(nextStep),
643
+ nextStepDetails: this.getNextStepDetails(nextStep)
644
+ };
645
+ this._executionChain.push({
646
+ stepEntity,
647
+ executionType: 'prompt',
648
+ executionResult,
649
+ nextStepDecision,
650
+ startTime,
651
+ endTime: new Date(),
652
+ durationMs: new Date().getTime() - startTime.getTime()
653
+ });
654
+ const outputData = {
655
+ promptResult: {
656
+ success: promptResult.success,
657
+ llmResponse: promptResult.llmResponse,
658
+ modelUsed: promptResult.runInfo?.modelName,
659
+ tokensUsed: promptResult.runInfo?.promptRun?.TotalTokensUsed,
660
+ totalCost: promptResult.runInfo?.promptRun?.TotalCost
661
+ },
662
+ nextStep: {
663
+ decision: nextStep.step,
664
+ reasoning: nextStepDecision.reasoning
665
+ }
666
+ };
667
+ await this.finalizeStepEntity(stepEntity, promptResult.success, promptResult.success ? undefined : promptResult.errorMessage, outputData);
668
+ if (nextStep.step === 'chat') {
669
+ return { terminate: true, returnValue: nextStep };
670
+ }
671
+ else if (nextStep.step === 'success' || nextStep.step === 'failed') {
672
+ return { terminate: true, returnValue: nextStep.returnValue };
673
+ }
674
+ else {
675
+ return { terminate: false, nextStep };
676
+ }
677
+ }
678
+ catch (error) {
679
+ await this.finalizeStepEntity(stepEntity, false, error.message);
680
+ throw error;
681
+ }
682
+ }
683
+ async executeSubAgentStep(params, subAgentRequest) {
684
+ if (params.cancellationToken?.aborted) {
685
+ throw new Error('Cancelled before sub-agent execution');
686
+ }
687
+ params.onProgress?.({
688
+ step: 'subagent_execution',
689
+ percentage: 60,
690
+ message: this.formatHierarchicalMessage(`Delegating to ${subAgentRequest.name} agent`),
691
+ metadata: {
692
+ subAgentId: subAgentRequest.id,
693
+ subAgentName: subAgentRequest.name,
694
+ reason: subAgentRequest.message
695
+ }
696
+ });
697
+ params.conversationMessages.push({
698
+ role: 'assistant',
699
+ content: `I'm delegating this task to the "${subAgentRequest.name}" agent.\n\nReason: ${subAgentRequest.message}`
700
+ });
701
+ const startTime = new Date();
702
+ const inputData = {
703
+ subAgentId: subAgentRequest.id,
704
+ subAgentName: subAgentRequest.name,
705
+ message: subAgentRequest.message,
706
+ terminateAfter: subAgentRequest.terminateAfter,
707
+ conversationMessages: params.conversationMessages,
708
+ parentAgentHierarchy: this._runContext?.agentHierarchy
709
+ };
710
+ const stepEntity = await this.createStepEntity('subagent', `Execute Sub-Agent: ${subAgentRequest.name}`, params.contextUser, subAgentRequest.id, inputData);
711
+ try {
712
+ const subAgentResult = await this.ExecuteSubAgent(params, subAgentRequest);
713
+ if (params.cancellationToken?.aborted) {
714
+ await this.finalizeStepEntity(stepEntity, false, 'Cancelled during sub-agent execution');
715
+ throw new Error('Cancelled during sub-agent execution');
716
+ }
717
+ const executionResult = {
718
+ type: 'sub-agent',
719
+ subAgentId: subAgentRequest.id,
720
+ subAgentName: subAgentRequest.name,
721
+ result: subAgentResult
722
+ };
723
+ this._subAgentRuns.push(subAgentResult);
724
+ const shouldTerminate = subAgentRequest.terminateAfter;
725
+ const nextStepType = subAgentResult.returnValue?.step || 'retry';
726
+ const nextStepDecision = {
727
+ decision: shouldTerminate ? 'success' : 'retry',
728
+ reasoning: shouldTerminate ? 'Sub-agent execution completed, terminating as requested' : 'Sub-agent completed, continuing execution',
729
+ nextStepDetails: { type: nextStepType, returnValue: subAgentResult.returnValue }
730
+ };
731
+ this._executionChain.push({
732
+ stepEntity,
733
+ executionType: 'sub-agent',
734
+ executionResult,
735
+ nextStepDecision,
736
+ startTime,
737
+ endTime: new Date(),
738
+ durationMs: new Date().getTime() - startTime.getTime()
739
+ });
740
+ const outputData = {
741
+ subAgentResult: {
742
+ success: subAgentResult.success,
743
+ finalStep: subAgentResult.finalStep,
744
+ returnValue: subAgentResult.returnValue,
745
+ errorMessage: subAgentResult.errorMessage,
746
+ agentRunId: subAgentResult.agentRun?.ID,
747
+ stepCount: this.countStepsInTree(subAgentResult.executionTree)
748
+ },
749
+ shouldTerminate: shouldTerminate,
750
+ nextStep: nextStepDecision.decision
751
+ };
752
+ await this.finalizeStepEntity(stepEntity, subAgentResult.success, subAgentResult.errorMessage, outputData);
753
+ const subAgentSummary = {
754
+ subAgentName: subAgentRequest.name,
755
+ subAgentId: subAgentRequest.id,
756
+ success: subAgentResult.success,
757
+ finalStep: subAgentResult.finalStep,
758
+ returnValue: subAgentResult.returnValue,
759
+ errorMessage: subAgentResult.errorMessage || null
760
+ };
761
+ const resultMessage = subAgentResult.success
762
+ ? `Sub-agent completed successfully:\n${JSON.stringify(subAgentSummary, null, 2)}`
763
+ : `Sub-agent failed:\n${JSON.stringify(subAgentSummary, null, 2)}`;
764
+ params.conversationMessages.push({
765
+ role: 'user',
766
+ content: resultMessage
767
+ });
768
+ if (shouldTerminate) {
769
+ return { terminate: true, returnValue: subAgentResult.returnValue };
770
+ }
771
+ else {
772
+ return {
773
+ terminate: false,
774
+ nextStep: {
775
+ step: 'retry',
776
+ retryReason: `Analyzing results from "${subAgentRequest.name}" agent to integrate findings`
777
+ }
778
+ };
779
+ }
780
+ }
781
+ catch (error) {
782
+ await this.finalizeStepEntity(stepEntity, false, error.message);
783
+ throw error;
784
+ }
785
+ }
786
+ async executeActionsStep(params, actions) {
787
+ if (params.cancellationToken?.aborted) {
788
+ throw new Error('Cancelled before action execution');
789
+ }
790
+ let progressMessage;
791
+ if (actions.length === 1) {
792
+ const action = actions[0];
793
+ progressMessage = `Executing action: **${action.name}**`;
794
+ if (action.params && Object.keys(action.params).length > 0) {
795
+ const paramsList = Object.entries(action.params)
796
+ .map(([key, value]) => {
797
+ const displayValue = typeof value === 'object'
798
+ ? JSON.stringify(value, null, 2)
799
+ : String(value);
800
+ return ` - \`${key}\`: ${displayValue}`;
801
+ })
802
+ .join('\n');
803
+ progressMessage += `\n${paramsList}`;
804
+ }
805
+ }
806
+ else {
807
+ progressMessage = `Executing ${actions.length} actions:`;
808
+ actions.forEach(action => {
809
+ progressMessage += `\n\n• **${action.name}**`;
810
+ if (action.params && Object.keys(action.params).length > 0) {
811
+ const paramsList = Object.entries(action.params)
812
+ .map(([key, value]) => {
813
+ const displayValue = typeof value === 'object'
814
+ ? JSON.stringify(value, null, 2)
815
+ : String(value);
816
+ return ` - \`${key}\`: ${displayValue}`;
817
+ })
818
+ .join('\n');
819
+ progressMessage += `\n${paramsList}`;
820
+ }
821
+ });
822
+ }
823
+ params.onProgress?.({
824
+ step: 'action_execution',
825
+ percentage: 50,
826
+ message: this.formatHierarchicalMessage(progressMessage),
827
+ metadata: {
828
+ actionCount: actions.length,
829
+ actionNames: actions.map(a => a.name)
830
+ }
831
+ });
832
+ const actionMessage = actions.length === 1
833
+ ? `I'm executing the "${actions[0].name}" action...`
834
+ : `I'm executing ${actions.length} actions to gather the information needed:\n${actions.map(a => `• ${a.name}`).join('\n')}`;
835
+ params.conversationMessages.push({
836
+ role: 'assistant',
837
+ content: actionMessage
838
+ });
839
+ const actionSteps = [];
840
+ for (const action of actions) {
841
+ const startTime = new Date();
842
+ const stepEntity = await this.createStepEntity('action', `Execute Action: ${action.name}`, params.contextUser, action.id);
843
+ actionSteps.push({ action, stepEntity, startTime });
844
+ }
845
+ const actionPromises = actionSteps.map(async ({ action, stepEntity, startTime }) => {
846
+ try {
847
+ const actionResults = await this.ExecuteActions(params, [action], params.contextUser);
848
+ const actionResult = actionResults[0];
849
+ const executionResult = {
850
+ type: 'action',
851
+ actionId: action.id,
852
+ actionName: action.name,
853
+ result: actionResult
854
+ };
855
+ const nextStepDecision = {
856
+ decision: 'retry',
857
+ reasoning: 'Action completed successfully',
858
+ nextStepDetails: undefined
859
+ };
860
+ this._executionChain.push({
861
+ stepEntity,
862
+ executionType: 'action',
863
+ executionResult,
864
+ nextStepDecision,
865
+ startTime,
866
+ endTime: new Date(),
867
+ durationMs: new Date().getTime() - startTime.getTime()
868
+ });
869
+ const outputData = {
870
+ actionResult: {
871
+ success: actionResult.Success,
872
+ resultCode: actionResult.ResultCode,
873
+ message: actionResult.Message,
874
+ result: actionResult.ResultType === 'ComplexObject'
875
+ ? actionResult.Complex
876
+ : actionResult.Simple
877
+ }
878
+ };
879
+ await this.finalizeStepEntity(stepEntity, actionResult.Success, actionResult.Success ? undefined : actionResult.Message, outputData);
880
+ return { success: true, result: actionResult };
881
+ }
882
+ catch (error) {
883
+ await this.finalizeStepEntity(stepEntity, false, error.message);
884
+ return { success: false, error: error.message };
885
+ }
886
+ });
887
+ const actionResults = await Promise.all(actionPromises);
888
+ if (params.cancellationToken?.aborted) {
889
+ throw new Error('Cancelled after action execution');
890
+ }
891
+ const actionSummaries = actionSteps.map((step, index) => {
892
+ const result = actionResults[index];
893
+ const actionResult = result.success ? result.result : null;
894
+ return {
895
+ actionName: step.action.name,
896
+ actionId: step.action.id,
897
+ params: step.action.params,
898
+ success: result.success,
899
+ resultCode: actionResult?.ResultCode || (result.success ? 'SUCCESS' : 'ERROR'),
900
+ message: result.success ? actionResult?.Message || 'Action completed' : result.error
901
+ };
902
+ });
903
+ const failedActions = actionSummaries.filter(a => !a.success);
904
+ const resultsMessage = failedActions.length > 0
905
+ ? `Action results (${failedActions.length} failed):\n${JSON.stringify(actionSummaries, null, 2)}`
906
+ : `Action results (all succeeded):\n${JSON.stringify(actionSummaries, null, 2)}`;
907
+ params.conversationMessages.push({
908
+ role: 'user',
909
+ content: resultsMessage
910
+ });
911
+ return {
912
+ terminate: false,
913
+ nextStep: {
914
+ step: 'retry',
915
+ retryReason: failedActions.length > 0
916
+ ? `Processing results with ${failedActions.length} failed action(s): ${failedActions.map(a => a.actionName).join(', ')}`
917
+ : `Analyzing results from ${actionSummaries.length} completed action(s) to formulate response`
918
+ }
919
+ };
920
+ }
921
+ async executeChatStep(params, userMessage) {
922
+ const startTime = new Date();
923
+ const stepEntity = await this.createStepEntity('chat', 'User Interaction', params.contextUser);
924
+ const executionResult = {
925
+ type: 'chat',
926
+ userMessage,
927
+ result: { success: false, continueExecution: false }
928
+ };
929
+ const nextStepDecision = {
930
+ decision: 'failed',
931
+ reasoning: 'Chat functionality not implemented in base agent'
932
+ };
933
+ this._executionChain.push({
934
+ stepEntity,
935
+ executionType: 'chat',
936
+ executionResult,
937
+ nextStepDecision,
938
+ startTime,
939
+ endTime: new Date(),
940
+ durationMs: new Date().getTime() - startTime.getTime()
941
+ });
942
+ await this.finalizeStepEntity(stepEntity, false, 'Chat not implemented');
943
+ return { terminate: true };
944
+ }
945
+ async createFailureResult(errorMessage, contextUser) {
946
+ if (this._agentRun) {
947
+ this._agentRun.Status = 'Failed';
948
+ this._agentRun.CompletedAt = new Date();
949
+ this._agentRun.Success = false;
950
+ this._agentRun.ErrorMessage = errorMessage;
951
+ await this._agentRun.Save();
952
+ }
953
+ return {
954
+ success: false,
955
+ finalStep: 'failed',
956
+ errorMessage,
957
+ agentRun: this._agentRun,
958
+ executionTree: this.buildExecutionTree()
959
+ };
960
+ }
961
+ async createCancelledResult(message, contextUser) {
962
+ if (this._agentRun) {
963
+ this._agentRun.Status = 'Cancelled';
964
+ this._agentRun.CompletedAt = new Date();
965
+ this._agentRun.Success = false;
966
+ this._agentRun.ErrorMessage = message;
967
+ await this._agentRun.Save();
968
+ }
969
+ return {
970
+ success: false,
971
+ finalStep: 'failed',
972
+ errorMessage: message,
973
+ cancelled: true,
974
+ cancellationReason: 'user_requested',
975
+ agentRun: this._agentRun,
976
+ executionTree: this.buildExecutionTree()
977
+ };
978
+ }
979
+ async finalizeAgentRun(finalStep, returnValue, contextUser) {
980
+ if (this._agentRun) {
981
+ this._agentRun.Status = 'Completed';
982
+ this._agentRun.CompletedAt = new Date();
983
+ this._agentRun.Success = finalStep === 'success';
984
+ this._agentRun.Result = returnValue ? JSON.stringify(returnValue) : null;
985
+ await this._agentRun.Save();
986
+ }
987
+ return {
988
+ success: finalStep === 'success' || finalStep === 'chat',
989
+ finalStep,
990
+ returnValue,
991
+ agentRun: this._agentRun,
992
+ executionTree: this.buildExecutionTree()
993
+ };
994
+ }
995
+ countStepsInTree(nodes) {
996
+ let count = 0;
997
+ for (const node of nodes) {
998
+ count++;
999
+ if (node.children && node.children.length > 0) {
1000
+ count += this.countStepsInTree(node.children);
1001
+ }
1002
+ }
1003
+ return count;
1004
+ }
1005
+ buildExecutionTree() {
1006
+ const executionTree = [];
1007
+ const allEvents = [];
1008
+ let maxProgressStepNumber = 0;
1009
+ for (const progressStep of this._allProgressSteps) {
1010
+ allEvents.push({
1011
+ type: 'progress',
1012
+ timestamp: progressStep.timestamp,
1013
+ data: progressStep
1014
+ });
1015
+ }
1016
+ for (const chainStep of this._executionChain) {
1017
+ allEvents.push({
1018
+ type: 'execution',
1019
+ timestamp: chainStep.startTime,
1020
+ data: chainStep
1021
+ });
1022
+ }
1023
+ allEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
1024
+ for (const event of allEvents) {
1025
+ if (event.type === 'progress') {
1026
+ const progressData = event.data;
1027
+ maxProgressStepNumber++;
1028
+ const progressNode = {
1029
+ step: {
1030
+ ID: `progress-${event.timestamp.getTime()}`,
1031
+ StepNumber: maxProgressStepNumber,
1032
+ StepName: progressData.message,
1033
+ StepType: progressData.step || 'progress',
1034
+ Status: 'Completed',
1035
+ StartedAt: event.timestamp,
1036
+ CompletedAt: event.timestamp
1037
+ },
1038
+ inputData: null,
1039
+ outputData: {
1040
+ percentage: progressData.percentage,
1041
+ metadata: progressData.metadata
1042
+ },
1043
+ executionType: progressData.step || 'progress',
1044
+ startTime: event.timestamp,
1045
+ endTime: event.timestamp,
1046
+ durationMs: 0,
1047
+ children: [],
1048
+ depth: progressData.depth || this._runContext?.depth || 0,
1049
+ parentStepId: null,
1050
+ agentHierarchy: progressData.agentHierarchy || this._runContext?.agentHierarchy || []
1051
+ };
1052
+ executionTree.push(progressNode);
1053
+ }
1054
+ else {
1055
+ const chainStep = event.data;
1056
+ const stepEntity = chainStep.stepEntity;
1057
+ let inputData = null;
1058
+ let outputData = null;
1059
+ try {
1060
+ if (stepEntity.InputData) {
1061
+ inputData = JSON.parse(stepEntity.InputData);
1062
+ }
1063
+ if (stepEntity.OutputData) {
1064
+ outputData = JSON.parse(stepEntity.OutputData);
1065
+ }
1066
+ }
1067
+ catch (e) {
1068
+ inputData = stepEntity.InputData;
1069
+ outputData = stepEntity.OutputData;
1070
+ }
1071
+ const node = {
1072
+ step: stepEntity,
1073
+ inputData,
1074
+ outputData,
1075
+ executionType: chainStep.executionType,
1076
+ startTime: chainStep.startTime,
1077
+ endTime: chainStep.endTime,
1078
+ durationMs: chainStep.durationMs,
1079
+ nextStepDecision: chainStep.nextStepDecision,
1080
+ children: [],
1081
+ depth: this._runContext?.depth || 0,
1082
+ parentStepId: null,
1083
+ agentHierarchy: this._runContext?.agentHierarchy || []
1084
+ };
1085
+ if (chainStep.executionType === 'sub-agent' && chainStep.executionResult?.type === 'sub-agent') {
1086
+ const subAgentResult = chainStep.executionResult.result;
1087
+ if (subAgentResult.executionTree) {
1088
+ node.children = subAgentResult.executionTree.map(childNode => ({
1089
+ ...childNode,
1090
+ parentStepId: stepEntity.ID,
1091
+ depth: (this._runContext?.depth || 0) + 1
1092
+ }));
1093
+ this.sortExecutionTreeByStepNumber(node.children);
1094
+ }
1095
+ }
1096
+ executionTree.push(node);
1097
+ }
1098
+ }
1099
+ this.sortExecutionTreeByStepNumber(executionTree);
1100
+ return executionTree;
1101
+ }
1102
+ sortExecutionTreeByStepNumber(nodes) {
1103
+ nodes.sort((a, b) => {
1104
+ const aStepNumber = a.step?.StepNumber || 0;
1105
+ const bStepNumber = b.step?.StepNumber || 0;
1106
+ return aStepNumber - bStepNumber;
1107
+ });
1108
+ for (const node of nodes) {
1109
+ if (node.children && node.children.length > 0) {
1110
+ this.sortExecutionTreeByStepNumber(node.children);
1111
+ }
1112
+ }
1113
+ }
1114
+ getNextStepReasoning(nextStep) {
1115
+ switch (nextStep.step) {
1116
+ case 'success':
1117
+ return 'Agent completed successfully';
1118
+ case 'failed':
1119
+ return `Agent failed: ${nextStep.errorMessage || 'Unknown error'}`;
1120
+ case 'retry':
1121
+ return nextStep.retryReason || 'Retrying with additional context';
1122
+ case 'sub-agent':
1123
+ return `Invoking sub-agent: ${nextStep.subAgent?.name}`;
1124
+ case 'actions':
1125
+ return `Executing ${nextStep.actions?.length || 0} action(s)`;
1126
+ case 'chat':
1127
+ return 'User interaction required';
1128
+ default:
1129
+ return 'Unknown next step';
1130
+ }
1131
+ }
1132
+ getNextStepDetails(nextStep) {
1133
+ switch (nextStep.step) {
1134
+ case 'success':
1135
+ case 'failed':
1136
+ return { type: 'complete', returnValue: nextStep.returnValue };
1137
+ case 'retry':
1138
+ return {
1139
+ type: 'retry',
1140
+ retryReason: nextStep.retryReason || '',
1141
+ retryInstructions: nextStep.retryInstructions || ''
1142
+ };
1143
+ case 'sub-agent':
1144
+ return nextStep.subAgent ? { type: 'sub-agent', subAgent: nextStep.subAgent } : undefined;
1145
+ case 'actions':
1146
+ return nextStep.actions ? { type: 'action', actions: nextStep.actions } : undefined;
1147
+ case 'chat':
1148
+ return { type: 'chat', message: nextStep.userMessage || '' };
1149
+ default:
1150
+ return undefined;
1151
+ }
1152
+ }
154
1153
  }
155
1154
  exports.BaseAgent = BaseAgent;
156
1155
  //# sourceMappingURL=base-agent.js.map