@memberjunction/ng-dashboards 2.47.0 → 2.49.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.
Files changed (92) hide show
  1. package/README.md +105 -2
  2. package/dist/AI/ai-dashboard.component.d.ts +2 -0
  3. package/dist/AI/ai-dashboard.component.d.ts.map +1 -1
  4. package/dist/AI/ai-dashboard.component.js +66 -43
  5. package/dist/AI/ai-dashboard.component.js.map +1 -1
  6. package/dist/AI/components/agents/agent-configuration.component.js +45 -58
  7. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  8. package/dist/AI/components/agents/agent-editor.component.d.ts +6 -1
  9. package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
  10. package/dist/AI/components/agents/agent-editor.component.js +368 -366
  11. package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
  12. package/dist/AI/components/agents/agent-filter-panel.component.js +83 -85
  13. package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
  14. package/dist/AI/components/charts/performance-heatmap.component.d.ts +66 -0
  15. package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -0
  16. package/dist/AI/components/charts/performance-heatmap.component.js +428 -0
  17. package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -0
  18. package/dist/AI/components/charts/time-series-chart.component.d.ts +66 -0
  19. package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -0
  20. package/dist/AI/components/charts/time-series-chart.component.js +547 -0
  21. package/dist/AI/components/charts/time-series-chart.component.js.map +1 -0
  22. package/dist/AI/components/execution-monitoring.component.d.ts +157 -5
  23. package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
  24. package/dist/AI/components/execution-monitoring.component.js +2032 -20
  25. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  26. package/dist/AI/components/models/model-management.component.js +211 -237
  27. package/dist/AI/components/models/model-management.component.js.map +1 -1
  28. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +208 -226
  29. package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
  30. package/dist/AI/components/prompts/prompt-filter-panel.component.js +97 -99
  31. package/dist/AI/components/prompts/prompt-filter-panel.component.js.map +1 -1
  32. package/dist/AI/components/prompts/prompt-management.component.js +381 -424
  33. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  34. package/dist/AI/components/prompts/prompt-version-control.component.js +173 -191
  35. package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
  36. package/dist/AI/components/system/system-config-filter-panel.component.js +85 -87
  37. package/dist/AI/components/system/system-config-filter-panel.component.js.map +1 -1
  38. package/dist/AI/components/system/system-configuration.component.js +86 -99
  39. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  40. package/dist/AI/components/widgets/kpi-card.component.d.ts +25 -0
  41. package/dist/AI/components/widgets/kpi-card.component.d.ts.map +1 -0
  42. package/dist/AI/components/widgets/kpi-card.component.js +163 -0
  43. package/dist/AI/components/widgets/kpi-card.component.js.map +1 -0
  44. package/dist/AI/components/widgets/live-execution-widget.component.d.ts +25 -0
  45. package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -0
  46. package/dist/AI/components/widgets/live-execution-widget.component.js +298 -0
  47. package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -0
  48. package/dist/AI/index.d.ts +7 -0
  49. package/dist/AI/index.d.ts.map +1 -0
  50. package/dist/AI/index.js +9 -0
  51. package/dist/AI/index.js.map +1 -0
  52. package/dist/AI/services/ai-instrumentation.service.d.ts +109 -0
  53. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -0
  54. package/dist/AI/services/ai-instrumentation.service.js +490 -0
  55. package/dist/AI/services/ai-instrumentation.service.js.map +1 -0
  56. package/dist/Actions/actions-management-dashboard.component.js +40 -41
  57. package/dist/Actions/actions-management-dashboard.component.js.map +1 -1
  58. package/dist/Actions/components/actions-list-view.component.js +117 -134
  59. package/dist/Actions/components/actions-list-view.component.js.map +1 -1
  60. package/dist/Actions/components/actions-overview.component.js +274 -296
  61. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  62. package/dist/Actions/components/categories-list-view.component.js +12 -14
  63. package/dist/Actions/components/categories-list-view.component.js.map +1 -1
  64. package/dist/Actions/components/code-management.component.js +12 -14
  65. package/dist/Actions/components/code-management.component.js.map +1 -1
  66. package/dist/Actions/components/entity-integration.component.js +12 -14
  67. package/dist/Actions/components/entity-integration.component.js.map +1 -1
  68. package/dist/Actions/components/execution-monitoring.component.js +238 -256
  69. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  70. package/dist/Actions/components/executions-list-view.component.js +12 -14
  71. package/dist/Actions/components/executions-list-view.component.js.map +1 -1
  72. package/dist/Actions/components/scheduled-actions.component.js +12 -14
  73. package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
  74. package/dist/Actions/components/security-permissions.component.js +12 -14
  75. package/dist/Actions/components/security-permissions.component.js.map +1 -1
  76. package/dist/EntityAdmin/components/entity-details.component.js +105 -107
  77. package/dist/EntityAdmin/components/entity-details.component.js.map +1 -1
  78. package/dist/EntityAdmin/components/entity-filter-panel.component.js +100 -102
  79. package/dist/EntityAdmin/components/entity-filter-panel.component.js.map +1 -1
  80. package/dist/EntityAdmin/components/erd-composite.component.js +84 -100
  81. package/dist/EntityAdmin/components/erd-composite.component.js.map +1 -1
  82. package/dist/EntityAdmin/components/erd-diagram.component.js +50 -50
  83. package/dist/EntityAdmin/components/erd-diagram.component.js.map +1 -1
  84. package/dist/EntityAdmin/entity-admin-dashboard.component.js +45 -49
  85. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  86. package/dist/generic/base-dashboard.js +28 -40
  87. package/dist/generic/base-dashboard.js.map +1 -1
  88. package/dist/module.d.ts +16 -12
  89. package/dist/module.d.ts.map +1 -1
  90. package/dist/module.js +36 -15
  91. package/dist/module.js.map +1 -1
  92. package/package.json +6 -6
@@ -1,30 +1,2042 @@
1
- import { Component, Output, EventEmitter } from '@angular/core';
1
+ import { Component, Output, EventEmitter, Input } from '@angular/core';
2
+ import { Subject } from 'rxjs';
3
+ import { map, takeUntil, debounceTime } from 'rxjs/operators';
4
+ import { RunView } from '@memberjunction/core';
2
5
  import * as i0 from "@angular/core";
