@memberjunction/ng-ai-test-harness 5.42.0 → 5.44.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 +1 @@
1
- {"version":3,"file":"agent-execution-monitor.component.d.ts","sourceRoot":"","sources":["../../src/lib/agent-execution-monitor.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-execution-monitor.component.d.ts","sourceRoot":"","sources":["../../src/lib/agent-execution-monitor.component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-execution-monitor.component.dom.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-execution-monitor.component.dom.test.d.ts","sourceRoot":"","sources":["../../src/lib/agent-execution-monitor.component.dom.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { renderComponentFixture, query, text, queryAll, attr } from '@memberjunction/ng-test-utils';
3
+ import { AgentExecutionMonitorComponent } from './agent-execution-monitor.component';
4
+ const makeStats = (overrides = {}) => ({
5
+ totalSteps: 0,
6
+ completedSteps: 0,
7
+ failedSteps: 0,
8
+ totalTokens: 0,
9
+ totalCost: 0,
10
+ stepsByType: {},
11
+ totalPrompts: 0,
12
+ ...overrides,
13
+ });
14
+ describe('AgentExecutionMonitorComponent (DOM)', () => {
15
+ it('shows the empty state when there is no run and no live steps', () => {
16
+ // When there is no run and no live steps, the monitor renders the canonical
17
+ // <mj-empty-state> placeholder inside the execution tree, carrying the
18
+ // "Waiting for execution to begin..." title. (The empty-state's own internal
19
+ // markup is its own concern; here we assert the monitor renders it with the
20
+ // right message.)
21
+ const f = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'live' } });
22
+ const empty = query(f, '.execution-tree mj-empty-state');
23
+ expect(empty).not.toBeNull();
24
+ expect(attr(f, '.execution-tree mj-empty-state', 'title')).toContain('Waiting for execution to begin');
25
+ });
26
+ it('renders the LIVE indicator only in live mode', () => {
27
+ const live = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'live' } });
28
+ expect(query(live, '.live-indicator')).not.toBeNull();
29
+ expect(query(live, '.execution-monitor.live-mode')).not.toBeNull();
30
+ const historical = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'historical' } });
31
+ expect(query(historical, '.live-indicator')).toBeNull();
32
+ });
33
+ it('shows the current-step name in live mode when a currentStep is set', () => {
34
+ const f = renderComponentFixture(AgentExecutionMonitorComponent, {
35
+ inputs: { mode: 'live' },
36
+ setup: (c) => {
37
+ c.currentStep = { StepName: 'Calling sub-agent' };
38
+ },
39
+ });
40
+ expect(text(f, '.current-status .step-name')).toBe('Calling sub-agent');
41
+ });
42
+ it('renders the stats footer values from the stats object', () => {
43
+ const f = renderComponentFixture(AgentExecutionMonitorComponent, {
44
+ inputs: { mode: 'historical' },
45
+ setup: (c) => {
46
+ c.stats = makeStats({
47
+ totalSteps: 5,
48
+ completedSteps: 4,
49
+ failedSteps: 1,
50
+ totalPrompts: 3,
51
+ totalTokens: 12345,
52
+ totalCost: 0.1234,
53
+ });
54
+ },
55
+ });
56
+ const values = queryAll(f, '.stats-grid .stat-value').map((e) => (e.textContent ?? '').trim());
57
+ const joined = values.join(' || ');
58
+ expect(joined).toContain('4/5');
59
+ expect(joined).toContain('(1 failed)');
60
+ expect(joined).toContain('3'); // prompts
61
+ expect(joined).toContain('12,345'); // tokens (toLocaleString)
62
+ expect(joined).toContain('0.1234'); // cost
63
+ });
64
+ it('renders the duration stat only when stats.totalDuration is set', () => {
65
+ const without = renderComponentFixture(AgentExecutionMonitorComponent, {
66
+ inputs: { mode: 'historical' },
67
+ setup: (c) => {
68
+ c.stats = makeStats();
69
+ },
70
+ });
71
+ expect(without.nativeElement.textContent).not.toContain('Duration');
72
+ const withDur = renderComponentFixture(AgentExecutionMonitorComponent, {
73
+ inputs: { mode: 'historical' },
74
+ setup: (c) => {
75
+ c.stats = makeStats({ totalDuration: 65000 });
76
+ }, // 1m 5s
77
+ });
78
+ expect(withDur.nativeElement.textContent).toContain('Duration');
79
+ const last = queryAll(withDur, '.stats-grid .stat-value').pop();
80
+ expect(last?.textContent).toContain('1m 5s');
81
+ });
82
+ it('renders pluralized step-type badges from stats.stepsByType', () => {
83
+ const f = renderComponentFixture(AgentExecutionMonitorComponent, {
84
+ inputs: { mode: 'historical' },
85
+ setup: (c) => {
86
+ c.stats = makeStats({ stepsByType: { Prompt: 2, Validation: 1 } });
87
+ },
88
+ });
89
+ const badges = queryAll(f, '.step-types .type-badge').map((b) => (b.textContent ?? '').trim());
90
+ expect(badges).toContain('2 Prompts'); // count !== 1 → pluralized
91
+ expect(badges).toContain('1 Validation'); // count === 1 → singular
92
+ });
93
+ // NOTE: the "View Run" button (gated on `mode==='historical' && agentRun &&
94
+ // isExecutionComplete()`) is NOT DOM-tested here. The moment `agentRun` is truthy,
95
+ // ngAfterViewInit → processAgentRun → calculateStats RECOMPUTES `stats` from
96
+ // `agentRun.Steps` (overwriting any hand-set stats back to zero), so the only honest
97
+ // way to satisfy `isExecutionComplete()` is to feed entity-shaped Steps through the
98
+ // imperative tree-builder path — out of scope for a unit test. Deferred to a live/e2e
99
+ // test. Its emission (onViewRunClick → viewRunClick) is covered by class-level specs.
100
+ });
101
+ //# sourceMappingURL=agent-execution-monitor.component.dom.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-execution-monitor.component.dom.test.js","sourceRoot":"","sources":["../../src/lib/agent-execution-monitor.component.dom.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it, expect } from 'vitest';\nimport { renderComponentFixture, query, text, queryAll, attr } from '@memberjunction/ng-test-utils';\nimport { AgentExecutionMonitorComponent } from './agent-execution-monitor.component';\n\n/**\n * DOM-level spec for <mj-agent-execution-monitor> — the presentational surface only:\n * header (LIVE indicator / current-step), empty state, the stats footer, the step-type\n * badges, and the \"View Run\" button + its @Output.\n *\n * The execution TREE itself is rendered by imperatively creating child ExecutionNode\n * components into a #executionNodesContainer ViewContainerRef from inside ngOnChanges'\n * data-processing path. That path needs entity-shaped data and View refs — out of scope\n * for a unit test — so we deliberately do NOT drive `agentRun`/`liveSteps` via setInput\n * (which would fire ngOnChanges → processing). Internal state (`stats`, `currentStep`,\n * `agentRun`) is set via `setup` BEFORE the first detectChanges (zoneless §5 safe) so the\n * footer/header bindings render without invoking the tree builder.\n */\n\ntype Stats = AgentExecutionMonitorComponent['stats'];\n\nconst makeStats = (overrides: Partial<Stats> = {}): Stats => ({\n totalSteps: 0,\n completedSteps: 0,\n failedSteps: 0,\n totalTokens: 0,\n totalCost: 0,\n stepsByType: {},\n totalPrompts: 0,\n ...overrides,\n});\n\ndescribe('AgentExecutionMonitorComponent (DOM)', () => {\n it('shows the empty state when there is no run and no live steps', () => {\n // When there is no run and no live steps, the monitor renders the canonical\n // <mj-empty-state> placeholder inside the execution tree, carrying the\n // \"Waiting for execution to begin...\" title. (The empty-state's own internal\n // markup is its own concern; here we assert the monitor renders it with the\n // right message.)\n const f = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'live' } });\n const empty = query(f, '.execution-tree mj-empty-state');\n expect(empty).not.toBeNull();\n expect(attr(f, '.execution-tree mj-empty-state', 'title')).toContain('Waiting for execution to begin');\n });\n\n it('renders the LIVE indicator only in live mode', () => {\n const live = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'live' } });\n expect(query(live, '.live-indicator')).not.toBeNull();\n expect(query(live, '.execution-monitor.live-mode')).not.toBeNull();\n\n const historical = renderComponentFixture(AgentExecutionMonitorComponent, { inputs: { mode: 'historical' } });\n expect(query(historical, '.live-indicator')).toBeNull();\n });\n\n it('shows the current-step name in live mode when a currentStep is set', () => {\n const f = renderComponentFixture(AgentExecutionMonitorComponent, {\n inputs: { mode: 'live' },\n setup: (c) => {\n c.currentStep = { StepName: 'Calling sub-agent' } as AgentExecutionMonitorComponent['currentStep'];\n },\n });\n expect(text(f, '.current-status .step-name')).toBe('Calling sub-agent');\n });\n\n it('renders the stats footer values from the stats object', () => {\n const f = renderComponentFixture(AgentExecutionMonitorComponent, {\n inputs: { mode: 'historical' },\n setup: (c) => {\n c.stats = makeStats({\n totalSteps: 5,\n completedSteps: 4,\n failedSteps: 1,\n totalPrompts: 3,\n totalTokens: 12345,\n totalCost: 0.1234,\n });\n },\n });\n const values = queryAll(f, '.stats-grid .stat-value').map((e) => (e.textContent ?? '').trim());\n const joined = values.join(' || ');\n expect(joined).toContain('4/5');\n expect(joined).toContain('(1 failed)');\n expect(joined).toContain('3'); // prompts\n expect(joined).toContain('12,345'); // tokens (toLocaleString)\n expect(joined).toContain('0.1234'); // cost\n });\n\n it('renders the duration stat only when stats.totalDuration is set', () => {\n const without = renderComponentFixture(AgentExecutionMonitorComponent, {\n inputs: { mode: 'historical' },\n setup: (c) => {\n c.stats = makeStats();\n },\n });\n expect(without.nativeElement.textContent).not.toContain('Duration');\n\n const withDur = renderComponentFixture(AgentExecutionMonitorComponent, {\n inputs: { mode: 'historical' },\n setup: (c) => {\n c.stats = makeStats({ totalDuration: 65000 });\n }, // 1m 5s\n });\n expect(withDur.nativeElement.textContent).toContain('Duration');\n const last = queryAll(withDur, '.stats-grid .stat-value').pop();\n expect(last?.textContent).toContain('1m 5s');\n });\n\n it('renders pluralized step-type badges from stats.stepsByType', () => {\n const f = renderComponentFixture(AgentExecutionMonitorComponent, {\n inputs: { mode: 'historical' },\n setup: (c) => {\n c.stats = makeStats({ stepsByType: { Prompt: 2, Validation: 1 } });\n },\n });\n const badges = queryAll(f, '.step-types .type-badge').map((b) => (b.textContent ?? '').trim());\n expect(badges).toContain('2 Prompts'); // count !== 1 → pluralized\n expect(badges).toContain('1 Validation'); // count === 1 → singular\n });\n\n // NOTE: the \"View Run\" button (gated on `mode==='historical' && agentRun &&\n // isExecutionComplete()`) is NOT DOM-tested here. The moment `agentRun` is truthy,\n // ngAfterViewInit → processAgentRun → calculateStats RECOMPUTES `stats` from\n // `agentRun.Steps` (overwriting any hand-set stats back to zero), so the only honest\n // way to satisfy `isExecutionComplete()` is to feed entity-shaped Steps through the\n // imperative tree-builder path — out of scope for a unit test. Deferred to a live/e2e\n // test. Its emission (onViewRunClick → viewRunClick) is covered by class-level specs.\n});\n"]}
@@ -4,6 +4,7 @@ import { takeUntil } from 'rxjs/operators';
4
4
  import { ExecutionNodeComponent } from './agent-execution-node.component';
