@memberjunction/ng-ai-test-harness 5.43.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.
- package/dist/lib/agent-execution-monitor.component.d.ts.map +1 -1
- package/dist/lib/agent-execution-monitor.component.dom.test.d.ts +2 -0
- package/dist/lib/agent-execution-monitor.component.dom.test.d.ts.map +1 -0
- package/dist/lib/agent-execution-monitor.component.dom.test.js +101 -0
- package/dist/lib/agent-execution-monitor.component.dom.test.js.map +1 -0
- package/dist/lib/agent-execution-monitor.component.js +13 -16
- package/dist/lib/agent-execution-monitor.component.js.map +1 -1
- package/dist/lib/agent-execution-node.component.dom.test.d.ts +2 -0
- package/dist/lib/agent-execution-node.component.dom.test.d.ts.map +1 -0
- package/dist/lib/agent-execution-node.component.dom.test.js +122 -0
- package/dist/lib/agent-execution-node.component.dom.test.js.map +1 -0
- package/dist/lib/ai-test-harness.component.js +189 -209
- package/dist/lib/ai-test-harness.component.js.map +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -4
- package/dist/module.js.map +1 -1
- package/package.json +16 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-execution-monitor.component.d.ts","sourceRoot":"","sources":["../../src/lib/agent-execution-monitor.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,SAAS,EAAE,aAAa,EAAE,SAAS,EAAa,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAA2B,gBAAgB,EAAwB,YAAY,EAAE,MAAM,eAAe,CAAC;AAI9N,OAAO,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;;AAG1G;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,MAAM,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,YAAY,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,
|
|
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 @@
|
|
|
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.ɵɵ
|
|
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",
|
|
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",
|
|
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"], [
|
|
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,
|
|
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 .
|
|
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
|
-
<
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
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 .
|
|
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:
|
|
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
|