6
+ import * as i1 from "../services/ai-instrumentation.service";
7
+ import * as i2 from "@angular/forms";
8
+ import * as i3 from "@progress/kendo-angular-layout";
9
+ import * as i4 from "./widgets/kpi-card.component";
10
+ import * as i5 from "./widgets/live-execution-widget.component";
11
+ import * as i6 from "./charts/time-series-chart.component";
12
+ import * as i7 from "./charts/performance-heatmap.component";
13
+ import * as i8 from "@angular/common";
14
+ const _forTrack0 = ($index, $item) => $item.title;
15
+ const _forTrack1 = ($index, $item) => $item.id;
16
+ const _forTrack2 = ($index, $item) => $item.model;
17
+ const _c0 = () => [];
18
+ function ExecutionMonitoringComponent_For_40_Template(rf, ctx) { if (rf & 1) {
19
+ const _r1 = i0.ɵɵgetCurrentView();
20
+ i0.ɵɵelementStart(0, "app-kpi-card", 52);
21
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_For_40_Template_app_kpi_card_click_0_listener() { const kpi_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onKpiClick(kpi_r2)); });
22
+ i0.ɵɵelementEnd();
23
+ } if (rf & 2) {
24
+ const kpi_r2 = ctx.$implicit;
25
+ const ctx_r2 = i0.ɵɵnextContext();
26
+ i0.ɵɵclassProp("clickable", ctx_r2.isKpiClickable(kpi_r2));
27
+ i0.ɵɵproperty("data", kpi_r2);
28
+ } }
29
+ function ExecutionMonitoringComponent_Conditional_52_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelementStart(0, "div", 28)(1, "div", 53)(2, "div", 54);
31
+ i0.ɵɵelement(3, "i", 55);
32
+ i0.ɵɵelementEnd();
33
+ i0.ɵɵelementStart(4, "div", 56)(5, "div", 57);
34
+ i0.ɵɵtext(6, "Success Rate");
35
+ i0.ɵɵelementEnd();
36
+ i0.ɵɵelementStart(7, "div", 58);
37
+ i0.ɵɵtext(8);
38
+ i0.ɵɵelementEnd();
39
+ i0.ɵɵelementStart(9, "div", 59);
40
+ i0.ɵɵtext(10);
41
+ i0.ɵɵelementEnd()()();
42
+ i0.ɵɵelementStart(11, "div", 53)(12, "div", 60);
43
+ i0.ɵɵelement(13, "i", 61);
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(14, "div", 56)(15, "div", 57);
46
+ i0.ɵɵtext(16, "Error Rate");
47
+ i0.ɵɵelementEnd();
48
+ i0.ɵɵelementStart(17, "div", 58);
49
+ i0.ɵɵtext(18);
50
+ i0.ɵɵelementEnd();
51
+ i0.ɵɵelementStart(19, "div", 59);
52
+ i0.ɵɵtext(20);
53
+ i0.ɵɵelementEnd()()();
54
+ i0.ɵɵelementStart(21, "div", 53)(22, "div", 62);
55
+ i0.ɵɵelement(23, "i", 63);
56
+ i0.ɵɵelementEnd();
57
+ i0.ɵɵelementStart(24, "div", 56)(25, "div", 57);
58
+ i0.ɵɵtext(26, "Avg Response Time");
59
+ i0.ɵɵelementEnd();
60
+ i0.ɵɵelementStart(27, "div", 58);
61
+ i0.ɵɵtext(28);
62
+ i0.ɵɵelementEnd();
63
+ i0.ɵɵelementStart(29, "div", 59);
64
+ i0.ɵɵtext(30, "Across all models");
65
+ i0.ɵɵelementEnd()()();
66
+ i0.ɵɵelementStart(31, "div", 53)(32, "div", 64);
67
+ i0.ɵɵelement(33, "i", 49);
68
+ i0.ɵɵelementEnd();
69
+ i0.ɵɵelementStart(34, "div", 56)(35, "div", 57);
70
+ i0.ɵɵtext(36, "Active Executions");
71
+ i0.ɵɵelementEnd();
72
+ i0.ɵɵelementStart(37, "div", 58);
73
+ i0.ɵɵtext(38);
74
+ i0.ɵɵelementEnd();
75
+ i0.ɵɵelementStart(39, "div", 59);
76
+ i0.ɵɵtext(40, "Currently running");
77
+ i0.ɵɵelementEnd()()()();
78
+ } if (rf & 2) {
79
+ const kpis_r4 = ctx;
80
+ const ctx_r2 = i0.ɵɵnextContext();
81
+ i0.ɵɵadvance(8);
82
+ i0.ɵɵtextInterpolate1("", (kpis_r4.successRate * 100).toFixed(1), "%");
83
+ i0.ɵɵadvance(2);
84
+ i0.ɵɵtextInterpolate1("Last ", ctx_r2.selectedTimeRange, "");
85
+ i0.ɵɵadvance(8);
86
+ i0.ɵɵtextInterpolate1("", (kpis_r4.errorRate * 100).toFixed(1), "%");
87
+ i0.ɵɵadvance(2);
88
+ i0.ɵɵtextInterpolate1("", kpis_r4.totalExecutions, " total executions");
89
+ i0.ɵɵadvance(8);
90
+ i0.ɵɵtextInterpolate1("", (kpis_r4.avgExecutionTime / 1000).toFixed(2), "s");
91
+ i0.ɵɵadvance(10);
92
+ i0.ɵɵtextInterpolate(kpis_r4.activeExecutions);
93
+ } }
94
+ function ExecutionMonitoringComponent_For_59_Conditional_3_Template(rf, ctx) { if (rf & 1) {
95
+ const _r7 = i0.ɵɵgetCurrentView();
96
+ i0.ɵɵelementStart(0, "button", 68);
97
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_For_59_Conditional_3_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r7); const tab_r6 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeTab($event, tab_r6.id)); });
98
+ i0.ɵɵelement(1, "i", 69);
99
+ i0.ɵɵelementEnd();
100
+ } }
101
+ function ExecutionMonitoringComponent_For_59_Template(rf, ctx) { if (rf & 1) {
102
+ const _r5 = i0.ɵɵgetCurrentView();
103
+ i0.ɵɵelementStart(0, "div", 65);
104
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_For_59_Template_div_click_0_listener() { const tab_r6 = i0.ɵɵrestoreView(_r5).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectTab(tab_r6.id)); });
105
+ i0.ɵɵelementStart(1, "span", 66);
106
+ i0.ɵɵtext(2);
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵtemplate(3, ExecutionMonitoringComponent_For_59_Conditional_3_Template, 2, 0, "button", 67);
109
+ i0.ɵɵelementEnd();
110
+ } if (rf & 2) {
111
+ const tab_r6 = ctx.$implicit;
112
+ const ctx_r2 = i0.ɵɵnextContext();
113
+ i0.ɵɵclassProp("active", ctx_r2.activeTabId === tab_r6.id);
114
+ i0.ɵɵadvance(2);
115
+ i0.ɵɵtextInterpolate(tab_r6.title);
116
+ i0.ɵɵadvance();
117
+ i0.ɵɵconditional(tab_r6.closeable ? 3 : -1);
118
+ } }
119
+ function ExecutionMonitoringComponent_Conditional_61_Template(rf, ctx) { if (rf & 1) {
120
+ const _r8 = i0.ɵɵgetCurrentView();
121
+ i0.ɵɵelementStart(0, "div", 35)(1, "app-time-series-chart", 70);
122
+ i0.ɵɵpipe(2, "async");
123
+ i0.ɵɵlistener("dataPointClick", function ExecutionMonitoringComponent_Conditional_61_Template_app_time_series_chart_dataPointClick_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDataPointClick($event)); })("timeRangeChange", function ExecutionMonitoringComponent_Conditional_61_Template_app_time_series_chart_timeRangeChange_1_listener($event) { i0.ɵɵrestoreView(_r8); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onChartTimeRangeChange($event)); });
124
+ i0.ɵɵelementEnd()();
125
+ } if (rf & 2) {
126
+ let tmp_1_0;
127
+ const ctx_r2 = i0.ɵɵnextContext();
128
+ i0.ɵɵadvance();
129
+ i0.ɵɵproperty("data", (tmp_1_0 = i0.ɵɵpipeBind1(2, 2, ctx_r2.trends$)) !== null && tmp_1_0 !== undefined ? tmp_1_0 : i0.ɵɵpureFunction0(4, _c0))("config", ctx_r2.timeSeriesConfig);
130
+ } }
131
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_6_Template(rf, ctx) { if (rf & 1) {
132
+ i0.ɵɵelementStart(0, "span", 74);
133
+ i0.ɵɵtext(1);
134
+ i0.ɵɵelementEnd();
135
+ } if (rf & 2) {
136
+ const ctx_r2 = i0.ɵɵnextContext(2);
137
+ i0.ɵɵadvance();
138
+ i0.ɵɵtextInterpolate(ctx_r2.getFormattedTimestamp(ctx_r2.activeTab));
139
+ } }
140
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_7_Template(rf, ctx) { if (rf & 1) {
141
+ i0.ɵɵelementStart(0, "span", 75);
142
+ i0.ɵɵtext(1);
143
+ i0.ɵɵelementEnd();
144
+ } if (rf & 2) {
145
+ const ctx_r2 = i0.ɵɵnextContext(2);
146
+ i0.ɵɵadvance();
147
+ i0.ɵɵtextInterpolate(ctx_r2.getFormattedMetricLabel(ctx_r2.activeTab));
148
+ } }
149
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_8_Template(rf, ctx) { if (rf & 1) {
150
+ i0.ɵɵelementStart(0, "div", 76);
151
+ i0.ɵɵelement(1, "i", 79);
152
+ i0.ɵɵtext(2, " Loading execution details... ");
153
+ i0.ɵɵelementEnd();
154
+ } }
155
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_9_For_19_Template(rf, ctx) { if (rf & 1) {
156
+ const _r9 = i0.ɵɵgetCurrentView();
157
+ i0.ɵɵelementStart(0, "div", 83);
158
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Conditional_62_Conditional_9_For_19_Template_div_click_0_listener() { const execution_r10 = i0.ɵɵrestoreView(_r9).$implicit; const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.viewExecutionDetail(execution_r10)); });
159
+ i0.ɵɵelementStart(1, "div", 84)(2, "span", 85);
160
+ i0.ɵɵtext(3);
161
+ i0.ɵɵelementEnd()();
162
+ i0.ɵɵelementStart(4, "div", 84);
163
+ i0.ɵɵtext(5);
164
+ i0.ɵɵelementEnd();
165
+ i0.ɵɵelementStart(6, "div", 84);
166
+ i0.ɵɵtext(7);
167
+ i0.ɵɵelementEnd();
168
+ i0.ɵɵelementStart(8, "div", 84)(9, "span", 86);
169
+ i0.ɵɵtext(10);
170
+ i0.ɵɵelementEnd()();
171
+ i0.ɵɵelementStart(11, "div", 84);
172
+ i0.ɵɵtext(12);
173
+ i0.ɵɵelementEnd();
174
+ i0.ɵɵelementStart(13, "div", 84);
175
+ i0.ɵɵtext(14);
176
+ i0.ɵɵelementEnd();
177
+ i0.ɵɵelementStart(15, "div", 84);
178
+ i0.ɵɵtext(16);
179
+ i0.ɵɵelementEnd();
180
+ i0.ɵɵelementStart(17, "div", 84);
181
+ i0.ɵɵtext(18);
182
+ i0.ɵɵelementEnd()();
183
+ } if (rf & 2) {
184
+ const execution_r10 = ctx.$implicit;
185
+ const ctx_r2 = i0.ɵɵnextContext(3);
186
+ i0.ɵɵadvance(2);
187
+ i0.ɵɵclassMap("type-badge--" + execution_r10.type);
188
+ i0.ɵɵadvance();
189
+ i0.ɵɵtextInterpolate1(" ", execution_r10.type, " ");
190
+ i0.ɵɵadvance(2);
191
+ i0.ɵɵtextInterpolate(execution_r10.name);
192
+ i0.ɵɵadvance(2);
193
+ i0.ɵɵtextInterpolate(execution_r10.model || "N/A");
194
+ i0.ɵɵadvance(2);
195
+ i0.ɵɵclassMap("status-badge--" + execution_r10.status);
196
+ i0.ɵɵadvance();
197
+ i0.ɵɵtextInterpolate1(" ", execution_r10.status, " ");
198
+ i0.ɵɵadvance(2);
199
+ i0.ɵɵtextInterpolate(ctx_r2.formatDuration(execution_r10.duration));
200
+ i0.ɵɵadvance(2);
201
+ i0.ɵɵtextInterpolate(ctx_r2.formatCurrency(execution_r10.cost));
202
+ i0.ɵɵadvance(2);
203
+ i0.ɵɵtextInterpolate(execution_r10.tokens.toLocaleString());
204
+ i0.ɵɵadvance(2);
205
+ i0.ɵɵtextInterpolate(ctx_r2.formatTime(execution_r10.startTime));
206
+ } }
207
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_9_Template(rf, ctx) { if (rf & 1) {
208
+ i0.ɵɵelementStart(0, "div", 77)(1, "div", 80)(2, "div", 81);
209
+ i0.ɵɵtext(3, "Type");
210
+ i0.ɵɵelementEnd();
211
+ i0.ɵɵelementStart(4, "div", 81);
212
+ i0.ɵɵtext(5, "Name");
213
+ i0.ɵɵelementEnd();
214
+ i0.ɵɵelementStart(6, "div", 81);
215
+ i0.ɵɵtext(7, "Model");
216
+ i0.ɵɵelementEnd();
217
+ i0.ɵɵelementStart(8, "div", 81);
218
+ i0.ɵɵtext(9, "Status");
219
+ i0.ɵɵelementEnd();
220
+ i0.ɵɵelementStart(10, "div", 81);
221
+ i0.ɵɵtext(11, "Duration");
222
+ i0.ɵɵelementEnd();
223
+ i0.ɵɵelementStart(12, "div", 81);
224
+ i0.ɵɵtext(13, "Cost");
225
+ i0.ɵɵelementEnd();
226
+ i0.ɵɵelementStart(14, "div", 81);
227
+ i0.ɵɵtext(15, "Tokens");
228
+ i0.ɵɵelementEnd();
229
+ i0.ɵɵelementStart(16, "div", 81);
230
+ i0.ɵɵtext(17, "Time");
231
+ i0.ɵɵelementEnd()();
232
+ i0.ɵɵrepeaterCreate(18, ExecutionMonitoringComponent_Conditional_62_Conditional_9_For_19_Template, 19, 12, "div", 82, _forTrack1);
233
+ i0.ɵɵelementEnd();
234
+ } if (rf & 2) {
235
+ const ctx_r2 = i0.ɵɵnextContext(2);
236
+ i0.ɵɵadvance(18);
237
+ i0.ɵɵrepeater(ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data);
238
+ } }
239
+ function ExecutionMonitoringComponent_Conditional_62_Conditional_10_Template(rf, ctx) { if (rf & 1) {
240
+ i0.ɵɵelementStart(0, "div", 78);
241
+ i0.ɵɵelement(1, "i", 87);
242
+ i0.ɵɵelementStart(2, "p");
243
+ i0.ɵɵtext(3, "No executions found for this time period");
244
+ i0.ɵɵelementEnd()();
245
+ } }
246
+ function ExecutionMonitoringComponent_Conditional_62_Template(rf, ctx) { if (rf & 1) {
247
+ i0.ɵɵelementStart(0, "div", 36)(1, "div", 71)(2, "h4");
248
+ i0.ɵɵelement(3, "i", 72);
249
+ i0.ɵɵtext(4);
250
+ i0.ɵɵelementEnd();
251
+ i0.ɵɵelementStart(5, "div", 73);
252
+ i0.ɵɵtemplate(6, ExecutionMonitoringComponent_Conditional_62_Conditional_6_Template, 2, 1, "span", 74)(7, ExecutionMonitoringComponent_Conditional_62_Conditional_7_Template, 2, 1, "span", 75);
253
+ i0.ɵɵelementEnd()();
254
+ i0.ɵɵtemplate(8, ExecutionMonitoringComponent_Conditional_62_Conditional_8_Template, 3, 0, "div", 76)(9, ExecutionMonitoringComponent_Conditional_62_Conditional_9_Template, 20, 0, "div", 77)(10, ExecutionMonitoringComponent_Conditional_62_Conditional_10_Template, 4, 0, "div", 78);
255
+ i0.ɵɵelementEnd();
256
+ } if (rf & 2) {
257
+ const ctx_r2 = i0.ɵɵnextContext();
258
+ i0.ɵɵadvance(4);
259
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.activeTab == null ? null : ctx_r2.activeTab.title, " ");
260
+ i0.ɵɵadvance(2);
261
+ i0.ɵɵconditional((ctx_r2.activeTab == null ? null : ctx_r2.activeTab.timestamp) ? 6 : -1);
262
+ i0.ɵɵadvance();
263
+ i0.ɵɵconditional((ctx_r2.activeTab == null ? null : ctx_r2.activeTab.metric) ? 7 : -1);
264
+ i0.ɵɵadvance();
265
+ i0.ɵɵconditional(ctx_r2.loadingDrillDown ? 8 : (ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.length) > 0 ? 9 : 10);
266
+ } }
267
+ function ExecutionMonitoringComponent_Conditional_63_Conditional_5_Template(rf, ctx) { if (rf & 1) {
268
+ i0.ɵɵelementStart(0, "div", 76);
269
+ i0.ɵɵelement(1, "i", 79);
270
+ i0.ɵɵtext(2, " Loading model details... ");
271
+ i0.ɵɵelementEnd();
272
+ } }
273
+ function ExecutionMonitoringComponent_Conditional_63_Conditional_6_Conditional_32_Template(rf, ctx) { if (rf & 1) {
274
+ i0.ɵɵelementStart(0, "div", 93)(1, "h5");
275
+ i0.ɵɵtext(2, "Description");
276
+ i0.ɵɵelementEnd();
277
+ i0.ɵɵelementStart(3, "p");
278
+ i0.ɵɵtext(4);
279
+ i0.ɵɵelementEnd()();
280
+ } if (rf & 2) {
281
+ const ctx_r2 = i0.ɵɵnextContext(3);
282
+ i0.ɵɵadvance(4);
283
+ i0.ɵɵtextInterpolate(ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.description);
284
+ } }
285
+ function ExecutionMonitoringComponent_Conditional_63_Conditional_6_Template(rf, ctx) { if (rf & 1) {
286
+ i0.ɵɵelementStart(0, "div", 89)(1, "div", 90)(2, "div", 91)(3, "label");
287
+ i0.ɵɵtext(4, "Model Name:");
288
+ i0.ɵɵelementEnd();
289
+ i0.ɵɵelementStart(5, "span");
290
+ i0.ɵɵtext(6);
291
+ i0.ɵɵelementEnd()();
292
+ i0.ɵɵelementStart(7, "div", 91)(8, "label");
293
+ i0.ɵɵtext(9, "Vendor:");
294
+ i0.ɵɵelementEnd();
295
+ i0.ɵɵelementStart(10, "span");
296
+ i0.ɵɵtext(11);
297
+ i0.ɵɵelementEnd()();
298
+ i0.ɵɵelementStart(12, "div", 91)(13, "label");
299
+ i0.ɵɵtext(14, "API Name:");
300
+ i0.ɵɵelementEnd();
301
+ i0.ɵɵelementStart(15, "span");
302
+ i0.ɵɵtext(16);
303
+ i0.ɵɵelementEnd()();
304
+ i0.ɵɵelementStart(17, "div", 91)(18, "label");
305
+ i0.ɵɵtext(19, "Input Cost:");
306
+ i0.ɵɵelementEnd();
307
+ i0.ɵɵelementStart(20, "span");
308
+ i0.ɵɵtext(21);
309
+ i0.ɵɵelementEnd()();
310
+ i0.ɵɵelementStart(22, "div", 91)(23, "label");
311
+ i0.ɵɵtext(24, "Output Cost:");
312
+ i0.ɵɵelementEnd();
313
+ i0.ɵɵelementStart(25, "span");
314
+ i0.ɵɵtext(26);
315
+ i0.ɵɵelementEnd()();
316
+ i0.ɵɵelementStart(27, "div", 91)(28, "label");
317
+ i0.ɵɵtext(29, "Active:");
318
+ i0.ɵɵelementEnd();
319
+ i0.ɵɵelementStart(30, "span", 92);
320
+ i0.ɵɵtext(31);
321
+ i0.ɵɵelementEnd()()();
322
+ i0.ɵɵtemplate(32, ExecutionMonitoringComponent_Conditional_63_Conditional_6_Conditional_32_Template, 5, 1, "div", 93);
323
+ i0.ɵɵelementEnd();
324
+ } if (rf & 2) {
325
+ const ctx_r2 = i0.ɵɵnextContext(2);
326
+ i0.ɵɵadvance(6);
327
+ i0.ɵɵtextInterpolate(ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.name);
328
+ i0.ɵɵadvance(5);
329
+ i0.ɵɵtextInterpolate(ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.vendor);
330
+ i0.ɵɵadvance(5);
331
+ i0.ɵɵtextInterpolate(ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.apiName);
332
+ i0.ɵɵadvance(5);
333
+ i0.ɵɵtextInterpolate1("$", (ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.inputTokenCost == null ? null : ctx_r2.activeTab.data.inputTokenCost.toFixed(6)) || "0", " per token");
334
+ i0.ɵɵadvance(5);
335
+ i0.ɵɵtextInterpolate1("$", (ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.outputTokenCost == null ? null : ctx_r2.activeTab.data.outputTokenCost.toFixed(6)) || "0", " per token");
336
+ i0.ɵɵadvance(4);
337
+ i0.ɵɵclassProp("active", ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.isActive);
338
+ i0.ɵɵadvance();
339
+ i0.ɵɵtextInterpolate1(" ", (ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.isActive) ? "Yes" : "No", " ");
340
+ i0.ɵɵadvance();
341
+ i0.ɵɵconditional((ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.description) ? 32 : -1);
342
+ } }
343
+ function ExecutionMonitoringComponent_Conditional_63_Template(rf, ctx) { if (rf & 1) {
344
+ i0.ɵɵelementStart(0, "div", 37)(1, "div", 71)(2, "h4");
345
+ i0.ɵɵelement(3, "i", 88);
346
+ i0.ɵɵtext(4);
347
+ i0.ɵɵelementEnd()();
348
+ i0.ɵɵtemplate(5, ExecutionMonitoringComponent_Conditional_63_Conditional_5_Template, 3, 0, "div", 76)(6, ExecutionMonitoringComponent_Conditional_63_Conditional_6_Template, 33, 9, "div", 89);
349
+ i0.ɵɵelementEnd();
350
+ } if (rf & 2) {
351
+ const ctx_r2 = i0.ɵɵnextContext();
352
+ i0.ɵɵadvance(4);
353
+ i0.ɵɵtextInterpolate1(" Model Details: ", ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data == null ? null : ctx_r2.activeTab.data.name, " ");
354
+ i0.ɵɵadvance();
355
+ i0.ɵɵconditional(ctx_r2.loadingDrillDown ? 5 : (ctx_r2.activeTab == null ? null : ctx_r2.activeTab.data) ? 6 : -1);
356
+ } }
357
+ function ExecutionMonitoringComponent_Conditional_78_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
358
+ i0.ɵɵelementStart(0, "div", 95)(1, "div", 96)(2, "span", 97);
359
+ i0.ɵɵtext(3);
360
+ i0.ɵɵelementEnd();
361
+ i0.ɵɵelementStart(4, "span", 98);
362
+ i0.ɵɵtext(5);
363
+ i0.ɵɵelementEnd()();
364
+ i0.ɵɵelementStart(6, "div", 99);
365
+ i0.ɵɵelement(7, "div", 100);
366
+ i0.ɵɵelementEnd();
367
+ i0.ɵɵelementStart(8, "div", 101);
368
+ i0.ɵɵtext(9);
369
+ i0.ɵɵelementEnd()();
370
+ } if (rf & 2) {
371
+ const item_r11 = ctx.$implicit;
372
+ const costData_r12 = i0.ɵɵnextContext();
373
+ const ctx_r2 = i0.ɵɵnextContext(2);
374
+ i0.ɵɵadvance(3);
375
+ i0.ɵɵtextInterpolate(item_r11.model);
376
+ i0.ɵɵadvance(2);
377
+ i0.ɵɵtextInterpolate(ctx_r2.formatCurrency(item_r11.cost));
378
+ i0.ɵɵadvance(2);
379
+ i0.ɵɵstyleProp("width", ctx_r2.getCostBarWidth(item_r11.cost, ctx_r2.getMaxCost(costData_r12)), "%");
380
+ i0.ɵɵadvance(2);
381
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.formatTokens(item_r11.tokens), " tokens ");
382
+ } }
383
+ function ExecutionMonitoringComponent_Conditional_78_Conditional_1_Template(rf, ctx) { if (rf & 1) {
384
+ i0.ɵɵelementStart(0, "div", 94);
385
+ i0.ɵɵrepeaterCreate(1, ExecutionMonitoringComponent_Conditional_78_Conditional_1_For_2_Template, 10, 5, "div", 95, _forTrack2);
386
+ i0.ɵɵelementEnd();
387
+ } if (rf & 2) {
388
+ i0.ɵɵadvance();
389
+ i0.ɵɵrepeater(ctx.slice(0, 8));
390
+ } }
391
+ function ExecutionMonitoringComponent_Conditional_78_Template(rf, ctx) { if (rf & 1) {
392
+ i0.ɵɵelementStart(0, "div", 47);
393
+ i0.ɵɵtemplate(1, ExecutionMonitoringComponent_Conditional_78_Conditional_1_Template, 3, 0, "div", 94);
394
+ i0.ɵɵpipe(2, "async");
395
+ i0.ɵɵelementEnd();
396
+ } if (rf & 2) {
397
+ let tmp_1_0;
398
+ const ctx_r2 = i0.ɵɵnextContext();
399
+ i0.ɵɵadvance();
400
+ i0.ɵɵconditional((tmp_1_0 = i0.ɵɵpipeBind1(2, 1, ctx_r2.costData$)) ? 1 : -1, tmp_1_0);
401
+ } }
402
+ function ExecutionMonitoringComponent_Conditional_85_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
403
+ i0.ɵɵelementStart(0, "div", 103)(1, "div", 104)(2, "span", 97);
404
+ i0.ɵɵtext(3);
405
+ i0.ɵɵelementEnd();
406
+ i0.ɵɵelementStart(4, "span", 105);
407
+ i0.ɵɵtext(5);
408
+ i0.ɵɵelementEnd()();
409
+ i0.ɵɵelementStart(6, "div", 106)(7, "div", 107);
410
+ i0.ɵɵelement(8, "div", 108)(9, "div", 109);
411
+ i0.ɵɵelementEnd();
412
+ i0.ɵɵelementStart(10, "div", 110)(11, "span", 111);
413
+ i0.ɵɵtext(12);
414
+ i0.ɵɵelementEnd();
415
+ i0.ɵɵelementStart(13, "span", 112);
416
+ i0.ɵɵtext(14);
417
+ i0.ɵɵelementEnd()()();
418
+ i0.ɵɵelementStart(15, "div", 113);
419
+ i0.ɵɵtext(16);
420
+ i0.ɵɵelementEnd()();
421
+ } if (rf & 2) {
422
+ const item_r13 = ctx.$implicit;
423
+ const ctx_r2 = i0.ɵɵnextContext(3);
424
+ i0.ɵɵadvance(3);
425
+ i0.ɵɵtextInterpolate(item_r13.model);
426
+ i0.ɵɵadvance(2);
427
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.getTokenRatio(item_r13.inputTokens, item_r13.outputTokens), " ");
428
+ i0.ɵɵadvance(3);
429
+ i0.ɵɵstyleProp("width", ctx_r2.getTokenPercentage(item_r13.inputTokens, item_r13.inputTokens + item_r13.outputTokens), "%");
430
+ i0.ɵɵadvance();
431
+ i0.ɵɵstyleProp("width", ctx_r2.getTokenPercentage(item_r13.outputTokens, item_r13.inputTokens + item_r13.outputTokens), "%");
432
+ i0.ɵɵadvance(3);
433
+ i0.ɵɵtextInterpolate1("Input: ", ctx_r2.formatTokens(item_r13.inputTokens), "");
434
+ i0.ɵɵadvance(2);
435
+ i0.ɵɵtextInterpolate1("Output: ", ctx_r2.formatTokens(item_r13.outputTokens), "");
436
+ i0.ɵɵadvance(2);
437
+ i0.ɵɵtextInterpolate1(" ", ctx_r2.formatCostPerToken(item_r13.cost, item_r13.inputTokens + item_r13.outputTokens), " ");
438
+ } }
439
+ function ExecutionMonitoringComponent_Conditional_85_Conditional_1_Template(rf, ctx) { if (rf & 1) {
440
+ i0.ɵɵelementStart(0, "div", 102);
441
+ i0.ɵɵrepeaterCreate(1, ExecutionMonitoringComponent_Conditional_85_Conditional_1_For_2_Template, 17, 9, "div", 103, _forTrack2);
442
+ i0.ɵɵelementEnd();
443
+ } if (rf & 2) {
444
+ i0.ɵɵadvance();
445
+ i0.ɵɵrepeater(ctx.slice(0, 6));
446
+ } }
447
+ function ExecutionMonitoringComponent_Conditional_85_Template(rf, ctx) { if (rf & 1) {
448
+ i0.ɵɵelementStart(0, "div", 47);
449
+ i0.ɵɵtemplate(1, ExecutionMonitoringComponent_Conditional_85_Conditional_1_Template, 3, 0, "div", 102);
450
+ i0.ɵɵpipe(2, "async");
451
+ i0.ɵɵelementEnd();
452
+ } if (rf & 2) {
453
+ let tmp_1_0;
454
+ const ctx_r2 = i0.ɵɵnextContext();
455
+ i0.ɵɵadvance();
456
+ i0.ɵɵconditional((tmp_1_0 = i0.ɵɵpipeBind1(2, 1, ctx_r2.tokenEfficiency$)) ? 1 : -1, tmp_1_0);
457
+ } }
458
+ function ExecutionMonitoringComponent_Conditional_92_Template(rf, ctx) { if (rf & 1) {
459
+ const _r14 = i0.ɵɵgetCurrentView();
460
+ i0.ɵɵelementStart(0, "div", 50)(1, "app-live-execution-widget", 114);
461
+ i0.ɵɵpipe(2, "async");
462
+ i0.ɵɵlistener("executionClick", function ExecutionMonitoringComponent_Conditional_92_Template_app_live_execution_widget_executionClick_1_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onExecutionClick($event)); });
463
+ i0.ɵɵelementEnd()();
464
+ } if (rf & 2) {
465
+ let tmp_1_0;
466
+ const ctx_r2 = i0.ɵɵnextContext();
467
+ i0.ɵɵadvance();
468
+ i0.ɵɵproperty("executions", (tmp_1_0 = i0.ɵɵpipeBind1(2, 1, ctx_r2.liveExecutions$)) !== null && tmp_1_0 !== undefined ? tmp_1_0 : i0.ɵɵpureFunction0(3, _c0));
469
+ } }
470
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_28_Template(rf, ctx) { if (rf & 1) {
471
+ i0.ɵɵelementStart(0, "div", 127)(1, "label");
472
+ i0.ɵɵtext(2, "Completed:");
473
+ i0.ɵɵelementEnd();
474
+ i0.ɵɵelementStart(3, "span");
475
+ i0.ɵɵtext(4);
476
+ i0.ɵɵpipe(5, "date");
477
+ i0.ɵɵelementEnd()();
478
+ } if (rf & 2) {
479
+ const ctx_r2 = i0.ɵɵnextContext(3);
480
+ i0.ɵɵadvance(4);
481
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(5, 1, ctx_r2.executionDetails.endTime, "medium"));
482
+ } }
483
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_48_Template(rf, ctx) { if (rf & 1) {
484
+ i0.ɵɵelementStart(0, "div", 127)(1, "label");
485
+ i0.ɵɵtext(2, "Model:");
486
+ i0.ɵɵelementEnd();
487
+ i0.ɵɵelementStart(3, "span");
488
+ i0.ɵɵtext(4);
489
+ i0.ɵɵelementEnd()();
490
+ } if (rf & 2) {
491
+ const ctx_r2 = i0.ɵɵnextContext(3);
492
+ i0.ɵɵadvance(4);
493
+ i0.ɵɵtextInterpolate(ctx_r2.executionDetails.model);
494
+ } }
495
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_49_Template(rf, ctx) { if (rf & 1) {
496
+ i0.ɵɵelementStart(0, "div", 125)(1, "h4");
497
+ i0.ɵɵtext(2, "Error Information");
498
+ i0.ɵɵelementEnd();
499
+ i0.ɵɵelementStart(3, "div", 128);
500
+ i0.ɵɵtext(4);
501
+ i0.ɵɵelementEnd()();
502
+ } if (rf & 2) {
503
+ const ctx_r2 = i0.ɵɵnextContext(3);
504
+ i0.ɵɵadvance(4);
505
+ i0.ɵɵtextInterpolate(ctx_r2.executionDetails.errorMessage);
506
+ } }
507
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_50_For_5_Template(rf, ctx) { if (rf & 1) {
508
+ i0.ɵɵelementStart(0, "div", 130)(1, "div", 131)(2, "span", 132);
509
+ i0.ɵɵtext(3);
510
+ i0.ɵɵelementEnd();
511
+ i0.ɵɵelementStart(4, "span", 133);
512
+ i0.ɵɵtext(5);
513
+ i0.ɵɵelementEnd();
514
+ i0.ɵɵelementStart(6, "span", 134);
515
+ i0.ɵɵtext(7);
516
+ i0.ɵɵelementEnd()();
517
+ i0.ɵɵelementStart(8, "div", 135)(9, "span");
518
+ i0.ɵɵtext(10);
519
+ i0.ɵɵelementEnd();
520
+ i0.ɵɵelementStart(11, "span");
521
+ i0.ɵɵtext(12);
522
+ i0.ɵɵelementEnd()()();
523
+ } if (rf & 2) {
524
+ const child_r16 = ctx.$implicit;
525
+ const ctx_r2 = i0.ɵɵnextContext(4);
526
+ i0.ɵɵadvance(3);
527
+ i0.ɵɵtextInterpolate(child_r16.name);
528
+ i0.ɵɵadvance(2);
529
+ i0.ɵɵtextInterpolate(child_r16.type);
530
+ i0.ɵɵadvance();
531
+ i0.ɵɵclassMap("status-badge--" + child_r16.status);
532
+ i0.ɵɵadvance();
533
+ i0.ɵɵtextInterpolate1(" ", child_r16.status, " ");
534
+ i0.ɵɵadvance(3);
535
+ i0.ɵɵtextInterpolate(ctx_r2.formatCurrency(child_r16.cost));
536
+ i0.ɵɵadvance(2);
537
+ i0.ɵɵtextInterpolate1("", child_r16.tokens.toLocaleString(), " tokens");
538
+ } }
539
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_50_Template(rf, ctx) { if (rf & 1) {
540
+ i0.ɵɵelementStart(0, "div", 125)(1, "h4");
541
+ i0.ɵɵtext(2);
542
+ i0.ɵɵelementEnd();
543
+ i0.ɵɵelementStart(3, "div", 129);
544
+ i0.ɵɵrepeaterCreate(4, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_50_For_5_Template, 13, 7, "div", 130, _forTrack1);
545
+ i0.ɵɵelementEnd()();
546
+ } if (rf & 2) {
547
+ const ctx_r2 = i0.ɵɵnextContext(3);
548
+ i0.ɵɵadvance(2);
549
+ i0.ɵɵtextInterpolate1("Child Executions (", ctx_r2.executionDetails.children.length, ")");
550
+ i0.ɵɵadvance(2);
551
+ i0.ɵɵrepeater(ctx_r2.executionDetails.children);
552
+ } }
553
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_12_Template(rf, ctx) { if (rf & 1) {
554
+ i0.ɵɵelementStart(0, "div", 123)(1, "div", 125)(2, "h4");
555
+ i0.ɵɵtext(3, "Basic Information");
556
+ i0.ɵɵelementEnd();
557
+ i0.ɵɵelementStart(4, "div", 126)(5, "div", 127)(6, "label");
558
+ i0.ɵɵtext(7, "Type:");
559
+ i0.ɵɵelementEnd();
560
+ i0.ɵɵelementStart(8, "span");
561
+ i0.ɵɵtext(9);
562
+ i0.ɵɵpipe(10, "titlecase");
563
+ i0.ɵɵelementEnd()();
564
+ i0.ɵɵelementStart(11, "div", 127)(12, "label");
565
+ i0.ɵɵtext(13, "Name:");
566
+ i0.ɵɵelementEnd();
567
+ i0.ɵɵelementStart(14, "span");
568
+ i0.ɵɵtext(15);
569
+ i0.ɵɵelementEnd()();
570
+ i0.ɵɵelementStart(16, "div", 127)(17, "label");
571
+ i0.ɵɵtext(18, "Status:");
572
+ i0.ɵɵelementEnd();
573
+ i0.ɵɵelementStart(19, "span", 86);
574
+ i0.ɵɵtext(20);
575
+ i0.ɵɵpipe(21, "titlecase");
576
+ i0.ɵɵelementEnd()();
577
+ i0.ɵɵelementStart(22, "div", 127)(23, "label");
578
+ i0.ɵɵtext(24, "Started:");
579
+ i0.ɵɵelementEnd();
580
+ i0.ɵɵelementStart(25, "span");
581
+ i0.ɵɵtext(26);
582
+ i0.ɵɵpipe(27, "date");
583
+ i0.ɵɵelementEnd()();
584
+ i0.ɵɵtemplate(28, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_28_Template, 6, 4, "div", 127);
585
+ i0.ɵɵelementStart(29, "div", 127)(30, "label");
586
+ i0.ɵɵtext(31, "Duration:");
587
+ i0.ɵɵelementEnd();
588
+ i0.ɵɵelementStart(32, "span");
589
+ i0.ɵɵtext(33);
590
+ i0.ɵɵelementEnd()()()();
591
+ i0.ɵɵelementStart(34, "div", 125)(35, "h4");
592
+ i0.ɵɵtext(36, "Resource Usage");
593
+ i0.ɵɵelementEnd();
594
+ i0.ɵɵelementStart(37, "div", 126)(38, "div", 127)(39, "label");
595
+ i0.ɵɵtext(40, "Cost:");
596
+ i0.ɵɵelementEnd();
597
+ i0.ɵɵelementStart(41, "span");
598
+ i0.ɵɵtext(42);
599
+ i0.ɵɵelementEnd()();
600
+ i0.ɵɵelementStart(43, "div", 127)(44, "label");
601
+ i0.ɵɵtext(45, "Tokens:");
602
+ i0.ɵɵelementEnd();
603
+ i0.ɵɵelementStart(46, "span");
604
+ i0.ɵɵtext(47);
605
+ i0.ɵɵelementEnd()();
606
+ i0.ɵɵtemplate(48, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_48_Template, 5, 1, "div", 127);
607
+ i0.ɵɵelementEnd()();
608
+ i0.ɵɵtemplate(49, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_49_Template, 5, 1, "div", 125)(50, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Conditional_50_Template, 6, 1, "div", 125);
609
+ i0.ɵɵelementEnd();
610
+ } if (rf & 2) {
611
+ const ctx_r2 = i0.ɵɵnextContext(2);
612
+ i0.ɵɵadvance(9);
613
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(10, 13, ctx_r2.executionDetails.type));
614
+ i0.ɵɵadvance(6);
615
+ i0.ɵɵtextInterpolate(ctx_r2.executionDetails.name);
616
+ i0.ɵɵadvance(4);
617
+ i0.ɵɵclassMap("status-badge--" + ctx_r2.executionDetails.status);
618
+ i0.ɵɵadvance();
619
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(21, 15, ctx_r2.executionDetails.status), " ");
620
+ i0.ɵɵadvance(6);
621
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(27, 17, ctx_r2.executionDetails.startTime, "medium"));
622
+ i0.ɵɵadvance(2);
623
+ i0.ɵɵconditional(ctx_r2.executionDetails.endTime ? 28 : -1);
624
+ i0.ɵɵadvance(5);
625
+ i0.ɵɵtextInterpolate(ctx_r2.formatDuration(ctx_r2.getDuration(ctx_r2.executionDetails)));
626
+ i0.ɵɵadvance(9);
627
+ i0.ɵɵtextInterpolate(ctx_r2.formatCurrency(ctx_r2.executionDetails.cost, 6));
628
+ i0.ɵɵadvance(5);
629
+ i0.ɵɵtextInterpolate(ctx_r2.executionDetails.tokens.toLocaleString());
630
+ i0.ɵɵadvance();
631
+ i0.ɵɵconditional(ctx_r2.executionDetails.model ? 48 : -1);
632
+ i0.ɵɵadvance();
633
+ i0.ɵɵconditional(ctx_r2.executionDetails.errorMessage ? 49 : -1);
634
+ i0.ɵɵadvance();
635
+ i0.ɵɵconditional(ctx_r2.executionDetails.children.length > 0 ? 50 : -1);
636
+ } }
637
+ function ExecutionMonitoringComponent_Conditional_93_Conditional_13_Template(rf, ctx) { if (rf & 1) {
638
+ i0.ɵɵelementStart(0, "div", 124);
639
+ i0.ɵɵelement(1, "div", 136);
640
+ i0.ɵɵelementStart(2, "p");
641
+ i0.ɵɵtext(3, "Loading execution details...");
642
+ i0.ɵɵelementEnd()();
643
+ } }
644
+ function ExecutionMonitoringComponent_Conditional_93_Template(rf, ctx) { if (rf & 1) {
645
+ const _r15 = i0.ɵɵgetCurrentView();
646
+ i0.ɵɵelementStart(0, "div", 115);
647
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Conditional_93_Template_div_click_0_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeExecutionModal()); });
648
+ i0.ɵɵelementStart(1, "div", 116);
649
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Conditional_93_Template_div_click_1_listener($event) { i0.ɵɵrestoreView(_r15); return i0.ɵɵresetView($event.stopPropagation()); });
650
+ i0.ɵɵelementStart(2, "div", 117)(3, "h3");
651
+ i0.ɵɵtext(4, "Execution Details");
652
+ i0.ɵɵelementEnd();
653
+ i0.ɵɵelementStart(5, "div", 118)(6, "button", 119);
654
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Conditional_93_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.openFullRecord()); });
655
+ i0.ɵɵelement(7, "i", 120);
656
+ i0.ɵɵtext(8, " Open ");
657
+ i0.ɵɵelementEnd();
658
+ i0.ɵɵelementStart(9, "button", 121);
659
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Conditional_93_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.closeExecutionModal()); });
660
+ i0.ɵɵelement(10, "i", 69);
661
+ i0.ɵɵelementEnd()()();
662
+ i0.ɵɵelementStart(11, "div", 122);
663
+ i0.ɵɵtemplate(12, ExecutionMonitoringComponent_Conditional_93_Conditional_12_Template, 51, 20, "div", 123)(13, ExecutionMonitoringComponent_Conditional_93_Conditional_13_Template, 4, 0, "div", 124);
664
+ i0.ɵɵelementEnd()()();
665
+ } if (rf & 2) {
666
+ const ctx_r2 = i0.ɵɵnextContext();
667
+ i0.ɵɵadvance(12);
668
+ i0.ɵɵconditional(ctx_r2.executionDetails ? 12 : -1);
669
+ i0.ɵɵadvance();
670
+ i0.ɵɵconditional(ctx_r2.loadingExecutionDetails ? 13 : -1);
671
+ } }
3
672
  export class ExecutionMonitoringComponent {
4
- constructor() {
5
- this.openEntityRecord = new EventEmitter();
673
+ instrumentationService;
674
+ initialState;
675
+ openEntityRecord = new EventEmitter();
676
+ stateChange = new EventEmitter();
677
+ destroy$ = new Subject();
678
+ stateChangeSubject$ = new Subject();
679
+ // Configuration
680
+ refreshInterval = 30000; // 30 seconds
681
+ selectedTimeRange = '24h';
682
+ isLoading = false;
683
+ // Chart configurations
684
+ timeSeriesConfig = {
685
+ showGrid: true,
686
+ showTooltip: true,
687
+ animationDuration: 500,
688
+ useDualAxis: true
689
+ };
690
+ heatmapConfig = {
691
+ height: 350,
692
+ showTooltip: true,
693
+ animationDuration: 300
694
+ };
695
+ // Data streams
696
+ kpis$;
697
+ trends$;
698
+ liveExecutions$;
699
+ chartData$;
700
+ // Derived data streams
701
+ kpiCards$;
702
+ performanceMatrix$;
703
+ costData$;
704
+ tokenEfficiency$;
705
+ // Modal state
706
+ selectedExecution = null;
707
+ executionDetails = null;
708
+ loadingExecutionDetails = false;
709
+ // Drill-down tab state
710
+ drillDownTabs = [];
711
+ activeTabId = 'main-chart';
712
+ loadingDrillDown = false;
713
+ // Panel state for collapsible sections
714
+ panelStates = {
715
+ cost: true,
716
+ efficiency: true, // Expanded by default
717
+ executions: false
718
+ };
719
+ get activeTab() {
720
+ return this.drillDownTabs.find(tab => tab.id === this.activeTabId);
6
721
  }
7
- onOpenEntityRecord(entityName, recordId) {
8
- this.openEntityRecord.emit({ entityName, recordId });
722
+ constructor(instrumentationService) {
723
+ this.instrumentationService = instrumentationService;
724
+ // Initialize data streams
725
+ this.kpis$ = this.instrumentationService.kpis$;
726
+ this.trends$ = this.instrumentationService.trends$;
727
+ this.liveExecutions$ = this.instrumentationService.liveExecutions$;
728
+ this.chartData$ = this.instrumentationService.chartData$;
729
+ // Derived streams
730
+ this.kpiCards$ = this.kpis$.pipe(map(kpis => this.createKPICards(kpis)));
731
+ this.performanceMatrix$ = this.chartData$.pipe(map(data => data.performanceMatrix.map(item => ({
732
+ agent: item.agent,
733
+ model: item.model,
734
+ avgTime: item.avgTime,
735
+ successRate: item.successRate
736
+ }))));
737
+ this.costData$ = this.chartData$.pipe(map(data => data.costByModel));
738
+ this.tokenEfficiency$ = this.chartData$.pipe(map(data => data.tokenEfficiency));
9
739
  }
740
+ ngOnInit() {
741
+ // Load initial state if provided
742
+ if (this.initialState) {
743
+ this.loadUserState(this.initialState);
744
+ }
745
+ else {
746
+ // Default initialization
747
+ this.instrumentationService.setRefreshInterval(this.refreshInterval);
748
+ this.setTimeRange(this.selectedTimeRange);
749
+ // Initialize with main chart tab
750
+ this.drillDownTabs = [
751
+ {
752
+ id: 'main-chart',
753
+ title: 'Execution Trends',
754
+ type: 'chart',
755
+ closeable: false
756
+ }
757
+ ];
758
+ }
759
+ // Set up debounced state change emission
760
+ this.stateChangeSubject$.pipe(debounceTime(2000), // 2 second debounce
761
+ takeUntil(this.destroy$)).subscribe(state => {
762
+ this.stateChange.emit(state);
763
+ });
764
+ }
765
+ ngOnDestroy() {
766
+ this.destroy$.next();
767
+ this.destroy$.complete();
768
+ this.stateChangeSubject$.complete();
769
+ }
770
+ getCurrentState() {
771
+ return {
772
+ selectedTimeRange: this.selectedTimeRange,
773
+ refreshInterval: this.refreshInterval,
774
+ panelStates: { ...this.panelStates },
775
+ drillDownTabs: this.drillDownTabs.map(tab => ({
776
+ id: tab.id,
777
+ title: tab.title,
778
+ type: tab.type,
779
+ timestamp: tab.timestamp?.toISOString(),
780
+ metric: tab.metric
781
+ })),
782
+ activeTabId: this.activeTabId
783
+ };
784
+ }
785
+ emitStateChange() {
786
+ const currentState = this.getCurrentState();
787
+ this.stateChangeSubject$.next(currentState);
788
+ }
789
+ loadUserState(state) {
790
+ if (state.selectedTimeRange) {
791
+ this.selectedTimeRange = state.selectedTimeRange;
792
+ this.setTimeRange(state.selectedTimeRange);
793
+ }
794
+ if (state.refreshInterval !== undefined) {
795
+ this.refreshInterval = state.refreshInterval;
796
+ this.instrumentationService.setRefreshInterval(this.refreshInterval);
797
+ }
798
+ if (state.panelStates) {
799
+ // Only override if state has explicit panel states, otherwise keep defaults
800
+ this.panelStates = { ...this.panelStates, ...state.panelStates };
801
+ }
802
+ if (state.drillDownTabs && state.drillDownTabs.length > 0) {
803
+ this.drillDownTabs = state.drillDownTabs.map(tab => ({
804
+ ...tab,
805
+ type: tab.type,
806
+ timestamp: tab.timestamp ? new Date(tab.timestamp) : undefined,
807
+ closeable: tab.id !== 'main-chart'
808
+ }));
809
+ }
810
+ else {
811
+ // Initialize with default tab if not provided
812
+ this.drillDownTabs = [
813
+ {
814
+ id: 'main-chart',
815
+ title: 'Execution Trends',
816
+ type: 'chart',
817
+ closeable: false
818
+ }
819
+ ];
820
+ }
821
+ if (state.activeTabId) {
822
+ this.activeTabId = state.activeTabId;
823
+ }
824
+ }
825
+ createKPICards(kpis) {
826
+ return [
827
+ {
828
+ title: 'Total Executions',
829
+ value: kpis.totalExecutions,
830
+ icon: 'fa-chart-bar',
831
+ color: 'primary',
832
+ subtitle: `${kpis.activeExecutions} active`
833
+ },
834
+ {
835
+ title: 'Total Cost',
836
+ value: `$${kpis.totalCost.toFixed(4)}`,
837
+ icon: 'fa-dollar-sign',
838
+ color: 'warning',
839
+ subtitle: `${kpis.costCurrency} • $${kpis.dailyCostBurn.toFixed(2)}/day`
840
+ },
841
+ {
842
+ title: 'Success Rate',
843
+ value: `${(kpis.successRate * 100).toFixed(1)}%`,
844
+ icon: 'fa-check-circle',
845
+ color: 'success',
846
+ subtitle: `${(kpis.errorRate * 100).toFixed(1)}% errors`
847
+ },
848
+ {
849
+ title: 'Avg Response Time',
850
+ value: `${(kpis.avgExecutionTime / 1000).toFixed(2)}s`,
851
+ icon: 'fa-clock',
852
+ color: 'info',
853
+ subtitle: 'All models average'
854
+ },
855
+ {
856
+ title: 'Token Usage',
857
+ value: this.formatTokens(kpis.totalTokens),
858
+ icon: 'fa-coins',
859
+ color: 'primary',
860
+ subtitle: `$${kpis.costPerToken.toFixed(6)}/token`
861
+ },
862
+ {
863
+ title: 'Top Model',
864
+ value: kpis.topModel,
865
+ icon: 'fa-microchip',
866
+ color: 'info',
867
+ subtitle: 'Most used'
868
+ }
869
+ ];
870
+ }
871
+ onRefreshIntervalChange() {
872
+ this.instrumentationService.setRefreshInterval(this.refreshInterval);
873
+ this.emitStateChange();
874
+ }
875
+ onTimeRangeChange() {
876
+ this.setTimeRange(this.selectedTimeRange);
877
+ this.emitStateChange();
878
+ }
879
+ setTimeRange(range) {
880
+ const now = new Date();
881
+ let start;
882
+ switch (range) {
883
+ case '1h':
884
+ start = new Date(now.getTime() - 60 * 60 * 1000);
885
+ break;
886
+ case '6h':
887
+ start = new Date(now.getTime() - 6 * 60 * 60 * 1000);
888
+ break;
889
+ case '24h':
890
+ start = new Date(now.getTime() - 24 * 60 * 60 * 1000);
891
+ break;
892
+ case '7d':
893
+ start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
894
+ break;
895
+ case '30d':
896
+ start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
897
+ break;
898
+ default:
899
+ start = new Date(now.getTime() - 24 * 60 * 60 * 1000);
900
+ }
901
+ this.instrumentationService.setDateRange(start, now);
902
+ }
903
+ refreshData() {
904
+ this.isLoading = true;
905
+ // Force refresh by temporarily setting interval to 0 and back
906
+ const currentInterval = this.refreshInterval;
907
+ this.instrumentationService.setRefreshInterval(0);
908
+ setTimeout(() => {
909
+ this.instrumentationService.setRefreshInterval(currentInterval);
910
+ this.isLoading = false;
911
+ }, 100);
912
+ }
913
+ onExecutionClick(execution) {
914
+ this.selectedExecution = execution;
915
+ this.loadExecutionDetails(execution);
916
+ }
917
+ onDataPointClick(event) {
918
+ const timestamp = event.data.timestamp;
919
+ const metric = event.metric;
920
+ // Create new drill-down tab
921
+ const tabId = `drill-down-${timestamp.getTime()}-${metric}`;
922
+ const tabTitle = `${this.getMetricDisplayLabel(metric)} - ${this.formatTimestamp(timestamp)}`;
923
+ const newTab = {
924
+ id: tabId,
925
+ title: tabTitle,
926
+ type: 'executions',
927
+ timestamp: timestamp,
928
+ metric: metric,
929
+ closeable: true
930
+ };
931
+ // Add tab if it doesn't exist
932
+ if (!this.drillDownTabs.find(tab => tab.id === tabId)) {
933
+ this.drillDownTabs.push(newTab);
934
+ this.emitStateChange(); // Emit state when new tab is added
935
+ }
936
+ // Switch to the new tab
937
+ this.selectTab(tabId);
938
+ // Load drill-down data
939
+ this.loadDrillDownData(newTab);
940
+ }
941
+ onChartTimeRangeChange(range) {
942
+ this.selectedTimeRange = range;
943
+ this.setTimeRange(range);
944
+ }
945
+ getMetricValue(data, metric) {
946
+ switch (metric) {
947
+ case 'executions': return data.executions;
948
+ case 'cost': return data.cost;
949
+ case 'tokens': return data.tokens;
950
+ case 'avgTime': return data.avgTime;
951
+ case 'errors': return data.errors;
952
+ default: return 0;
953
+ }
954
+ }
955
+ formatMetricValue(metric, value) {
956
+ switch (metric) {
957
+ case 'executions': return value.toLocaleString();
958
+ case 'cost': return `$${value.toFixed(4)}`;
959
+ case 'tokens': return value.toLocaleString();
960
+ case 'avgTime': return `${(value / 1000).toFixed(1)}s`;
961
+ case 'errors': return value.toString();
962
+ default: return value.toString();
963
+ }
964
+ }
965
+ async loadExecutionDetails(execution) {
966
+ this.loadingExecutionDetails = true;
967
+ this.executionDetails = null;
968
+ try {
969
+ const details = await this.instrumentationService.getExecutionDetails(execution.id, execution.type);
970
+ this.executionDetails = details;
971
+ }
972
+ catch (error) {
973
+ console.error('Error loading execution details:', error);
974
+ }
975
+ finally {
976
+ this.loadingExecutionDetails = false;
977
+ }
978
+ }
979
+ closeExecutionModal() {
980
+ this.selectedExecution = null;
981
+ this.executionDetails = null;
982
+ this.loadingExecutionDetails = false;
983
+ }
984
+ openFullRecord() {
985
+ if (this.selectedExecution) {
986
+ // Determine the entity name based on the execution type
987
+ const entityName = this.selectedExecution.type === 'prompt'
988
+ ? 'MJ: AI Prompt Runs'
989
+ : 'MJ: AI Agent Runs';
990
+ // Emit the event to open the full record
991
+ this.openEntityRecord.emit({
992
+ entityName: entityName,
993
+ recordId: this.selectedExecution.id
994
+ });
995
+ // Close the modal
996
+ this.closeExecutionModal();
997
+ }
998
+ }
999
+ // Utility methods for templates
1000
+ trackByKpiTitle(index, kpi) {
1001
+ return kpi.title;
1002
+ }
1003
+ trackByCostModel(index, item) {
1004
+ return item.model;
1005
+ }
1006
+ trackByEfficiencyModel(index, item) {
1007
+ return item.model;
1008
+ }
1009
+ formatTokens(tokens) {
1010
+ if (tokens >= 1000000) {
1011
+ return `${(tokens / 1000000).toFixed(1)}M`;
1012
+ }
1013
+ else if (tokens >= 1000) {
1014
+ return `${(tokens / 1000).toFixed(1)}K`;
1015
+ }
1016
+ return tokens.toString();
1017
+ }
1018
+ formatCurrency(amount, decimals = 4) {
1019
+ return `$${amount.toFixed(decimals)}`;
1020
+ }
1021
+ formatCostPerToken(cost, tokens) {
1022
+ const costPer1K = tokens > 0 ? (cost / tokens) * 1000 : 0;
1023
+ return `$${costPer1K.toFixed(4)}/1K tokens`;
1024
+ }
1025
+ getCostBarWidth(cost, maxCost) {
1026
+ return maxCost > 0 ? (cost / maxCost) * 100 : 0;
1027
+ }
1028
+ getMaxCost(costData) {
1029
+ return Math.max(...costData.map(item => item.cost));
1030
+ }
1031
+ getTokenRatio(input, output) {
1032
+ const total = input + output;
1033
+ if (total === 0)
1034
+ return '0:0';
1035
+ const ratio = output / input;
1036
+ return `1:${ratio.toFixed(1)}`;
1037
+ }
1038
+ getTokenPercentage(tokens, total) {
1039
+ return total > 0 ? (tokens / total) * 100 : 0;
1040
+ }
1041
+ getCostPerToken(cost, tokens) {
1042
+ const costPer1K = tokens > 0 ? (cost / tokens) * 1000 : 0;
1043
+ return costPer1K.toFixed(4);
1044
+ }
1045
+ // Tab management methods
1046
+ selectTab(tabId) {
1047
+ this.activeTabId = tabId;
1048
+ // Trigger chart resize after tab switch to fix chart rendering
1049
+ setTimeout(() => {
1050
+ window.dispatchEvent(new Event('resize'));
1051
+ }, 100);
1052
+ this.emitStateChange();
1053
+ }
1054
+ closeTab(event, tabId) {
1055
+ event.stopPropagation();
1056
+ const tabIndex = this.drillDownTabs.findIndex(tab => tab.id === tabId);
1057
+ if (tabIndex === -1)
1058
+ return;
1059
+ // Remove the tab
1060
+ this.drillDownTabs.splice(tabIndex, 1);
1061
+ // If we closed the active tab, switch to another tab
1062
+ if (this.activeTabId === tabId) {
1063
+ if (this.drillDownTabs.length > 0) {
1064
+ // Switch to the previous tab or first tab
1065
+ const newActiveIndex = Math.max(0, tabIndex - 1);
1066
+ this.activeTabId = this.drillDownTabs[newActiveIndex].id;
1067
+ // Trigger resize after tab switch
1068
+ setTimeout(() => {
1069
+ window.dispatchEvent(new Event('resize'));
1070
+ }, 100);
1071
+ }
1072
+ else {
1073
+ // No tabs left, this shouldn't happen as main chart is not closeable
1074
+ this.activeTabId = 'main-chart';
1075
+ }
1076
+ }
1077
+ this.emitStateChange();
1078
+ }
1079
+ // KPI click handling
1080
+ onKpiClick(kpi) {
1081
+ if (kpi.title === 'Top Model' && kpi.value !== 'N/A') {
1082
+ this.openModelDrillDown(String(kpi.value));
1083
+ }
1084
+ // Add other KPI drill-downs as needed
1085
+ }
1086
+ isKpiClickable(kpi) {
1087
+ return kpi.title === 'Top Model' && kpi.value !== 'N/A';
1088
+ }
1089
+ async openModelDrillDown(modelName) {
1090
+ const tabId = `model-detail-${modelName.replace(/[^a-zA-Z0-9]/g, '-')}`;
1091
+ const tabTitle = `Model: ${modelName}`;
1092
+ // Check if tab already exists
1093
+ if (this.drillDownTabs.find(tab => tab.id === tabId)) {
1094
+ this.selectTab(tabId);
1095
+ return;
1096
+ }
1097
+ // Create new model detail tab
1098
+ const newTab = {
1099
+ id: tabId,
1100
+ title: tabTitle,
1101
+ type: 'model-detail',
1102
+ closeable: true
1103
+ };
1104
+ this.drillDownTabs.push(newTab);
1105
+ this.selectTab(tabId);
1106
+ // Load model details
1107
+ this.loadModelDetails(newTab, modelName);
1108
+ }
1109
+ async loadDrillDownData(tab) {
1110
+ if (!tab.timestamp)
1111
+ return;
1112
+ this.loadingDrillDown = true;
1113
+ try {
1114
+ // Create time window around the clicked point (±30 minutes)
1115
+ const startTime = new Date(tab.timestamp.getTime() - 30 * 60 * 1000);
1116
+ const endTime = new Date(tab.timestamp.getTime() + 30 * 60 * 1000);
1117
+ // Load executions for this time period
1118
+ const [promptResults, agentResults] = await Promise.all([
1119
+ new RunView().RunView({
1120
+ EntityName: 'MJ: AI Prompt Runs',
1121
+ ExtraFilter: `RunAt >= '${startTime.toISOString()}' AND RunAt <= '${endTime.toISOString()}'`,
1122
+ OrderBy: 'RunAt DESC',
1123
+ ResultType: 'entity_object'
1124
+ }),
1125
+ new RunView().RunView({
1126
+ EntityName: 'MJ: AI Agent Runs',
1127
+ ExtraFilter: `StartedAt >= '${startTime.toISOString()}' AND StartedAt <= '${endTime.toISOString()}'`,
1128
+ OrderBy: 'StartedAt DESC',
1129
+ ResultType: 'entity_object'
1130
+ })
1131
+ ]);
1132
+ // Convert to ExecutionRecord format
1133
+ const executions = [];
1134
+ // Add prompt executions
1135
+ for (const run of promptResults.Results) {
1136
+ const duration = run.CompletedAt ?
1137
+ new Date(run.CompletedAt).getTime() - new Date(run.RunAt).getTime() :
1138
+ Date.now() - new Date(run.RunAt).getTime();
1139
+ executions.push({
1140
+ id: run.ID,
1141
+ type: 'prompt',
1142
+ name: await this.getPromptName(run.PromptID),
1143
+ model: run.ModelID ? await this.getModelName(run.ModelID) : undefined,
1144
+ status: run.Success ? 'completed' : (run.Success === false ? 'failed' : 'running'),
1145
+ startTime: new Date(run.RunAt),
1146
+ endTime: run.CompletedAt ? new Date(run.CompletedAt) : undefined,
1147
+ duration: duration,
1148
+ cost: run.Cost || 0,
1149
+ tokens: run.TokensUsed || 0,
1150
+ errorMessage: run.ErrorMessage || undefined
1151
+ });
1152
+ }
1153
+ // Add agent executions
1154
+ for (const run of agentResults.Results) {
1155
+ const duration = run.CompletedAt ?
1156
+ new Date(run.CompletedAt).getTime() - new Date(run.StartedAt).getTime() :
1157
+ Date.now() - new Date(run.StartedAt).getTime();
1158
+ executions.push({
1159
+ id: run.ID,
1160
+ type: 'agent',
1161
+ name: await this.getAgentName(run.AgentID),
1162
+ status: run.Status.toLowerCase(),
1163
+ startTime: new Date(run.StartedAt),
1164
+ endTime: run.CompletedAt ? new Date(run.CompletedAt) : undefined,
1165
+ duration: duration,
1166
+ cost: run.TotalCost || 0,
1167
+ tokens: run.TotalTokensUsed || 0,
1168
+ errorMessage: run.ErrorMessage || undefined
1169
+ });
1170
+ }
1171
+ // Sort by start time (most recent first)
1172
+ executions.sort((a, b) => b.startTime.getTime() - a.startTime.getTime());
1173
+ // Update tab data
1174
+ tab.data = executions;
1175
+ }
1176
+ catch (error) {
1177
+ console.error('Error loading drill-down data:', error);
1178
+ tab.data = [];
1179
+ }
1180
+ finally {
1181
+ this.loadingDrillDown = false;
1182
+ }
1183
+ }
1184
+ async loadModelDetails(tab, modelName) {
1185
+ this.loadingDrillDown = true;
1186
+ try {
1187
+ // Find model by name
1188
+ const rv = new RunView();
1189
+ const result = await rv.RunView({
1190
+ EntityName: 'AI Models',
1191
+ ExtraFilter: `Name = '${modelName.replace(/'/g, "''")}'`,
1192
+ ResultType: 'entity_object'
1193
+ });
1194
+ const model = result.Results[0];
1195
+ if (model) {
1196
+ tab.data = {
1197
+ name: model.Name,
1198
+ vendor: model.Vendor,
1199
+ apiName: model.APIName,
1200
+ inputTokenCost: 0, // Not available in current model
1201
+ outputTokenCost: 0, // Not available in current model
1202
+ isActive: model.IsActive,
1203
+ description: model.Description
1204
+ };
1205
+ }
1206
+ else {
1207
+ tab.data = null;
1208
+ }
1209
+ }
1210
+ catch (error) {
1211
+ console.error('Error loading model details:', error);
1212
+ tab.data = null;
1213
+ }
1214
+ finally {
1215
+ this.loadingDrillDown = false;
1216
+ }
1217
+ }
1218
+ // Helper methods for drill-down
1219
+ async getPromptName(promptId) {
1220
+ try {
1221
+ const rv = new RunView();
1222
+ const result = await rv.RunView({
1223
+ EntityName: 'AI Prompts',
1224
+ ExtraFilter: `ID = '${promptId}'`,
1225
+ ResultType: 'entity_object'
1226
+ });
1227
+ return result.Results[0]?.Name || 'Unknown Prompt';
1228
+ }
1229
+ catch {
1230
+ return 'Unknown Prompt';
1231
+ }
1232
+ }
1233
+ async getAgentName(agentId) {
1234
+ try {
1235
+ const rv = new RunView();
1236
+ const result = await rv.RunView({
1237
+ EntityName: 'AI Agents',
1238
+ ExtraFilter: `ID = '${agentId}'`,
1239
+ ResultType: 'entity_object'
1240
+ });
1241
+ return result.Results[0]?.Name || 'Unknown Agent';
1242
+ }
1243
+ catch {
1244
+ return 'Unknown Agent';
1245
+ }
1246
+ }
1247
+ async getModelName(modelId) {
1248
+ try {
1249
+ const rv = new RunView();
1250
+ const result = await rv.RunView({
1251
+ EntityName: 'AI Models',
1252
+ ExtraFilter: `ID = '${modelId}'`,
1253
+ ResultType: 'entity_object'
1254
+ });
1255
+ return result.Results[0]?.Name || 'Unknown Model';
1256
+ }
1257
+ catch {
1258
+ return 'Unknown Model';
1259
+ }
1260
+ }
1261
+ formatTimestamp(timestamp) {
1262
+ return timestamp.toLocaleString();
1263
+ }
1264
+ formatTime(time) {
1265
+ return time.toLocaleTimeString();
1266
+ }
1267
+ getMetricDisplayLabel(metric) {
1268
+ const labels = {
1269
+ executions: 'Executions',
1270
+ cost: 'Cost',
1271
+ tokens: 'Tokens',
1272
+ avgTime: 'Avg Time',
1273
+ errors: 'Errors'
1274
+ };
1275
+ return labels[metric] || metric;
1276
+ }
1277
+ getFormattedTimestamp(tab) {
1278
+ return tab?.timestamp ? this.formatTimestamp(tab.timestamp) : '';
1279
+ }
1280
+ getFormattedMetricLabel(tab) {
1281
+ return tab?.metric ? this.getMetricDisplayLabel(tab.metric) : '';
1282
+ }
1283
+ // Panel management methods
1284
+ togglePanel(panelName) {
1285
+ this.panelStates[panelName] = !this.panelStates[panelName];
1286
+ this.emitStateChange();
1287
+ }
1288
+ viewExecutionDetail(execution) {
1289
+ // Convert ExecutionRecord to LiveExecution format for the modal
1290
+ const liveExecution = {
1291
+ id: execution.id,
1292
+ type: execution.type,
1293
+ name: execution.name,
1294
+ status: execution.status,
1295
+ startTime: execution.startTime,
1296
+ duration: execution.duration,
1297
+ cost: execution.cost,
1298
+ tokens: execution.tokens
1299
+ };
1300
+ this.onExecutionClick(liveExecution);
1301
+ }
1302
+ formatDuration(milliseconds) {
1303
+ const seconds = Math.floor(milliseconds / 1000);
1304
+ const minutes = Math.floor(seconds / 60);
1305
+ const hours = Math.floor(minutes / 60);
1306
+ if (hours > 0) {
1307
+ return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
1308
+ }
1309
+ else if (minutes > 0) {
1310
+ return `${minutes}m ${seconds % 60}s`;
1311
+ }
1312
+ else {
1313
+ return `${seconds}s`;
1314
+ }
1315
+ }
1316
+ getDuration(details) {
1317
+ const start = details.startTime.getTime();
1318
+ const end = details.endTime ? details.endTime.getTime() : Date.now();
1319
+ return end - start;
1320
+ }
1321
+ onSplitterLayoutChange(event) {
1322
+ // Trigger window resize event to force charts to recalculate dimensions
1323
+ setTimeout(() => {
1324
+ window.dispatchEvent(new Event('resize'));
1325
+ }, 100);
1326
+ // Emit state change when splitter changes
1327
+ this.emitStateChange();
1328
+ }
1329
+ static ɵfac = function ExecutionMonitoringComponent_Factory(t) { return new (t || ExecutionMonitoringComponent)(i0.ɵɵdirectiveInject(i1.AIInstrumentationService)); };
1330
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ExecutionMonitoringComponent, selectors: [["app-execution-monitoring"]], inputs: { initialState: "initialState" }, outputs: { openEntityRecord: "openEntityRecord", stateChange: "stateChange" }, decls: 94, vars: 52, consts: [[1, "execution-monitoring"], [1, "monitoring-header"], [1, "monitoring-title"], [1, "fa-solid", "fa-chart-line"], [1, "monitoring-controls"], [1, "refresh-control"], [3, "ngModelChange", "change", "ngModel"], [3, "value"], [1, "time-range-control"], ["value", "1h"], ["value", "6h"], ["value", "24h"], ["value", "7d"], ["value", "30d"], [1, "refresh-btn", 3, "click", "disabled"], [1, "fa-solid", "fa-refresh"], [1, "kpi-dashboard"], [1, "kpi-grid"], [3, "data", "clickable"], ["orientation", "vertical", 1, "dashboard-splitter", 3, "layoutChange"], ["size", "45%", 3, "resizable", "collapsible"], ["orientation", "horizontal", 3, "layoutChange"], ["size", "30%", 3, "resizable", "collapsible", "collapsed"], [1, "dashboard-section", "system-status"], [1, "status-container"], [1, "chart-header"], [1, "chart-title"], [1, "fa-solid", "fa-heartbeat"], [1, "status-metrics"], [3, "resizable", "collapsible"], [1, "dashboard-section", "drill-down-container"], [1, "drill-down-tabs"], [1, "tab-header"], [1, "tab-item", 3, "active"], [1, "tab-content"], [1, "tab-pane", "trends-chart"], [1, "tab-pane", "executions-drill-down"], [1, "tab-pane", "model-detail"], ["size", "50%", 3, "resizable", "collapsible"], [1, "dashboard-section", "performance-matrix"], ["title", "Agent vs Model Performance", 3, "data", "config"], [1, "dashboard-section", "analysis-panels"], [1, "analysis-panel"], [1, "panel-header", 3, "click"], [1, "panel-title"], [1, "fa-solid", "fa-dollar-sign"], [1, "fa-solid", "panel-toggle-icon"], [1, "panel-content"], [1, "fa-solid", "fa-chart-pie"], [1, "fa-solid", "fa-bolt"], [1, "panel-content", "live-executions-panel"], [1, "execution-modal"], [3, "click", "data"], [1, "status-metric"], [1, "status-icon", "status-icon--success"], [1, "fa-solid", "fa-check"], [1, "status-info"], [1, "status-label"], [1, "status-value"], [1, "status-subtitle"], [1, "status-icon", "status-icon--warning"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "status-icon", "status-icon--info"], [1, "fa-solid", "fa-clock"], [1, "status-icon", "status-icon--primary"], [1, "tab-item", 3, "click"], [1, "tab-title"], ["title", "Close tab", 1, "tab-close"], ["title", "Close tab", 1, "tab-close", 3, "click"], [1, "fa-solid", "fa-times"], ["title", "Execution Trends", 3, "dataPointClick", "timeRangeChange", "data", "config"], [1, "drill-down-header"], [1, "fa-solid", "fa-list"], [1, "drill-down-meta"], [1, "timestamp"], [1, "metric-badge"], [1, "loading-spinner"], [1, "executions-table"], [1, "no-data"], [1, "fa-solid", "fa-spinner", "fa-spin"], [1, "table-header"], [1, "header-cell"], [1, "table-row"], [1, "table-row", 3, "click"], [1, "table-cell"], [1, "type-badge"], [1, "status-badge"], [1, "fa-solid", "fa-inbox"], [1, "fa-solid", "fa-microchip"], [1, "model-details"], [1, "model-info-grid"], [1, "info-item"], [1, "status-indicator"], [1, "model-description"], [1, "cost-bars"], [1, "cost-bar-item"], [1, "cost-bar-info"], [1, "model-name"], [1, "cost-value"], [1, "cost-bar-container"], [1, "cost-bar"], [1, "token-info"], [1, "efficiency-items"], [1, "efficiency-item"], [1, "efficiency-header"], [1, "efficiency-ratio"], [1, "token-breakdown"], [1, "token-bar"], [1, "token-segment", "token-segment--input"], [1, "token-segment", "token-segment--output"], [1, "token-labels"], [1, "input-label"], [1, "output-label"], [1, "cost-per-token"], [3, "executionClick", "executions"], [1, "execution-modal", 3, "click"], [1, "execution-modal-content", 3, "click"], [1, "execution-modal-header"], [1, "modal-header-actions"], [1, "open-record-btn", 3, "click"], [1, "fa-solid", "fa-external-link-alt"], [1, "close-btn", 3, "click"], [1, "execution-modal-body"], [1, "execution-details"], [1, "loading-details"], [1, "detail-section"], [1, "detail-grid"], [1, "detail-item"], [1, "error-message"], [1, "child-executions"], [1, "child-execution"], [1, "child-info"], [1, "child-name"], [1, "child-type"], [1, "child-status"], [1, "child-metrics"], [1, "spinner"]], template: function ExecutionMonitoringComponent_Template(rf, ctx) { if (rf & 1) {
1331
+ i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h2", 2);
1332
+ i0.ɵɵelement(3, "i", 3);
1333
+ i0.ɵɵtext(4, " AI Execution Monitoring ");
1334
+ i0.ɵɵelementEnd();
1335
+ i0.ɵɵelementStart(5, "div", 4)(6, "div", 5)(7, "label");
1336
+ i0.ɵɵtext(8, "Refresh:");
1337
+ i0.ɵɵelementEnd();
1338
+ i0.ɵɵelementStart(9, "select", 6);
1339
+ i0.ɵɵtwoWayListener("ngModelChange", function ExecutionMonitoringComponent_Template_select_ngModelChange_9_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.refreshInterval, $event) || (ctx.refreshInterval = $event); return $event; });
1340
+ i0.ɵɵlistener("change", function ExecutionMonitoringComponent_Template_select_change_9_listener() { return ctx.onRefreshIntervalChange(); });
1341
+ i0.ɵɵelementStart(10, "option", 7);
1342
+ i0.ɵɵtext(11, "Manual");
1343
+ i0.ɵɵelementEnd();
1344
+ i0.ɵɵelementStart(12, "option", 7);
1345
+ i0.ɵɵtext(13, "10s");
1346
+ i0.ɵɵelementEnd();
1347
+ i0.ɵɵelementStart(14, "option", 7);
1348
+ i0.ɵɵtext(15, "30s");
1349
+ i0.ɵɵelementEnd();
1350
+ i0.ɵɵelementStart(16, "option", 7);
1351
+ i0.ɵɵtext(17, "1m");
1352
+ i0.ɵɵelementEnd();
1353
+ i0.ɵɵelementStart(18, "option", 7);
1354
+ i0.ɵɵtext(19, "5m");
1355
+ i0.ɵɵelementEnd()()();
1356
+ i0.ɵɵelementStart(20, "div", 8)(21, "label");
1357
+ i0.ɵɵtext(22, "Time Range:");
1358
+ i0.ɵɵelementEnd();
1359
+ i0.ɵɵelementStart(23, "select", 6);
1360
+ i0.ɵɵtwoWayListener("ngModelChange", function ExecutionMonitoringComponent_Template_select_ngModelChange_23_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.selectedTimeRange, $event) || (ctx.selectedTimeRange = $event); return $event; });
1361
+ i0.ɵɵlistener("change", function ExecutionMonitoringComponent_Template_select_change_23_listener() { return ctx.onTimeRangeChange(); });
1362
+ i0.ɵɵelementStart(24, "option", 9);
1363
+ i0.ɵɵtext(25, "Last Hour");
1364
+ i0.ɵɵelementEnd();
1365
+ i0.ɵɵelementStart(26, "option", 10);
1366
+ i0.ɵɵtext(27, "Last 6 Hours");
1367
+ i0.ɵɵelementEnd();
1368
+ i0.ɵɵelementStart(28, "option", 11);
1369
+ i0.ɵɵtext(29, "Last 24 Hours");
1370
+ i0.ɵɵelementEnd();
1371
+ i0.ɵɵelementStart(30, "option", 12);
1372
+ i0.ɵɵtext(31, "Last 7 Days");
1373
+ i0.ɵɵelementEnd();
1374
+ i0.ɵɵelementStart(32, "option", 13);
1375
+ i0.ɵɵtext(33, "Last 30 Days");
1376
+ i0.ɵɵelementEnd()()();
1377
+ i0.ɵɵelementStart(34, "button", 14);
1378
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Template_button_click_34_listener() { return ctx.refreshData(); });
1379
+ i0.ɵɵelement(35, "i", 15);
1380
+ i0.ɵɵtext(36, " Refresh ");
1381
+ i0.ɵɵelementEnd()()();
1382
+ i0.ɵɵelementStart(37, "div", 16)(38, "div", 17);
1383
+ i0.ɵɵrepeaterCreate(39, ExecutionMonitoringComponent_For_40_Template, 1, 3, "app-kpi-card", 18, _forTrack0);
1384
+ i0.ɵɵpipe(41, "async");
1385
+ i0.ɵɵelementEnd()();
1386
+ i0.ɵɵelementStart(42, "kendo-splitter", 19);
1387
+ i0.ɵɵlistener("layoutChange", function ExecutionMonitoringComponent_Template_kendo_splitter_layoutChange_42_listener($event) { return ctx.onSplitterLayoutChange($event); });
1388
+ i0.ɵɵelementStart(43, "kendo-splitter-pane", 20)(44, "kendo-splitter", 21);
1389
+ i0.ɵɵlistener("layoutChange", function ExecutionMonitoringComponent_Template_kendo_splitter_layoutChange_44_listener($event) { return ctx.onSplitterLayoutChange($event); });
1390
+ i0.ɵɵelementStart(45, "kendo-splitter-pane", 22)(46, "div", 23)(47, "div", 24)(48, "div", 25)(49, "h4", 26);
1391
+ i0.ɵɵelement(50, "i", 27);
1392
+ i0.ɵɵtext(51, " System Health ");
1393
+ i0.ɵɵelementEnd()();
1394
+ i0.ɵɵtemplate(52, ExecutionMonitoringComponent_Conditional_52_Template, 41, 6, "div", 28);
1395
+ i0.ɵɵpipe(53, "async");
1396
+ i0.ɵɵelementEnd()()();
1397
+ i0.ɵɵelementStart(54, "kendo-splitter-pane", 29)(55, "div", 30)(56, "div", 31)(57, "div", 32);
1398
+ i0.ɵɵrepeaterCreate(58, ExecutionMonitoringComponent_For_59_Template, 4, 4, "div", 33, _forTrack1);
1399
+ i0.ɵɵelementEnd();
1400
+ i0.ɵɵelementStart(60, "div", 34);
1401
+ i0.ɵɵtemplate(61, ExecutionMonitoringComponent_Conditional_61_Template, 3, 5, "div", 35)(62, ExecutionMonitoringComponent_Conditional_62_Template, 11, 4, "div", 36)(63, ExecutionMonitoringComponent_Conditional_63_Template, 7, 2, "div", 37);
1402
+ i0.ɵɵelementEnd()()()()()();
1403
+ i0.ɵɵelementStart(64, "kendo-splitter-pane", 29)(65, "kendo-splitter", 21);
1404
+ i0.ɵɵlistener("layoutChange", function ExecutionMonitoringComponent_Template_kendo_splitter_layoutChange_65_listener($event) { return ctx.onSplitterLayoutChange($event); });
1405
+ i0.ɵɵelementStart(66, "kendo-splitter-pane", 38)(67, "div", 39);
1406
+ i0.ɵɵelement(68, "app-performance-heatmap", 40);
1407
+ i0.ɵɵpipe(69, "async");
1408
+ i0.ɵɵelementEnd()();
1409
+ i0.ɵɵelementStart(70, "kendo-splitter-pane", 29)(71, "div", 41)(72, "div", 42)(73, "div", 43);
1410
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Template_div_click_73_listener() { return ctx.togglePanel("cost"); });
1411
+ i0.ɵɵelementStart(74, "span", 44);
1412
+ i0.ɵɵelement(75, "i", 45);
1413
+ i0.ɵɵtext(76, " Cost Analysis ");
1414
+ i0.ɵɵelementEnd();
1415
+ i0.ɵɵelement(77, "i", 46);
1416
+ i0.ɵɵelementEnd();
1417
+ i0.ɵɵtemplate(78, ExecutionMonitoringComponent_Conditional_78_Template, 3, 3, "div", 47);
1418
+ i0.ɵɵelementEnd();
1419
+ i0.ɵɵelementStart(79, "div", 42)(80, "div", 43);
1420
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Template_div_click_80_listener() { return ctx.togglePanel("efficiency"); });
1421
+ i0.ɵɵelementStart(81, "span", 44);
1422
+ i0.ɵɵelement(82, "i", 48);
1423
+ i0.ɵɵtext(83, " Token Efficiency ");
1424
+ i0.ɵɵelementEnd();
1425
+ i0.ɵɵelement(84, "i", 46);
1426
+ i0.ɵɵelementEnd();
1427
+ i0.ɵɵtemplate(85, ExecutionMonitoringComponent_Conditional_85_Template, 3, 3, "div", 47);
1428
+ i0.ɵɵelementEnd();
1429
+ i0.ɵɵelementStart(86, "div", 42)(87, "div", 43);
1430
+ i0.ɵɵlistener("click", function ExecutionMonitoringComponent_Template_div_click_87_listener() { return ctx.togglePanel("executions"); });
1431
+ i0.ɵɵelementStart(88, "span", 44);
1432
+ i0.ɵɵelement(89, "i", 49);
1433
+ i0.ɵɵtext(90, " Live Executions ");
1434
+ i0.ɵɵelementEnd();
1435
+ i0.ɵɵelement(91, "i", 46);
1436
+ i0.ɵɵelementEnd();
1437
+ i0.ɵɵtemplate(92, ExecutionMonitoringComponent_Conditional_92_Template, 3, 4, "div", 50);
1438
+ i0.ɵɵelementEnd()()()()()();
1439
+ i0.ɵɵtemplate(93, ExecutionMonitoringComponent_Conditional_93_Template, 14, 2, "div", 51);
1440
+ i0.ɵɵelementEnd();
1441
+ } if (rf & 2) {
1442
+ let tmp_15_0;
1443
+ let tmp_26_0;
1444
+ i0.ɵɵadvance(9);
1445
+ i0.ɵɵtwoWayProperty("ngModel", ctx.refreshInterval);
1446
+ i0.ɵɵadvance();
1447
+ i0.ɵɵproperty("value", 0);
1448
+ i0.ɵɵadvance(2);
1449
+ i0.ɵɵproperty("value", 10000);
1450
+ i0.ɵɵadvance(2);
1451
+ i0.ɵɵproperty("value", 30000);
1452
+ i0.ɵɵadvance(2);
1453
+ i0.ɵɵproperty("value", 60000);
1454
+ i0.ɵɵadvance(2);
1455
+ i0.ɵɵproperty("value", 300000);
1456
+ i0.ɵɵadvance(5);
1457
+ i0.ɵɵtwoWayProperty("ngModel", ctx.selectedTimeRange);
1458
+ i0.ɵɵadvance(11);
1459
+ i0.ɵɵproperty("disabled", ctx.isLoading);
1460
+ i0.ɵɵadvance();
1461
+ i0.ɵɵclassProp("spinning", ctx.isLoading);
1462
+ i0.ɵɵadvance(4);
1463
+ i0.ɵɵrepeater(i0.ɵɵpipeBind1(41, 45, ctx.kpiCards$));
1464
+ i0.ɵɵadvance(4);
1465
+ i0.ɵɵproperty("resizable", true)("collapsible", false);
1466
+ i0.ɵɵadvance(2);
1467
+ i0.ɵɵproperty("resizable", true)("collapsible", true)("collapsed", false);
1468
+ i0.ɵɵadvance(7);
1469
+ i0.ɵɵconditional((tmp_15_0 = i0.ɵɵpipeBind1(53, 47, ctx.kpis$)) ? 52 : -1, tmp_15_0);
1470
+ i0.ɵɵadvance(2);
1471
+ i0.ɵɵproperty("resizable", true)("collapsible", false);
1472
+ i0.ɵɵadvance(4);
1473
+ i0.ɵɵrepeater(ctx.drillDownTabs);
1474
+ i0.ɵɵadvance(3);
1475
+ i0.ɵɵconditional((ctx.activeTab == null ? null : ctx.activeTab.type) === "chart" ? 61 : -1);
1476
+ i0.ɵɵadvance();
1477
+ i0.ɵɵconditional((ctx.activeTab == null ? null : ctx.activeTab.type) === "executions" ? 62 : -1);
1478
+ i0.ɵɵadvance();
1479
+ i0.ɵɵconditional((ctx.activeTab == null ? null : ctx.activeTab.type) === "model-detail" ? 63 : -1);
1480
+ i0.ɵɵadvance();
1481
+ i0.ɵɵproperty("resizable", true)("collapsible", false);
1482
+ i0.ɵɵadvance(2);
1483
+ i0.ɵɵproperty("resizable", true)("collapsible", false);
1484
+ i0.ɵɵadvance(2);
1485
+ i0.ɵɵproperty("data", (tmp_26_0 = i0.ɵɵpipeBind1(69, 49, ctx.performanceMatrix$)) !== null && tmp_26_0 !== undefined ? tmp_26_0 : i0.ɵɵpureFunction0(51, _c0))("config", ctx.heatmapConfig);
1486
+ i0.ɵɵadvance(2);
1487
+ i0.ɵɵproperty("resizable", true)("collapsible", false);
1488
+ i0.ɵɵadvance(7);
1489
+ i0.ɵɵclassProp("fa-chevron-down", !ctx.panelStates.cost)("fa-chevron-up", ctx.panelStates.cost);
1490
+ i0.ɵɵadvance();
1491
+ i0.ɵɵconditional(ctx.panelStates.cost ? 78 : -1);
1492
+ i0.ɵɵadvance(6);
1493
+ i0.ɵɵclassProp("fa-chevron-down", !ctx.panelStates.efficiency)("fa-chevron-up", ctx.panelStates.efficiency);
1494
+ i0.ɵɵadvance();
1495
+ i0.ɵɵconditional(ctx.panelStates.efficiency ? 85 : -1);
1496
+ i0.ɵɵadvance(6);
1497
+ i0.ɵɵclassProp("fa-chevron-down", !ctx.panelStates.executions)("fa-chevron-up", ctx.panelStates.executions);
1498
+ i0.ɵɵadvance();
1499
+ i0.ɵɵconditional(ctx.panelStates.executions ? 92 : -1);
1500
+ i0.ɵɵadvance();
1501
+ i0.ɵɵconditional(ctx.selectedExecution ? 93 : -1);
1502
+ } }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.SplitterComponent, i3.SplitterPaneComponent, i4.KPICardComponent, i5.LiveExecutionWidgetComponent, i6.TimeSeriesChartComponent, i7.PerformanceHeatmapComponent, i8.AsyncPipe, i8.TitleCasePipe, i8.DatePipe], styles: [".execution-monitoring[_ngcontent-%COMP%] {\n padding: 20px;\n background: #f8f9fa;\n min-height: 100vh;\n }\n\n .monitoring-header[_ngcontent-%COMP%] {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n margin-bottom: 20px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n }\n\n .monitoring-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .monitoring-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .monitoring-controls[_ngcontent-%COMP%] {\n display: flex;\n gap: 16px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .refresh-control[_ngcontent-%COMP%], .time-range-control[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n }\n\n .refresh-control[_ngcontent-%COMP%] label[_ngcontent-%COMP%], .time-range-control[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n color: #666;\n font-weight: 500;\n }\n\n .refresh-control[_ngcontent-%COMP%] select[_ngcontent-%COMP%], .time-range-control[_ngcontent-%COMP%] select[_ngcontent-%COMP%] {\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n background: white;\n }\n\n .refresh-btn[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: background 0.2s ease;\n }\n\n .refresh-btn[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: #1976d2;\n }\n\n .refresh-btn[_ngcontent-%COMP%]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .refresh-btn[_ngcontent-%COMP%] i.spinning[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n }\n\n @keyframes _ngcontent-%COMP%_spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .kpi-dashboard[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n }\n\n .kpi-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n gap: 16px;\n }\n\n .dashboard-splitter[_ngcontent-%COMP%] {\n height: calc(100vh - 550px); \n\n min-height: 600px;\n margin-bottom: 20px;\n }\n\n .dashboard-section[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n \n\n [_nghost-%COMP%] .k-splitter-pane {\n overflow: hidden;\n }\n\n [_nghost-%COMP%] .k-splitter .k-splitter-pane {\n padding: 10px;\n }\n\n [_nghost-%COMP%] .k-splitter-horizontal > .k-splitter-pane {\n padding: 10px 5px;\n }\n\n [_nghost-%COMP%] .k-splitter-vertical > .k-splitter-pane {\n padding: 5px 10px;\n }\n\n \n\n .cost-chart-container[_ngcontent-%COMP%], .efficiency-chart-container[_ngcontent-%COMP%], .status-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .chart-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n }\n\n .chart-title[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .chart-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .cost-bars[_ngcontent-%COMP%], .efficiency-items[_ngcontent-%COMP%] {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .cost-bar-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .cost-bar-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n }\n\n .cost-bar-info[_ngcontent-%COMP%] {\n min-width: 120px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .model-name[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #333;\n }\n\n .cost-value[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #ff9800;\n font-weight: 600;\n }\n\n .cost-bar-container[_ngcontent-%COMP%] {\n flex: 1;\n height: 8px;\n background: #f0f0f0;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .cost-bar[_ngcontent-%COMP%] {\n height: 100%;\n background: linear-gradient(90deg, #ff9800, #f57c00);\n border-radius: 4px;\n transition: width 0.3s ease;\n }\n\n .token-info[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #666;\n min-width: 80px;\n text-align: right;\n }\n\n \n\n .efficiency-item[_ngcontent-%COMP%] {\n padding: 12px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .efficiency-item[_ngcontent-%COMP%]:last-child {\n border-bottom: none;\n }\n\n .efficiency-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n }\n\n .efficiency-ratio[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #2196f3;\n font-weight: 600;\n }\n\n .token-breakdown[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .token-bar[_ngcontent-%COMP%] {\n height: 6px;\n background: #f0f0f0;\n border-radius: 3px;\n overflow: hidden;\n display: flex;\n }\n\n .token-segment[_ngcontent-%COMP%] {\n height: 100%;\n }\n\n .token-segment--input[_ngcontent-%COMP%] {\n background: #4caf50;\n }\n\n .token-segment--output[_ngcontent-%COMP%] {\n background: #2196f3;\n }\n\n .token-labels[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n font-size: 10px;\n color: #666;\n }\n\n .input-label[_ngcontent-%COMP%] {\n color: #4caf50;\n }\n\n .output-label[_ngcontent-%COMP%] {\n color: #2196f3;\n }\n\n .cost-per-token[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n }\n\n \n\n .status-metrics[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 16px;\n flex: 1;\n }\n\n .status-metric[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: #f8f9fa;\n border-radius: 6px;\n }\n\n .status-icon[_ngcontent-%COMP%] {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .status-icon--success[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .status-icon--warning[_ngcontent-%COMP%] {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n }\n\n .status-icon--info[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .status-icon--primary[_ngcontent-%COMP%] {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n\n .status-info[_ngcontent-%COMP%] {\n flex: 1;\n }\n\n .status-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #666;\n font-weight: 500;\n }\n\n .status-value[_ngcontent-%COMP%] {\n font-size: 18px;\n font-weight: 700;\n color: #333;\n margin: 2px 0;\n }\n\n .status-subtitle[_ngcontent-%COMP%] {\n font-size: 10px;\n color: #999;\n }\n\n \n\n .execution-modal[_ngcontent-%COMP%] {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 20px;\n }\n\n .execution-modal-content[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n max-width: 800px;\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .execution-modal-header[_ngcontent-%COMP%] {\n padding: 20px;\n border-bottom: 1px solid #f0f0f0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .execution-modal-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n }\n\n .modal-header-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .open-record-btn[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n }\n\n .open-record-btn[_ngcontent-%COMP%]:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.3);\n }\n\n .open-record-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n .close-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n font-size: 16px;\n color: #999;\n cursor: pointer;\n padding: 4px;\n }\n\n .close-btn[_ngcontent-%COMP%]:hover {\n color: #333;\n }\n\n .execution-modal-body[_ngcontent-%COMP%] {\n padding: 20px;\n overflow-y: auto;\n flex: 1;\n }\n\n .execution-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 20px;\n }\n\n .detail-section[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 6px;\n }\n\n .detail-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n }\n\n .detail-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .detail-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .detail-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #333;\n }\n\n .status-badge[_ngcontent-%COMP%] {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .status-badge--completed[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .status-badge--running[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .status-badge--failed[_ngcontent-%COMP%] {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n .error-message[_ngcontent-%COMP%] {\n background: #fff3e0;\n border: 1px solid #ffcc02;\n border-radius: 4px;\n padding: 12px;\n font-size: 12px;\n color: #e65100;\n font-family: monospace;\n }\n\n .child-executions[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .child-execution[_ngcontent-%COMP%] {\n background: #f8f9fa;\n border-radius: 4px;\n padding: 12px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .child-info[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .child-name[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 500;\n color: #333;\n }\n\n .child-type[_ngcontent-%COMP%] {\n font-size: 10px;\n background: #e0e0e0;\n padding: 2px 6px;\n border-radius: 3px;\n color: #666;\n }\n\n .child-status[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 3px;\n }\n\n .child-metrics[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n font-size: 11px;\n color: #666;\n }\n\n .loading-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n gap: 12px;\n }\n\n .spinner[_ngcontent-%COMP%] {\n width: 32px;\n height: 32px;\n border: 3px solid #f3f3f3;\n border-top: 3px solid #2196f3;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_spin 1s linear infinite;\n }\n\n \n\n .drill-down-container[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .drill-down-tabs[_ngcontent-%COMP%] {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .tab-header[_ngcontent-%COMP%] {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n background: #f8f9fa;\n min-height: 40px;\n overflow-x: auto;\n }\n\n .tab-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f8f9fa;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: #666;\n white-space: nowrap;\n transition: all 0.2s ease;\n min-width: 120px;\n justify-content: space-between;\n }\n\n .tab-item[_ngcontent-%COMP%]:hover {\n background: #e9ecef;\n color: #333;\n }\n\n .tab-item.active[_ngcontent-%COMP%] {\n background: white;\n color: #2196f3;\n border-bottom-color: #2196f3;\n }\n\n .tab-title[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .tab-close[_ngcontent-%COMP%] {\n background: none;\n border: none;\n color: #999;\n cursor: pointer;\n padding: 2px;\n border-radius: 2px;\n font-size: 10px;\n width: 16px;\n height: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n }\n\n .tab-close[_ngcontent-%COMP%]:hover {\n background: rgba(0, 0, 0, 0.1);\n color: #333;\n }\n\n .tab-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .tab-pane[_ngcontent-%COMP%] {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .trends-chart[_ngcontent-%COMP%] {\n padding: 0;\n }\n\n .trends-chart[_ngcontent-%COMP%] app-time-series-chart[_ngcontent-%COMP%] {\n height: 100%;\n display: block;\n overflow: hidden;\n }\n\n \n\n .tab-pane.trends-chart[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n \n\n .executions-drill-down[_ngcontent-%COMP%] {\n padding: 20px;\n overflow-y: auto;\n }\n\n .drill-down-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 12px;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .drill-down-header[_ngcontent-%COMP%] h4[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .drill-down-meta[_ngcontent-%COMP%] {\n display: flex;\n gap: 12px;\n align-items: center;\n font-size: 12px;\n }\n\n .timestamp[_ngcontent-%COMP%] {\n color: #666;\n background: #f0f0f0;\n padding: 4px 8px;\n border-radius: 4px;\n }\n\n .metric-badge[_ngcontent-%COMP%] {\n background: #2196f3;\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-weight: 500;\n }\n\n .loading-spinner[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n gap: 12px;\n }\n\n .executions-table[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .table-header[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 80px 1fr 120px 100px 100px 80px 100px 120px;\n gap: 12px;\n background: #f8f9fa;\n padding: 12px 16px;\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .table-row[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 80px 1fr 120px 100px 100px 80px 100px 120px;\n gap: 12px;\n padding: 12px 16px;\n border-top: 1px solid #f0f0f0;\n cursor: pointer;\n transition: background 0.2s ease;\n align-items: center;\n }\n\n .table-row[_ngcontent-%COMP%]:hover {\n background: #f8f9fa;\n }\n\n .table-cell[_ngcontent-%COMP%] {\n font-size: 12px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .type-badge[_ngcontent-%COMP%] {\n background: #e9ecef;\n color: #666;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .type-badge--prompt[_ngcontent-%COMP%] {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .type-badge--agent[_ngcontent-%COMP%] {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .no-data[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: #999;\n gap: 16px;\n }\n\n .no-data[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n color: #ddd;\n }\n\n .no-data[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n }\n\n \n\n .model-detail[_ngcontent-%COMP%] {\n padding: 20px;\n overflow-y: auto;\n }\n\n .model-details[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n\n .model-info-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 16px;\n }\n\n .info-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 16px;\n background: #f8f9fa;\n border-radius: 6px;\n }\n\n .info-item[_ngcontent-%COMP%] label[_ngcontent-%COMP%] {\n font-size: 11px;\n color: #666;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0;\n }\n\n .info-item[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #333;\n font-weight: 500;\n }\n\n .status-indicator[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n }\n\n .status-indicator.active[_ngcontent-%COMP%] {\n color: #4caf50;\n }\n\n .status-indicator.active[_ngcontent-%COMP%]::before {\n content: '';\n width: 6px;\n height: 6px;\n background: #4caf50;\n border-radius: 50%;\n }\n\n .model-description[_ngcontent-%COMP%] {\n padding: 20px;\n background: #f8f9fa;\n border-radius: 8px;\n }\n\n .model-description[_ngcontent-%COMP%] h5[_ngcontent-%COMP%] {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n }\n\n .model-description[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n }\n\n \n\n .clickable[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .clickable[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n \n\n .analysis-panels[_ngcontent-%COMP%] {\n padding: 10px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n }\n\n .analysis-panel[_ngcontent-%COMP%] {\n margin-bottom: 12px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n background: white;\n overflow: hidden;\n }\n\n .analysis-panel[_ngcontent-%COMP%]:last-child {\n margin-bottom: 0;\n }\n\n .panel-header[_ngcontent-%COMP%] {\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n cursor: pointer;\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: background 0.2s ease;\n }\n\n .panel-header[_ngcontent-%COMP%]:hover {\n background: #e9ecef;\n }\n\n .panel-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n color: #333;\n font-size: 14px;\n }\n\n .panel-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: #2196f3;\n width: 16px;\n }\n\n .panel-toggle-icon[_ngcontent-%COMP%] {\n color: #666;\n font-size: 12px;\n transition: transform 0.2s ease;\n }\n\n .panel-content[_ngcontent-%COMP%] {\n padding: 16px;\n border-top: 1px solid #f0f0f0;\n animation: _ngcontent-%COMP%_slideDown 0.2s ease-out;\n }\n\n @keyframes _ngcontent-%COMP%_slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 500px;\n }\n }\n\n .live-executions-panel[_ngcontent-%COMP%] {\n padding: 0;\n }\n\n .live-executions-panel[_ngcontent-%COMP%] app-live-execution-widget[_ngcontent-%COMP%] {\n height: 300px;\n display: block;\n }\n\n \n\n @media (max-width: 1200px) {\n .dashboard-splitter[_ngcontent-%COMP%] {\n height: calc(100vh - 270px); \n\n margin-bottom: 20px;\n }\n \n .table-header[_ngcontent-%COMP%], \n .table-row[_ngcontent-%COMP%] {\n grid-template-columns: 60px 1fr 100px 80px 80px 60px 80px 100px;\n gap: 8px;\n }\n \n .model-info-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .analysis-panels[_ngcontent-%COMP%] {\n padding: 8px;\n }\n \n .analysis-panel[_ngcontent-%COMP%] {\n margin-bottom: 8px;\n }\n }\n\n @media (max-width: 768px) {\n .execution-monitoring[_ngcontent-%COMP%] {\n padding: 12px;\n }\n \n .monitoring-header[_ngcontent-%COMP%] {\n flex-direction: column;\n align-items: flex-start;\n }\n \n .monitoring-controls[_ngcontent-%COMP%] {\n width: 100%;\n justify-content: flex-start;\n }\n \n .dashboard-splitter[_ngcontent-%COMP%] {\n height: calc(100vh - 270px); \n\n min-height: 400px;\n margin-bottom: 20px;\n }\n \n .kpi-grid[_ngcontent-%COMP%] {\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n }\n\n \n\n [_nghost-%COMP%] .k-splitter .k-splitter-pane {\n padding: 5px;\n }\n\n [_nghost-%COMP%] .k-splitter-horizontal > .k-splitter-pane {\n padding: 5px 2px;\n }\n\n [_nghost-%COMP%] .k-splitter-vertical > .k-splitter-pane {\n padding: 2px 5px;\n }\n \n .tab-header[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n \n .tab-item[_ngcontent-%COMP%] {\n min-width: 100px;\n padding: 6px 12px;\n }\n \n .table-header[_ngcontent-%COMP%], \n .table-row[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n gap: 4px;\n text-align: left;\n }\n \n .table-row[_ngcontent-%COMP%] {\n display: block;\n padding: 16px;\n }\n \n .table-cell[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 8px;\n }\n \n .table-cell[_ngcontent-%COMP%]:before {\n content: attr(data-label) ': ';\n font-weight: 600;\n color: #666;\n font-size: 11px;\n text-transform: uppercase;\n }\n \n .executions-drill-down[_ngcontent-%COMP%], \n .model-detail[_ngcontent-%COMP%] {\n padding: 12px;\n }\n \n .panel-content[_ngcontent-%COMP%] {\n padding: 12px;\n }\n \n .panel-header[_ngcontent-%COMP%] {\n padding: 10px 12px;\n }\n \n .panel-title[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n }"] });
10
1503
  }
