@memberjunction/ng-ai-test-harness 2.58.0 → 2.59.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.
- package/dist/lib/agent-execution-monitor.component.d.ts +18 -4
- package/dist/lib/agent-execution-monitor.component.d.ts.map +1 -1
- package/dist/lib/agent-execution-monitor.component.js +297 -87
- package/dist/lib/agent-execution-monitor.component.js.map +1 -1
- package/dist/lib/agent-execution-node.component.d.ts +5 -2
- package/dist/lib/agent-execution-node.component.d.ts.map +1 -1
- package/dist/lib/agent-execution-node.component.js +175 -110
- package/dist/lib/agent-execution-node.component.js.map +1 -1
- package/dist/lib/ai-test-harness.component.d.ts +8 -0
- package/dist/lib/ai-test-harness.component.d.ts.map +1 -1
- package/dist/lib/ai-test-harness.component.js +140 -24
- package/dist/lib/ai-test-harness.component.js.map +1 -1
- package/package.json +8 -8
|
@@ -144,14 +144,40 @@ export class AgentExecutionMonitorComponent {
|
|
|
144
144
|
this.destroy$ = new Subject();
|
|
145
145
|
}
|
|
146
146
|
ngOnChanges(changes) {
|
|
147
|
+
console.log('🔄 Execution Monitor ngOnChanges:', {
|
|
148
|
+
executionDataChanged: !!changes['executionData'],
|
|
149
|
+
modeChanged: !!changes['mode'],
|
|
150
|
+
hasExecutionData: !!this.executionData,
|
|
151
|
+
currentTreeLength: this.executionTree.length
|
|
152
|
+
});
|
|
147
153
|
if (changes['executionData']) {
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
// Log the change details
|
|
155
|
+
const oldData = changes['executionData'].previousValue;
|
|
156
|
+
const newData = changes['executionData'].currentValue;
|
|
157
|
+
console.log('📊 Execution data changed:', {
|
|
158
|
+
oldDataExists: !!oldData,
|
|
159
|
+
newDataExists: !!newData,
|
|
160
|
+
newDataKeys: newData ? Object.keys(newData) : [],
|
|
161
|
+
executionTreeLength: newData?.executionTree?.length,
|
|
162
|
+
forceRefresh: newData?._forceRefresh
|
|
163
|
+
});
|
|
164
|
+
// Check if this is a different execution by comparing run IDs
|
|
165
|
+
const oldRunId = oldData?.agentRun?.ID || oldData?.promptRun?.ID;
|
|
166
|
+
const newRunId = newData?.agentRun?.ID || newData?.promptRun?.ID;
|
|
167
|
+
const isDifferentExecution = oldRunId && newRunId && oldRunId !== newRunId;
|
|
168
|
+
const isStartingNewLiveExecution = this.mode === 'live' &&
|
|
169
|
+
newData &&
|
|
170
|
+
newData.liveSteps &&
|
|
171
|
+
newData.liveSteps.length === 0 &&
|
|
172
|
+
this.executionTree.length > 0;
|
|
173
|
+
const isForceRefresh = newData && newData._forceRefresh;
|
|
174
|
+
// Clear if it's a genuinely different execution, starting fresh live execution, or force refresh
|
|
175
|
+
if (isDifferentExecution || isStartingNewLiveExecution || isForceRefresh) {
|
|
176
|
+
console.log('🗑️ Clearing execution tree due to:', {
|
|
177
|
+
isDifferentExecution,
|
|
178
|
+
isStartingNewLiveExecution,
|
|
179
|
+
isForceRefresh
|
|
180
|
+
});
|
|
155
181
|
this.processedStepIds.clear();
|
|
156
182
|
this.newlyAddedNodeIds.clear();
|
|
157
183
|
this.clearNodeComponents();
|
|
@@ -159,37 +185,59 @@ export class AgentExecutionMonitorComponent {
|
|
|
159
185
|
this.currentStep = null;
|
|
160
186
|
this.calculateStats();
|
|
161
187
|
}
|
|
162
|
-
//
|
|
188
|
+
// Check for auto-expand flag
|
|
189
|
+
if (this.executionData && this.executionData._autoExpandAll) {
|
|
190
|
+
// Auto-expand all nodes after a short delay to ensure rendering is complete
|
|
191
|
+
setTimeout(() => {
|
|
192
|
+
this.expandAllNodes();
|
|
193
|
+
}, 50);
|
|
194
|
+
}
|
|
195
|
+
// Process data (this will preserve existing nodes if it's the same execution)
|
|
163
196
|
this.processExecutionData();
|
|
164
197
|
}
|
|
165
|
-
// Handle mode changes
|
|
198
|
+
// Handle mode changes - be more selective about when to clear
|
|
166
199
|
if (changes['mode'] && !changes['mode'].firstChange) {
|
|
167
|
-
|
|
168
|
-
|
|
200
|
+
const previousMode = changes['mode'].previousValue;
|
|
201
|
+
const currentMode = changes['mode'].currentValue;
|
|
202
|
+
console.log('🔄 Mode changed:', { previousMode, currentMode });
|
|
203
|
+
// Only clear when switching from live to historical AND we don't have historical data
|
|
204
|
+
if (previousMode === 'live' && currentMode === 'historical') {
|
|
169
205
|
// Stop live updates
|
|
170
206
|
if (this.updateSubscription) {
|
|
171
207
|
this.updateSubscription.unsubscribe();
|
|
172
208
|
this.updateSubscription = undefined;
|
|
173
209
|
}
|
|
174
|
-
//
|
|
175
|
-
this.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
210
|
+
// Only clear if we don't have valid historical data to show
|
|
211
|
+
if (!this.executionData || (!this.executionData.executionTree && !this.executionData.steps)) {
|
|
212
|
+
this.processedStepIds.clear();
|
|
213
|
+
this.newlyAddedNodeIds.clear();
|
|
214
|
+
this.clearNodeComponents();
|
|
215
|
+
this.executionTree = [];
|
|
216
|
+
}
|
|
179
217
|
}
|
|
180
218
|
this.processExecutionData();
|
|
181
219
|
}
|
|
182
220
|
}
|
|
183
221
|
ngAfterViewInit() {
|
|
184
222
|
this.viewInitialized = true;
|
|
223
|
+
console.log('🎯 View initialized, checking for pending data:', {
|
|
224
|
+
hasExecutionData: !!this.executionData,
|
|
225
|
+
treeLength: this.executionTree.length,
|
|
226
|
+
hasContainer: !!this.executionNodesContainer
|
|
227
|
+
});
|
|
185
228
|
// Initial setup for scroll behavior
|
|
186
229
|
if (this.mode === 'live') {
|
|
187
230
|
this.checkIfUserAtBottom();
|
|
188
231
|
}
|
|
189
232
|
// If we have data waiting to be rendered, render it now
|
|
190
233
|
if (this.executionData && this.executionTree.length === 0) {
|
|
234
|
+
console.log('⚡ Processing pending execution data after view init');
|
|
191
235
|
this.processExecutionData();
|
|
192
236
|
}
|
|
237
|
+
else if (this.executionTree.length > 0 && this.nodeComponentMap.size === 0) {
|
|
238
|
+
console.log('⚡ Re-rendering existing tree after view init');
|
|
239
|
+
this.renderTree();
|
|
240
|
+
}
|
|
193
241
|
}
|
|
194
242
|
ngOnDestroy() {
|
|
195
243
|
this.destroy$.next();
|
|
@@ -214,15 +262,23 @@ export class AgentExecutionMonitorComponent {
|
|
|
214
262
|
* Process execution data based on mode
|
|
215
263
|
*/
|
|
216
264
|
processExecutionData() {
|
|
265
|
+
console.log('⚙️ Processing execution data:', {
|
|
266
|
+
mode: this.mode,
|
|
267
|
+
hasExecutionData: !!this.executionData,
|
|
268
|
+
currentTreeLength: this.executionTree.length,
|
|
269
|
+
viewInitialized: this.viewInitialized,
|
|
270
|
+
hasContainer: !!this.executionNodesContainer
|
|
271
|
+
});
|
|
217
272
|
if (this.mode === 'historical') {
|
|
218
|
-
//
|
|
219
|
-
this.
|
|
273
|
+
// Only clear processed step IDs if we don't have existing data or it's different data
|
|
274
|
+
if (this.executionTree.length === 0) {
|
|
275
|
+
this.processedStepIds.clear();
|
|
276
|
+
}
|
|
220
277
|
// Process historical data
|
|
221
278
|
this.buildTreeFromHistoricalData();
|
|
222
279
|
}
|
|
223
280
|
else {
|
|
224
|
-
// For live mode,
|
|
225
|
-
// This prevents losing state when switching tabs
|
|
281
|
+
// For live mode, preserve existing data when possible
|
|
226
282
|
if (this.executionTree.length === 0) {
|
|
227
283
|
this.processedStepIds.clear();
|
|
228
284
|
this.newlyAddedNodeIds.clear();
|
|
@@ -230,16 +286,26 @@ export class AgentExecutionMonitorComponent {
|
|
|
230
286
|
// Set up live updates
|
|
231
287
|
this.setupLiveUpdates();
|
|
232
288
|
}
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
289
|
+
// Always calculate stats when we have data or when processing new data
|
|
290
|
+
this.calculateStats();
|
|
291
|
+
// Force change detection after processing
|
|
292
|
+
if (this.viewInitialized) {
|
|
293
|
+
this.cdr.markForCheck();
|
|
294
|
+
this.cdr.detectChanges();
|
|
236
295
|
}
|
|
237
296
|
}
|
|
238
297
|
/**
|
|
239
298
|
* Build tree from historical execution data
|
|
240
299
|
*/
|
|
241
300
|
buildTreeFromHistoricalData() {
|
|
301
|
+
console.log('🏗️ Building tree from historical data:', {
|
|
302
|
+
hasExecutionData: !!this.executionData,
|
|
303
|
+
executionTreeLength: this.executionData?.executionTree?.length,
|
|
304
|
+
stepsLength: this.executionData?.steps?.length,
|
|
305
|
+
currentTreeLength: this.executionTree.length
|
|
306
|
+
});
|
|
242
307
|
if (!this.executionData) {
|
|
308
|
+
console.log('⚠️ No execution data available');
|
|
243
309
|
this.clearNodeComponents();
|
|
244
310
|
this.executionTree = [];
|
|
245
311
|
return;
|
|
@@ -248,47 +314,74 @@ export class AgentExecutionMonitorComponent {
|
|
|
248
314
|
this.clearNodeComponents();
|
|
249
315
|
// Handle executionTree format - historical mode should only use saved database data
|
|
250
316
|
if (this.executionData.executionTree) {
|
|
317
|
+
console.log('📊 Converting execution tree with', this.executionData.executionTree.length, 'nodes');
|
|
251
318
|
const allNodes = this.convertExecutionTree(this.executionData.executionTree);
|
|
319
|
+
console.log('🔄 Converted to', allNodes.length, 'tree nodes');
|
|
252
320
|
// Filter out live-only nodes in historical mode
|
|
253
321
|
this.executionTree = this.filterNodesForMode(allNodes, 'historical');
|
|
322
|
+
console.log('✅ After filtering for historical mode:', this.executionTree.length, 'nodes');
|
|
254
323
|
}
|
|
255
324
|
else if (this.executionData.steps) {
|
|
325
|
+
console.log('📊 Converting legacy steps with', this.executionData.steps.length, 'steps');
|
|
256
326
|
// Handle legacy steps format
|
|
257
327
|
const allNodes = this.convertLegacySteps(this.executionData.steps);
|
|
258
328
|
this.executionTree = this.filterNodesForMode(allNodes, 'historical');
|
|
329
|
+
console.log('✅ After converting legacy steps:', this.executionTree.length, 'nodes');
|
|
259
330
|
}
|
|
260
331
|
else {
|
|
332
|
+
console.log('⚠️ No executionTree or steps found in data');
|
|
261
333
|
this.executionTree = [];
|
|
262
334
|
}
|
|
263
|
-
//
|
|
335
|
+
// Always render the tree if we have a container
|
|
264
336
|
if (this.executionNodesContainer) {
|
|
337
|
+
console.log('🎨 Rendering tree with', this.executionTree.length, 'nodes');
|
|
265
338
|
this.renderTree();
|
|
266
339
|
}
|
|
340
|
+
else {
|
|
341
|
+
console.log('⚠️ No execution nodes container available for rendering');
|
|
342
|
+
}
|
|
267
343
|
}
|
|
268
344
|
/**
|
|
269
345
|
* Render the execution tree using dynamic components
|
|
270
346
|
*/
|
|
271
347
|
renderTree() {
|
|
348
|
+
console.log('🎨 Rendering execution tree:', {
|
|
349
|
+
hasContainer: !!this.executionNodesContainer,
|
|
350
|
+
treeLength: this.executionTree.length,
|
|
351
|
+
viewInitialized: this.viewInitialized
|
|
352
|
+
});
|
|
272
353
|
if (!this.executionNodesContainer) {
|
|
273
354
|
console.warn('📊 Execution Monitor: No container available for rendering');
|
|
274
355
|
return;
|
|
275
356
|
}
|
|
276
357
|
// Clear and recreate all components for historical view
|
|
277
358
|
this.clearNodeComponents();
|
|
359
|
+
console.log('🔄 Creating components for', this.executionTree.length, 'nodes');
|
|
278
360
|
// Create components for each root node
|
|
279
361
|
for (const node of this.executionTree) {
|
|
280
|
-
this.createNodeComponent(node, this.executionNodesContainer);
|
|
362
|
+
const componentRef = this.createNodeComponent(node, this.executionNodesContainer);
|
|
363
|
+
console.log('✅ Created component for node:', node.name, 'depth:', node.depth);
|
|
281
364
|
}
|
|
365
|
+
// Force change detection after rendering
|
|
366
|
+
this.cdr.markForCheck();
|
|
367
|
+
this.cdr.detectChanges();
|
|
368
|
+
console.log('🎯 Tree rendering complete. Components created:', this.nodeComponentMap.size);
|
|
282
369
|
}
|
|
283
370
|
/**
|
|
284
371
|
* Create a component for a node and its children
|
|
372
|
+
* This now ensures proper depth is passed and used for indentation
|
|
285
373
|
*/
|
|
286
374
|
createNodeComponent(node, container) {
|
|
287
375
|
const componentRef = container.createComponent(ExecutionNodeComponent);
|
|
288
376
|
const instance = componentRef.instance;
|
|
377
|
+
// IMPORTANT: Ensure the node has the correct depth
|
|
378
|
+
// Create a new node object to ensure Angular detects the change
|
|
379
|
+
const nodeWithDepth = {
|
|
380
|
+
...node,
|
|
381
|
+
depth: node.depth || 0 // Ensure depth is always defined
|
|
382
|
+
};
|
|
289
383
|
// Set inputs
|
|
290
|
-
instance.node =
|
|
291
|
-
// No need to apply margin here - it's handled in the component template
|
|
384
|
+
instance.node = nodeWithDepth;
|
|
292
385
|
// Subscribe to outputs
|
|
293
386
|
instance.toggleNode.subscribe((n) => this.toggleNode(n));
|
|
294
387
|
instance.userInteracted.subscribe(() => this.onUserInteraction());
|
|
@@ -301,25 +394,25 @@ export class AgentExecutionMonitorComponent {
|
|
|
301
394
|
}
|
|
302
395
|
/**
|
|
303
396
|
* Convert new execution tree format to display nodes
|
|
397
|
+
* FIXED: Maintain proper hierarchy for sub-agents instead of flattening
|
|
304
398
|
*/
|
|
305
399
|
convertExecutionTree(nodes, depth = 0) {
|
|
400
|
+
const treeNodes = [];
|
|
306
401
|
// Sort nodes by StepNumber before processing
|
|
307
402
|
const sortedNodes = [...nodes].sort((a, b) => {
|
|
308
403
|
const aStepNum = a.step?.StepNumber || 0;
|
|
309
404
|
const bStepNum = b.step?.StepNumber || 0;
|
|
310
405
|
return aStepNum - bStepNum;
|
|
311
406
|
});
|
|
312
|
-
|
|
313
|
-
// Parse the step name for markdown content
|
|
407
|
+
for (const node of sortedNodes) {
|
|
408
|
+
// Parse the step name for markdown content
|
|
314
409
|
const stepName = node.step?.StepName || 'Unknown Step';
|
|
315
410
|
let name = stepName;
|
|
316
411
|
let detailsMarkdown;
|
|
317
|
-
// Check if the step name contains markdown
|
|
412
|
+
// Check if the step name contains markdown
|
|
318
413
|
if (stepName.includes('\n') || stepName.includes('**') || stepName.includes('##')) {
|
|
319
|
-
// Split by newline and use first line as name
|
|
320
414
|
const lines = stepName.split('\n');
|
|
321
415
|
name = lines[0].trim();
|
|
322
|
-
// Rest is markdown details
|
|
323
416
|
if (lines.length > 1) {
|
|
324
417
|
detailsMarkdown = lines.slice(1).join('\n').trim();
|
|
325
418
|
}
|
|
@@ -343,7 +436,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
343
436
|
const inputPreview = this.createPreview(node.inputData);
|
|
344
437
|
const outputPreview = this.createPreview(node.outputData);
|
|
345
438
|
const treeNode = {
|
|
346
|
-
id: node.step?.ID || `node-${Date.now()}-${
|
|
439
|
+
id: node.step?.ID || `node-${Date.now()}-${Math.random()}`,
|
|
347
440
|
name: name,
|
|
348
441
|
type: this.mapStepType(node.executionType || node.step?.StepType),
|
|
349
442
|
status: this.mapStepStatus(node.step?.Status),
|
|
@@ -354,13 +447,13 @@ export class AgentExecutionMonitorComponent {
|
|
|
354
447
|
inputPreview: inputPreview,
|
|
355
448
|
outputPreview: outputPreview,
|
|
356
449
|
error: node.step?.ErrorMessage,
|
|
357
|
-
expanded: false,
|
|
358
|
-
depth:
|
|
450
|
+
expanded: false, // Start collapsed for sub-agents
|
|
451
|
+
depth: depth, // Use actual depth for proper indentation
|
|
359
452
|
tokensUsed: this.extractTokens(node.outputData),
|
|
360
453
|
cost: this.extractCost(node.outputData),
|
|
361
454
|
detailsMarkdown: detailsMarkdown,
|
|
362
455
|
detailsExpanded: false,
|
|
363
|
-
children:
|
|
456
|
+
children: undefined, // Will be set below
|
|
364
457
|
displayMode: displayMode
|
|
365
458
|
};
|
|
366
459
|
// Add agent metadata if this is a sub-agent node
|
|
@@ -376,8 +469,13 @@ export class AgentExecutionMonitorComponent {
|
|
|
376
469
|
treeNode.actionId = this.lastParsedActionData.actionId;
|
|
377
470
|
treeNode.actionIconClass = this.lastParsedActionData.actionIconClass;
|
|
378
471
|
}
|
|
379
|
-
|
|
380
|
-
|
|
472
|
+
// IMPORTANT: Process children recursively to maintain hierarchy
|
|
473
|
+
if (node.children && node.children.length > 0) {
|
|
474
|
+
treeNode.children = this.convertExecutionTree(node.children, depth + 1);
|
|
475
|
+
}
|
|
476
|
+
treeNodes.push(treeNode);
|
|
477
|
+
}
|
|
478
|
+
return treeNodes;
|
|
381
479
|
}
|
|
382
480
|
/**
|
|
383
481
|
* Convert legacy step format to tree nodes
|
|
@@ -423,6 +521,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
423
521
|
'validation': 'validation',
|
|
424
522
|
'prompt': 'prompt',
|
|
425
523
|
'action': 'action',
|
|
524
|
+
'action_execution': 'action',
|
|
426
525
|
'subagent': 'sub-agent',
|
|
427
526
|
'sub-agent': 'sub-agent',
|
|
428
527
|
'decision': 'decision',
|
|
@@ -595,6 +694,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
595
694
|
}
|
|
596
695
|
/**
|
|
597
696
|
* Convert live steps format to execution tree format
|
|
697
|
+
* FIXED: Ensure depth is properly preserved
|
|
598
698
|
*/
|
|
599
699
|
convertLiveStepsToTree(liveSteps) {
|
|
600
700
|
const treeNodes = [];
|
|
@@ -628,7 +728,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
628
728
|
startTime: step.startTime ? new Date(step.startTime) : new Date(),
|
|
629
729
|
agentPath: step.agentHierarchy || [],
|
|
630
730
|
expanded: false,
|
|
631
|
-
depth: step.depth
|
|
731
|
+
depth: step.depth !== undefined ? step.depth : 0, // Ensure depth is always defined
|
|
632
732
|
detailsMarkdown: detailsMarkdown,
|
|
633
733
|
detailsExpanded: false
|
|
634
734
|
};
|
|
@@ -690,6 +790,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
690
790
|
// Update the component if it exists
|
|
691
791
|
const componentRef = this.nodeComponentMap.get(nodeId);
|
|
692
792
|
if (componentRef) {
|
|
793
|
+
// Create a new object to ensure change detection
|
|
693
794
|
componentRef.instance.node = { ...node };
|
|
694
795
|
componentRef.changeDetectorRef.detectChanges();
|
|
695
796
|
}
|
|
@@ -732,31 +833,63 @@ export class AgentExecutionMonitorComponent {
|
|
|
732
833
|
this.stats.totalTokens = this.executionData.agentRun.TotalTokensUsed || 0;
|
|
733
834
|
this.stats.totalCost = this.executionData.agentRun.TotalCost || 0;
|
|
734
835
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
this.stats.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
if
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
836
|
+
// Calculate stats from execution tree nodes if we have them
|
|
837
|
+
if (this.executionTree.length > 0) {
|
|
838
|
+
const processNode = (node) => {
|
|
839
|
+
this.stats.totalSteps++;
|
|
840
|
+
if (node.status === 'completed')
|
|
841
|
+
this.stats.completedSteps++;
|
|
842
|
+
if (node.status === 'failed')
|
|
843
|
+
this.stats.failedSteps++;
|
|
844
|
+
// Only accumulate tokens if we don't have agent run data
|
|
845
|
+
if (!this.executionData?.agentRun) {
|
|
846
|
+
if (node.tokensUsed)
|
|
847
|
+
this.stats.totalTokens += node.tokensUsed;
|
|
848
|
+
if (node.cost)
|
|
849
|
+
this.stats.totalCost += node.cost;
|
|
850
|
+
}
|
|
851
|
+
if (node.duration)
|
|
852
|
+
this.stats.totalDuration += node.duration;
|
|
853
|
+
this.stats.stepsByType[node.type] = (this.stats.stepsByType[node.type] || 0) + 1;
|
|
854
|
+
// Count prompts
|
|
855
|
+
if (node.type === 'prompt' || node.promptCount) {
|
|
856
|
+
this.stats.totalPrompts += node.promptCount || 1;
|
|
857
|
+
}
|
|
858
|
+
if (node.children) {
|
|
859
|
+
node.children.forEach(child => processNode(child));
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
this.executionTree.forEach(node => processNode(node));
|
|
863
|
+
}
|
|
864
|
+
else if (this.executionData?.executionTree) {
|
|
865
|
+
// If we don't have processed tree nodes but have raw execution data, calculate from raw data
|
|
866
|
+
console.log('📈 Calculating stats from raw execution data since tree is empty');
|
|
867
|
+
const processRawNode = (node) => {
|
|
868
|
+
this.stats.totalSteps++;
|
|
869
|
+
const status = this.mapStepStatus(node.step?.Status);
|
|
870
|
+
if (status === 'completed')
|
|
871
|
+
this.stats.completedSteps++;
|
|
872
|
+
if (status === 'failed')
|
|
873
|
+
this.stats.failedSteps++;
|
|
874
|
+
if (node.durationMs)
|
|
875
|
+
this.stats.totalDuration += node.durationMs;
|
|
876
|
+
const nodeType = this.mapStepType(node.executionType || node.step?.StepType);
|
|
877
|
+
this.stats.stepsByType[nodeType] = (this.stats.stepsByType[nodeType] || 0) + 1;
|
|
878
|
+
if (nodeType === 'prompt') {
|
|
879
|
+
this.stats.totalPrompts += 1;
|
|
880
|
+
}
|
|
881
|
+
if (node.children) {
|
|
882
|
+
node.children.forEach((child) => processRawNode(child));
|
|
883
|
+
}
|
|
884
|
+
};
|
|
885
|
+
this.executionData.executionTree.forEach((node) => processRawNode(node));
|
|
886
|
+
}
|
|
887
|
+
console.log('📈 Stats calculated:', {
|
|
888
|
+
totalSteps: this.stats.totalSteps,
|
|
889
|
+
treeLength: this.executionTree.length,
|
|
890
|
+
executionDataExists: !!this.executionData,
|
|
891
|
+
hasRawExecutionTree: !!this.executionData?.executionTree
|
|
892
|
+
});
|
|
760
893
|
}
|
|
761
894
|
/**
|
|
762
895
|
* Toggle node expansion
|
|
@@ -775,18 +908,6 @@ export class AgentExecutionMonitorComponent {
|
|
|
775
908
|
this.cdr.markForCheck();
|
|
776
909
|
}
|
|
777
910
|
}
|
|
778
|
-
/**
|
|
779
|
-
* Check if node has expandable content
|
|
780
|
-
*/
|
|
781
|
-
hasExpandableContent(node) {
|
|
782
|
-
return !!(node.children && node.children.length > 0) ||
|
|
783
|
-
node.type === 'sub-agent' ||
|
|
784
|
-
node.type === 'action' ||
|
|
785
|
-
!!node.inputPreview ||
|
|
786
|
-
!!node.outputPreview ||
|
|
787
|
-
!!node.error ||
|
|
788
|
-
!!node.detailsMarkdown;
|
|
789
|
-
}
|
|
790
911
|
/**
|
|
791
912
|
* Handle scroll events
|
|
792
913
|
*/
|
|
@@ -915,6 +1036,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
915
1036
|
}
|
|
916
1037
|
/**
|
|
917
1038
|
* Append new live steps without re-rendering entire tree
|
|
1039
|
+
* FIXED: Ensure depth is properly preserved when creating nodes
|
|
918
1040
|
*/
|
|
919
1041
|
appendNewLiveSteps(liveSteps) {
|
|
920
1042
|
if (!liveSteps || liveSteps.length === 0)
|
|
@@ -995,13 +1117,13 @@ export class AgentExecutionMonitorComponent {
|
|
|
995
1117
|
}
|
|
996
1118
|
}
|
|
997
1119
|
else {
|
|
998
|
-
// Create new node
|
|
1120
|
+
// Create new node with proper depth
|
|
999
1121
|
const newNode = this.createNodeFromLiveStep(step);
|
|
1000
|
-
//
|
|
1001
|
-
if (
|
|
1002
|
-
|
|
1122
|
+
// Ensure depth is set from the step data
|
|
1123
|
+
if (step.depth !== undefined) {
|
|
1124
|
+
newNode.depth = step.depth;
|
|
1003
1125
|
}
|
|
1004
|
-
if (
|
|
1126
|
+
if (newNode.depth === 0) {
|
|
1005
1127
|
// Add to tree and create component
|
|
1006
1128
|
this.executionTree.push(newNode);
|
|
1007
1129
|
this.createNodeComponent(newNode, this.executionNodesContainer);
|
|
@@ -1025,7 +1147,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
1025
1147
|
}
|
|
1026
1148
|
}
|
|
1027
1149
|
else {
|
|
1028
|
-
// If no parent found, add as root
|
|
1150
|
+
// If no parent found, add as root but preserve depth
|
|
1029
1151
|
this.executionTree.push(newNode);
|
|
1030
1152
|
this.createNodeComponent(newNode, this.executionNodesContainer);
|
|
1031
1153
|
}
|
|
@@ -1105,7 +1227,8 @@ export class AgentExecutionMonitorComponent {
|
|
|
1105
1227
|
* Filter nodes based on display mode
|
|
1106
1228
|
*/
|
|
1107
1229
|
filterNodesForMode(nodes, mode) {
|
|
1108
|
-
|
|
1230
|
+
console.log('🔍 Filtering nodes for mode:', mode, 'from', nodes.length, 'nodes');
|
|
1231
|
+
const filteredNodes = nodes.filter(node => {
|
|
1109
1232
|
// If no displayMode is set, default to showing in both modes
|
|
1110
1233
|
if (!node.displayMode) {
|
|
1111
1234
|
return true;
|
|
@@ -1118,8 +1241,11 @@ export class AgentExecutionMonitorComponent {
|
|
|
1118
1241
|
}
|
|
1119
1242
|
return true;
|
|
1120
1243
|
}
|
|
1244
|
+
console.log('📄 Filtering out node in', mode, 'mode:', node.name, 'displayMode:', node.displayMode);
|
|
1121
1245
|
return false;
|
|
1122
1246
|
});
|
|
1247
|
+
console.log('✅ Filtered to', filteredNodes.length, 'nodes for mode:', mode);
|
|
1248
|
+
return filteredNodes;
|
|
1123
1249
|
}
|
|
1124
1250
|
/**
|
|
1125
1251
|
* Build a map of nodes by ID for quick lookup
|
|
@@ -1134,6 +1260,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
1134
1260
|
}
|
|
1135
1261
|
/**
|
|
1136
1262
|
* Create a single node from a live step
|
|
1263
|
+
* FIXED: Ensure depth is properly set from step data
|
|
1137
1264
|
*/
|
|
1138
1265
|
createNodeFromLiveStep(step) {
|
|
1139
1266
|
const stepName = step.step?.StepName || 'Processing...';
|
|
@@ -1180,6 +1307,8 @@ export class AgentExecutionMonitorComponent {
|
|
|
1180
1307
|
const inputPreview = this.createPreview(step.inputData);
|
|
1181
1308
|
const outputPreview = this.createPreview(step.outputData);
|
|
1182
1309
|
const nodeType = this.mapStepType(step.executionType || step.step?.StepType);
|
|
1310
|
+
// IMPORTANT: Use the depth from step data, ensure it's always defined
|
|
1311
|
+
const nodeDepth = step.depth !== undefined ? step.depth : 0;
|
|
1183
1312
|
const node = {
|
|
1184
1313
|
id: step.step?.ID || this.generateStepId(step),
|
|
1185
1314
|
name: name,
|
|
@@ -1190,7 +1319,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
1190
1319
|
duration: step.durationMs,
|
|
1191
1320
|
agentPath: step.agentHierarchy || [],
|
|
1192
1321
|
expanded: false,
|
|
1193
|
-
depth:
|
|
1322
|
+
depth: nodeDepth, // Use the extracted depth
|
|
1194
1323
|
detailsMarkdown: detailsMarkdown,
|
|
1195
1324
|
detailsExpanded: false,
|
|
1196
1325
|
inputPreview: inputPreview,
|
|
@@ -1292,6 +1421,87 @@ export class AgentExecutionMonitorComponent {
|
|
|
1292
1421
|
}
|
|
1293
1422
|
return false;
|
|
1294
1423
|
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Expands nodes in the execution tree that have children
|
|
1426
|
+
* Called when auto-expand flag is detected or execution completes
|
|
1427
|
+
*/
|
|
1428
|
+
expandAllNodes() {
|
|
1429
|
+
if (!this.executionTree || this.executionTree.length === 0) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
console.log('🔄 Starting auto-expansion of nodes with children', this.executionTree.length);
|
|
1433
|
+
// Recursively expand only nodes that have children
|
|
1434
|
+
const expandNodeRecursively = (nodes) => {
|
|
1435
|
+
for (const node of nodes) {
|
|
1436
|
+
// Only expand nodes that have children (sub-nodes)
|
|
1437
|
+
const hasChildren = node.children && node.children.length > 0;
|
|
1438
|
+
if (hasChildren) {
|
|
1439
|
+
node.expanded = true;
|
|
1440
|
+
console.log(`Expanding node with children: ${node.name}`, {
|
|
1441
|
+
childCount: node.children?.length,
|
|
1442
|
+
nodeType: node.type
|
|
1443
|
+
});
|
|
1444
|
+
// Update the corresponding component if it exists
|
|
1445
|
+
const componentRef = this.nodeComponentMap.get(node.id);
|
|
1446
|
+
if (componentRef) {
|
|
1447
|
+
// Create a new object to ensure change detection
|
|
1448
|
+
const updatedNode = { ...node, expanded: true };
|
|
1449
|
+
componentRef.instance.node = updatedNode;
|
|
1450
|
+
componentRef.changeDetectorRef.markForCheck();
|
|
1451
|
+
componentRef.changeDetectorRef.detectChanges();
|
|
1452
|
+
console.log(`Updated component for node: ${node.name}`);
|
|
1453
|
+
}
|
|
1454
|
+
else {
|
|
1455
|
+
console.log(`No component found for node: ${node.name}`);
|
|
1456
|
+
}
|
|
1457
|
+
// Expand children recursively
|
|
1458
|
+
expandNodeRecursively(node.children);
|
|
1459
|
+
}
|
|
1460
|
+
else {
|
|
1461
|
+
console.log(`Skipping node without children: ${node.name}`, {
|
|
1462
|
+
hasExpandableContent: this.hasExpandableContent(node),
|
|
1463
|
+
hasInputPreview: !!node.inputPreview,
|
|
1464
|
+
hasOutputPreview: !!node.outputPreview,
|
|
1465
|
+
hasError: !!node.error,
|
|
1466
|
+
hasDetailsMarkdown: !!node.detailsMarkdown
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
expandNodeRecursively(this.executionTree);
|
|
1472
|
+
// Trigger change detection for the entire component
|
|
1473
|
+
this.cdr.markForCheck();
|
|
1474
|
+
this.cdr.detectChanges();
|
|
1475
|
+
console.log('✅ Completed auto-expansion of nodes with children');
|
|
1476
|
+
// Scroll to top after expansion to show the full tree
|
|
1477
|
+
setTimeout(() => {
|
|
1478
|
+
this.scrollToTop();
|
|
1479
|
+
}, 100);
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Scroll the execution tree to the top
|
|
1483
|
+
*/
|
|
1484
|
+
scrollToTop() {
|
|
1485
|
+
if (this.executionTreeContainer) {
|
|
1486
|
+
const element = this.executionTreeContainer.nativeElement;
|
|
1487
|
+
element.scrollTo({
|
|
1488
|
+
top: 0,
|
|
1489
|
+
behavior: 'smooth'
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Check if node has expandable content
|
|
1495
|
+
*/
|
|
1496
|
+
hasExpandableContent(node) {
|
|
1497
|
+
return !!(node.children && node.children.length > 0) ||
|
|
1498
|
+
node.type === 'sub-agent' ||
|
|
1499
|
+
node.type === 'action' ||
|
|
1500
|
+
!!node.inputPreview ||
|
|
1501
|
+
!!node.outputPreview ||
|
|
1502
|
+
!!node.error ||
|
|
1503
|
+
!!node.detailsMarkdown;
|
|
1504
|
+
}
|
|
1295
1505
|
static { this.ɵfac = function AgentExecutionMonitorComponent_Factory(t) { return new (t || AgentExecutionMonitorComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
|
|
1296
1506
|
static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AgentExecutionMonitorComponent, selectors: [["mj-agent-execution-monitor"]], viewQuery: function AgentExecutionMonitorComponent_Query(rf, ctx) { if (rf & 1) {
|
|
1297
1507
|
i0.ɵɵviewQuery(_c0, 5);
|
|
@@ -1371,7 +1581,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
1371
1581
|
i0.ɵɵconditional(ctx.stats.totalDuration ? 37 : -1);
|
|
1372
1582
|
i0.ɵɵadvance();
|
|
1373
1583
|
i0.ɵɵconditional(ctx.getStepTypes().length > 0 ? 38 : -1);
|
|
1374
|
-
} }, dependencies: [CommonModule], styles: ["[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n \n .execution-monitor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n \n\n .monitor-header[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 8px;\n }\n\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .live-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: #ff4444;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.5px;\n }\n\n .pulse[_ngcontent-%COMP%] {\n display: inline-block;\n width: 8px;\n height: 8px;\n background: white;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n }\n\n @keyframes _ngcontent-%COMP%_pulse {\n 0% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.8); }\n 100% { opacity: 1; transform: scale(1); }\n }\n\n .current-status[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n }\n\n .status-label[_ngcontent-%COMP%] {\n font-weight: 500;\n }\n\n .agent-path[_ngcontent-%COMP%] {\n color: #999;\n }\n\n .step-name[_ngcontent-%COMP%] {\n color: #1a1a1a;\n font-weight: 500;\n }\n\n \n\n .execution-tree[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: auto;\n padding: 16px;\n min-height: 0;\n }\n \n .nodes-container[_ngcontent-%COMP%] {\n \n\n }\n\n .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #999;\n text-align: center;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }\n\n \n\n .tree-node[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n }\n\n .node-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n }\n\n .node-header[_ngcontent-%COMP%]:hover {\n background: #e8f0fe;\n border-color: #2196f3;\n }\n\n .expand-icon[_ngcontent-%COMP%], .expand-spacer[_ngcontent-%COMP%] {\n width: 16px;\n text-align: center;\n color: #666;\n font-size: 10px;\n }\n\n .status-icon[_ngcontent-%COMP%] {\n width: 20px;\n text-align: center;\n font-size: 14px;\n }\n\n .status-pending[_ngcontent-%COMP%] { color: #999; }\n .status-running[_ngcontent-%COMP%] { color: #2196f3; }\n .status-completed[_ngcontent-%COMP%] { color: #4caf50; }\n .status-failed[_ngcontent-%COMP%] { color: #f44336; }\n\n .type-icon[_ngcontent-%COMP%] {\n width: 20px;\n text-align: center;\n font-size: 14px;\n color: #666;\n }\n\n .node-name[_ngcontent-%COMP%] {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: #1a1a1a;\n }\n\n .node-duration[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n font-weight: 500;\n }\n\n .node-metrics[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 12px;\n }\n\n .tokens[_ngcontent-%COMP%] {\n color: #666;\n }\n\n .cost[_ngcontent-%COMP%] {\n color: #2196f3;\n font-weight: 500;\n }\n\n \n\n .node-details[_ngcontent-%COMP%] {\n margin: 8px 0 8px 44px;\n padding: 12px;\n background: #f5f5f5;\n border-radius: 4px;\n font-size: 12px;\n }\n\n .detail-section[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n }\n\n .detail-section[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n }\n\n .detail-section.error[_ngcontent-%COMP%] {\n color: #d32f2f;\n }\n\n .detail-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n margin-bottom: 4px;\n color: #666;\n }\n\n .detail-section.error[_ngcontent-%COMP%] .detail-label[_ngcontent-%COMP%] {\n color: #d32f2f;\n }\n\n .detail-label[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .detail-content[_ngcontent-%COMP%] {\n padding-left: 18px;\n color: #333;\n line-height: 1.4;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n \n\n .monitor-footer[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f8f9fa;\n border-top: 1px solid #e0e0e0;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n }\n\n .stat-item[_ngcontent-%COMP%] {\n text-align: center;\n }\n\n .stat-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 11px;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .stat-value[_ngcontent-%COMP%] {\n display: block;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n }\n\n .failed-count[_ngcontent-%COMP%] {\n color: #f44336;\n font-size: 12px;\n font-weight: normal;\n }\n\n .step-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n }\n\n .type-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 8px;\n background: #e3f2fd;\n color: #1976d2;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n \n\n .details-toggle[_ngcontent-%COMP%] {\n margin-left: 8px;\n padding: 2px 6px;\n background: transparent;\n border: 1px solid #ddd;\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n color: #666;\n transition: all 0.2s ease;\n }\n \n .details-toggle[_ngcontent-%COMP%]:hover {\n background: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n \n \n\n .markdown-details[_ngcontent-%COMP%] {\n margin: 8px 0 8px 44px;\n padding: 12px;\n background: #f9fafb;\n border-left: 3px solid #2196f3;\n border-radius: 0 4px 4px 0;\n font-size: 13px;\n line-height: 1.6;\n }\n \n .markdown-details[_ngcontent-%COMP%] h2[_ngcontent-%COMP%] {\n font-size: 16px;\n margin: 0 0 8px 0;\n color: #1a1a1a;\n }\n \n .markdown-details[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n font-size: 14px;\n margin: 8px 0 6px 0;\n color: #333;\n }\n \n .markdown-details[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n font-size: 13px;\n margin: 6px 0 4px 0;\n color: #555;\n }\n \n .markdown-details[_ngcontent-%COMP%] ul[_ngcontent-%COMP%] {\n margin: 4px 0;\n padding-left: 20px;\n }\n \n .markdown-details[_ngcontent-%COMP%] li[_ngcontent-%COMP%] {\n margin: 2px 0;\n }\n \n .markdown-details[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: #e8f0fe;\n padding: 1px 4px;\n border-radius: 3px;\n font-family: 'Consolas', 'Monaco', monospace;\n font-size: 12px;\n }\n \n .markdown-details[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] {\n background: #f5f5f5;\n padding: 8px;\n border-radius: 4px;\n overflow-x: auto;\n margin: 8px 0;\n }\n \n .markdown-details[_ngcontent-%COMP%] pre[_ngcontent-%COMP%] code[_ngcontent-%COMP%] {\n background: none;\n padding: 0;\n }\n \n .markdown-details[_ngcontent-%COMP%] strong[_ngcontent-%COMP%] {\n font-weight: 600;\n color: #1a1a1a;\n }\n \n .markdown-details[_ngcontent-%COMP%] em[_ngcontent-%COMP%] {\n font-style: italic;\n color: #555;\n }\n\n \n\n .execution-history-toggle[_ngcontent-%COMP%] {\n background: transparent;\n border: none;\n padding: 4px 8px;\n margin-left: 4px;\n cursor: pointer;\n color: #666;\n font-size: 12px;\n border-radius: 3px;\n transition: all 0.2s ease;\n }\n \n .execution-history-toggle[_ngcontent-%COMP%]:hover {\n background: #e3f2fd;\n color: #2196f3;\n }\n \n \n\n .view-run-btn[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n margin-left: auto;\n }\n \n .view-run-btn[_ngcontent-%COMP%]:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n }\n \n .view-run-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n \n\n @media (max-width: 768px) {\n .monitor-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .execution-tree[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .node-header[_ngcontent-%COMP%] {\n padding: 6px 8px;\n gap: 6px;\n }\n\n .node-metrics[_ngcontent-%COMP%] {\n display: none;\n }\n \n .markdown-details[_ngcontent-%COMP%] {\n margin-left: 20px;\n font-size: 12px;\n }\n }"], changeDetection: 0 }); }
|
|
1584
|
+
} }, dependencies: [CommonModule], styles: ["[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n \n .execution-monitor[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n \n\n .monitor-header[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .header-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 8px;\n }\n\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .live-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: #ff4444;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.5px;\n }\n\n .pulse[_ngcontent-%COMP%] {\n display: inline-block;\n width: 8px;\n height: 8px;\n background: white;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_pulse 2s infinite;\n }\n\n @keyframes _ngcontent-%COMP%_pulse {\n 0% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.8); }\n 100% { opacity: 1; transform: scale(1); }\n }\n\n .current-status[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n }\n\n .status-label[_ngcontent-%COMP%] {\n font-weight: 500;\n }\n\n .agent-path[_ngcontent-%COMP%] {\n color: #999;\n }\n\n .step-name[_ngcontent-%COMP%] {\n color: #1a1a1a;\n font-weight: 500;\n }\n\n \n\n .execution-tree[_ngcontent-%COMP%] {\n flex: 1;\n overflow-y: auto;\n overflow-x: auto;\n padding: 16px;\n min-height: 0;\n }\n \n .nodes-container[_ngcontent-%COMP%] {\n \n\n }\n\n .empty-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #999;\n text-align: center;\n }\n\n .empty-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n }\n\n .empty-state[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }\n\n \n\n .tree-node[_ngcontent-%COMP%] {\n margin-bottom: 4px;\n }\n\n \n\n .monitor-footer[_ngcontent-%COMP%] {\n padding: 16px;\n background: #f8f9fa;\n border-top: 1px solid #e0e0e0;\n }\n\n .stats-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n }\n\n .stat-item[_ngcontent-%COMP%] {\n text-align: center;\n }\n\n .stat-label[_ngcontent-%COMP%] {\n display: block;\n font-size: 11px;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .stat-value[_ngcontent-%COMP%] {\n display: block;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n }\n\n .failed-count[_ngcontent-%COMP%] {\n color: #f44336;\n font-size: 12px;\n font-weight: normal;\n }\n\n .step-types[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n }\n\n .type-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 4px 8px;\n background: #e3f2fd;\n color: #1976d2;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n \n \n\n .view-run-btn[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n margin-left: auto;\n }\n \n .view-run-btn[_ngcontent-%COMP%]:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n }\n \n .view-run-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n \n\n @media (max-width: 768px) {\n .monitor-header[_ngcontent-%COMP%] {\n padding: 12px;\n }\n\n .execution-tree[_ngcontent-%COMP%] {\n padding: 12px;\n }\n }"], changeDetection: 0 }); }
|
|
1375
1585
|
}
|
|
1376
1586
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AgentExecutionMonitorComponent, [{
|
|
1377
1587
|
type: Component,
|
|
@@ -1463,7 +1673,7 @@ export class AgentExecutionMonitorComponent {
|
|
|
1463
1673
|
}
|
|
1464
1674
|
</div>
|
|
1465
1675
|
</div>
|
|
1466
|
-
`, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n \n .execution-monitor {\n display: flex;\n flex-direction: column;\n flex: 1;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n /* Header */\n .monitor-header {\n padding: 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 8px;\n }\n\n .header-title i {\n color: #2196f3;\n }\n\n .live-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: #ff4444;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.5px;\n }\n\n .pulse {\n display: inline-block;\n width: 8px;\n height: 8px;\n background: white;\n border-radius: 50%;\n animation: pulse 2s infinite;\n }\n\n @keyframes pulse {\n 0% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.8); }\n 100% { opacity: 1; transform: scale(1); }\n }\n\n .current-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n }\n\n .status-label {\n font-weight: 500;\n }\n\n .agent-path {\n color: #999;\n }\n\n .step-name {\n color: #1a1a1a;\n font-weight: 500;\n }\n\n /* Execution Tree */\n .execution-tree {\n flex: 1;\n overflow-y: auto;\n overflow-x: auto;\n padding: 16px;\n min-height: 0;\n }\n \n .nodes-container {\n /* No extra padding needed, indentation handled by node margins */\n }\n\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #999;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 14px;\n }\n\n /* Tree Nodes */\n .tree-node {\n margin-bottom: 4px;\n }\n\n .node-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.2s ease;\n user-select: none;\n }\n\n .node-header:hover {\n background: #e8f0fe;\n border-color: #2196f3;\n }\n\n .expand-icon, .expand-spacer {\n width: 16px;\n text-align: center;\n color: #666;\n font-size: 10px;\n }\n\n .status-icon {\n width: 20px;\n text-align: center;\n font-size: 14px;\n }\n\n .status-pending { color: #999; }\n .status-running { color: #2196f3; }\n .status-completed { color: #4caf50; }\n .status-failed { color: #f44336; }\n\n .type-icon {\n width: 20px;\n text-align: center;\n font-size: 14px;\n color: #666;\n }\n\n .node-name {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: #1a1a1a;\n }\n\n .node-duration {\n font-size: 12px;\n color: #666;\n font-weight: 500;\n }\n\n .node-metrics {\n display: flex;\n gap: 12px;\n font-size: 12px;\n }\n\n .tokens {\n color: #666;\n }\n\n .cost {\n color: #2196f3;\n font-weight: 500;\n }\n\n /* Node Details */\n .node-details {\n margin: 8px 0 8px 44px;\n padding: 12px;\n background: #f5f5f5;\n border-radius: 4px;\n font-size: 12px;\n }\n\n .detail-section {\n margin-bottom: 8px;\n }\n\n .detail-section:last-child {\n margin-bottom: 0;\n }\n\n .detail-section.error {\n color: #d32f2f;\n }\n\n .detail-label {\n display: flex;\n align-items: center;\n gap: 6px;\n font-weight: 600;\n margin-bottom: 4px;\n color: #666;\n }\n\n .detail-section.error .detail-label {\n color: #d32f2f;\n }\n\n .detail-label i {\n font-size: 12px;\n }\n\n .detail-content {\n padding-left: 18px;\n color: #333;\n line-height: 1.4;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n /* Footer */\n .monitor-footer {\n padding: 16px;\n background: #f8f9fa;\n border-top: 1px solid #e0e0e0;\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n }\n\n .stat-item {\n text-align: center;\n }\n\n .stat-label {\n display: block;\n font-size: 11px;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .stat-value {\n display: block;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n }\n\n .failed-count {\n color: #f44336;\n font-size: 12px;\n font-weight: normal;\n }\n\n .step-types {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n }\n\n .type-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #e3f2fd;\n color: #1976d2;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n /* Details Toggle Button */\n .details-toggle {\n margin-left: 8px;\n padding: 2px 6px;\n background: transparent;\n border: 1px solid #ddd;\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n color: #666;\n transition: all 0.2s ease;\n }\n \n .details-toggle:hover {\n background: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n \n /* Markdown Details Section */\n .markdown-details {\n margin: 8px 0 8px 44px;\n padding: 12px;\n background: #f9fafb;\n border-left: 3px solid #2196f3;\n border-radius: 0 4px 4px 0;\n font-size: 13px;\n line-height: 1.6;\n }\n \n .markdown-details h2 {\n font-size: 16px;\n margin: 0 0 8px 0;\n color: #1a1a1a;\n }\n \n .markdown-details h3 {\n font-size: 14px;\n margin: 8px 0 6px 0;\n color: #333;\n }\n \n .markdown-details h4 {\n font-size: 13px;\n margin: 6px 0 4px 0;\n color: #555;\n }\n \n .markdown-details ul {\n margin: 4px 0;\n padding-left: 20px;\n }\n \n .markdown-details li {\n margin: 2px 0;\n }\n \n .markdown-details code {\n background: #e8f0fe;\n padding: 1px 4px;\n border-radius: 3px;\n font-family: 'Consolas', 'Monaco', monospace;\n font-size: 12px;\n }\n \n .markdown-details pre {\n background: #f5f5f5;\n padding: 8px;\n border-radius: 4px;\n overflow-x: auto;\n margin: 8px 0;\n }\n \n .markdown-details pre code {\n background: none;\n padding: 0;\n }\n \n .markdown-details strong {\n font-weight: 600;\n color: #1a1a1a;\n }\n \n .markdown-details em {\n font-style: italic;\n color: #555;\n }\n\n /* Button styling for execution history toggle */\n .execution-history-toggle {\n background: transparent;\n border: none;\n padding: 4px 8px;\n margin-left: 4px;\n cursor: pointer;\n color: #666;\n font-size: 12px;\n border-radius: 3px;\n transition: all 0.2s ease;\n }\n \n .execution-history-toggle:hover {\n background: #e3f2fd;\n color: #2196f3;\n }\n \n /* View Run Button */\n .view-run-btn {\n background: #2196f3;\n color: white;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n margin-left: auto;\n }\n \n .view-run-btn:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n }\n \n .view-run-btn i {\n font-size: 12px;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .monitor-header {\n padding: 12px;\n }\n\n .execution-tree {\n padding: 12px;\n }\n\n .node-header {\n padding: 6px 8px;\n gap: 6px;\n }\n\n .node-metrics {\n display: none;\n }\n \n .markdown-details {\n margin-left: 20px;\n font-size: 12px;\n }\n }\n "] }]
|
|
1676
|
+
`, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n \n .execution-monitor {\n display: flex;\n flex-direction: column;\n flex: 1;\n background: #fff;\n border: 1px solid #e0e0e0;\n border-radius: 8px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n\n /* Header */\n .monitor-header {\n padding: 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .header-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n margin-bottom: 8px;\n }\n\n .header-title i {\n color: #2196f3;\n }\n\n .live-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: #ff4444;\n color: white;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.5px;\n }\n\n .pulse {\n display: inline-block;\n width: 8px;\n height: 8px;\n background: white;\n border-radius: 50%;\n animation: pulse 2s infinite;\n }\n\n @keyframes pulse {\n 0% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.5; transform: scale(0.8); }\n 100% { opacity: 1; transform: scale(1); }\n }\n\n .current-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n color: #666;\n }\n\n .status-label {\n font-weight: 500;\n }\n\n .agent-path {\n color: #999;\n }\n\n .step-name {\n color: #1a1a1a;\n font-weight: 500;\n }\n\n /* Execution Tree */\n .execution-tree {\n flex: 1;\n overflow-y: auto;\n overflow-x: auto;\n padding: 16px;\n min-height: 0;\n }\n \n .nodes-container {\n /* No extra padding needed, indentation handled by node margins */\n }\n\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #999;\n text-align: center;\n }\n\n .empty-state i {\n font-size: 48px;\n margin-bottom: 16px;\n opacity: 0.5;\n }\n\n .empty-state p {\n margin: 0;\n font-size: 14px;\n }\n\n /* Tree Nodes - These styles are for reference only, actual rendering is done by ExecutionNodeComponent */\n .tree-node {\n margin-bottom: 4px;\n }\n\n /* Footer */\n .monitor-footer {\n padding: 16px;\n background: #f8f9fa;\n border-top: 1px solid #e0e0e0;\n }\n\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));\n gap: 16px;\n margin-bottom: 12px;\n }\n\n .stat-item {\n text-align: center;\n }\n\n .stat-label {\n display: block;\n font-size: 11px;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .stat-value {\n display: block;\n font-size: 16px;\n font-weight: 600;\n color: #1a1a1a;\n }\n\n .failed-count {\n color: #f44336;\n font-size: 12px;\n font-weight: normal;\n }\n\n .step-types {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: center;\n }\n\n .type-badge {\n display: inline-block;\n padding: 4px 8px;\n background: #e3f2fd;\n color: #1976d2;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n \n /* View Run Button */\n .view-run-btn {\n background: #2196f3;\n color: white;\n border: none;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n margin-left: auto;\n }\n \n .view-run-btn:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0,0,0,0.2);\n }\n \n .view-run-btn i {\n font-size: 12px;\n }\n\n /* Responsive */\n @media (max-width: 768px) {\n .monitor-header {\n padding: 12px;\n }\n\n .execution-tree {\n padding: 12px;\n }\n }\n "] }]
|
|
1467
1677
|
}], () => [{ type: i0.ChangeDetectorRef }], { mode: [{
|
|
1468
1678
|
type: Input
|
|
1469
1679
|
}], executionData: [{
|
|
@@ -1483,5 +1693,5 @@ export class AgentExecutionMonitorComponent {
|
|
|
1483
1693
|
type: ViewChild,
|
|
1484
1694
|
args: ['executionNodesContainer', { read: ViewContainerRef }]
|
|
1485
1695
|
}] }); })();
|
|
1486
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AgentExecutionMonitorComponent, { className: "AgentExecutionMonitorComponent", filePath: "lib/agent-execution-monitor.component.ts", lineNumber:
|
|
1696
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AgentExecutionMonitorComponent, { className: "AgentExecutionMonitorComponent", filePath: "lib/agent-execution-monitor.component.ts", lineNumber: 406 }); })();
|
|
1487
1697
|
//# sourceMappingURL=agent-execution-monitor.component.js.map
|