5
5
  import { UUIDsEqual } from '@memberjunction/global';
6
6
  import * as i0 from "@angular/core";
7
+ import * as i1 from "@memberjunction/ng-ui-components";
7
8
  const _c0 = ["executionTreeContainer"];
8
9
  const _c1 = ["executionNodesContainer"];
9
10
  function AgentExecutionMonitorComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
@@ -37,11 +38,7 @@ function AgentExecutionMonitorComponent_Conditional_8_Template(rf, ctx) { if (rf
37
38
  i0.ɵɵtextInterpolate1(" View ", ctx_r1.runType === "agent" ? "Agent" : "Prompt", " Run ");
38
39
  } }
39
40
  function AgentExecutionMonitorComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
40
- i0.ɵɵelementStart(0, "div", 11);
41
- i0.ɵɵelement(1, "i", 24);
42
- i0.ɵɵelementStart(2, "p");
43
- i0.ɵɵtext(3, "Waiting for execution to begin...");
44
- i0.ɵɵelementEnd()();
41
+ i0.ɵɵelement(0, "mj-empty-state", 11);
45
42
  } }
46
43
  function AgentExecutionMonitorComponent_Conditional_21_Template(rf, ctx) { if (rf & 1) {
47
44
  i0.ɵɵelementStart(0, "span", 17);
@@ -65,7 +62,7 @@ function AgentExecutionMonitorComponent_Conditional_37_Template(rf, ctx) { if (r
65
62
  i0.ɵɵtextInterpolate(ctx_r1.formatDuration(ctx_r1.stats.totalDuration));
66
63
  } }
67
64
  function AgentExecutionMonitorComponent_Conditional_38_For_2_Template(rf, ctx) { if (rf & 1) {
68
- i0.ɵɵelementStart(0, "span", 25);
65
+ i0.ɵɵelementStart(0, "span", 24);
69
66
  i0.ɵɵtext(1);
70
67
  i0.ɵɵelementEnd();
71
68
  } if (rf & 2) {
@@ -76,7 +73,7 @@ function AgentExecutionMonitorComponent_Conditional_38_For_2_Template(rf, ctx) {
76
73
  } }
77
74
  function AgentExecutionMonitorComponent_Conditional_38_Template(rf, ctx) { if (rf & 1) {
78
75
  i0.ɵɵelementStart(0, "div", 18);
79
- i0.ɵɵrepeaterCreate(1, AgentExecutionMonitorComponent_Conditional_38_For_2_Template, 2, 2, "span", 25, i0.ɵɵrepeaterTrackByIdentity);
76
+ i0.ɵɵrepeaterCreate(1, AgentExecutionMonitorComponent_Conditional_38_For_2_Template, 2, 2, "span", 24, i0.ɵɵrepeaterTrackByIdentity);
80
77
  i0.ɵɵelementEnd();
81
78
  } if (rf & 2) {
82
79
  const ctx_r1 = i0.ɵɵnextContext();
@@ -975,7 +972,7 @@ export class AgentExecutionMonitorComponent {
975
972
  let _t;
976
973
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.executionTreeContainer = _t.first);
977
974
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.executionNodesContainer = _t.first);
978
- } }, inputs: { mode: "mode", agentRun: "agentRun", liveSteps: "liveSteps", autoExpand: "autoExpand", runId: "runId", runType: "runType" }, outputs: { viewRunClick: "viewRunClick" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 39, vars: 16, consts: [["executionTreeContainer", ""], ["executionNodesContainer", ""], [1, "execution-monitor"], [1, "monitor-header"], [1, "header-title"], [1, "fa-solid", "fa-diagram-project"], [1, "live-indicator"], [1, "current-status"], [1, "view-run-btn"], [1, "execution-tree", 3, "scroll", "click"], [1, "nodes-container"], [1, "empty-state"], [1, "monitor-footer"], [1, "stats-grid"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "failed-count"], [1, "step-types"], [1, "pulse"], [1, "status-label"], [1, "step-name"], [1, "view-run-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "fa-solid", "fa-hourglass-start"], [1, "type-badge"]], template: function AgentExecutionMonitorComponent_Template(rf, ctx) { if (rf & 1) {
975
+ } }, inputs: { mode: "mode", agentRun: "agentRun", liveSteps: "liveSteps", autoExpand: "autoExpand", runId: "runId", runType: "runType" }, outputs: { viewRunClick: "viewRunClick" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 39, vars: 16, consts: [["executionTreeContainer", ""], ["executionNodesContainer", ""], [1, "execution-monitor"], [1, "monitor-header"], [1, "header-title"], [1, "fa-solid", "fa-diagram-project"], [1, "live-indicator"], [1, "current-status"], [1, "view-run-btn"], [1, "execution-tree", 3, "scroll", "click"], [1, "nodes-container"], ["Icon", "fa-solid fa-hourglass-start", "Title", "Waiting for execution to begin...", "Size", "compact"], [1, "monitor-footer"], [1, "stats-grid"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "failed-count"], [1, "step-types"], [1, "pulse"], [1, "status-label"], [1, "step-name"], [1, "view-run-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "type-badge"]], template: function AgentExecutionMonitorComponent_Template(rf, ctx) { if (rf & 1) {
979
976
  const _r1 = i0.ɵɵgetCurrentView();
980
977
  i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4);
981
978
  i0.ɵɵelement(3, "i", 5);
@@ -990,7 +987,7 @@ export class AgentExecutionMonitorComponent {
990
987
  i0.ɵɵelementStart(9, "div", 9, 0);
991
988
  i0.ɵɵlistener("scroll", function AgentExecutionMonitorComponent_Template_div_scroll_9_listener($event) { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onScroll($event)); })("click", function AgentExecutionMonitorComponent_Template_div_click_9_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.onUserInteraction()); });
992
989
  i0.ɵɵelement(11, "div", 10, 1);
993
- i0.ɵɵconditionalCreate(13, AgentExecutionMonitorComponent_Conditional_13_Template, 4, 0, "div", 11);
990
+ i0.ɵɵconditionalCreate(13, AgentExecutionMonitorComponent_Conditional_13_Template, 1, 0, "mj-empty-state", 11);
994
991
  i0.ɵɵelementEnd();
995
992
  i0.ɵɵelementStart(14, "div", 12)(15, "div", 13)(16, "div", 14)(17, "span", 15);
996
993
  i0.ɵɵtext(18, "Steps");
@@ -1047,7 +1044,7 @@ export class AgentExecutionMonitorComponent {
1047
1044
  i0.ɵɵconditional(ctx.stats.totalDuration ? 37 : -1);
1048
1045
  i0.ɵɵadvance();
1049
1046
  i0.ɵɵconditional(ctx.getStepTypes().length > 0 ? 38 : -1);
1050
- } }, 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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n \n\n .monitor-header[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\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: var(--mj-text-primary);\n margin-bottom: 8px;\n }\n\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n }\n\n .live-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\n }\n\n .status-label[_ngcontent-%COMP%] {\n font-weight: 500;\n }\n\n .agent-path[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n }\n\n .step-name[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\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: var(--mj-text-muted);\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: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\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: var(--mj-text-primary);\n }\n\n .failed-count[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n \n\n .view-run-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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: var(--mj-brand-primary-hover);\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 }); }
1047
+ } }, dependencies: [i1.MJEmptyStateComponent], 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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n \n\n .monitor-header[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\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: var(--mj-text-primary);\n margin-bottom: 8px;\n }\n\n .header-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n }\n\n .live-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\n }\n\n .status-label[_ngcontent-%COMP%] {\n font-weight: 500;\n }\n\n .agent-path[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n }\n\n .step-name[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\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 .execution-tree[_ngcontent-%COMP%] mj-empty-state[_ngcontent-%COMP%] {\n height: 100%;\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: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\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: var(--mj-text-primary);\n }\n\n .failed-count[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n \n\n .view-run-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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: var(--mj-brand-primary-hover);\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 }); }
1051
1048
  }