11
- ExecutionMonitoringComponent.ɵfac = function ExecutionMonitoringComponent_Factory(t) { return new (t || ExecutionMonitoringComponent)(); };
12
- ExecutionMonitoringComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ExecutionMonitoringComponent, selectors: [["app-execution-monitoring"]], outputs: { openEntityRecord: "openEntityRecord" }, decls: 9, vars: 0, consts: [[1, "execution-monitoring"], [1, "header"], [1, "content"]], template: function ExecutionMonitoringComponent_Template(rf, ctx) { if (rf & 1) {
13
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h3");
14
- i0.ɵɵtext(3, "Execution Monitoring");
15
- i0.ɵɵelementEnd();
16
- i0.ɵɵelementStart(4, "p");
17
- i0.ɵɵtext(5, "Monitor AI agent execution and performance");
18
- i0.ɵɵelementEnd()();
19
- i0.ɵɵelementStart(6, "div", 2)(7, "p");
20
- i0.ɵɵtext(8, "Execution monitoring interface will be implemented here.");
21
- i0.ɵɵelementEnd()()();
22
- } }, styles: [".execution-monitoring[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n display: flex;\n flex-direction: column;\n\n .header {\n margin-bottom: 20px;\n \n h3 {\n margin: 0 0 8px 0;\n color: #2c3e50;\n font-size: 1.4rem;\n font-weight: 600;\n }\n \n p {\n margin: 0;\n color: #7f8c8d;\n font-size: 0.9rem;\n }\n }\n\n .content {\n flex: 1;\n background: #f8f9fa;\n border-radius: 8px;\n padding: 20px;\n border: 1px solid #e9ecef;\n }\n}"] });
23
1504
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ExecutionMonitoringComponent, [{
24
1505
  type: Component,
25
- args: [{ selector: 'app-execution-monitoring', template: "<div class=\"execution-monitoring\">\n <div class=\"header\">\n <h3>Execution Monitoring</h3>\n <p>Monitor AI agent execution and performance</p>\n </div>\n \n <div class=\"content\">\n <p>Execution monitoring interface will be implemented here.</p>\n </div>\n</div>", styles: [".execution-monitoring {\n padding: 20px;\n height: 100%;\n display: flex;\n flex-direction: column;\n\n .header {\n margin-bottom: 20px;\n \n h3 {\n margin: 0 0 8px 0;\n color: #2c3e50;\n font-size: 1.4rem;\n font-weight: 600;\n }\n \n p {\n margin: 0;\n color: #7f8c8d;\n font-size: 0.9rem;\n }\n }\n\n .content {\n flex: 1;\n background: #f8f9fa;\n border-radius: 8px;\n padding: 20px;\n border: 1px solid #e9ecef;\n }\n}"] }]
26
- }], () => [], { openEntityRecord: [{
1506
+ args: [{ selector: 'app-execution-monitoring', template: `
1507
+ <div class="execution-monitoring">
1508
+ <!-- Header Controls -->
1509
+ <div class="monitoring-header">
1510
+ <h2 class="monitoring-title">
1511
+ <i class="fa-solid fa-chart-line"></i>
1512
+ AI Execution Monitoring
1513
+ </h2>
1514
+
1515
+ <div class="monitoring-controls">
1516
+ <div class="refresh-control">
1517
+ <label>Refresh:</label>
1518
+ <select [(ngModel)]="refreshInterval" (change)="onRefreshIntervalChange()">
1519
+ <option [value]="0">Manual</option>
1520
+ <option [value]="10000">10s</option>
1521
+ <option [value]="30000">30s</option>
1522
+ <option [value]="60000">1m</option>
1523
+ <option [value]="300000">5m</option>
1524
+ </select>
1525
+ </div>
1526
+
1527
+ <div class="time-range-control">
1528
+ <label>Time Range:</label>
1529
+ <select [(ngModel)]="selectedTimeRange" (change)="onTimeRangeChange()">
1530
+ <option value="1h">Last Hour</option>
1531
+ <option value="6h">Last 6 Hours</option>
1532
+ <option value="24h">Last 24 Hours</option>
1533
+ <option value="7d">Last 7 Days</option>
1534
+ <option value="30d">Last 30 Days</option>
1535
+ </select>
1536
+ </div>
1537
+
1538
+ <button class="refresh-btn" (click)="refreshData()" [disabled]="isLoading">
1539
+ <i class="fa-solid fa-refresh" [class.spinning]="isLoading"></i>
1540
+ Refresh
1541
+ </button>
1542
+ </div>
1543
+ </div>
1544
+
1545
+ <!-- KPI Dashboard -->
1546
+ <div class="kpi-dashboard">
1547
+ <div class="kpi-grid">
1548
+ @for (kpi of kpiCards$ | async; track kpi.title) {
1549
+ <app-kpi-card
1550
+ [data]="kpi"
1551
+ (click)="onKpiClick(kpi)"
1552
+ [class.clickable]="isKpiClickable(kpi)"
1553
+ ></app-kpi-card>
1554
+ }
1555
+ </div>
1556
+ </div>
1557
+
1558
+ <!-- Main Dashboard with Kendo Splitter -->
1559
+ <kendo-splitter class="dashboard-splitter" orientation="vertical" (layoutChange)="onSplitterLayoutChange($event)">
1560
+ <!-- Top Row: System Health and Trends Chart -->
1561
+ <kendo-splitter-pane size="45%" [resizable]="true" [collapsible]="false">
1562
+ <kendo-splitter orientation="horizontal" (layoutChange)="onSplitterLayoutChange($event)">
1563
+ <!-- System Health -->
1564
+ <kendo-splitter-pane size="30%" [resizable]="true" [collapsible]="true" [collapsed]="false">
1565
+ <div class="dashboard-section system-status">
1566
+ <div class="status-container">
1567
+ <div class="chart-header">
1568
+ <h4 class="chart-title">
1569
+ <i class="fa-solid fa-heartbeat"></i>
1570
+ System Health
1571
+ </h4>
1572
+ </div>
1573
+ @if (kpis$ | async; as kpis) {
1574
+ <div class="status-metrics">
1575
+ <div class="status-metric">
1576
+ <div class="status-icon status-icon--success">
1577
+ <i class="fa-solid fa-check"></i>
1578
+ </div>
1579
+ <div class="status-info">
1580
+ <div class="status-label">Success Rate</div>
1581
+ <div class="status-value">{{ (kpis.successRate * 100).toFixed(1) }}%</div>
1582
+ <div class="status-subtitle">Last {{ selectedTimeRange }}</div>
1583
+ </div>
1584
+ </div>
1585
+
1586
+ <div class="status-metric">
1587
+ <div class="status-icon status-icon--warning">
1588
+ <i class="fa-solid fa-exclamation-triangle"></i>
1589
+ </div>
1590
+ <div class="status-info">
1591
+ <div class="status-label">Error Rate</div>
1592
+ <div class="status-value">{{ (kpis.errorRate * 100).toFixed(1) }}%</div>
1593
+ <div class="status-subtitle">{{ kpis.totalExecutions }} total executions</div>
1594
+ </div>
1595
+ </div>
1596
+
1597
+ <div class="status-metric">
1598
+ <div class="status-icon status-icon--info">
1599
+ <i class="fa-solid fa-clock"></i>
1600
+ </div>
1601
+ <div class="status-info">
1602
+ <div class="status-label">Avg Response Time</div>
1603
+ <div class="status-value">{{ (kpis.avgExecutionTime / 1000).toFixed(2) }}s</div>
1604
+ <div class="status-subtitle">Across all models</div>
1605
+ </div>
1606
+ </div>
1607
+
1608
+ <div class="status-metric">
1609
+ <div class="status-icon status-icon--primary">
1610
+ <i class="fa-solid fa-bolt"></i>
1611
+ </div>
1612
+ <div class="status-info">
1613
+ <div class="status-label">Active Executions</div>
1614
+ <div class="status-value">{{ kpis.activeExecutions }}</div>
1615
+ <div class="status-subtitle">Currently running</div>
1616
+ </div>
1617
+ </div>
1618
+ </div>
1619
+ }
1620
+ </div>
1621
+ </div>
1622
+ </kendo-splitter-pane>
1623
+
1624
+ <!-- Drill-down Tab Container -->
1625
+ <kendo-splitter-pane [resizable]="true" [collapsible]="false">
1626
+ <div class="dashboard-section drill-down-container">
1627
+ <div class="drill-down-tabs">
1628
+ <div class="tab-header">
1629
+ @for (tab of drillDownTabs; track tab.id) {
1630
+ <div
1631
+ class="tab-item"
1632
+ [class.active]="activeTabId === tab.id"
1633
+ (click)="selectTab(tab.id)"
1634
+ >
1635
+ <span class="tab-title">{{ tab.title }}</span>
1636
+ @if (tab.closeable) {
1637
+ <button
1638
+ class="tab-close"
1639
+ (click)="closeTab($event, tab.id)"
1640
+ title="Close tab"
1641
+ >
1642
+ <i class="fa-solid fa-times"></i>
1643
+ </button>
1644
+ }
1645
+ </div>
1646
+ }
1647
+ </div>
1648
+
1649
+ <div class="tab-content">
1650
+ @if (activeTab?.type === 'chart') {
1651
+ <div class="tab-pane trends-chart">
1652
+ <app-time-series-chart
1653
+ [data]="(trends$ | async) ?? []"
1654
+ title="Execution Trends"
1655
+ [config]="timeSeriesConfig"
1656
+ (dataPointClick)="onDataPointClick($event)"
1657
+ (timeRangeChange)="onChartTimeRangeChange($event)"
1658
+ ></app-time-series-chart>
1659
+ </div>
1660
+ }
1661
+
1662
+ @if (activeTab?.type === 'executions') {
1663
+ <div class="tab-pane executions-drill-down">
1664
+ <div class="drill-down-header">
1665
+ <h4>
1666
+ <i class="fa-solid fa-list"></i>
1667
+ {{ activeTab?.title }}
1668
+ </h4>
1669
+ <div class="drill-down-meta">
1670
+ @if (activeTab?.timestamp) {
1671
+ <span class="timestamp">{{ getFormattedTimestamp(activeTab) }}</span>
1672
+ }
1673
+ @if (activeTab?.metric) {
1674
+ <span class="metric-badge">{{ getFormattedMetricLabel(activeTab) }}</span>
1675
+ }
1676
+ </div>
1677
+ </div>
1678
+
1679
+ @if (loadingDrillDown) {
1680
+ <div class="loading-spinner">
1681
+ <i class="fa-solid fa-spinner fa-spin"></i>
1682
+ Loading execution details...
1683
+ </div>
1684
+ } @else if (activeTab?.data?.length > 0) {
1685
+ <div class="executions-table">
1686
+ <div class="table-header">
1687
+ <div class="header-cell">Type</div>
1688
+ <div class="header-cell">Name</div>
1689
+ <div class="header-cell">Model</div>
1690
+ <div class="header-cell">Status</div>
1691
+ <div class="header-cell">Duration</div>
1692
+ <div class="header-cell">Cost</div>
1693
+ <div class="header-cell">Tokens</div>
1694
+ <div class="header-cell">Time</div>
1695
+ </div>
1696
+ @for (execution of activeTab?.data; track execution.id) {
1697
+ <div
1698
+ class="table-row"
1699
+ (click)="viewExecutionDetail(execution)"
1700
+ >
1701
+ <div class="table-cell">
1702
+ <span class="type-badge" [class]="'type-badge--' + execution.type">
1703
+ {{ execution.type }}
1704
+ </span>
1705
+ </div>
1706
+ <div class="table-cell">{{ execution.name }}</div>
1707
+ <div class="table-cell">{{ execution.model || 'N/A' }}</div>
1708
+ <div class="table-cell">
1709
+ <span class="status-badge" [class]="'status-badge--' + execution.status">
1710
+ {{ execution.status }}
1711
+ </span>
1712
+ </div>
1713
+ <div class="table-cell">{{ formatDuration(execution.duration) }}</div>
1714
+ <div class="table-cell">{{ formatCurrency(execution.cost) }}</div>
1715
+ <div class="table-cell">{{ execution.tokens.toLocaleString() }}</div>
1716
+ <div class="table-cell">{{ formatTime(execution.startTime) }}</div>
1717
+ </div>
1718
+ }
1719
+ </div>
1720
+ } @else {
1721
+ <div class="no-data">
1722
+ <i class="fa-solid fa-inbox"></i>
1723
+ <p>No executions found for this time period</p>
1724
+ </div>
1725
+ }
1726
+ </div>
1727
+ }
1728
+
1729
+ @if (activeTab?.type === 'model-detail') {
1730
+ <div class="tab-pane model-detail">
1731
+ <div class="drill-down-header">
1732
+ <h4>
1733
+ <i class="fa-solid fa-microchip"></i>
1734
+ Model Details: {{ activeTab?.data?.name }}
1735
+ </h4>
1736
+ </div>
1737
+
1738
+ @if (loadingDrillDown) {
1739
+ <div class="loading-spinner">
1740
+ <i class="fa-solid fa-spinner fa-spin"></i>
1741
+ Loading model details...
1742
+ </div>
1743
+ } @else if (activeTab?.data) {
1744
+ <div class="model-details">
1745
+ <div class="model-info-grid">
1746
+ <div class="info-item">
1747
+ <label>Model Name:</label>
1748
+ <span>{{ activeTab?.data?.name }}</span>
1749
+ </div>
1750
+ <div class="info-item">
1751
+ <label>Vendor:</label>
1752
+ <span>{{ activeTab?.data?.vendor }}</span>
1753
+ </div>
1754
+ <div class="info-item">
1755
+ <label>API Name:</label>
1756
+ <span>{{ activeTab?.data?.apiName }}</span>
1757
+ </div>
1758
+ <div class="info-item">
1759
+ <label>Input Cost:</label>
1760
+ <span>\${{ activeTab?.data?.inputTokenCost?.toFixed(6) || '0' }} per token</span>
1761
+ </div>
1762
+ <div class="info-item">
1763
+ <label>Output Cost:</label>
1764
+ <span>\${{ activeTab?.data?.outputTokenCost?.toFixed(6) || '0' }} per token</span>
1765
+ </div>
1766
+ <div class="info-item">
1767
+ <label>Active:</label>
1768
+ <span class="status-indicator" [class.active]="activeTab?.data?.isActive">
1769
+ {{ activeTab?.data?.isActive ? 'Yes' : 'No' }}
1770
+ </span>
1771
+ </div>
1772
+ </div>
1773
+
1774
+ @if (activeTab?.data?.description) {
1775
+ <div class="model-description">
1776
+ <h5>Description</h5>
1777
+ <p>{{ activeTab?.data?.description }}</p>
1778
+ </div>
1779
+ }
1780
+ </div>
1781
+ }
1782
+ </div>
1783
+ }
1784
+ </div>
1785
+ </div>
1786
+ </div>
1787
+ </kendo-splitter-pane>
1788
+ </kendo-splitter>
1789
+ </kendo-splitter-pane>
1790
+
1791
+ <!-- Bottom Row: Analysis Panels with Expansion Layout -->
1792
+ <kendo-splitter-pane [resizable]="true" [collapsible]="false">
1793
+ <kendo-splitter orientation="horizontal" (layoutChange)="onSplitterLayoutChange($event)">
1794
+ <!-- Left: Performance Heatmap -->
1795
+ <kendo-splitter-pane size="50%" [resizable]="true" [collapsible]="false">
1796
+ <div class="dashboard-section performance-matrix">
1797
+ <app-performance-heatmap
1798
+ [data]="(performanceMatrix$ | async) ?? []"
1799
+ title="Agent vs Model Performance"
1800
+ [config]="heatmapConfig"
1801
+ ></app-performance-heatmap>
1802
+ </div>
1803
+ </kendo-splitter-pane>
1804
+
1805
+ <!-- Right: Analysis Panels with Collapsible Sections -->
1806
+ <kendo-splitter-pane [resizable]="true" [collapsible]="false">
1807
+ <div class="dashboard-section analysis-panels">
1808
+
1809
+ <!-- Cost Analysis Panel -->
1810
+ <div class="analysis-panel">
1811
+ <div class="panel-header" (click)="togglePanel('cost')">
1812
+ <span class="panel-title">
1813
+ <i class="fa-solid fa-dollar-sign"></i>
1814
+ Cost Analysis
1815
+ </span>
1816
+ <i class="fa-solid panel-toggle-icon" [class.fa-chevron-down]="!panelStates.cost" [class.fa-chevron-up]="panelStates.cost"></i>
1817
+ </div>
1818
+ @if (panelStates.cost) {
1819
+ <div class="panel-content">
1820
+ @if (costData$ | async; as costData) {
1821
+ <div class="cost-bars">
1822
+ @for (item of costData.slice(0, 8); track item.model) {
1823
+ <div class="cost-bar-item">
1824
+ <div class="cost-bar-info">
1825
+ <span class="model-name">{{ item.model }}</span>
1826
+ <span class="cost-value">{{ formatCurrency(item.cost) }}</span>
1827
+ </div>
1828
+ <div class="cost-bar-container">
1829
+ <div
1830
+ class="cost-bar"
1831
+ [style.width.%]="getCostBarWidth(item.cost, getMaxCost(costData))"
1832
+ ></div>
1833
+ </div>
1834
+ <div class="token-info">
1835
+ {{ formatTokens(item.tokens) }} tokens
1836
+ </div>
1837
+ </div>
1838
+ }
1839
+ </div>
1840
+ }
1841
+ </div>
1842
+ }
1843
+ </div>
1844
+
1845
+ <!-- Token Efficiency Panel -->
1846
+ <div class="analysis-panel">
1847
+ <div class="panel-header" (click)="togglePanel('efficiency')">
1848
+ <span class="panel-title">
1849
+ <i class="fa-solid fa-chart-pie"></i>
1850
+ Token Efficiency
1851
+ </span>
1852
+ <i class="fa-solid panel-toggle-icon" [class.fa-chevron-down]="!panelStates.efficiency" [class.fa-chevron-up]="panelStates.efficiency"></i>
1853
+ </div>
1854
+ @if (panelStates.efficiency) {
1855
+ <div class="panel-content">
1856
+ @if (tokenEfficiency$ | async; as efficiencyData) {
1857
+ <div class="efficiency-items">
1858
+ @for (item of efficiencyData.slice(0, 6); track item.model) {
1859
+ <div class="efficiency-item">
1860
+ <div class="efficiency-header">
1861
+ <span class="model-name">{{ item.model }}</span>
1862
+ <span class="efficiency-ratio">
1863
+ {{ getTokenRatio(item.inputTokens, item.outputTokens) }}
1864
+ </span>
1865
+ </div>
1866
+ <div class="token-breakdown">
1867
+ <div class="token-bar">
1868
+ <div
1869
+ class="token-segment token-segment--input"
1870
+ [style.width.%]="getTokenPercentage(item.inputTokens, item.inputTokens + item.outputTokens)"
1871
+ ></div>
1872
+ <div
1873
+ class="token-segment token-segment--output"
1874
+ [style.width.%]="getTokenPercentage(item.outputTokens, item.inputTokens + item.outputTokens)"
1875
+ ></div>
1876
+ </div>
1877
+ <div class="token-labels">
1878
+ <span class="input-label">Input: {{ formatTokens(item.inputTokens) }}</span>
1879
+ <span class="output-label">Output: {{ formatTokens(item.outputTokens) }}</span>
1880
+ </div>
1881
+ </div>
1882
+ <div class="cost-per-token">
1883
+ {{ formatCostPerToken(item.cost, item.inputTokens + item.outputTokens) }}
1884
+ </div>
1885
+ </div>
1886
+ }
1887
+ </div>
1888
+ }
1889
+ </div>
1890
+ }
1891
+ </div>
1892
+
1893
+ <!-- Live Executions Panel -->
1894
+ <div class="analysis-panel">
1895
+ <div class="panel-header" (click)="togglePanel('executions')">
1896
+ <span class="panel-title">
1897
+ <i class="fa-solid fa-bolt"></i>
1898
+ Live Executions
1899
+ </span>
1900
+ <i class="fa-solid panel-toggle-icon" [class.fa-chevron-down]="!panelStates.executions" [class.fa-chevron-up]="panelStates.executions"></i>
1901
+ </div>
1902
+ @if (panelStates.executions) {
1903
+ <div class="panel-content live-executions-panel">
1904
+ <app-live-execution-widget
1905
+ [executions]="(liveExecutions$ | async) ?? []"
1906
+ (executionClick)="onExecutionClick($event)"
1907
+ ></app-live-execution-widget>
1908
+ </div>
1909
+ }
1910
+ </div>
1911
+ </div>
1912
+ </kendo-splitter-pane>
1913
+ </kendo-splitter>
1914
+ </kendo-splitter-pane>
1915
+ </kendo-splitter>
1916
+
1917
+ <!-- Execution Details Modal -->
1918
+ @if (selectedExecution) {
1919
+ <div class="execution-modal" (click)="closeExecutionModal()">
1920
+ <div class="execution-modal-content" (click)="$event.stopPropagation()">
1921
+ <div class="execution-modal-header">
1922
+ <h3>Execution Details</h3>
1923
+ <div class="modal-header-actions">
1924
+ <button class="open-record-btn" (click)="openFullRecord()">
1925
+ <i class="fa-solid fa-external-link-alt"></i>
1926
+ Open
1927
+ </button>
1928
+ <button class="close-btn" (click)="closeExecutionModal()">
1929
+ <i class="fa-solid fa-times"></i>
1930
+ </button>
1931
+ </div>
1932
+ </div>
1933
+ <div class="execution-modal-body">
1934
+ @if (executionDetails) {
1935
+ <div class="execution-details">
1936
+ <div class="detail-section">
1937
+ <h4>Basic Information</h4>
1938
+ <div class="detail-grid">
1939
+ <div class="detail-item">
1940
+ <label>Type:</label>
1941
+ <span>{{ executionDetails.type | titlecase }}</span>
1942
+ </div>
1943
+ <div class="detail-item">
1944
+ <label>Name:</label>
1945
+ <span>{{ executionDetails.name }}</span>
1946
+ </div>
1947
+ <div class="detail-item">
1948
+ <label>Status:</label>
1949
+ <span class="status-badge" [class]="'status-badge--' + executionDetails.status">
1950
+ {{ executionDetails.status | titlecase }}
1951
+ </span>
1952
+ </div>
1953
+ <div class="detail-item">
1954
+ <label>Started:</label>
1955
+ <span>{{ executionDetails.startTime | date:'medium' }}</span>
1956
+ </div>
1957
+ @if (executionDetails.endTime) {
1958
+ <div class="detail-item">
1959
+ <label>Completed:</label>
1960
+ <span>{{ executionDetails.endTime | date:'medium' }}</span>
1961
+ </div>
1962
+ }
1963
+ <div class="detail-item">
1964
+ <label>Duration:</label>
1965
+ <span>{{ formatDuration(getDuration(executionDetails)) }}</span>
1966
+ </div>
1967
+ </div>
1968
+ </div>
1969
+
1970
+ <div class="detail-section">
1971
+ <h4>Resource Usage</h4>
1972
+ <div class="detail-grid">
1973
+ <div class="detail-item">
1974
+ <label>Cost:</label>
1975
+ <span>{{ formatCurrency(executionDetails.cost, 6) }}</span>
1976
+ </div>
1977
+ <div class="detail-item">
1978
+ <label>Tokens:</label>
1979
+ <span>{{ executionDetails.tokens.toLocaleString() }}</span>
1980
+ </div>
1981
+ @if (executionDetails.model) {
1982
+ <div class="detail-item">
1983
+ <label>Model:</label>
1984
+ <span>{{ executionDetails.model }}</span>
1985
+ </div>
1986
+ }
1987
+ </div>
1988
+ </div>
1989
+
1990
+ @if (executionDetails.errorMessage) {
1991
+ <div class="detail-section">
1992
+ <h4>Error Information</h4>
1993
+ <div class="error-message">{{ executionDetails.errorMessage }}</div>
1994
+ </div>
1995
+ }
1996
+
1997
+ @if (executionDetails.children.length > 0) {
1998
+ <div class="detail-section">
1999
+ <h4>Child Executions ({{ executionDetails.children.length }})</h4>
2000
+ <div class="child-executions">
2001
+ @for (child of executionDetails.children; track child.id) {
2002
+ <div class="child-execution">
2003
+ <div class="child-info">
2004
+ <span class="child-name">{{ child.name }}</span>
2005
+ <span class="child-type">{{ child.type }}</span>
2006
+ <span class="child-status" [class]="'status-badge--' + child.status">
2007
+ {{ child.status }}
2008
+ </span>
2009
+ </div>
2010
+ <div class="child-metrics">
2011
+ <span>{{ formatCurrency(child.cost) }}</span>
2012
+ <span>{{ child.tokens.toLocaleString() }} tokens</span>
2013
+ </div>
2014
+ </div>
2015
+ }
2016
+ </div>
2017
+ </div>
2018
+ }
2019
+ </div>
2020
+ }
2021
+
2022
+ @if (loadingExecutionDetails) {
2023
+ <div class="loading-details">
2024
+ <div class="spinner"></div>
2025
+ <p>Loading execution details...</p>
2026
+ </div>
2027
+ }
2028
+ </div>
2029
+ </div>
2030
+ </div>
2031
+ }
2032
+ </div>
2033
+ `, styles: ["\n .execution-monitoring {\n padding: 20px;\n background: #f8f9fa;\n min-height: 100vh;\n }\n\n .monitoring-header {\n background: white;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n margin-bottom: 20px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-wrap: wrap;\n gap: 16px;\n }\n\n .monitoring-title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .monitoring-title i {\n color: #2196f3;\n }\n\n .monitoring-controls {\n display: flex;\n gap: 16px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .refresh-control, .time-range-control {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n }\n\n .refresh-control label, .time-range-control label {\n color: #666;\n font-weight: 500;\n }\n\n .refresh-control select, .time-range-control select {\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n font-size: 12px;\n background: white;\n }\n\n .refresh-btn {\n background: #2196f3;\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: 4px;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: background 0.2s ease;\n }\n\n .refresh-btn:hover:not(:disabled) {\n background: #1976d2;\n }\n\n .refresh-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n .refresh-btn i.spinning {\n animation: spin 1s linear infinite;\n }\n\n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n\n .kpi-dashboard {\n margin-bottom: 20px;\n }\n\n .kpi-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));\n gap: 16px;\n }\n\n .dashboard-splitter {\n height: calc(100vh - 550px); /* Increased to account for headers and margins */\n min-height: 600px;\n margin-bottom: 20px;\n }\n\n .dashboard-section {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n /* Ensure splitter panes take full height */\n :host ::ng-deep .k-splitter-pane {\n overflow: hidden;\n }\n\n :host ::ng-deep .k-splitter .k-splitter-pane {\n padding: 10px;\n }\n\n :host ::ng-deep .k-splitter-horizontal > .k-splitter-pane {\n padding: 10px 5px;\n }\n\n :host ::ng-deep .k-splitter-vertical > .k-splitter-pane {\n padding: 5px 10px;\n }\n\n /* Cost Analysis Styles */\n .cost-chart-container, .efficiency-chart-container, .status-container {\n padding: 20px;\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .chart-header {\n margin-bottom: 16px;\n }\n\n .chart-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .chart-title i {\n color: #2196f3;\n }\n\n .cost-bars, .efficiency-items {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .cost-bar-item {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .cost-bar-item:last-child {\n border-bottom: none;\n }\n\n .cost-bar-info {\n min-width: 120px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n .model-name {\n font-size: 12px;\n font-weight: 500;\n color: #333;\n }\n\n .cost-value {\n font-size: 11px;\n color: #ff9800;\n font-weight: 600;\n }\n\n .cost-bar-container {\n flex: 1;\n height: 8px;\n background: #f0f0f0;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .cost-bar {\n height: 100%;\n background: linear-gradient(90deg, #ff9800, #f57c00);\n border-radius: 4px;\n transition: width 0.3s ease;\n }\n\n .token-info {\n font-size: 10px;\n color: #666;\n min-width: 80px;\n text-align: right;\n }\n\n /* Token Efficiency Styles */\n .efficiency-item {\n padding: 12px 0;\n border-bottom: 1px solid #f0f0f0;\n }\n\n .efficiency-item:last-child {\n border-bottom: none;\n }\n\n .efficiency-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n }\n\n .efficiency-ratio {\n font-size: 11px;\n color: #2196f3;\n font-weight: 600;\n }\n\n .token-breakdown {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .token-bar {\n height: 6px;\n background: #f0f0f0;\n border-radius: 3px;\n overflow: hidden;\n display: flex;\n }\n\n .token-segment {\n height: 100%;\n }\n\n .token-segment--input {\n background: #4caf50;\n }\n\n .token-segment--output {\n background: #2196f3;\n }\n\n .token-labels {\n display: flex;\n justify-content: space-between;\n font-size: 10px;\n color: #666;\n }\n\n .input-label {\n color: #4caf50;\n }\n\n .output-label {\n color: #2196f3;\n }\n\n .cost-per-token {\n font-size: 10px;\n color: #999;\n margin-top: 4px;\n }\n\n /* System Status Styles */\n .status-metrics {\n display: flex;\n flex-direction: column;\n gap: 16px;\n flex: 1;\n }\n\n .status-metric {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px;\n background: #f8f9fa;\n border-radius: 6px;\n }\n\n .status-icon {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n }\n\n .status-icon--success {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .status-icon--warning {\n background: rgba(255, 152, 0, 0.1);\n color: #ff9800;\n }\n\n .status-icon--info {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .status-icon--primary {\n background: rgba(156, 39, 176, 0.1);\n color: #9c27b0;\n }\n\n .status-info {\n flex: 1;\n }\n\n .status-label {\n font-size: 12px;\n color: #666;\n font-weight: 500;\n }\n\n .status-value {\n font-size: 18px;\n font-weight: 700;\n color: #333;\n margin: 2px 0;\n }\n\n .status-subtitle {\n font-size: 10px;\n color: #999;\n }\n\n /* Execution Modal Styles */\n .execution-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n padding: 20px;\n }\n\n .execution-modal-content {\n background: white;\n border-radius: 8px;\n max-width: 800px;\n width: 100%;\n max-height: 80vh;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .execution-modal-header {\n padding: 20px;\n border-bottom: 1px solid #f0f0f0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .execution-modal-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #333;\n }\n\n .modal-header-actions {\n display: flex;\n gap: 12px;\n align-items: center;\n }\n\n .open-record-btn {\n background: #2196f3;\n color: white;\n border: none;\n padding: 8px 16px;\n border-radius: 4px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s ease;\n }\n\n .open-record-btn:hover {\n background: #1976d2;\n transform: translateY(-1px);\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.3);\n }\n\n .open-record-btn i {\n font-size: 12px;\n }\n\n .close-btn {\n background: none;\n border: none;\n font-size: 16px;\n color: #999;\n cursor: pointer;\n padding: 4px;\n }\n\n .close-btn:hover {\n color: #333;\n }\n\n .execution-modal-body {\n padding: 20px;\n overflow-y: auto;\n flex: 1;\n }\n\n .execution-details {\n display: flex;\n flex-direction: column;\n gap: 20px;\n }\n\n .detail-section h4 {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 6px;\n }\n\n .detail-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 12px;\n }\n\n .detail-item {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .detail-item label {\n font-size: 11px;\n color: #666;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .detail-item span {\n font-size: 13px;\n color: #333;\n }\n\n .status-badge {\n display: inline-block;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .status-badge--completed {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .status-badge--running {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .status-badge--failed {\n background: rgba(244, 67, 54, 0.1);\n color: #f44336;\n }\n\n .error-message {\n background: #fff3e0;\n border: 1px solid #ffcc02;\n border-radius: 4px;\n padding: 12px;\n font-size: 12px;\n color: #e65100;\n font-family: monospace;\n }\n\n .child-executions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .child-execution {\n background: #f8f9fa;\n border-radius: 4px;\n padding: 12px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n\n .child-info {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .child-name {\n font-size: 12px;\n font-weight: 500;\n color: #333;\n }\n\n .child-type {\n font-size: 10px;\n background: #e0e0e0;\n padding: 2px 6px;\n border-radius: 3px;\n color: #666;\n }\n\n .child-status {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 3px;\n }\n\n .child-metrics {\n display: flex;\n gap: 12px;\n font-size: 11px;\n color: #666;\n }\n\n .loading-details {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n gap: 12px;\n }\n\n .spinner {\n width: 32px;\n height: 32px;\n border: 3px solid #f3f3f3;\n border-top: 3px solid #2196f3;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n\n /* Drill-down Tab Styles */\n .drill-down-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .drill-down-tabs {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .tab-header {\n display: flex;\n border-bottom: 1px solid #e0e0e0;\n background: #f8f9fa;\n min-height: 40px;\n overflow-x: auto;\n }\n\n .tab-item {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: #f8f9fa;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: #666;\n white-space: nowrap;\n transition: all 0.2s ease;\n min-width: 120px;\n justify-content: space-between;\n }\n\n .tab-item:hover {\n background: #e9ecef;\n color: #333;\n }\n\n .tab-item.active {\n background: white;\n color: #2196f3;\n border-bottom-color: #2196f3;\n }\n\n .tab-title {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .tab-close {\n background: none;\n border: none;\n color: #999;\n cursor: pointer;\n padding: 2px;\n border-radius: 2px;\n font-size: 10px;\n width: 16px;\n height: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease;\n }\n\n .tab-close:hover {\n background: rgba(0, 0, 0, 0.1);\n color: #333;\n }\n\n .tab-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .tab-pane {\n height: 100%;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .trends-chart {\n padding: 0;\n }\n\n .trends-chart app-time-series-chart {\n height: 100%;\n display: block;\n overflow: hidden;\n }\n\n /* Ensure chart fits within tab pane */\n .tab-pane.trends-chart {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* Drill-down specific styles */\n .executions-drill-down {\n padding: 20px;\n overflow-y: auto;\n }\n\n .drill-down-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 20px;\n padding-bottom: 12px;\n border-bottom: 1px solid #e0e0e0;\n }\n\n .drill-down-header h4 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .drill-down-meta {\n display: flex;\n gap: 12px;\n align-items: center;\n font-size: 12px;\n }\n\n .timestamp {\n color: #666;\n background: #f0f0f0;\n padding: 4px 8px;\n border-radius: 4px;\n }\n\n .metric-badge {\n background: #2196f3;\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-weight: 500;\n }\n\n .loading-spinner {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 40px;\n color: #666;\n gap: 12px;\n }\n\n .executions-table {\n display: flex;\n flex-direction: column;\n gap: 0;\n border: 1px solid #e0e0e0;\n border-radius: 6px;\n overflow: hidden;\n }\n\n .table-header {\n display: grid;\n grid-template-columns: 80px 1fr 120px 100px 100px 80px 100px 120px;\n gap: 12px;\n background: #f8f9fa;\n padding: 12px 16px;\n font-size: 11px;\n font-weight: 600;\n color: #666;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .table-row {\n display: grid;\n grid-template-columns: 80px 1fr 120px 100px 100px 80px 100px 120px;\n gap: 12px;\n padding: 12px 16px;\n border-top: 1px solid #f0f0f0;\n cursor: pointer;\n transition: background 0.2s ease;\n align-items: center;\n }\n\n .table-row:hover {\n background: #f8f9fa;\n }\n\n .table-cell {\n font-size: 12px;\n color: #333;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .type-badge {\n background: #e9ecef;\n color: #666;\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n }\n\n .type-badge--prompt {\n background: rgba(33, 150, 243, 0.1);\n color: #2196f3;\n }\n\n .type-badge--agent {\n background: rgba(76, 175, 80, 0.1);\n color: #4caf50;\n }\n\n .no-data {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n color: #999;\n gap: 16px;\n }\n\n .no-data i {\n font-size: 48px;\n color: #ddd;\n }\n\n .no-data p {\n margin: 0;\n font-size: 14px;\n }\n\n /* Model detail styles */\n .model-detail {\n padding: 20px;\n overflow-y: auto;\n }\n\n .model-details {\n display: flex;\n flex-direction: column;\n gap: 24px;\n }\n\n .model-info-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 16px;\n }\n\n .info-item {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 16px;\n background: #f8f9fa;\n border-radius: 6px;\n }\n\n .info-item label {\n font-size: 11px;\n color: #666;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin: 0;\n }\n\n .info-item span {\n font-size: 14px;\n color: #333;\n font-weight: 500;\n }\n\n .status-indicator {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n }\n\n .status-indicator.active {\n color: #4caf50;\n }\n\n .status-indicator.active::before {\n content: '';\n width: 6px;\n height: 6px;\n background: #4caf50;\n border-radius: 50%;\n }\n\n .model-description {\n padding: 20px;\n background: #f8f9fa;\n border-radius: 8px;\n }\n\n .model-description h5 {\n margin: 0 0 12px 0;\n font-size: 14px;\n font-weight: 600;\n color: #333;\n }\n\n .model-description p {\n margin: 0;\n font-size: 13px;\n color: #666;\n line-height: 1.5;\n }\n\n /* Clickable KPI cards */\n .clickable {\n cursor: pointer;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .clickable:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n\n /* Collapsible Panel Styles */\n .analysis-panels {\n padding: 10px;\n height: 100%;\n overflow-y: auto;\n background: #f8f9fa;\n }\n\n .analysis-panel {\n margin-bottom: 12px;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n background: white;\n overflow: hidden;\n }\n\n .analysis-panel:last-child {\n margin-bottom: 0;\n }\n\n .panel-header {\n padding: 12px 16px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n cursor: pointer;\n display: flex;\n justify-content: space-between;\n align-items: center;\n transition: background 0.2s ease;\n }\n\n .panel-header:hover {\n background: #e9ecef;\n }\n\n .panel-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n color: #333;\n font-size: 14px;\n }\n\n .panel-title i {\n color: #2196f3;\n width: 16px;\n }\n\n .panel-toggle-icon {\n color: #666;\n font-size: 12px;\n transition: transform 0.2s ease;\n }\n\n .panel-content {\n padding: 16px;\n border-top: 1px solid #f0f0f0;\n animation: slideDown 0.2s ease-out;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n max-height: 0;\n }\n to {\n opacity: 1;\n max-height: 500px;\n }\n }\n\n .live-executions-panel {\n padding: 0;\n }\n\n .live-executions-panel app-live-execution-widget {\n height: 300px;\n display: block;\n }\n\n /* Responsive Design */\n @media (max-width: 1200px) {\n .dashboard-splitter {\n height: calc(100vh - 270px); /* Consistent with main height */\n margin-bottom: 20px;\n }\n \n .table-header,\n .table-row {\n grid-template-columns: 60px 1fr 100px 80px 80px 60px 80px 100px;\n gap: 8px;\n }\n \n .model-info-grid {\n grid-template-columns: 1fr;\n }\n \n .analysis-panels {\n padding: 8px;\n }\n \n .analysis-panel {\n margin-bottom: 8px;\n }\n }\n\n @media (max-width: 768px) {\n .execution-monitoring {\n padding: 12px;\n }\n \n .monitoring-header {\n flex-direction: column;\n align-items: flex-start;\n }\n \n .monitoring-controls {\n width: 100%;\n justify-content: flex-start;\n }\n \n .dashboard-splitter {\n height: calc(100vh - 270px); /* Consistent with main height */\n min-height: 400px;\n margin-bottom: 20px;\n }\n \n .kpi-grid {\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n }\n\n /* Reduce padding on smaller screens */\n :host ::ng-deep .k-splitter .k-splitter-pane {\n padding: 5px;\n }\n\n :host ::ng-deep .k-splitter-horizontal > .k-splitter-pane {\n padding: 5px 2px;\n }\n\n :host ::ng-deep .k-splitter-vertical > .k-splitter-pane {\n padding: 2px 5px;\n }\n \n .tab-header {\n overflow-x: auto;\n }\n \n .tab-item {\n min-width: 100px;\n padding: 6px 12px;\n }\n \n .table-header,\n .table-row {\n grid-template-columns: 1fr;\n gap: 4px;\n text-align: left;\n }\n \n .table-row {\n display: block;\n padding: 16px;\n }\n \n .table-cell {\n display: block;\n margin-bottom: 8px;\n }\n \n .table-cell:before {\n content: attr(data-label) ': ';\n font-weight: 600;\n color: #666;\n font-size: 11px;\n text-transform: uppercase;\n }\n \n .executions-drill-down,\n .model-detail {\n padding: 12px;\n }\n \n .panel-content {\n padding: 12px;\n }\n \n .panel-header {\n padding: 10px 12px;\n }\n \n .panel-title {\n font-size: 13px;\n }\n }\n "] }]
2034
+ }], () => [{ type: i1.AIInstrumentationService }], { initialState: [{
2035
+ type: Input
2036
+ }], openEntityRecord: [{
2037
+ type: Output
2038
+ }], stateChange: [{
27
2039
  type: Output
28
2040
  }] }); })();
29
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ExecutionMonitoringComponent, { className: "ExecutionMonitoringComponent", filePath: "src/AI/components/execution-monitoring.component.ts", lineNumber: 8 }); })();
2041
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ExecutionMonitoringComponent, { className: "ExecutionMonitoringComponent", filePath: "src/AI/components/execution-monitoring.component.ts", lineNumber: 1723 }); })();
30
2042
  //# sourceMappingURL=execution-monitoring.component.js.map