1052
1049
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AgentExecutionMonitorComponent, [{
1053
1050
  type: Component,
@@ -1089,10 +1086,10 @@ export class AgentExecutionMonitorComponent {
1089
1086
  <div #executionNodesContainer class="nodes-container">
1090
1087
  </div>
1091
1088
  @if (!agentRun && liveSteps.length === 0) {
1092
- <div class="empty-state">
1093
- <i class="fa-solid fa-hourglass-start"></i>
1094
- <p>Waiting for execution to begin...</p>
1095
- </div>
1089
+ <mj-empty-state
1090
+ Icon="fa-solid fa-hourglass-start"
1091
+ Title="Waiting for execution to begin..."
1092
+ Size="compact" />
1096
1093
  }
1097
1094
  </div>
1098
1095
 
@@ -1138,7 +1135,7 @@ export class AgentExecutionMonitorComponent {
1138
1135
  }
1139
1136
  </div>
1140
1137
  </div>
1141
- `, 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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n /* Header */\n .monitor-header {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\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: var(--mj-text-primary);\n margin-bottom: 8px;\n }\n\n .header-title i {\n color: var(--mj-brand-primary);\n }\n\n .live-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\n }\n\n .status-label {\n font-weight: 500;\n }\n\n .agent-path {\n color: var(--mj-text-muted);\n }\n\n .step-name {\n color: var(--mj-text-primary);\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: var(--mj-text-muted);\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: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\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: var(--mj-text-primary);\n }\n\n .failed-count {\n color: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n /* View Run Button */\n .view-run-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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: var(--mj-brand-primary-hover);\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 "] }]
1138
+ `, 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: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n }\n\n /* Header */\n .monitor-header {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\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: var(--mj-text-primary);\n margin-bottom: 8px;\n }\n\n .header-title i {\n color: var(--mj-brand-primary);\n }\n\n .live-indicator {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\n }\n\n .status-label {\n font-weight: 500;\n }\n\n .agent-path {\n color: var(--mj-text-muted);\n }\n\n .step-name {\n color: var(--mj-text-primary);\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 .execution-tree mj-empty-state {\n height: 100%;\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: var(--mj-bg-surface-card);\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-text-secondary);\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: var(--mj-text-primary);\n }\n\n .failed-count {\n color: var(--mj-status-error);\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: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n }\n\n /* View Run Button */\n .view-run-btn {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\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: var(--mj-brand-primary-hover);\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 "] }]
1142
1139
  }], () => [{ type: i0.ChangeDetectorRef }], { mode: [{
1143
1140
  type: Input
1144
1141
  }], agentRun: [{
@@ -1160,5 +1157,5 @@ export class AgentExecutionMonitorComponent {
1160
1157
  type: ViewChild,
1161
1158
  args: ['executionNodesContainer', { read: ViewContainerRef }]
1162
1159
  }] }); })();
1163
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AgentExecutionMonitorComponent, { className: "AgentExecutionMonitorComponent", filePath: "lib/agent-execution-monitor.component.ts", lineNumber: 369 }); })();
1160
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AgentExecutionMonitorComponent, { className: "AgentExecutionMonitorComponent", filePath: "lib/agent-execution-monitor.component.ts", lineNumber: 352 }); })();
1164
1161
  //# sourceMappingURL=agent-execution-monitor.component.js.map