@memberjunction/ng-core-entity-forms 2.72.0 → 2.74.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 (57) hide show
  1. package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
  2. package/dist/lib/custom/AIAgents/ai-agent-form.component.js +592 -580
  3. package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
  4. package/dist/lib/custom/Queries/query-category-dialog.component.d.ts +33 -0
  5. package/dist/lib/custom/Queries/query-category-dialog.component.d.ts.map +1 -0
  6. package/dist/lib/custom/Queries/query-category-dialog.component.js +241 -0
  7. package/dist/lib/custom/Queries/query-category-dialog.component.js.map +1 -0
  8. package/dist/lib/custom/Queries/query-form.component.d.ts +135 -0
  9. package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -0
  10. package/dist/lib/custom/Queries/query-form.component.js +1563 -0
  11. package/dist/lib/custom/Queries/query-form.component.js.map +1 -0
  12. package/dist/lib/custom/Queries/query-run-dialog.component.d.ts +66 -0
  13. package/dist/lib/custom/Queries/query-run-dialog.component.d.ts.map +1 -0
  14. package/dist/lib/custom/Queries/query-run-dialog.component.js +788 -0
  15. package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -0
  16. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +162 -0
  17. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -0
  18. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +2091 -0
  19. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -0
  20. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js +1 -1
  21. package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js.map +1 -1
  22. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts +2 -8
  23. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
  24. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +122 -128
  25. package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
  26. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts +6 -1
  27. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
  28. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +218 -156
  29. package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
  30. package/dist/lib/custom/custom-forms.module.d.ts +26 -22
  31. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  32. package/dist/lib/custom/custom-forms.module.js +23 -3
  33. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  34. package/dist/lib/generated/Entities/Query/query.form.component.js +14 -4
  35. package/dist/lib/generated/Entities/Query/query.form.component.js.map +1 -1
  36. package/dist/lib/generated/Entities/Query/sections/details.component.d.ts.map +1 -1
  37. package/dist/lib/generated/Entities/Query/sections/details.component.js +13 -4
  38. package/dist/lib/generated/Entities/Query/sections/details.component.js.map +1 -1
  39. package/dist/lib/generated/Entities/QueryEntity/sections/details.component.d.ts.map +1 -1
  40. package/dist/lib/generated/Entities/QueryEntity/sections/details.component.js +22 -4
  41. package/dist/lib/generated/Entities/QueryEntity/sections/details.component.js.map +1 -1
  42. package/dist/lib/generated/Entities/QueryField/sections/details.component.d.ts.map +1 -1
  43. package/dist/lib/generated/Entities/QueryField/sections/details.component.js +22 -4
  44. package/dist/lib/generated/Entities/QueryField/sections/details.component.js.map +1 -1
  45. package/dist/lib/generated/Entities/QueryParameter/queryparameter.form.component.d.ts +10 -0
  46. package/dist/lib/generated/Entities/QueryParameter/queryparameter.form.component.d.ts.map +1 -0
  47. package/dist/lib/generated/Entities/QueryParameter/queryparameter.form.component.js +59 -0
  48. package/dist/lib/generated/Entities/QueryParameter/queryparameter.form.component.js.map +1 -0
  49. package/dist/lib/generated/Entities/QueryParameter/sections/details.component.d.ts +11 -0
  50. package/dist/lib/generated/Entities/QueryParameter/sections/details.component.d.ts.map +1 -0
  51. package/dist/lib/generated/Entities/QueryParameter/sections/details.component.js +172 -0
  52. package/dist/lib/generated/Entities/QueryParameter/sections/details.component.js.map +1 -0
  53. package/dist/lib/generated/generated-forms.module.d.ts +265 -263
  54. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  55. package/dist/lib/generated/generated-forms.module.js +74 -66
  56. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  57. package/package.json +18 -16
@@ -0,0 +1,2091 @@
1
+ import { Component, Input, ViewChild } from '@angular/core';
2
+ import { Subject } from 'rxjs';
3
+ import { RunView } from '@memberjunction/core';
4
+ import * as d3 from 'd3';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common";
7
+ import * as i2 from "@progress/kendo-angular-layout";
8
+ import * as i3 from "@progress/kendo-angular-buttons";
9
+ const _c0 = ["modelDistributionChart"];
10
+ const _c1 = ["executionTimeChart"];
11
+ const _c2 = ["costByVendorChart"];
12
+ const _c3 = ["tokenUsageChart"];
13
+ const _c4 = ["actionSuccessRateChart"];
14
+ const _c5 = ["stepTypeChart"];
15
+ const _c6 = ["promptTimeDistributionChart"];
16
+ const _c7 = ["promptTokenDistributionChart"];
17
+ const _c8 = ["promptCostDistributionChart"];
18
+ const _c9 = ["promptCountByNameChart"];
19
+ function AIAgentRunAnalyticsComponent_div_1_Template(rf, ctx) { if (rf & 1) {
20
+ i0.ɵɵelementStart(0, "div", 14);
21
+ i0.ɵɵelement(1, "i", 15);
22
+ i0.ɵɵelementStart(2, "p");
23
+ i0.ɵɵtext(3, "Loading analytics data...");
24
+ i0.ɵɵelementEnd()();
25
+ } }
26
+ function AIAgentRunAnalyticsComponent_div_2_Template(rf, ctx) { if (rf & 1) {
27
+ const _r1 = i0.ɵɵgetCurrentView();
28
+ i0.ɵɵelementStart(0, "div", 16);
29
+ i0.ɵɵelement(1, "i", 17);
30
+ i0.ɵɵelementStart(2, "p");
31
+ i0.ɵɵtext(3);
32
+ i0.ɵɵelementEnd();
33
+ i0.ɵɵelementStart(4, "button", 18);
34
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_2_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.loadData()); });
35
+ i0.ɵɵtext(5, "Retry");
36
+ i0.ɵɵelementEnd()();
37
+ } if (rf & 2) {
38
+ const ctx_r1 = i0.ɵɵnextContext();
39
+ i0.ɵɵadvance(3);
40
+ i0.ɵɵtextInterpolate(ctx_r1.error);
41
+ } }
42
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_3_Template(rf, ctx) { if (rf & 1) {
43
+ i0.ɵɵelement(0, "i", 23);
44
+ i0.ɵɵtext(1, " Overview ");
45
+ } }
46
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_4_span_12_Template(rf, ctx) { if (rf & 1) {
47
+ i0.ɵɵelementStart(0, "span", 39);
48
+ i0.ɵɵtext(1);
49
+ i0.ɵɵelementEnd();
50
+ } if (rf & 2) {
51
+ const ctx_r1 = i0.ɵɵnextContext(3);
52
+ i0.ɵɵadvance();
53
+ i0.ɵɵtextInterpolate1("", ctx_r1.promptMetrics.statusBreakdown.failed, " failed");
54
+ } }
55
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_4_span_24_Template(rf, ctx) { if (rf & 1) {
56
+ i0.ɵɵelementStart(0, "span", 39);
57
+ i0.ɵɵtext(1);
58
+ i0.ɵɵelementEnd();
59
+ } if (rf & 2) {
60
+ const ctx_r1 = i0.ɵɵnextContext(3);
61
+ i0.ɵɵadvance();
62
+ i0.ɵɵtextInterpolate1("", ctx_r1.actionMetrics.statusBreakdown.failed, " failed");
63
+ } }
64
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_4_Template(rf, ctx) { if (rf & 1) {
65
+ i0.ɵɵelementStart(0, "div", 24)(1, "div", 25)(2, "div", 26);
66
+ i0.ɵɵelement(3, "i", 27);
67
+ i0.ɵɵelementEnd();
68
+ i0.ɵɵelementStart(4, "div", 28)(5, "h3");
69
+ i0.ɵɵtext(6, "Total Prompts");
70
+ i0.ɵɵelementEnd();
71
+ i0.ɵɵelementStart(7, "div", 29);
72
+ i0.ɵɵtext(8);
73
+ i0.ɵɵelementEnd();
74
+ i0.ɵɵelementStart(9, "div", 30)(10, "span", 31);
75
+ i0.ɵɵtext(11);
76
+ i0.ɵɵelementEnd();
77
+ i0.ɵɵtemplate(12, AIAgentRunAnalyticsComponent_div_3_ng_template_4_span_12_Template, 2, 1, "span", 32);
78
+ i0.ɵɵelementEnd()()();
79
+ i0.ɵɵelementStart(13, "div", 25)(14, "div", 33);
80
+ i0.ɵɵelement(15, "i", 34);
81
+ i0.ɵɵelementEnd();
82
+ i0.ɵɵelementStart(16, "div", 28)(17, "h3");
83
+ i0.ɵɵtext(18, "Total Actions");
84
+ i0.ɵɵelementEnd();
85
+ i0.ɵɵelementStart(19, "div", 29);
86
+ i0.ɵɵtext(20);
87
+ i0.ɵɵelementEnd();
88
+ i0.ɵɵelementStart(21, "div", 30)(22, "span", 31);
89
+ i0.ɵɵtext(23);
90
+ i0.ɵɵelementEnd();
91
+ i0.ɵɵtemplate(24, AIAgentRunAnalyticsComponent_div_3_ng_template_4_span_24_Template, 2, 1, "span", 32);
92
+ i0.ɵɵelementEnd()()();
93
+ i0.ɵɵelementStart(25, "div", 25)(26, "div", 35);
94
+ i0.ɵɵelement(27, "i", 36);
95
+ i0.ɵɵelementEnd();
96
+ i0.ɵɵelementStart(28, "div", 28)(29, "h3");
97
+ i0.ɵɵtext(30, "Total Cost");
98
+ i0.ɵɵelementEnd();
99
+ i0.ɵɵelementStart(31, "div", 29);
100
+ i0.ɵɵtext(32);
101
+ i0.ɵɵelementEnd();
102
+ i0.ɵɵelementStart(33, "div", 30)(34, "span");
103
+ i0.ɵɵtext(35);
104
+ i0.ɵɵelementEnd()()()();
105
+ i0.ɵɵelementStart(36, "div", 25)(37, "div", 37);
106
+ i0.ɵɵelement(38, "i", 38);
107
+ i0.ɵɵelementEnd();
108
+ i0.ɵɵelementStart(39, "div", 28)(40, "h3");
109
+ i0.ɵɵtext(41, "Execution Time");
110
+ i0.ɵɵelementEnd();
111
+ i0.ɵɵelementStart(42, "div", 29);
112
+ i0.ɵɵtext(43);
113
+ i0.ɵɵelementEnd();
114
+ i0.ɵɵelementStart(44, "div", 30)(45, "span");
115
+ i0.ɵɵtext(46);
116
+ i0.ɵɵelementEnd()()()()();
117
+ } if (rf & 2) {
118
+ const ctx_r1 = i0.ɵɵnextContext(2);
119
+ i0.ɵɵadvance(8);
120
+ i0.ɵɵtextInterpolate(ctx_r1.promptMetrics.totalCount);
121
+ i0.ɵɵadvance(3);
122
+ i0.ɵɵtextInterpolate1("", ctx_r1.promptMetrics.statusBreakdown.success, " successful");
123
+ i0.ɵɵadvance();
124
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.statusBreakdown.failed > 0);
125
+ i0.ɵɵadvance(8);
126
+ i0.ɵɵtextInterpolate(ctx_r1.actionMetrics.totalCount);
127
+ i0.ɵɵadvance(3);
128
+ i0.ɵɵtextInterpolate1("", ctx_r1.actionMetrics.statusBreakdown.success, " successful");
129
+ i0.ɵɵadvance();
130
+ i0.ɵɵproperty("ngIf", ctx_r1.actionMetrics.statusBreakdown.failed > 0);
131
+ i0.ɵɵadvance(8);
132
+ i0.ɵɵtextInterpolate(ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
133
+ i0.ɵɵadvance(3);
134
+ i0.ɵɵtextInterpolate1("", ctx_r1.promptMetrics.tokenUsage.totalInput + ctx_r1.promptMetrics.tokenUsage.totalOutput, " tokens");
135
+ i0.ɵɵadvance(8);
136
+ i0.ɵɵtextInterpolate(ctx_r1.formatDuration(ctx_r1.promptMetrics.totalExecutionTime + ctx_r1.actionMetrics.totalExecutionTime));
137
+ i0.ɵɵadvance(3);
138
+ i0.ɵɵtextInterpolate1("", ctx_r1.timelineMetrics.totalSteps, " total steps");
139
+ } }
140
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_6_Template(rf, ctx) { if (rf & 1) {
141
+ i0.ɵɵelement(0, "i", 27);
142
+ i0.ɵɵtext(1, " Prompt Analytics ");
143
+ } }
144
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_1_Template(rf, ctx) { if (rf & 1) {
145
+ const _r4 = i0.ɵɵgetCurrentView();
146
+ i0.ɵɵelementStart(0, "div", 49)(1, "button", 50);
147
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_1_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
148
+ i0.ɵɵelement(2, "i", 47);
149
+ i0.ɵɵtext(3);
150
+ i0.ɵɵelementEnd()();
151
+ } if (rf & 2) {
152
+ const ctx_r1 = i0.ɵɵnextContext(3);
153
+ i0.ɵɵadvance(2);
154
+ i0.ɵɵproperty("ngClass", ctx_r1.viewMode === "grid" ? "fa-expand-arrows-alt" : "fa-compress-arrows-alt");
155
+ i0.ɵɵadvance();
156
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.viewMode === "grid" ? "Expand All" : "Collapse All", " ");
157
+ } }
158
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_2_Template(rf, ctx) { if (rf & 1) {
159
+ i0.ɵɵelementStart(0, "div", 51);
160
+ i0.ɵɵelement(1, "i", 52);
161
+ i0.ɵɵelementStart(2, "p");
162
+ i0.ɵɵtext(3, "No prompt executions found in this agent run.");
163
+ i0.ɵɵelementEnd();
164
+ i0.ɵɵelementStart(4, "p", 53);
165
+ i0.ɵɵtext(5, "This agent run may have only executed actions without any AI prompts.");
166
+ i0.ɵɵelementEnd()();
167
+ } }
168
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_div_12_div_1_Template(rf, ctx) { if (rf & 1) {
169
+ i0.ɵɵelementStart(0, "div", 70);
170
+ i0.ɵɵelement(1, "span", 71);
171
+ i0.ɵɵelementStart(2, "span", 72);
172
+ i0.ɵɵtext(3);
173
+ i0.ɵɵelementEnd()();
174
+ } if (rf & 2) {
175
+ const item_r6 = ctx.$implicit;
176
+ const ctx_r1 = i0.ɵɵnextContext(5);
177
+ i0.ɵɵadvance();
178
+ i0.ɵɵstyleProp("background-color", ctx_r1.getModelColor(item_r6.key));
179
+ i0.ɵɵadvance(2);
180
+ i0.ɵɵtextInterpolate3("", item_r6.key, ": ", item_r6.value.count, " (", (item_r6.value.count / ctx_r1.promptMetrics.totalCount * 100).toFixed(1), "%)");
181
+ } }
182
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_div_12_Template(rf, ctx) { if (rf & 1) {
183
+ i0.ɵɵelementStart(0, "div", 68);
184
+ i0.ɵɵtemplate(1, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_div_12_div_1_Template, 4, 5, "div", 69);
185
+ i0.ɵɵpipe(2, "keyvalue");
186
+ i0.ɵɵelementEnd();
187
+ } if (rf & 2) {
188
+ const ctx_r1 = i0.ɵɵnextContext(4);
189
+ i0.ɵɵadvance();
190
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.byModel));
191
+ } }
192
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template(rf, ctx) { if (rf & 1) {
193
+ const _r5 = i0.ɵɵgetCurrentView();
194
+ i0.ɵɵelementStart(0, "div", 54)(1, "div", 55)(2, "div", 56);
195
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
196
+ i0.ɵɵelementStart(3, "h3");
197
+ i0.ɵɵelement(4, "i", 57);
198
+ i0.ɵɵtext(5, " Prompts by Model");
199
+ i0.ɵɵelementEnd();
200
+ i0.ɵɵelementStart(6, "button", 58);
201
+ i0.ɵɵelement(7, "i", 47);
202
+ i0.ɵɵelementEnd()();
203
+ i0.ɵɵelementStart(8, "div", 59)(9, "div", 60);
204
+ i0.ɵɵelement(10, "div", 61, 0);
205
+ i0.ɵɵtemplate(12, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_div_12_Template, 3, 3, "div", 62);
206
+ i0.ɵɵelementEnd()()();
207
+ i0.ɵɵelementStart(13, "div", 55)(14, "div", 56);
208
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
209
+ i0.ɵɵelementStart(15, "h3");
210
+ i0.ɵɵelement(16, "i", 38);
211
+ i0.ɵɵtext(17, " Average Execution Time by Vendor");
212
+ i0.ɵɵelementEnd();
213
+ i0.ɵɵelementStart(18, "button", 58);
214
+ i0.ɵɵelement(19, "i", 47);
215
+ i0.ɵɵelementEnd()();
216
+ i0.ɵɵelementStart(20, "div", 59)(21, "div", 60);
217
+ i0.ɵɵelement(22, "div", 63, 1);
218
+ i0.ɵɵelementEnd()()();
219
+ i0.ɵɵelementStart(24, "div", 55)(25, "div", 56);
220
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
221
+ i0.ɵɵelementStart(26, "h3");
222
+ i0.ɵɵelement(27, "i", 36);
223
+ i0.ɵɵtext(28, " Cost Distribution by Vendor");
224
+ i0.ɵɵelementEnd();
225
+ i0.ɵɵelementStart(29, "button", 58);
226
+ i0.ɵɵelement(30, "i", 47);
227
+ i0.ɵɵelementEnd()();
228
+ i0.ɵɵelementStart(31, "div", 59)(32, "div", 60);
229
+ i0.ɵɵelement(33, "div", 64, 2);
230
+ i0.ɵɵelementStart(35, "div", 65);
231
+ i0.ɵɵtext(36);
232
+ i0.ɵɵelementEnd()()()();
233
+ i0.ɵɵelementStart(37, "div", 55)(38, "div", 56);
234
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
235
+ i0.ɵɵelementStart(39, "h3");
236
+ i0.ɵɵelement(40, "i", 66);
237
+ i0.ɵɵtext(41, " Token Usage by Model");
238
+ i0.ɵɵelementEnd();
239
+ i0.ɵɵelementStart(42, "button", 58);
240
+ i0.ɵɵelement(43, "i", 47);
241
+ i0.ɵɵelementEnd()();
242
+ i0.ɵɵelementStart(44, "div", 59)(45, "div", 60);
243
+ i0.ɵɵelement(46, "div", 67, 3);
244
+ i0.ɵɵelementEnd()()()();
245
+ } if (rf & 2) {
246
+ const ctx_r1 = i0.ɵɵnextContext(3);
247
+ i0.ɵɵadvance();
248
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["modelDistribution"]);
249
+ i0.ɵɵadvance(6);
250
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["modelDistribution"] ? "fa-compress" : "fa-expand");
251
+ i0.ɵɵadvance(5);
252
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.byModel.size > 0);
253
+ i0.ɵɵadvance();
254
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["executionTime"]);
255
+ i0.ɵɵadvance(6);
256
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["executionTime"] ? "fa-compress" : "fa-expand");
257
+ i0.ɵɵadvance(5);
258
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["costByVendor"]);
259
+ i0.ɵɵadvance(6);
260
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["costByVendor"] ? "fa-compress" : "fa-expand");
261
+ i0.ɵɵadvance(6);
262
+ i0.ɵɵtextInterpolate1("Total: ", ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost), "");
263
+ i0.ɵɵadvance();
264
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["tokenUsage"]);
265
+ i0.ɵɵadvance(6);
266
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["tokenUsage"] ? "fa-compress" : "fa-expand");
267
+ } }
268
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template(rf, ctx) { if (rf & 1) {
269
+ const _r7 = i0.ɵɵgetCurrentView();
270
+ i0.ɵɵelementStart(0, "div", 73)(1, "div", 55)(2, "div", 56);
271
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptTime")); });
272
+ i0.ɵɵelementStart(3, "h3");
273
+ i0.ɵɵelement(4, "i", 74);
274
+ i0.ɵɵtext(5, " Average Execution Time by Prompt");
275
+ i0.ɵɵelementEnd();
276
+ i0.ɵɵelementStart(6, "button", 58);
277
+ i0.ɵɵelement(7, "i", 47);
278
+ i0.ɵɵelementEnd()();
279
+ i0.ɵɵelementStart(8, "div", 59)(9, "div", 60);
280
+ i0.ɵɵelement(10, "div", 75, 4);
281
+ i0.ɵɵelementEnd()()();
282
+ i0.ɵɵelementStart(12, "div", 55)(13, "div", 56);
283
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptToken")); });
284
+ i0.ɵɵelementStart(14, "h3");
285
+ i0.ɵɵelement(15, "i", 76);
286
+ i0.ɵɵtext(16, " Token Usage by Prompt");
287
+ i0.ɵɵelementEnd();
288
+ i0.ɵɵelementStart(17, "button", 58);
289
+ i0.ɵɵelement(18, "i", 47);
290
+ i0.ɵɵelementEnd()();
291
+ i0.ɵɵelementStart(19, "div", 59)(20, "div", 60);
292
+ i0.ɵɵelement(21, "div", 77, 5);
293
+ i0.ɵɵelementEnd()()();
294
+ i0.ɵɵelementStart(23, "div", 55)(24, "div", 56);
295
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template_div_click_24_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCost")); });
296
+ i0.ɵɵelementStart(25, "h3");
297
+ i0.ɵɵelement(26, "i", 57);
298
+ i0.ɵɵtext(27, " Cost Distribution by Prompt");
299
+ i0.ɵɵelementEnd();
300
+ i0.ɵɵelementStart(28, "button", 58);
301
+ i0.ɵɵelement(29, "i", 47);
302
+ i0.ɵɵelementEnd()();
303
+ i0.ɵɵelementStart(30, "div", 59)(31, "div", 60);
304
+ i0.ɵɵelement(32, "div", 78, 6);
305
+ i0.ɵɵelementEnd()()();
306
+ i0.ɵɵelementStart(34, "div", 55)(35, "div", 56);
307
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template_div_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCount")); });
308
+ i0.ɵɵelementStart(36, "h3");
309
+ i0.ɵɵelement(37, "i", 79);
310
+ i0.ɵɵtext(38, " Prompt Execution Count");
311
+ i0.ɵɵelementEnd();
312
+ i0.ɵɵelementStart(39, "button", 58);
313
+ i0.ɵɵelement(40, "i", 47);
314
+ i0.ɵɵelementEnd()();
315
+ i0.ɵɵelementStart(41, "div", 59)(42, "div", 60);
316
+ i0.ɵɵelement(43, "div", 80, 7);
317
+ i0.ɵɵelementEnd()()()();
318
+ } if (rf & 2) {
319
+ const ctx_r1 = i0.ɵɵnextContext(3);
320
+ i0.ɵɵadvance();
321
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptTime"]);
322
+ i0.ɵɵadvance(6);
323
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptTime"] ? "fa-compress" : "fa-expand");
324
+ i0.ɵɵadvance(5);
325
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptToken"]);
326
+ i0.ɵɵadvance(6);
327
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptToken"] ? "fa-compress" : "fa-expand");
328
+ i0.ɵɵadvance(5);
329
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCost"]);
330
+ i0.ɵɵadvance(6);
331
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCost"] ? "fa-compress" : "fa-expand");
332
+ i0.ɵɵadvance(5);
333
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCount"]);
334
+ i0.ɵɵadvance(6);
335
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCount"] ? "fa-compress" : "fa-expand");
336
+ } }
337
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_9_tr_15_Template(rf, ctx) { if (rf & 1) {
338
+ i0.ɵɵelementStart(0, "tr")(1, "td");
339
+ i0.ɵɵtext(2);
340
+ i0.ɵɵelementEnd();
341
+ i0.ɵɵelementStart(3, "td");
342
+ i0.ɵɵtext(4);
343
+ i0.ɵɵelementEnd();
344
+ i0.ɵɵelementStart(5, "td");
345
+ i0.ɵɵtext(6);
346
+ i0.ɵɵelementEnd();
347
+ i0.ɵɵelementStart(7, "td");
348
+ i0.ɵɵtext(8);
349
+ i0.ɵɵelementEnd();
350
+ i0.ɵɵelementStart(9, "td")(10, "span", 83);
351
+ i0.ɵɵtext(11);
352
+ i0.ɵɵelementEnd()()();
353
+ } if (rf & 2) {
354
+ const prompt_r8 = ctx.$implicit;
355
+ const ctx_r1 = i0.ɵɵnextContext(4);
356
+ i0.ɵɵadvance(2);
357
+ i0.ɵɵtextInterpolate(prompt_r8.key);
358
+ i0.ɵɵadvance(2);
359
+ i0.ɵɵtextInterpolate(prompt_r8.value.count);
360
+ i0.ɵɵadvance(2);
361
+ i0.ɵɵtextInterpolate(ctx_r1.formatDuration(prompt_r8.value.avgTime));
362
+ i0.ɵɵadvance(2);
363
+ i0.ɵɵtextInterpolate(ctx_r1.formatDuration(prompt_r8.value.totalTime));
364
+ i0.ɵɵadvance(3);
365
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.calculatePromptSuccessRate(prompt_r8.key), "% ");
366
+ } }
367
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_9_Template(rf, ctx) { if (rf & 1) {
368
+ i0.ɵɵelementStart(0, "div", 81)(1, "table")(2, "thead")(3, "tr")(4, "th");
369
+ i0.ɵɵtext(5, "Prompt Name");
370
+ i0.ɵɵelementEnd();
371
+ i0.ɵɵelementStart(6, "th");
372
+ i0.ɵɵtext(7, "Count");
373
+ i0.ɵɵelementEnd();
374
+ i0.ɵɵelementStart(8, "th");
375
+ i0.ɵɵtext(9, "Avg Time");
376
+ i0.ɵɵelementEnd();
377
+ i0.ɵɵelementStart(10, "th");
378
+ i0.ɵɵtext(11, "Total Time");
379
+ i0.ɵɵelementEnd();
380
+ i0.ɵɵelementStart(12, "th");
381
+ i0.ɵɵtext(13, "Success Rate");
382
+ i0.ɵɵelementEnd()()();
383
+ i0.ɵɵelementStart(14, "tbody");
384
+ i0.ɵɵtemplate(15, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_9_tr_15_Template, 12, 5, "tr", 82);
385
+ i0.ɵɵpipe(16, "keyvalue");
386
+ i0.ɵɵelementEnd()()();
387
+ } if (rf & 2) {
388
+ const ctx_r1 = i0.ɵɵnextContext(3);
389
+ i0.ɵɵadvance(15);
390
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(16, 1, ctx_r1.promptMetrics.byPrompt));
391
+ } }
392
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_7_Template(rf, ctx) { if (rf & 1) {
393
+ const _r3 = i0.ɵɵgetCurrentView();
394
+ i0.ɵɵelementStart(0, "div", 40);
395
+ i0.ɵɵtemplate(1, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_1_Template, 4, 2, "div", 41)(2, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_2_Template, 6, 0, "div", 42)(3, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_3_Template, 48, 14, "div", 43)(4, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_4_Template, 45, 12, "div", 44);
396
+ i0.ɵɵelementStart(5, "div", 45)(6, "button", 46);
397
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_7_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.promptDetailsExpanded = !ctx_r1.promptDetailsExpanded); });
398
+ i0.ɵɵelement(7, "i", 47);
399
+ i0.ɵɵtext(8, " Detailed Prompt Metrics ");
400
+ i0.ɵɵelementEnd();
401
+ i0.ɵɵtemplate(9, AIAgentRunAnalyticsComponent_div_3_ng_template_7_div_9_Template, 17, 3, "div", 48);
402
+ i0.ɵɵelementEnd()();
403
+ } if (rf & 2) {
404
+ const ctx_r1 = i0.ɵɵnextContext(2);
405
+ i0.ɵɵadvance();
406
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.totalCount > 0);
407
+ i0.ɵɵadvance();
408
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.totalCount === 0);
409
+ i0.ɵɵadvance();
410
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.totalCount > 0);
411
+ i0.ɵɵadvance();
412
+ i0.ɵɵproperty("ngIf", ctx_r1.promptMetrics.totalCount > 0);
413
+ i0.ɵɵadvance(3);
414
+ i0.ɵɵproperty("ngClass", ctx_r1.promptDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
415
+ i0.ɵɵadvance(2);
416
+ i0.ɵɵproperty("ngIf", ctx_r1.promptDetailsExpanded);
417
+ } }
418
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_9_Template(rf, ctx) { if (rf & 1) {
419
+ i0.ɵɵelement(0, "i", 34);
420
+ i0.ɵɵtext(1, " Action Analytics ");
421
+ } }
422
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_28_tr_15_Template(rf, ctx) { if (rf & 1) {
423
+ i0.ɵɵelementStart(0, "tr")(1, "td");
424
+ i0.ɵɵtext(2);
425
+ i0.ɵɵelementEnd();
426
+ i0.ɵɵelementStart(3, "td");
427
+ i0.ɵɵtext(4);
428
+ i0.ɵɵelementEnd();
429
+ i0.ɵɵelementStart(5, "td");
430
+ i0.ɵɵtext(6);
431
+ i0.ɵɵelementEnd();
432
+ i0.ɵɵelementStart(7, "td")(8, "span", 83);
433
+ i0.ɵɵtext(9);
434
+ i0.ɵɵelementEnd()();
435
+ i0.ɵɵelementStart(10, "td");
436
+ i0.ɵɵtext(11);
437
+ i0.ɵɵelementEnd()();
438
+ } if (rf & 2) {
439
+ const action_r10 = ctx.$implicit;
440
+ const ctx_r1 = i0.ɵɵnextContext(4);
441
+ i0.ɵɵadvance(2);
442
+ i0.ɵɵtextInterpolate(action_r10.key);
443
+ i0.ɵɵadvance(2);
444
+ i0.ɵɵtextInterpolate(action_r10.value.count);
445
+ i0.ɵɵadvance(2);
446
+ i0.ɵɵtextInterpolate(ctx_r1.formatDuration(action_r10.value.avgTime));
447
+ i0.ɵɵadvance(2);
448
+ i0.ɵɵclassProp("high", action_r10.value.successRate > 0.9)("medium", action_r10.value.successRate > 0.7 && action_r10.value.successRate <= 0.9)("low", action_r10.value.successRate <= 0.7);
449
+ i0.ɵɵadvance();
450
+ i0.ɵɵtextInterpolate1(" ", (action_r10.value.successRate * 100).toFixed(1), "% ");
451
+ i0.ɵɵadvance(2);
452
+ i0.ɵɵtextInterpolate(ctx_r1.getActionType(action_r10.key));
453
+ } }
454
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_28_Template(rf, ctx) { if (rf & 1) {
455
+ i0.ɵɵelementStart(0, "div", 81)(1, "table")(2, "thead")(3, "tr")(4, "th");
456
+ i0.ɵɵtext(5, "Action Name");
457
+ i0.ɵɵelementEnd();
458
+ i0.ɵɵelementStart(6, "th");
459
+ i0.ɵɵtext(7, "Count");
460
+ i0.ɵɵelementEnd();
461
+ i0.ɵɵelementStart(8, "th");
462
+ i0.ɵɵtext(9, "Avg Time");
463
+ i0.ɵɵelementEnd();
464
+ i0.ɵɵelementStart(10, "th");
465
+ i0.ɵɵtext(11, "Success Rate");
466
+ i0.ɵɵelementEnd();
467
+ i0.ɵɵelementStart(12, "th");
468
+ i0.ɵɵtext(13, "Type");
469
+ i0.ɵɵelementEnd()()();
470
+ i0.ɵɵelementStart(14, "tbody");
471
+ i0.ɵɵtemplate(15, AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_28_tr_15_Template, 12, 11, "tr", 82);
472
+ i0.ɵɵpipe(16, "keyvalue");
473
+ i0.ɵɵelementEnd()()();
474
+ } if (rf & 2) {
475
+ const ctx_r1 = i0.ɵɵnextContext(3);
476
+ i0.ɵɵadvance(15);
477
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(16, 1, ctx_r1.actionMetrics.byAction));
478
+ } }
479
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_30_div_7_Template(rf, ctx) { if (rf & 1) {
480
+ i0.ɵɵelementStart(0, "div", 96)(1, "span", 97);
481
+ i0.ɵɵtext(2);
482
+ i0.ɵɵelementEnd();
483
+ i0.ɵɵelementStart(3, "span", 98);
484
+ i0.ɵɵtext(4);
485
+ i0.ɵɵelementEnd()();
486
+ } if (rf & 2) {
487
+ const error_r11 = ctx.$implicit;
488
+ i0.ɵɵadvance(2);
489
+ i0.ɵɵtextInterpolate1("", error_r11.count, "x");
490
+ i0.ɵɵadvance(2);
491
+ i0.ɵɵtextInterpolate(error_r11.message);
492
+ } }
493
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_30_Template(rf, ctx) { if (rf & 1) {
494
+ i0.ɵɵelementStart(0, "div", 91)(1, "h3");
495
+ i0.ɵɵelement(2, "i", 92);
496
+ i0.ɵɵtext(3, " Common Errors ");
497
+ i0.ɵɵelementEnd();
498
+ i0.ɵɵelementStart(4, "p", 93);
499
+ i0.ɵɵtext(5, " This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention. ");
500
+ i0.ɵɵelementEnd();
501
+ i0.ɵɵelementStart(6, "div", 94);
502
+ i0.ɵɵtemplate(7, AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_30_div_7_Template, 5, 2, "div", 95);
503
+ i0.ɵɵelementEnd()();
504
+ } if (rf & 2) {
505
+ const ctx_r1 = i0.ɵɵnextContext(3);
506
+ i0.ɵɵadvance(7);
507
+ i0.ɵɵproperty("ngForOf", ctx_r1.getTopErrors());
508
+ } }
509
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_31_Template(rf, ctx) { if (rf & 1) {
510
+ i0.ɵɵelementStart(0, "div", 99);
511
+ i0.ɵɵelement(1, "i", 100);
512
+ i0.ɵɵelementStart(2, "p");
513
+ i0.ɵɵtext(3, "No action errors detected in this run. All actions completed successfully!");
514
+ i0.ɵɵelementEnd()();
515
+ } }
516
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_10_Template(rf, ctx) { if (rf & 1) {
517
+ const _r9 = i0.ɵɵgetCurrentView();
518
+ i0.ɵɵelementStart(0, "div", 40)(1, "div", 54)(2, "div", 55)(3, "div", 56);
519
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_10_Template_div_click_3_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("actionSuccess")); });
520
+ i0.ɵɵelementStart(4, "h3");
521
+ i0.ɵɵelement(5, "i", 84);
522
+ i0.ɵɵtext(6, " Action Success Rate");
523
+ i0.ɵɵelementEnd();
524
+ i0.ɵɵelementStart(7, "button", 58);
525
+ i0.ɵɵelement(8, "i", 47);
526
+ i0.ɵɵelementEnd()();
527
+ i0.ɵɵelementStart(9, "div", 59)(10, "div", 60);
528
+ i0.ɵɵelement(11, "div", 85, 8);
529
+ i0.ɵɵelementEnd()()();
530
+ i0.ɵɵelementStart(13, "div", 55)(14, "div", 56);
531
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_10_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("stepType")); });
532
+ i0.ɵɵelementStart(15, "h3");
533
+ i0.ɵɵelement(16, "i", 86);
534
+ i0.ɵɵtext(17, " Step Type Distribution");
535
+ i0.ɵɵelementEnd();
536
+ i0.ɵɵelementStart(18, "button", 58);
537
+ i0.ɵɵelement(19, "i", 47);
538
+ i0.ɵɵelementEnd()();
539
+ i0.ɵɵelementStart(20, "div", 59)(21, "div", 60);
540
+ i0.ɵɵelement(22, "div", 87, 9);
541
+ i0.ɵɵelementEnd()()()();
542
+ i0.ɵɵelementStart(24, "div", 45)(25, "button", 46);
543
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_div_3_ng_template_10_Template_button_click_25_listener() { i0.ɵɵrestoreView(_r9); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.actionDetailsExpanded = !ctx_r1.actionDetailsExpanded); });
544
+ i0.ɵɵelement(26, "i", 47);
545
+ i0.ɵɵtext(27, " Detailed Action Metrics ");
546
+ i0.ɵɵelementEnd();
547
+ i0.ɵɵtemplate(28, AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_28_Template, 17, 3, "div", 48);
548
+ i0.ɵɵelementEnd();
549
+ i0.ɵɵelementStart(29, "div", 88);
550
+ i0.ɵɵtemplate(30, AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_30_Template, 8, 1, "div", 89)(31, AIAgentRunAnalyticsComponent_div_3_ng_template_10_div_31_Template, 4, 0, "div", 90);
551
+ i0.ɵɵelementEnd()();
552
+ } if (rf & 2) {
553
+ const ctx_r1 = i0.ɵɵnextContext(2);
554
+ i0.ɵɵadvance(2);
555
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["actionSuccess"]);
556
+ i0.ɵɵadvance(6);
557
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["actionSuccess"] ? "fa-compress" : "fa-expand");
558
+ i0.ɵɵadvance(5);
559
+ i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["stepType"]);
560
+ i0.ɵɵadvance(6);
561
+ i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["stepType"] ? "fa-compress" : "fa-expand");
562
+ i0.ɵɵadvance(7);
563
+ i0.ɵɵproperty("ngClass", ctx_r1.actionDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
564
+ i0.ɵɵadvance(2);
565
+ i0.ɵɵproperty("ngIf", ctx_r1.actionDetailsExpanded);
566
+ i0.ɵɵadvance(2);
567
+ i0.ɵɵproperty("ngIf", ctx_r1.actionMetrics.errorAnalysis.size > 0);
568
+ i0.ɵɵadvance();
569
+ i0.ɵɵproperty("ngIf", ctx_r1.actionMetrics.errorAnalysis.size === 0);
570
+ } }
571
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_12_Template(rf, ctx) { if (rf & 1) {
572
+ i0.ɵɵelement(0, "i", 101);
573
+ i0.ɵɵtext(1, " Model Performance Comparison ");
574
+ } }
575
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_13_tr_22_Template(rf, ctx) { if (rf & 1) {
576
+ i0.ɵɵelementStart(0, "tr")(1, "td");
577
+ i0.ɵɵtext(2);
578
+ i0.ɵɵelementEnd();
579
+ i0.ɵɵelementStart(3, "td");
580
+ i0.ɵɵtext(4);
581
+ i0.ɵɵelementEnd();
582
+ i0.ɵɵelementStart(5, "td");
583
+ i0.ɵɵtext(6);
584
+ i0.ɵɵelementEnd();
585
+ i0.ɵɵelementStart(7, "td");
586
+ i0.ɵɵtext(8);
587
+ i0.ɵɵelementEnd();
588
+ i0.ɵɵelementStart(9, "td");
589
+ i0.ɵɵtext(10);
590
+ i0.ɵɵelementEnd();
591
+ i0.ɵɵelementStart(11, "td");
592
+ i0.ɵɵtext(12);
593
+ i0.ɵɵelementEnd();
594
+ i0.ɵɵelementStart(13, "td");
595
+ i0.ɵɵtext(14);
596
+ i0.ɵɵpipe(15, "number");
597
+ i0.ɵɵelementEnd();
598
+ i0.ɵɵelementStart(16, "td");
599
+ i0.ɵɵtext(17);
600
+ i0.ɵɵpipe(18, "number");
601
+ i0.ɵɵelementEnd()();
602
+ } if (rf & 2) {
603
+ const model_r12 = ctx.$implicit;
604
+ const ctx_r1 = i0.ɵɵnextContext(3);
605
+ i0.ɵɵadvance(2);
606
+ i0.ɵɵtextInterpolate(model_r12.name);
607
+ i0.ɵɵadvance(2);
608
+ i0.ɵɵtextInterpolate(model_r12.vendor);
609
+ i0.ɵɵadvance(2);
610
+ i0.ɵɵtextInterpolate(model_r12.count);
611
+ i0.ɵɵadvance(2);
612
+ i0.ɵɵtextInterpolate(ctx_r1.formatDuration(model_r12.avgTime));
613
+ i0.ɵɵadvance(2);
614
+ i0.ɵɵtextInterpolate(ctx_r1.formatCost(model_r12.totalCost));
615
+ i0.ɵɵadvance(2);
616
+ i0.ɵɵtextInterpolate(ctx_r1.formatCost(model_r12.avgCost));
617
+ i0.ɵɵadvance(2);
618
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(15, 8, model_r12.inputTokens, "1.0-0"));
619
+ i0.ɵɵadvance(3);
620
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(18, 11, model_r12.outputTokens, "1.0-0"));
621
+ } }
622
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_13_Template(rf, ctx) { if (rf & 1) {
623
+ i0.ɵɵelementStart(0, "div", 40)(1, "div", 102)(2, "table")(3, "thead")(4, "tr")(5, "th");
624
+ i0.ɵɵtext(6, "Model");
625
+ i0.ɵɵelementEnd();
626
+ i0.ɵɵelementStart(7, "th");
627
+ i0.ɵɵtext(8, "Vendor");
628
+ i0.ɵɵelementEnd();
629
+ i0.ɵɵelementStart(9, "th");
630
+ i0.ɵɵtext(10, "Prompts");
631
+ i0.ɵɵelementEnd();
632
+ i0.ɵɵelementStart(11, "th");
633
+ i0.ɵɵtext(12, "Avg Time");
634
+ i0.ɵɵelementEnd();
635
+ i0.ɵɵelementStart(13, "th");
636
+ i0.ɵɵtext(14, "Total Cost");
637
+ i0.ɵɵelementEnd();
638
+ i0.ɵɵelementStart(15, "th");
639
+ i0.ɵɵtext(16, "Avg Cost/Prompt");
640
+ i0.ɵɵelementEnd();
641
+ i0.ɵɵelementStart(17, "th");
642
+ i0.ɵɵtext(18, "Input Tokens");
643
+ i0.ɵɵelementEnd();
644
+ i0.ɵɵelementStart(19, "th");
645
+ i0.ɵɵtext(20, "Output Tokens");
646
+ i0.ɵɵelementEnd()()();
647
+ i0.ɵɵelementStart(21, "tbody");
648
+ i0.ɵɵtemplate(22, AIAgentRunAnalyticsComponent_div_3_ng_template_13_tr_22_Template, 19, 14, "tr", 82);
649
+ i0.ɵɵelementEnd()()()();
650
+ } if (rf & 2) {
651
+ const ctx_r1 = i0.ɵɵnextContext(2);
652
+ i0.ɵɵadvance(22);
653
+ i0.ɵɵproperty("ngForOf", ctx_r1.getModelPerformanceData());
654
+ } }
655
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_15_Template(rf, ctx) { if (rf & 1) {
656
+ i0.ɵɵelement(0, "i", 103);
657
+ i0.ɵɵtext(1, " Execution Timeline Analysis ");
658
+ } }
659
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_16_div_26_Template(rf, ctx) { if (rf & 1) {
660
+ i0.ɵɵelementStart(0, "div", 111);
661
+ i0.ɵɵelement(1, "i", 47);
662
+ i0.ɵɵelementStart(2, "span", 112);
663
+ i0.ɵɵtext(3);
664
+ i0.ɵɵelementEnd();
665
+ i0.ɵɵelementStart(4, "span", 113);
666
+ i0.ɵɵtext(5);
667
+ i0.ɵɵelementEnd();
668
+ i0.ɵɵelementStart(6, "span", 114);
669
+ i0.ɵɵtext(7);
670
+ i0.ɵɵelementEnd()();
671
+ } if (rf & 2) {
672
+ const type_r13 = ctx.$implicit;
673
+ const ctx_r1 = i0.ɵɵnextContext(3);
674
+ i0.ɵɵadvance();
675
+ i0.ɵɵproperty("ngClass", ctx_r1.getStepTypeIcon(type_r13.key));
676
+ i0.ɵɵadvance(2);
677
+ i0.ɵɵtextInterpolate(type_r13.key);
678
+ i0.ɵɵadvance(2);
679
+ i0.ɵɵtextInterpolate(type_r13.value);
680
+ i0.ɵɵadvance(2);
681
+ i0.ɵɵtextInterpolate1("(", (type_r13.value / ctx_r1.timelineMetrics.totalSteps * 100).toFixed(1), "%)");
682
+ } }
683
+ function AIAgentRunAnalyticsComponent_div_3_ng_template_16_Template(rf, ctx) { if (rf & 1) {
684
+ i0.ɵɵelementStart(0, "div", 40)(1, "div", 104)(2, "div", 105)(3, "span", 106);
685
+ i0.ɵɵtext(4, "Total Steps");
686
+ i0.ɵɵelementEnd();
687
+ i0.ɵɵelementStart(5, "span", 107);
688
+ i0.ɵɵtext(6);
689
+ i0.ɵɵelementEnd()();
690
+ i0.ɵɵelementStart(7, "div", 105)(8, "span", 106);
691
+ i0.ɵɵtext(9, "Parallel Executions");
692
+ i0.ɵɵelementEnd();
693
+ i0.ɵɵelementStart(10, "span", 107);
694
+ i0.ɵɵtext(11);
695
+ i0.ɵɵelementEnd()();
696
+ i0.ɵɵelementStart(12, "div", 105)(13, "span", 106);
697
+ i0.ɵɵtext(14, "Max Nesting Depth");
698
+ i0.ɵɵelementEnd();
699
+ i0.ɵɵelementStart(15, "span", 107);
700
+ i0.ɵɵtext(16);
701
+ i0.ɵɵelementEnd()();
702
+ i0.ɵɵelementStart(17, "div", 105)(18, "span", 106);
703
+ i0.ɵɵtext(19, "Sub-Agent Runs");
704
+ i0.ɵɵelementEnd();
705
+ i0.ɵɵelementStart(20, "span", 107);
706
+ i0.ɵɵtext(21);
707
+ i0.ɵɵelementEnd()()();
708
+ i0.ɵɵelementStart(22, "div", 108)(23, "h3");
709
+ i0.ɵɵtext(24, "Steps by Type");
710
+ i0.ɵɵelementEnd();
711
+ i0.ɵɵelementStart(25, "div", 109);
712
+ i0.ɵɵtemplate(26, AIAgentRunAnalyticsComponent_div_3_ng_template_16_div_26_Template, 8, 4, "div", 110);
713
+ i0.ɵɵpipe(27, "keyvalue");
714
+ i0.ɵɵelementEnd()()();
715
+ } if (rf & 2) {
716
+ const ctx_r1 = i0.ɵɵnextContext(2);
717
+ i0.ɵɵadvance(6);
718
+ i0.ɵɵtextInterpolate(ctx_r1.timelineMetrics.totalSteps);
719
+ i0.ɵɵadvance(5);
720
+ i0.ɵɵtextInterpolate(ctx_r1.timelineMetrics.parallelExecutions);
721
+ i0.ɵɵadvance(5);
722
+ i0.ɵɵtextInterpolate(ctx_r1.timelineMetrics.deepestNesting);
723
+ i0.ɵɵadvance(5);
724
+ i0.ɵɵtextInterpolate(ctx_r1.subAgentRuns.length);
725
+ i0.ɵɵadvance(5);
726
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind1(27, 5, ctx_r1.timelineMetrics.stepsByType));
727
+ } }
728
+ function AIAgentRunAnalyticsComponent_div_3_Template(rf, ctx) { if (rf & 1) {
729
+ i0.ɵɵelementStart(0, "div", 19)(1, "kendo-panelbar")(2, "kendo-panelbar-item", 20);
730
+ i0.ɵɵtemplate(3, AIAgentRunAnalyticsComponent_div_3_ng_template_3_Template, 2, 0, "ng-template", 21)(4, AIAgentRunAnalyticsComponent_div_3_ng_template_4_Template, 47, 10, "ng-template", 22);
731
+ i0.ɵɵelementEnd();
732
+ i0.ɵɵelementStart(5, "kendo-panelbar-item", 20);
733
+ i0.ɵɵtemplate(6, AIAgentRunAnalyticsComponent_div_3_ng_template_6_Template, 2, 0, "ng-template", 21)(7, AIAgentRunAnalyticsComponent_div_3_ng_template_7_Template, 10, 6, "ng-template", 22);
734
+ i0.ɵɵelementEnd();
735
+ i0.ɵɵelementStart(8, "kendo-panelbar-item", 20);
736
+ i0.ɵɵtemplate(9, AIAgentRunAnalyticsComponent_div_3_ng_template_9_Template, 2, 0, "ng-template", 21)(10, AIAgentRunAnalyticsComponent_div_3_ng_template_10_Template, 32, 10, "ng-template", 22);
737
+ i0.ɵɵelementEnd();
738
+ i0.ɵɵelementStart(11, "kendo-panelbar-item", 20);
739
+ i0.ɵɵtemplate(12, AIAgentRunAnalyticsComponent_div_3_ng_template_12_Template, 2, 0, "ng-template", 21)(13, AIAgentRunAnalyticsComponent_div_3_ng_template_13_Template, 23, 1, "ng-template", 22);
740
+ i0.ɵɵelementEnd();
741
+ i0.ɵɵelementStart(14, "kendo-panelbar-item", 20);
742
+ i0.ɵɵtemplate(15, AIAgentRunAnalyticsComponent_div_3_ng_template_15_Template, 2, 0, "ng-template", 21)(16, AIAgentRunAnalyticsComponent_div_3_ng_template_16_Template, 28, 7, "ng-template", 22);
743
+ i0.ɵɵelementEnd()()();
744
+ } if (rf & 2) {
745
+ i0.ɵɵadvance(2);
746
+ i0.ɵɵproperty("expanded", true);
747
+ i0.ɵɵadvance(3);
748
+ i0.ɵɵproperty("expanded", true);
749
+ i0.ɵɵadvance(3);
750
+ i0.ɵɵproperty("expanded", true);
751
+ i0.ɵɵadvance(3);
752
+ i0.ɵɵproperty("expanded", true);
753
+ i0.ɵɵadvance(3);
754
+ i0.ɵɵproperty("expanded", true);
755
+ } }
756
+ export class AIAgentRunAnalyticsComponent {
757
+ constructor(cdr) {
758
+ this.cdr = cdr;
759
+ this.destroy$ = new Subject();
760
+ // Chart expansion states
761
+ this.expandedCharts = {
762
+ modelDistribution: false,
763
+ executionTime: false,
764
+ costByVendor: false,
765
+ tokenUsage: false,
766
+ promptTime: false,
767
+ promptToken: false,
768
+ promptCost: false,
769
+ promptCount: false,
770
+ actionSuccess: false,
771
+ stepType: false
772
+ };
773
+ this.viewMode = 'grid';
774
+ // Loading state
775
+ this.isLoading = true;
776
+ this.error = null;
777
+ // Data
778
+ this.agentRun = null;
779
+ this.allPromptRuns = [];
780
+ this.allActionLogs = [];
781
+ this.allSteps = [];
782
+ this.subAgentRuns = [];
783
+ // Metrics
784
+ this.promptMetrics = this.initializePromptMetrics();
785
+ this.actionMetrics = this.initializeActionMetrics();
786
+ this.timelineMetrics = this.initializeTimelineMetrics();
787
+ // Expanded sections
788
+ this.promptDetailsExpanded = false;
789
+ this.actionDetailsExpanded = false;
790
+ // Expansion panel states
791
+ this.panelStates = {
792
+ summary: true,
793
+ prompts: true,
794
+ actions: true,
795
+ models: true,
796
+ timeline: true
797
+ };
798
+ }
799
+ ngOnInit() {
800
+ if (this.agentRunId) {
801
+ this.loadData();
802
+ }
803
+ }
804
+ ngOnDestroy() {
805
+ this.destroy$.next();
806
+ this.destroy$.complete();
807
+ }
808
+ ngAfterViewInit() {
809
+ // Charts will be rendered after data is loaded
810
+ }
811
+ async loadData() {
812
+ this.isLoading = true;
813
+ this.error = null;
814
+ try {
815
+ // Load all data including nested sub-agent runs
816
+ await this.loadAllRunData();
817
+ // Calculate metrics
818
+ this.calculatePromptMetrics();
819
+ this.calculateActionMetrics();
820
+ this.calculateTimelineMetrics();
821
+ // Prepare chart data
822
+ this.prepareChartData();
823
+ // Render charts after view updates
824
+ this.cdr.detectChanges();
825
+ setTimeout(() => {
826
+ this.renderCharts();
827
+ });
828
+ }
829
+ catch (error) {
830
+ console.error('Error loading analytics data:', error);
831
+ this.error = 'Failed to load analytics data';
832
+ }
833
+ finally {
834
+ this.isLoading = false;
835
+ this.cdr.detectChanges();
836
+ }
837
+ }
838
+ async loadAllRunData() {
839
+ const rv = new RunView();
840
+ // Get all agent runs in the hierarchy (including the main run and all sub-agent runs)
841
+ const agentRunIds = await this.getAllAgentRunIds(this.agentRunId);
842
+ console.log('Loading analytics for agent run IDs:', agentRunIds);
843
+ console.log('Number of agent run IDs:', agentRunIds.length);
844
+ // Batch load all data
845
+ const results = await rv.RunViews([
846
+ // Main agent run
847
+ {
848
+ EntityName: 'MJ: AI Agent Runs',
849
+ ExtraFilter: `ID = '${this.agentRunId}'`,
850
+ },
851
+ // All sub-agent runs
852
+ {
853
+ EntityName: 'MJ: AI Agent Runs',
854
+ ExtraFilter: agentRunIds.length > 1 ? `ID IN ('${agentRunIds.slice(1).join("','")}')` : `ID = '00000000-0000-0000-0000-000000000000'`,
855
+ },
856
+ // All prompt runs for all agent runs - linked through AI Agent Run Steps
857
+ {
858
+ EntityName: 'MJ: AI Prompt Runs',
859
+ ExtraFilter: `ID IN (SELECT TargetLogID FROM __mj.vwAIAgentRunSteps WHERE AgentRunID IN ('${agentRunIds.join("','")}') AND StepType = 'Prompt')`,
860
+ },
861
+ // All action logs - need to get via steps
862
+ {
863
+ EntityName: 'MJ: AI Agent Run Steps',
864
+ ExtraFilter: `AgentRunID IN ('${agentRunIds.join("','")}') AND StepType = 'Actions'`,
865
+ },
866
+ // All steps for timeline analysis
867
+ {
868
+ EntityName: 'MJ: AI Agent Run Steps',
869
+ ExtraFilter: `AgentRunID IN ('${agentRunIds.join("','")}')`,
870
+ ResultType: 'entity_object'
871
+ }
872
+ ]);
873
+ // Process results
874
+ console.log('RunViews results:', results.map((r, i) => ({
875
+ index: i,
876
+ success: r.Success,
877
+ count: r.Results?.length || 0,
878
+ errorMessage: r.ErrorMessage
879
+ })));
880
+ if (results[0].Success && results[0].Results && results[0].Results.length > 0) {
881
+ this.agentRun = results[0].Results[0];
882
+ }
883
+ if (results[1].Success) {
884
+ this.subAgentRuns = results[1].Results || [];
885
+ }
886
+ if (results[2].Success) {
887
+ this.allPromptRuns = results[2].Results || [];
888
+ console.log(`Found ${this.allPromptRuns.length} prompt runs for agent run IDs:`, agentRunIds);
889
+ console.log('Prompt runs query:', `ID IN (SELECT TargetLogID FROM __mj.vwAIAgentRunSteps WHERE AgentRunID IN ('${agentRunIds.join("','")}') AND StepType = 'Prompts')`);
890
+ if (this.allPromptRuns.length > 0) {
891
+ console.log('First prompt run sample:', this.allPromptRuns[0]);
892
+ }
893
+ }
894
+ else {
895
+ console.error('Failed to load prompt runs:', results[2].ErrorMessage);
896
+ }
897
+ if (results[3].Success) {
898
+ const actionSteps = results[3].Results || [];
899
+ // Now load the actual action logs
900
+ if (actionSteps.length > 0) {
901
+ const actionLogIds = actionSteps
902
+ .map(s => s.TargetLogID)
903
+ .filter(id => id != null);
904
+ if (actionLogIds.length > 0) {
905
+ const actionResult = await rv.RunView({
906
+ EntityName: 'Action Execution Logs',
907
+ ExtraFilter: `ID IN ('${actionLogIds.join("','")}')`
908
+ });
909
+ if (actionResult.Success) {
910
+ this.allActionLogs = actionResult.Results || [];
911
+ }
912
+ }
913
+ }
914
+ }
915
+ if (results[4].Success) {
916
+ this.allSteps = results[4].Results || [];
917
+ }
918
+ }
919
+ async getAllAgentRunIds(rootRunId) {
920
+ const allIds = [rootRunId];
921
+ const rv = new RunView();
922
+ // Recursively get all sub-agent run IDs
923
+ const getSubRunIds = async (parentId, depth = 0) => {
924
+ const result = await rv.RunView({
925
+ EntityName: 'MJ: AI Agent Runs',
926
+ ExtraFilter: `ParentRunID = '${parentId}'`,
927
+ ResultType: 'entity_object'
928
+ });
929
+ if (result.Success && result.Results) {
930
+ console.log(`Found ${result.Results.length} sub-agent runs at depth ${depth} for parent ${parentId}`);
931
+ for (const subRun of result.Results) {
932
+ allIds.push(subRun.ID);
933
+ await getSubRunIds(subRun.ID, depth + 1); // Recursive call
934
+ }
935
+ }
936
+ };
937
+ await getSubRunIds(rootRunId);
938
+ console.log(`Total agent run IDs found: ${allIds.length}`);
939
+ return allIds;
940
+ }
941
+ initializePromptMetrics() {
942
+ return {
943
+ totalCount: 0,
944
+ totalExecutionTime: 0,
945
+ averageExecutionTime: 0,
946
+ byModel: new Map(),
947
+ byVendor: new Map(),
948
+ byPrompt: new Map(),
949
+ statusBreakdown: { success: 0, failed: 0, timeout: 0 },
950
+ costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map() },
951
+ tokenUsage: { totalInput: 0, totalOutput: 0, byModel: new Map() }
952
+ };
953
+ }
954
+ initializeActionMetrics() {
955
+ return {
956
+ totalCount: 0,
957
+ totalExecutionTime: 0,
958
+ averageExecutionTime: 0,
959
+ byAction: new Map(),
960
+ byType: new Map(),
961
+ statusBreakdown: { success: 0, failed: 0, timeout: 0 },
962
+ errorAnalysis: new Map()
963
+ };
964
+ }
965
+ initializeTimelineMetrics() {
966
+ return {
967
+ totalSteps: 0,
968
+ stepsByType: new Map(),
969
+ parallelExecutions: 0,
970
+ deepestNesting: 0,
971
+ criticalPath: { steps: [], totalTime: 0 }
972
+ };
973
+ }
974
+ calculatePromptMetrics() {
975
+ const metrics = this.initializePromptMetrics();
976
+ for (const promptRun of this.allPromptRuns) {
977
+ metrics.totalCount++;
978
+ // Calculate execution time
979
+ const execTime = this.calculateExecutionTime(promptRun.RunAt, promptRun.CompletedAt);
980
+ metrics.totalExecutionTime += execTime;
981
+ // Update model metrics
982
+ const model = promptRun.Model || 'Unknown';
983
+ const modelMetric = metrics.byModel.get(model) || { count: 0, totalTime: 0, avgTime: 0 };
984
+ modelMetric.count++;
985
+ modelMetric.totalTime += execTime;
986
+ modelMetric.avgTime = modelMetric.totalTime / modelMetric.count;
987
+ metrics.byModel.set(model, modelMetric);
988
+ // Update vendor metrics
989
+ const vendor = promptRun.Vendor || 'Unknown';
990
+ const vendorMetric = metrics.byVendor.get(vendor) || { count: 0, totalTime: 0, avgTime: 0 };
991
+ vendorMetric.count++;
992
+ vendorMetric.totalTime += execTime;
993
+ vendorMetric.avgTime = vendorMetric.totalTime / vendorMetric.count;
994
+ metrics.byVendor.set(vendor, vendorMetric);
995
+ // Update prompt name metrics
996
+ const promptName = promptRun.Prompt || 'Unknown';
997
+ const promptMetric = metrics.byPrompt.get(promptName) || { count: 0, totalTime: 0, avgTime: 0 };
998
+ promptMetric.count++;
999
+ promptMetric.totalTime += execTime;
1000
+ promptMetric.avgTime = promptMetric.totalTime / promptMetric.count;
1001
+ metrics.byPrompt.set(promptName, promptMetric);
1002
+ // Status breakdown
1003
+ if (promptRun.Success) {
1004
+ metrics.statusBreakdown.success++;
1005
+ }
1006
+ else if (promptRun.ErrorMessage?.includes('timeout')) {
1007
+ metrics.statusBreakdown.timeout++;
1008
+ }
1009
+ else {
1010
+ metrics.statusBreakdown.failed++;
1011
+ }
1012
+ // Cost tracking
1013
+ const cost = promptRun.TotalCost || 0;
1014
+ metrics.costBreakdown.totalCost += cost;
1015
+ const modelCost = metrics.costBreakdown.byModel.get(model) || 0;
1016
+ metrics.costBreakdown.byModel.set(model, modelCost + cost);
1017
+ const vendorCost = metrics.costBreakdown.byVendor.get(vendor) || 0;
1018
+ metrics.costBreakdown.byVendor.set(vendor, vendorCost + cost);
1019
+ // Token usage
1020
+ const inputTokens = promptRun.TokensPrompt || 0;
1021
+ const outputTokens = promptRun.TokensCompletion || 0;
1022
+ metrics.tokenUsage.totalInput += inputTokens;
1023
+ metrics.tokenUsage.totalOutput += outputTokens;
1024
+ const modelTokens = metrics.tokenUsage.byModel.get(model) || { input: 0, output: 0 };
1025
+ modelTokens.input += inputTokens;
1026
+ modelTokens.output += outputTokens;
1027
+ metrics.tokenUsage.byModel.set(model, modelTokens);
1028
+ }
1029
+ // Calculate overall average
1030
+ if (metrics.totalCount > 0) {
1031
+ metrics.averageExecutionTime = metrics.totalExecutionTime / metrics.totalCount;
1032
+ }
1033
+ this.promptMetrics = metrics;
1034
+ }
1035
+ calculateActionMetrics() {
1036
+ const metrics = this.initializeActionMetrics();
1037
+ for (const actionLog of this.allActionLogs) {
1038
+ metrics.totalCount++;
1039
+ // Calculate execution time
1040
+ const execTime = this.calculateExecutionTime(actionLog.StartedAt, actionLog.EndedAt);
1041
+ metrics.totalExecutionTime += execTime;
1042
+ // Update action metrics
1043
+ const actionName = actionLog.Action || 'Unknown';
1044
+ const actionMetric = metrics.byAction.get(actionName) || { count: 0, totalTime: 0, avgTime: 0, successRate: 0 };
1045
+ actionMetric.count++;
1046
+ actionMetric.totalTime += execTime;
1047
+ actionMetric.avgTime = actionMetric.totalTime / actionMetric.count;
1048
+ // Track success rate
1049
+ if (actionLog.ResultCode === 'Success') {
1050
+ const successCount = (actionMetric.successRate * (actionMetric.count - 1) + 1);
1051
+ actionMetric.successRate = successCount / actionMetric.count;
1052
+ }
1053
+ else {
1054
+ actionMetric.successRate = (actionMetric.successRate * (actionMetric.count - 1)) / actionMetric.count;
1055
+ }
1056
+ metrics.byAction.set(actionName, actionMetric);
1057
+ // Update type metrics
1058
+ // Action type is not directly available on ActionExecutionLogEntity
1059
+ const actionType = 'Action'; // Generic type for now
1060
+ const typeMetric = metrics.byType.get(actionType) || { count: 0, totalTime: 0, avgTime: 0 };
1061
+ typeMetric.count++;
1062
+ typeMetric.totalTime += execTime;
1063
+ typeMetric.avgTime = typeMetric.totalTime / typeMetric.count;
1064
+ metrics.byType.set(actionType, typeMetric);
1065
+ // Status breakdown
1066
+ if (actionLog.ResultCode === 'Success') {
1067
+ metrics.statusBreakdown.success++;
1068
+ }
1069
+ else if (actionLog.ResultCode === 'Timeout') {
1070
+ metrics.statusBreakdown.timeout++;
1071
+ }
1072
+ else {
1073
+ metrics.statusBreakdown.failed++;
1074
+ // Error analysis
1075
+ if (actionLog.Message) {
1076
+ const errorCount = metrics.errorAnalysis.get(actionLog.Message) || 0;
1077
+ metrics.errorAnalysis.set(actionLog.Message, errorCount + 1);
1078
+ }
1079
+ }
1080
+ }
1081
+ // Calculate overall average
1082
+ if (metrics.totalCount > 0) {
1083
+ metrics.averageExecutionTime = metrics.totalExecutionTime / metrics.totalCount;
1084
+ }
1085
+ this.actionMetrics = metrics;
1086
+ }
1087
+ calculateTimelineMetrics() {
1088
+ const metrics = this.initializeTimelineMetrics();
1089
+ metrics.totalSteps = this.allSteps.length;
1090
+ // Count steps by type
1091
+ for (const step of this.allSteps) {
1092
+ const type = step.StepType || 'Unknown';
1093
+ const count = metrics.stepsByType.get(type) || 0;
1094
+ metrics.stepsByType.set(type, count + 1);
1095
+ }
1096
+ // TODO: Calculate parallel executions, deepest nesting, and critical path
1097
+ // This would require more complex analysis of the step relationships
1098
+ this.timelineMetrics = metrics;
1099
+ }
1100
+ calculateExecutionTime(start, end) {
1101
+ if (!start || !end)
1102
+ return 0;
1103
+ return new Date(end).getTime() - new Date(start).getTime();
1104
+ }
1105
+ prepareChartData() {
1106
+ // Model distribution pie chart
1107
+ this.modelDistributionChartData = {
1108
+ labels: Array.from(this.promptMetrics.byModel.keys()),
1109
+ datasets: [{
1110
+ data: Array.from(this.promptMetrics.byModel.values()).map(m => m.count),
1111
+ backgroundColor: this.generateColors(this.promptMetrics.byModel.size)
1112
+ }]
1113
+ };
1114
+ // Execution time by vendor bar chart
1115
+ this.executionTimeChartData = {
1116
+ labels: Array.from(this.promptMetrics.byVendor.keys()),
1117
+ datasets: [{
1118
+ label: 'Average Execution Time (ms)',
1119
+ data: Array.from(this.promptMetrics.byVendor.values()).map(v => v.avgTime),
1120
+ backgroundColor: 'rgba(54, 162, 235, 0.5)',
1121
+ borderColor: 'rgba(54, 162, 235, 1)',
1122
+ borderWidth: 1
1123
+ }]
1124
+ };
1125
+ // Cost by vendor doughnut chart
1126
+ this.costByVendorChartData = {
1127
+ labels: Array.from(this.promptMetrics.costBreakdown.byVendor.keys()),
1128
+ datasets: [{
1129
+ data: Array.from(this.promptMetrics.costBreakdown.byVendor.values()),
1130
+ backgroundColor: this.generateColors(this.promptMetrics.costBreakdown.byVendor.size)
1131
+ }]
1132
+ };
1133
+ // Token usage stacked bar chart
1134
+ const tokenModels = Array.from(this.promptMetrics.tokenUsage.byModel.keys());
1135
+ this.tokenUsageChartData = {
1136
+ labels: tokenModels,
1137
+ datasets: [
1138
+ {
1139
+ label: 'Input Tokens',
1140
+ data: tokenModels.map(m => this.promptMetrics.tokenUsage.byModel.get(m)?.input || 0),
1141
+ backgroundColor: 'rgba(255, 99, 132, 0.5)'
1142
+ },
1143
+ {
1144
+ label: 'Output Tokens',
1145
+ data: tokenModels.map(m => this.promptMetrics.tokenUsage.byModel.get(m)?.output || 0),
1146
+ backgroundColor: 'rgba(75, 192, 192, 0.5)'
1147
+ }
1148
+ ]
1149
+ };
1150
+ // Action success rate bar chart
1151
+ this.actionSuccessRateChartData = {
1152
+ labels: Array.from(this.actionMetrics.byAction.keys()),
1153
+ datasets: [{
1154
+ label: 'Success Rate (%)',
1155
+ data: Array.from(this.actionMetrics.byAction.values()).map(a => a.successRate * 100),
1156
+ backgroundColor: 'rgba(75, 192, 192, 0.5)',
1157
+ borderColor: 'rgba(75, 192, 192, 1)',
1158
+ borderWidth: 1
1159
+ }]
1160
+ };
1161
+ // Step type distribution pie chart
1162
+ this.stepTypeDistributionChartData = {
1163
+ labels: Array.from(this.timelineMetrics.stepsByType.keys()),
1164
+ datasets: [{
1165
+ data: Array.from(this.timelineMetrics.stepsByType.values()),
1166
+ backgroundColor: this.generateColors(this.timelineMetrics.stepsByType.size)
1167
+ }]
1168
+ };
1169
+ }
1170
+ generateColors(count) {
1171
+ const colors = [
1172
+ 'rgba(255, 99, 132, 0.5)',
1173
+ 'rgba(54, 162, 235, 0.5)',
1174
+ 'rgba(255, 206, 86, 0.5)',
1175
+ 'rgba(75, 192, 192, 0.5)',
1176
+ 'rgba(153, 102, 255, 0.5)',
1177
+ 'rgba(255, 159, 64, 0.5)',
1178
+ 'rgba(199, 199, 199, 0.5)',
1179
+ 'rgba(83, 102, 255, 0.5)',
1180
+ 'rgba(255, 99, 255, 0.5)',
1181
+ 'rgba(99, 255, 132, 0.5)'
1182
+ ];
1183
+ // Repeat colors if needed
1184
+ const result = [];
1185
+ for (let i = 0; i < count; i++) {
1186
+ result.push(colors[i % colors.length]);
1187
+ }
1188
+ return result;
1189
+ }
1190
+ formatDuration(ms) {
1191
+ if (ms < 1000)
1192
+ return `${ms.toFixed(0)}ms`;
1193
+ if (ms < 60000)
1194
+ return `${(ms / 1000).toFixed(1)}s`;
1195
+ if (ms < 3600000)
1196
+ return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
1197
+ return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`;
1198
+ }
1199
+ formatCost(cost) {
1200
+ if (cost < 0.01)
1201
+ return `$${cost.toFixed(4)}`;
1202
+ if (cost < 1)
1203
+ return `$${cost.toFixed(3)}`;
1204
+ return `$${cost.toFixed(2)}`;
1205
+ }
1206
+ refresh() {
1207
+ this.loadData();
1208
+ }
1209
+ renderCharts() {
1210
+ if (!this.modelDistributionChart)
1211
+ return; // Charts not ready yet
1212
+ this.renderModelDistributionChart();
1213
+ this.renderExecutionTimeChart();
1214
+ this.renderCostByVendorChart();
1215
+ this.renderTokenUsageChart();
1216
+ this.renderActionSuccessRateChart();
1217
+ this.renderStepTypeChart();
1218
+ // Additional prompt analytics charts
1219
+ this.renderPromptTimeDistributionChart();
1220
+ this.renderPromptTokenDistributionChart();
1221
+ this.renderPromptCostDistributionChart();
1222
+ this.renderPromptCountByNameChart();
1223
+ }
1224
+ renderModelDistributionChart() {
1225
+ const element = this.modelDistributionChart.nativeElement;
1226
+ const data = Array.from(this.promptMetrics.byModel.entries()).map(([name, metrics]) => ({
1227
+ name,
1228
+ value: metrics.count
1229
+ }));
1230
+ if (data.length === 0)
1231
+ return;
1232
+ // Clear previous chart
1233
+ d3.select(element).selectAll('*').remove();
1234
+ const isExpanded = this.expandedCharts['modelDistribution'];
1235
+ const width = isExpanded ? 500 : 300;
1236
+ const height = isExpanded ? 400 : 220;
1237
+ const radius = Math.min(width, height) / 2 - 40;
1238
+ const svg = d3.select(element)
1239
+ .append('svg')
1240
+ .attr('width', width)
1241
+ .attr('height', height)
1242
+ .append('g')
1243
+ .attr('transform', `translate(${width / 2}, ${height / 2})`);
1244
+ const color = d3.scaleOrdinal(d3.schemeCategory10);
1245
+ const pie = d3.pie()
1246
+ .value(d => d.value)
1247
+ .sort(null);
1248
+ const arc = d3.arc()
1249
+ .innerRadius(0)
1250
+ .outerRadius(radius);
1251
+ const arcs = svg.selectAll('arc')
1252
+ .data(pie(data))
1253
+ .enter()
1254
+ .append('g');
1255
+ arcs.append('path')
1256
+ .attr('d', arc)
1257
+ .attr('fill', (d, i) => color(i.toString()))
1258
+ .attr('stroke', 'white')
1259
+ .style('stroke-width', '2px');
1260
+ // Add labels
1261
+ arcs.append('text')
1262
+ .attr('transform', (d) => `translate(${arc.centroid(d)})`)
1263
+ .attr('text-anchor', 'middle')
1264
+ .style('font-size', '12px')
1265
+ .style('fill', 'white')
1266
+ .text((d) => d.data.value > 0 ? d.data.value : '');
1267
+ // Add title
1268
+ svg.append('text')
1269
+ .attr('x', 0)
1270
+ .attr('y', -radius - 25)
1271
+ .attr('text-anchor', 'middle')
1272
+ .style('font-size', '16px')
1273
+ .style('font-weight', 'bold')
1274
+ .text('Prompts by Model');
1275
+ }
1276
+ renderExecutionTimeChart() {
1277
+ const element = this.executionTimeChart.nativeElement;
1278
+ const data = Array.from(this.promptMetrics.byVendor.entries()).map(([name, metrics]) => ({
1279
+ name,
1280
+ value: metrics.avgTime
1281
+ }));
1282
+ if (data.length === 0)
1283
+ return;
1284
+ // Clear previous chart
1285
+ d3.select(element).selectAll('*').remove();
1286
+ const isExpanded = this.expandedCharts['executionTime'];
1287
+ const margin = { top: 40, right: 20, bottom: 70, left: 60 };
1288
+ const width = (isExpanded ? 600 : 320) - margin.left - margin.right;
1289
+ const height = (isExpanded ? 350 : 200) - margin.top - margin.bottom;
1290
+ const svg = d3.select(element)
1291
+ .append('svg')
1292
+ .attr('width', width + margin.left + margin.right)
1293
+ .attr('height', height + margin.top + margin.bottom)
1294
+ .append('g')
1295
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1296
+ const x = d3.scaleBand()
1297
+ .range([0, width])
1298
+ .domain(data.map(d => d.name))
1299
+ .padding(0.1);
1300
+ const y = d3.scaleLinear()
1301
+ .domain([0, d3.max(data, d => d.value) || 0])
1302
+ .range([height, 0]);
1303
+ // Add bars
1304
+ svg.selectAll('.bar')
1305
+ .data(data)
1306
+ .enter().append('rect')
1307
+ .attr('class', 'bar')
1308
+ .attr('x', d => x(d.name) || 0)
1309
+ .attr('width', x.bandwidth())
1310
+ .attr('y', d => y(d.value))
1311
+ .attr('height', d => height - y(d.value))
1312
+ .attr('fill', '#36a2eb');
1313
+ // Add x axis
1314
+ svg.append('g')
1315
+ .attr('transform', `translate(0,${height})`)
1316
+ .call(d3.axisBottom(x))
1317
+ .selectAll('text')
1318
+ .attr('transform', 'rotate(-45)')
1319
+ .style('text-anchor', 'end');
1320
+ // Add y axis
1321
+ svg.append('g')
1322
+ .call(d3.axisLeft(y).tickFormat(d => `${d}ms`));
1323
+ // Add title
1324
+ svg.append('text')
1325
+ .attr('x', width / 2)
1326
+ .attr('y', -20)
1327
+ .attr('text-anchor', 'middle')
1328
+ .style('font-size', '16px')
1329
+ .style('font-weight', 'bold')
1330
+ .text('Average Execution Time by Vendor');
1331
+ }
1332
+ renderCostByVendorChart() {
1333
+ const element = this.costByVendorChart.nativeElement;
1334
+ const data = Array.from(this.promptMetrics.costBreakdown.byVendor.entries()).map(([name, cost]) => ({
1335
+ name,
1336
+ value: cost
1337
+ }));
1338
+ if (data.length === 0)
1339
+ return;
1340
+ // Clear previous chart
1341
+ d3.select(element).selectAll('*').remove();
1342
+ const width = 300;
1343
+ const height = 220;
1344
+ const radius = Math.min(width, height) / 2 - 40;
1345
+ const svg = d3.select(element)
1346
+ .append('svg')
1347
+ .attr('width', width)
1348
+ .attr('height', height)
1349
+ .append('g')
1350
+ .attr('transform', `translate(${width / 2}, ${height / 2})`);
1351
+ const color = d3.scaleOrdinal(d3.schemeSet2);
1352
+ const pie = d3.pie()
1353
+ .value(d => d.value)
1354
+ .sort(null);
1355
+ const arc = d3.arc()
1356
+ .innerRadius(radius * 0.5) // Doughnut chart
1357
+ .outerRadius(radius);
1358
+ const arcs = svg.selectAll('arc')
1359
+ .data(pie(data))
1360
+ .enter()
1361
+ .append('g');
1362
+ arcs.append('path')
1363
+ .attr('d', arc)
1364
+ .attr('fill', (d, i) => color(i.toString()))
1365
+ .attr('stroke', 'white')
1366
+ .style('stroke-width', '2px');
1367
+ // Add title
1368
+ svg.append('text')
1369
+ .attr('x', 0)
1370
+ .attr('y', -radius - 25)
1371
+ .attr('text-anchor', 'middle')
1372
+ .style('font-size', '16px')
1373
+ .style('font-weight', 'bold')
1374
+ .text('Cost Distribution by Vendor');
1375
+ }
1376
+ renderTokenUsageChart() {
1377
+ const element = this.tokenUsageChart.nativeElement;
1378
+ const models = Array.from(this.promptMetrics.tokenUsage.byModel.keys());
1379
+ const inputData = models.map(model => ({
1380
+ model,
1381
+ type: 'Input',
1382
+ value: this.promptMetrics.tokenUsage.byModel.get(model)?.input || 0
1383
+ }));
1384
+ const outputData = models.map(model => ({
1385
+ model,
1386
+ type: 'Output',
1387
+ value: this.promptMetrics.tokenUsage.byModel.get(model)?.output || 0
1388
+ }));
1389
+ const data = [...inputData, ...outputData];
1390
+ if (data.length === 0)
1391
+ return;
1392
+ // Clear previous chart
1393
+ d3.select(element).selectAll('*').remove();
1394
+ const margin = { top: 40, right: 100, bottom: 70, left: 60 };
1395
+ const width = 320 - margin.left - margin.right;
1396
+ const height = 200 - margin.top - margin.bottom;
1397
+ const svg = d3.select(element)
1398
+ .append('svg')
1399
+ .attr('width', width + margin.left + margin.right)
1400
+ .attr('height', height + margin.top + margin.bottom)
1401
+ .append('g')
1402
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1403
+ const x0 = d3.scaleBand()
1404
+ .rangeRound([0, width])
1405
+ .paddingInner(0.1)
1406
+ .domain(models);
1407
+ const x1 = d3.scaleBand()
1408
+ .padding(0.05)
1409
+ .domain(['Input', 'Output'])
1410
+ .rangeRound([0, x0.bandwidth()]);
1411
+ const y = d3.scaleLinear()
1412
+ .rangeRound([height, 0])
1413
+ .domain([0, d3.max(data, d => d.value) || 0]);
1414
+ const color = d3.scaleOrdinal()
1415
+ .domain(['Input', 'Output'])
1416
+ .range(['#ff6384', '#4bc0c0']);
1417
+ const grouped = d3.group(data, d => d.model);
1418
+ svg.append('g')
1419
+ .selectAll('g')
1420
+ .data(grouped)
1421
+ .enter().append('g')
1422
+ .attr('transform', d => `translate(${x0(d[0]) || 0},0)`)
1423
+ .selectAll('rect')
1424
+ .data(d => d[1])
1425
+ .enter().append('rect')
1426
+ .attr('x', d => x1(d.type) || 0)
1427
+ .attr('y', d => y(d.value))
1428
+ .attr('width', x1.bandwidth())
1429
+ .attr('height', d => height - y(d.value))
1430
+ .attr('fill', d => color(d.type));
1431
+ // Add x axis
1432
+ svg.append('g')
1433
+ .attr('transform', `translate(0,${height})`)
1434
+ .call(d3.axisBottom(x0))
1435
+ .selectAll('text')
1436
+ .attr('transform', 'rotate(-45)')
1437
+ .style('text-anchor', 'end');
1438
+ // Add y axis
1439
+ svg.append('g')
1440
+ .call(d3.axisLeft(y));
1441
+ // Add legend
1442
+ const legend = svg.append('g')
1443
+ .attr('font-family', 'sans-serif')
1444
+ .attr('font-size', 10)
1445
+ .attr('text-anchor', 'end')
1446
+ .selectAll('g')
1447
+ .data(['Input', 'Output'])
1448
+ .enter().append('g')
1449
+ .attr('transform', (d, i) => `translate(0,${i * 20})`);
1450
+ legend.append('rect')
1451
+ .attr('x', width + 70)
1452
+ .attr('width', 19)
1453
+ .attr('height', 19)
1454
+ .attr('fill', d => color(d));
1455
+ legend.append('text')
1456
+ .attr('x', width + 65)
1457
+ .attr('y', 9.5)
1458
+ .attr('dy', '0.32em')
1459
+ .text(d => d);
1460
+ // Add title
1461
+ svg.append('text')
1462
+ .attr('x', width / 2)
1463
+ .attr('y', -20)
1464
+ .attr('text-anchor', 'middle')
1465
+ .style('font-size', '16px')
1466
+ .style('font-weight', 'bold')
1467
+ .text('Token Usage by Model');
1468
+ }
1469
+ renderActionSuccessRateChart() {
1470
+ const element = this.actionSuccessRateChart.nativeElement;
1471
+ const data = Array.from(this.actionMetrics.byAction.entries()).map(([name, metrics]) => ({
1472
+ name,
1473
+ value: metrics.successRate * 100
1474
+ }));
1475
+ if (data.length === 0)
1476
+ return;
1477
+ // Clear previous chart
1478
+ d3.select(element).selectAll('*').remove();
1479
+ const margin = { top: 40, right: 20, bottom: 100, left: 60 };
1480
+ const width = 320 - margin.left - margin.right;
1481
+ const height = 200 - margin.top - margin.bottom;
1482
+ const svg = d3.select(element)
1483
+ .append('svg')
1484
+ .attr('width', width + margin.left + margin.right)
1485
+ .attr('height', height + margin.top + margin.bottom)
1486
+ .append('g')
1487
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1488
+ const x = d3.scaleBand()
1489
+ .range([0, width])
1490
+ .domain(data.map(d => d.name))
1491
+ .padding(0.1);
1492
+ const y = d3.scaleLinear()
1493
+ .domain([0, 100])
1494
+ .range([height, 0]);
1495
+ // Add bars with color based on success rate
1496
+ svg.selectAll('.bar')
1497
+ .data(data)
1498
+ .enter().append('rect')
1499
+ .attr('class', 'bar')
1500
+ .attr('x', d => x(d.name) || 0)
1501
+ .attr('width', x.bandwidth())
1502
+ .attr('y', d => y(d.value))
1503
+ .attr('height', d => height - y(d.value))
1504
+ .attr('fill', d => d.value > 90 ? '#4bc0c0' : d.value > 70 ? '#ffce56' : '#ff6384');
1505
+ // Add x axis
1506
+ svg.append('g')
1507
+ .attr('transform', `translate(0,${height})`)
1508
+ .call(d3.axisBottom(x))
1509
+ .selectAll('text')
1510
+ .attr('transform', 'rotate(-45)')
1511
+ .style('text-anchor', 'end');
1512
+ // Add y axis
1513
+ svg.append('g')
1514
+ .call(d3.axisLeft(y).tickFormat(d => `${d}%`));
1515
+ // Add title
1516
+ svg.append('text')
1517
+ .attr('x', width / 2)
1518
+ .attr('y', -20)
1519
+ .attr('text-anchor', 'middle')
1520
+ .style('font-size', '16px')
1521
+ .style('font-weight', 'bold')
1522
+ .text('Action Success Rates');
1523
+ }
1524
+ renderStepTypeChart() {
1525
+ const element = this.stepTypeChart.nativeElement;
1526
+ const data = Array.from(this.timelineMetrics.stepsByType.entries()).map(([name, value]) => ({
1527
+ name,
1528
+ value
1529
+ }));
1530
+ if (data.length === 0)
1531
+ return;
1532
+ // Clear previous chart
1533
+ d3.select(element).selectAll('*').remove();
1534
+ const width = 300;
1535
+ const height = 220;
1536
+ const radius = Math.min(width, height) / 2 - 40;
1537
+ const svg = d3.select(element)
1538
+ .append('svg')
1539
+ .attr('width', width)
1540
+ .attr('height', height)
1541
+ .append('g')
1542
+ .attr('transform', `translate(${width / 2}, ${height / 2})`);
1543
+ const color = d3.scaleOrdinal(d3.schemeSet3);
1544
+ const pie = d3.pie()
1545
+ .value(d => d.value)
1546
+ .sort(null);
1547
+ const arc = d3.arc()
1548
+ .innerRadius(0)
1549
+ .outerRadius(radius);
1550
+ const arcs = svg.selectAll('arc')
1551
+ .data(pie(data))
1552
+ .enter()
1553
+ .append('g');
1554
+ arcs.append('path')
1555
+ .attr('d', arc)
1556
+ .attr('fill', (d, i) => color(i.toString()))
1557
+ .attr('stroke', 'white')
1558
+ .style('stroke-width', '2px');
1559
+ // Add labels
1560
+ arcs.append('text')
1561
+ .attr('transform', (d) => {
1562
+ const centroid = arc.centroid(d);
1563
+ return `translate(${centroid})`;
1564
+ })
1565
+ .attr('text-anchor', 'middle')
1566
+ .style('font-size', '12px')
1567
+ .style('fill', 'white')
1568
+ .text((d) => d.data.value > 0 ? d.data.value : '');
1569
+ // Add title
1570
+ svg.append('text')
1571
+ .attr('x', 0)
1572
+ .attr('y', -radius - 25)
1573
+ .attr('text-anchor', 'middle')
1574
+ .style('font-size', '16px')
1575
+ .style('font-weight', 'bold')
1576
+ .text('Step Type Distribution');
1577
+ }
1578
+ calculatePromptSuccessRate(promptName) {
1579
+ const successfulRuns = this.allPromptRuns.filter(run => run.Prompt === promptName && run.Success === true).length;
1580
+ const totalRuns = this.allPromptRuns.filter(run => run.Prompt === promptName).length;
1581
+ if (totalRuns === 0)
1582
+ return '0';
1583
+ return ((successfulRuns / totalRuns) * 100).toFixed(1);
1584
+ }
1585
+ toggleChartExpansion(chartKey) {
1586
+ this.expandedCharts[chartKey] = !this.expandedCharts[chartKey];
1587
+ // Re-render the chart after expansion state changes
1588
+ setTimeout(() => {
1589
+ this.renderCharts();
1590
+ }, 100);
1591
+ }
1592
+ toggleViewMode() {
1593
+ if (this.viewMode === 'grid') {
1594
+ this.viewMode = 'expanded';
1595
+ // Expand all charts
1596
+ Object.keys(this.expandedCharts).forEach(key => {
1597
+ this.expandedCharts[key] = true;
1598
+ });
1599
+ }
1600
+ else {
1601
+ this.viewMode = 'grid';
1602
+ // Collapse all charts
1603
+ Object.keys(this.expandedCharts).forEach(key => {
1604
+ this.expandedCharts[key] = false;
1605
+ });
1606
+ }
1607
+ setTimeout(() => {
1608
+ this.renderCharts();
1609
+ }, 100);
1610
+ }
1611
+ getActionType(actionName) {
1612
+ // Action type is not directly available on ActionExecutionLogEntity
1613
+ return 'Action';
1614
+ }
1615
+ getTopErrors() {
1616
+ return Array.from(this.actionMetrics.errorAnalysis.entries())
1617
+ .map(([message, count]) => {
1618
+ // Try to extract meaningful error message from potentially complex error strings
1619
+ let cleanMessage = message;
1620
+ // If it looks like a view execution result, extract the key part
1621
+ if (message.includes('View executed successfully but returned no data')) {
1622
+ cleanMessage = 'View executed successfully but returned no data';
1623
+ }
1624
+ else if (message.length > 200) {
1625
+ // For very long error messages, truncate and add ellipsis
1626
+ cleanMessage = message.substring(0, 200) + '...';
1627
+ }
1628
+ return { message: cleanMessage, count };
1629
+ })
1630
+ .sort((a, b) => b.count - a.count)
1631
+ .slice(0, 5); // Top 5 errors
1632
+ }
1633
+ getModelPerformanceData() {
1634
+ const modelData = new Map();
1635
+ for (const promptRun of this.allPromptRuns) {
1636
+ const model = promptRun.Model || 'Unknown';
1637
+ const vendor = promptRun.Vendor || 'Unknown';
1638
+ const key = `${model}|${vendor}`;
1639
+ if (!modelData.has(key)) {
1640
+ modelData.set(key, {
1641
+ name: model,
1642
+ vendor: vendor,
1643
+ count: 0,
1644
+ totalTime: 0,
1645
+ avgTime: 0,
1646
+ totalCost: 0,
1647
+ avgCost: 0,
1648
+ inputTokens: 0,
1649
+ outputTokens: 0
1650
+ });
1651
+ }
1652
+ const data = modelData.get(key);
1653
+ data.count++;
1654
+ const execTime = this.calculateExecutionTime(promptRun.RunAt, promptRun.CompletedAt);
1655
+ data.totalTime += execTime;
1656
+ data.avgTime = data.totalTime / data.count;
1657
+ data.totalCost += promptRun.TotalCost || 0;
1658
+ data.avgCost = data.totalCost / data.count;
1659
+ data.inputTokens += promptRun.TokensPrompt || 0;
1660
+ data.outputTokens += promptRun.TokensCompletion || 0;
1661
+ }
1662
+ return Array.from(modelData.values()).sort((a, b) => b.count - a.count);
1663
+ }
1664
+ getStepTypeIcon(stepType) {
1665
+ const iconMap = {
1666
+ 'Prompts': 'fa-microchip',
1667
+ 'Actions': 'fa-cog',
1668
+ 'Sub-Agent': 'fa-robot',
1669
+ 'Start': 'fa-play-circle',
1670
+ 'End': 'fa-stop-circle',
1671
+ 'Decision': 'fa-code-branch',
1672
+ 'Loop': 'fa-sync',
1673
+ 'Error': 'fa-exclamation-triangle'
1674
+ };
1675
+ return iconMap[stepType] || 'fa-circle';
1676
+ }
1677
+ getModelColor(model) {
1678
+ // Return a color from the same palette used in generateColors
1679
+ const colors = [
1680
+ 'rgba(255, 99, 132, 0.5)',
1681
+ 'rgba(54, 162, 235, 0.5)',
1682
+ 'rgba(255, 206, 86, 0.5)',
1683
+ 'rgba(75, 192, 192, 0.5)',
1684
+ 'rgba(153, 102, 255, 0.5)',
1685
+ 'rgba(255, 159, 64, 0.5)',
1686
+ 'rgba(199, 199, 199, 0.5)',
1687
+ 'rgba(83, 102, 255, 0.5)',
1688
+ 'rgba(255, 99, 255, 0.5)',
1689
+ 'rgba(99, 255, 132, 0.5)'
1690
+ ];
1691
+ // Use a simple hash of the model name to consistently pick a color
1692
+ let hash = 0;
1693
+ for (let i = 0; i < model.length; i++) {
1694
+ hash = model.charCodeAt(i) + ((hash << 5) - hash);
1695
+ }
1696
+ return colors[Math.abs(hash) % colors.length];
1697
+ }
1698
+ renderPromptTimeDistributionChart() {
1699
+ const element = this.promptTimeDistributionChart.nativeElement;
1700
+ const data = Array.from(this.promptMetrics.byPrompt.entries())
1701
+ .map(([name, metrics]) => ({
1702
+ name: name.length > 20 ? name.substring(0, 20) + '...' : name,
1703
+ value: metrics.avgTime
1704
+ }))
1705
+ .sort((a, b) => b.value - a.value)
1706
+ .slice(0, 10); // Top 10 prompts by avg time
1707
+ if (data.length === 0)
1708
+ return;
1709
+ // Clear previous chart
1710
+ d3.select(element).selectAll('*').remove();
1711
+ const margin = { top: 40, right: 20, bottom: 120, left: 80 };
1712
+ const width = 320 - margin.left - margin.right;
1713
+ const height = 200 - margin.top - margin.bottom;
1714
+ const svg = d3.select(element)
1715
+ .append('svg')
1716
+ .attr('width', width + margin.left + margin.right)
1717
+ .attr('height', height + margin.top + margin.bottom)
1718
+ .append('g')
1719
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1720
+ const x = d3.scaleBand()
1721
+ .range([0, width])
1722
+ .domain(data.map(d => d.name))
1723
+ .padding(0.1);
1724
+ const y = d3.scaleLinear()
1725
+ .domain([0, d3.max(data, d => d.value) || 0])
1726
+ .range([height, 0]);
1727
+ // Add bars
1728
+ svg.selectAll('.bar')
1729
+ .data(data)
1730
+ .enter().append('rect')
1731
+ .attr('class', 'bar')
1732
+ .attr('x', d => x(d.name) || 0)
1733
+ .attr('width', x.bandwidth())
1734
+ .attr('y', d => y(d.value))
1735
+ .attr('height', d => height - y(d.value))
1736
+ .attr('fill', '#667eea');
1737
+ // Add x axis
1738
+ svg.append('g')
1739
+ .attr('transform', `translate(0,${height})`)
1740
+ .call(d3.axisBottom(x))
1741
+ .selectAll('text')
1742
+ .attr('transform', 'rotate(-45)')
1743
+ .style('text-anchor', 'end')
1744
+ .style('font-size', '10px');
1745
+ // Add y axis
1746
+ svg.append('g')
1747
+ .call(d3.axisLeft(y).tickFormat(d => `${d}ms`));
1748
+ // Add title
1749
+ svg.append('text')
1750
+ .attr('x', width / 2)
1751
+ .attr('y', -20)
1752
+ .attr('text-anchor', 'middle')
1753
+ .style('font-size', '16px')
1754
+ .style('font-weight', 'bold')
1755
+ .text('Average Execution Time by Prompt');
1756
+ }
1757
+ renderPromptTokenDistributionChart() {
1758
+ const element = this.promptTokenDistributionChart.nativeElement;
1759
+ // Aggregate token data by prompt
1760
+ const promptTokenData = new Map();
1761
+ for (const run of this.allPromptRuns) {
1762
+ const promptName = run.Prompt || 'Unknown';
1763
+ const existing = promptTokenData.get(promptName) || { input: 0, output: 0 };
1764
+ existing.input += run.TokensPrompt || 0;
1765
+ existing.output += run.TokensCompletion || 0;
1766
+ promptTokenData.set(promptName, existing);
1767
+ }
1768
+ const topPrompts = Array.from(promptTokenData.entries())
1769
+ .sort((a, b) => (b[1].input + b[1].output) - (a[1].input + a[1].output))
1770
+ .slice(0, 8)
1771
+ .map(([name]) => name);
1772
+ const inputData = topPrompts.map(prompt => ({
1773
+ prompt: prompt.length > 15 ? prompt.substring(0, 15) + '...' : prompt,
1774
+ type: 'Input',
1775
+ value: promptTokenData.get(prompt)?.input || 0
1776
+ }));
1777
+ const outputData = topPrompts.map(prompt => ({
1778
+ prompt: prompt.length > 15 ? prompt.substring(0, 15) + '...' : prompt,
1779
+ type: 'Output',
1780
+ value: promptTokenData.get(prompt)?.output || 0
1781
+ }));
1782
+ const data = [...inputData, ...outputData];
1783
+ if (data.length === 0)
1784
+ return;
1785
+ // Clear previous chart
1786
+ d3.select(element).selectAll('*').remove();
1787
+ const margin = { top: 40, right: 100, bottom: 100, left: 80 };
1788
+ const width = 320 - margin.left - margin.right;
1789
+ const height = 200 - margin.top - margin.bottom;
1790
+ const svg = d3.select(element)
1791
+ .append('svg')
1792
+ .attr('width', width + margin.left + margin.right)
1793
+ .attr('height', height + margin.top + margin.bottom)
1794
+ .append('g')
1795
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1796
+ const x0 = d3.scaleBand()
1797
+ .rangeRound([0, width])
1798
+ .paddingInner(0.1)
1799
+ .domain(topPrompts.map(p => p.length > 15 ? p.substring(0, 15) + '...' : p));
1800
+ const x1 = d3.scaleBand()
1801
+ .padding(0.05)
1802
+ .domain(['Input', 'Output'])
1803
+ .rangeRound([0, x0.bandwidth()]);
1804
+ const y = d3.scaleLinear()
1805
+ .rangeRound([height, 0])
1806
+ .domain([0, d3.max(data, d => d.value) || 0]);
1807
+ const color = d3.scaleOrdinal()
1808
+ .domain(['Input', 'Output'])
1809
+ .range(['#764ba2', '#667eea']);
1810
+ const grouped = d3.group(data, d => d.prompt);
1811
+ svg.append('g')
1812
+ .selectAll('g')
1813
+ .data(grouped)
1814
+ .enter().append('g')
1815
+ .attr('transform', d => `translate(${x0(d[0]) || 0},0)`)
1816
+ .selectAll('rect')
1817
+ .data(d => d[1])
1818
+ .enter().append('rect')
1819
+ .attr('x', d => x1(d.type) || 0)
1820
+ .attr('y', d => y(d.value))
1821
+ .attr('width', x1.bandwidth())
1822
+ .attr('height', d => height - y(d.value))
1823
+ .attr('fill', d => color(d.type));
1824
+ // Add x axis
1825
+ svg.append('g')
1826
+ .attr('transform', `translate(0,${height})`)
1827
+ .call(d3.axisBottom(x0))
1828
+ .selectAll('text')
1829
+ .attr('transform', 'rotate(-45)')
1830
+ .style('text-anchor', 'end')
1831
+ .style('font-size', '10px');
1832
+ // Add y axis
1833
+ svg.append('g')
1834
+ .call(d3.axisLeft(y).tickFormat(d => d3.format('.2s')(d)));
1835
+ // Add legend
1836
+ const legend = svg.append('g')
1837
+ .attr('font-family', 'sans-serif')
1838
+ .attr('font-size', 10)
1839
+ .attr('text-anchor', 'end')
1840
+ .selectAll('g')
1841
+ .data(['Input', 'Output'])
1842
+ .enter().append('g')
1843
+ .attr('transform', (d, i) => `translate(0,${i * 20})`);
1844
+ legend.append('rect')
1845
+ .attr('x', width + 70)
1846
+ .attr('width', 19)
1847
+ .attr('height', 19)
1848
+ .attr('fill', d => color(d));
1849
+ legend.append('text')
1850
+ .attr('x', width + 65)
1851
+ .attr('y', 9.5)
1852
+ .attr('dy', '0.32em')
1853
+ .text(d => d);
1854
+ // Add title
1855
+ svg.append('text')
1856
+ .attr('x', width / 2)
1857
+ .attr('y', -20)
1858
+ .attr('text-anchor', 'middle')
1859
+ .style('font-size', '16px')
1860
+ .style('font-weight', 'bold')
1861
+ .text('Token Usage by Prompt');
1862
+ }
1863
+ renderPromptCostDistributionChart() {
1864
+ const element = this.promptCostDistributionChart.nativeElement;
1865
+ // Aggregate cost data by prompt
1866
+ const promptCostData = new Map();
1867
+ for (const run of this.allPromptRuns) {
1868
+ const promptName = run.Prompt || 'Unknown';
1869
+ const existing = promptCostData.get(promptName) || 0;
1870
+ promptCostData.set(promptName, existing + (run.TotalCost || 0));
1871
+ }
1872
+ const data = Array.from(promptCostData.entries())
1873
+ .filter(([_, cost]) => cost > 0)
1874
+ .map(([name, cost]) => ({
1875
+ name: name.length > 20 ? name.substring(0, 20) + '...' : name,
1876
+ value: cost
1877
+ }))
1878
+ .sort((a, b) => b.value - a.value)
1879
+ .slice(0, 10); // Top 10 prompts by cost
1880
+ if (data.length === 0)
1881
+ return;
1882
+ // Clear previous chart
1883
+ d3.select(element).selectAll('*').remove();
1884
+ const width = 300;
1885
+ const height = 220;
1886
+ const radius = Math.min(width, height) / 2 - 40;
1887
+ const svg = d3.select(element)
1888
+ .append('svg')
1889
+ .attr('width', width)
1890
+ .attr('height', height)
1891
+ .append('g')
1892
+ .attr('transform', `translate(${width / 2}, ${height / 2})`);
1893
+ const color = d3.scaleOrdinal(d3.schemePurples[9].slice(2));
1894
+ const pie = d3.pie()
1895
+ .value(d => d.value)
1896
+ .sort((a, b) => b.value - a.value);
1897
+ const arc = d3.arc()
1898
+ .innerRadius(radius * 0.5)
1899
+ .outerRadius(radius);
1900
+ const arcs = svg.selectAll('arc')
1901
+ .data(pie(data))
1902
+ .enter()
1903
+ .append('g');
1904
+ arcs.append('path')
1905
+ .attr('d', arc)
1906
+ .attr('fill', (d, i) => color(i.toString()))
1907
+ .attr('stroke', 'white')
1908
+ .style('stroke-width', '2px');
1909
+ // Add title
1910
+ svg.append('text')
1911
+ .attr('x', 0)
1912
+ .attr('y', -radius - 25)
1913
+ .attr('text-anchor', 'middle')
1914
+ .style('font-size', '16px')
1915
+ .style('font-weight', 'bold')
1916
+ .text('Cost Distribution by Prompt');
1917
+ // Add total cost in center
1918
+ svg.append('text')
1919
+ .attr('text-anchor', 'middle')
1920
+ .attr('dy', '-0.5em')
1921
+ .style('font-size', '14px')
1922
+ .style('font-weight', 'bold')
1923
+ .text('Total Cost');
1924
+ svg.append('text')
1925
+ .attr('text-anchor', 'middle')
1926
+ .attr('dy', '1em')
1927
+ .style('font-size', '18px')
1928
+ .style('font-weight', 'bold')
1929
+ .text(this.formatCost(data.reduce((sum, d) => sum + d.value, 0)));
1930
+ }
1931
+ renderPromptCountByNameChart() {
1932
+ const element = this.promptCountByNameChart.nativeElement;
1933
+ const data = Array.from(this.promptMetrics.byPrompt.entries())
1934
+ .map(([name, metrics]) => ({
1935
+ name: name.length > 20 ? name.substring(0, 20) + '...' : name,
1936
+ value: metrics.count
1937
+ }))
1938
+ .sort((a, b) => b.value - a.value)
1939
+ .slice(0, 10); // Top 10 prompts by count
1940
+ if (data.length === 0)
1941
+ return;
1942
+ // Clear previous chart
1943
+ d3.select(element).selectAll('*').remove();
1944
+ const margin = { top: 40, right: 20, bottom: 120, left: 60 };
1945
+ const width = 320 - margin.left - margin.right;
1946
+ const height = 200 - margin.top - margin.bottom;
1947
+ const svg = d3.select(element)
1948
+ .append('svg')
1949
+ .attr('width', width + margin.left + margin.right)
1950
+ .attr('height', height + margin.top + margin.bottom)
1951
+ .append('g')
1952
+ .attr('transform', `translate(${margin.left},${margin.top})`);
1953
+ const x = d3.scaleBand()
1954
+ .range([0, width])
1955
+ .domain(data.map(d => d.name))
1956
+ .padding(0.1);
1957
+ const y = d3.scaleLinear()
1958
+ .domain([0, d3.max(data, d => d.value) || 0])
1959
+ .range([height, 0]);
1960
+ // Create gradient
1961
+ const gradient = svg.append('defs')
1962
+ .append('linearGradient')
1963
+ .attr('id', 'promptCountGradient')
1964
+ .attr('x1', '0%')
1965
+ .attr('y1', '0%')
1966
+ .attr('x2', '0%')
1967
+ .attr('y2', '100%');
1968
+ gradient.append('stop')
1969
+ .attr('offset', '0%')
1970
+ .attr('stop-color', '#667eea')
1971
+ .attr('stop-opacity', 1);
1972
+ gradient.append('stop')
1973
+ .attr('offset', '100%')
1974
+ .attr('stop-color', '#764ba2')
1975
+ .attr('stop-opacity', 1);
1976
+ // Add bars
1977
+ svg.selectAll('.bar')
1978
+ .data(data)
1979
+ .enter().append('rect')
1980
+ .attr('class', 'bar')
1981
+ .attr('x', d => x(d.name) || 0)
1982
+ .attr('width', x.bandwidth())
1983
+ .attr('y', d => y(d.value))
1984
+ .attr('height', d => height - y(d.value))
1985
+ .attr('fill', 'url(#promptCountGradient)');
1986
+ // Add value labels on bars
1987
+ svg.selectAll('.bar-label')
1988
+ .data(data)
1989
+ .enter().append('text')
1990
+ .attr('class', 'bar-label')
1991
+ .attr('x', d => (x(d.name) || 0) + x.bandwidth() / 2)
1992
+ .attr('y', d => y(d.value) - 5)
1993
+ .attr('text-anchor', 'middle')
1994
+ .style('font-size', '12px')
1995
+ .style('font-weight', 'bold')
1996
+ .text(d => d.value);
1997
+ // Add x axis
1998
+ svg.append('g')
1999
+ .attr('transform', `translate(0,${height})`)
2000
+ .call(d3.axisBottom(x))
2001
+ .selectAll('text')
2002
+ .attr('transform', 'rotate(-45)')
2003
+ .style('text-anchor', 'end')
2004
+ .style('font-size', '10px');
2005
+ // Add y axis
2006
+ svg.append('g')
2007
+ .call(d3.axisLeft(y));
2008
+ // Add title
2009
+ svg.append('text')
2010
+ .attr('x', width / 2)
2011
+ .attr('y', -20)
2012
+ .attr('text-anchor', 'middle')
2013
+ .style('font-size', '16px')
2014
+ .style('font-weight', 'bold')
2015
+ .text('Prompt Execution Count');
2016
+ }
2017
+ static { this.ɵfac = function AIAgentRunAnalyticsComponent_Factory(t) { return new (t || AIAgentRunAnalyticsComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); }; }
2018
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AIAgentRunAnalyticsComponent, selectors: [["mj-ai-agent-run-analytics"]], viewQuery: function AIAgentRunAnalyticsComponent_Query(rf, ctx) { if (rf & 1) {
2019
+ i0.ɵɵviewQuery(_c0, 5);
2020
+ i0.ɵɵviewQuery(_c1, 5);
2021
+ i0.ɵɵviewQuery(_c2, 5);
2022
+ i0.ɵɵviewQuery(_c3, 5);
2023
+ i0.ɵɵviewQuery(_c4, 5);
2024
+ i0.ɵɵviewQuery(_c5, 5);
2025
+ i0.ɵɵviewQuery(_c6, 5);
2026
+ i0.ɵɵviewQuery(_c7, 5);
2027
+ i0.ɵɵviewQuery(_c8, 5);
2028
+ i0.ɵɵviewQuery(_c9, 5);
2029
+ } if (rf & 2) {
2030
+ let _t;
2031
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.modelDistributionChart = _t.first);
2032
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.executionTimeChart = _t.first);
2033
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.costByVendorChart = _t.first);
2034
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.tokenUsageChart = _t.first);
2035
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.actionSuccessRateChart = _t.first);
2036
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.stepTypeChart = _t.first);
2037
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTimeDistributionChart = _t.first);
2038
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTokenDistributionChart = _t.first);
2039
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCostDistributionChart = _t.first);
2040
+ i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCountByNameChart = _t.first);
2041
+ } }, inputs: { agentRunId: "agentRunId" }, decls: 4, vars: 3, consts: [["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], ["actionSuccessRateChart", ""], ["stepTypeChart", ""], [1, "analytics-container"], ["class", "loading-state", 4, "ngIf"], ["class", "error-state", 4, "ngIf"], ["class", "analytics-content", 4, "ngIf"], [1, "loading-state"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "error-state"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["kendoButton", "", 3, "click"], [1, "analytics-content"], [3, "expanded"], ["kendoPanelBarItemTitle", ""], ["kendoPanelBarContent", ""], [1, "fas", "fa-tachometer-alt"], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], ["class", "failed", 4, "ngIf"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "failed"], [1, "analytics-panel"], ["class", "view-mode-toggle", 4, "ngIf"], ["class", "no-data-message", 4, "ngIf"], ["class", "charts-grid", 4, "ngIf"], ["class", "charts-grid", "style", "margin-top: 20px;", 4, "ngIf"], [1, "detailed-metrics"], ["kendoButton", "", "fillMode", "flat", 3, "click"], [1, "fas", 3, "ngClass"], ["class", "metrics-table", 4, "ngIf"], [1, "view-mode-toggle"], ["kendoButton", "", "fillMode", "flat", "size", "small", 3, "click"], [1, "no-data-message"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "charts-grid"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-pie"], [1, "expand-btn"], [1, "chart-card-body"], [1, "chart-container"], ["id", "modelDistributionChart"], ["class", "chart-legend", 4, "ngIf"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "chart-legend"], ["class", "legend-item", 4, "ngFor", "ngForOf"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "metrics-table"], [4, "ngFor", "ngForOf"], [1, "success-rate"], [1, "fas", "fa-chart-bar"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], ["class", "error-analysis", 4, "ngIf"], ["class", "no-errors", 4, "ngIf"], [1, "error-analysis"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], ["class", "error-item", 4, "ngFor", "ngForOf"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "no-errors"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "model-comparison"], [1, "fas", "fa-stream"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], ["class", "step-type-item", 4, "ngFor", "ngForOf"], [1, "step-type-item"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
2042
+ i0.ɵɵelementStart(0, "div", 10);
2043
+ i0.ɵɵtemplate(1, AIAgentRunAnalyticsComponent_div_1_Template, 4, 0, "div", 11)(2, AIAgentRunAnalyticsComponent_div_2_Template, 6, 1, "div", 12)(3, AIAgentRunAnalyticsComponent_div_3_Template, 17, 5, "div", 13);
2044
+ i0.ɵɵelementEnd();
2045
+ } if (rf & 2) {
2046
+ i0.ɵɵadvance();
2047
+ i0.ɵɵproperty("ngIf", ctx.isLoading);
2048
+ i0.ɵɵadvance();
2049
+ i0.ɵɵproperty("ngIf", ctx.error && !ctx.isLoading);
2050
+ i0.ɵɵadvance();
2051
+ i0.ɵɵproperty("ngIf", !ctx.isLoading && !ctx.error);
2052
+ } }, dependencies: [i1.NgClass, i1.NgForOf, i1.NgIf, i2.PanelBarComponent, i2.PanelBarItemComponent, i2.PanelBarContentDirective, i2.PanelBarItemTitleDirective, i3.ButtonComponent, i1.DecimalPipe, i1.KeyValuePipe], styles: [".analytics-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: #f8f9fa;\n}\n\n\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: #6c757d;\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: #dc3545;\n}\n\n\n\n.summary-cards[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n padding: 20px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: white;\n}\n\n.card-icon.prompts[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n}\n\n.card-icon.actions[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n}\n\n.card-icon.cost[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);\n}\n\n.card-icon.time[_ngcontent-%COMP%] {\n background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);\n}\n\n.card-content[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: #212529;\n margin-bottom: 4px;\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #6c757d;\n}\n\n.metric-detail[_ngcontent-%COMP%] .success[_ngcontent-%COMP%] {\n color: #28a745;\n margin-right: 10px;\n}\n\n.metric-detail[_ngcontent-%COMP%] .failed[_ngcontent-%COMP%] {\n color: #dc3545;\n}\n\n\n\n.analytics-panel[_ngcontent-%COMP%] {\n padding: 15px;\n}\n\n\n\n .analytics-content .k-panelbar {\n border: none;\n background: transparent;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item {\n border: none;\n border-radius: 12px;\n margin-bottom: 12px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.06);\n background: white;\n overflow: hidden;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item > .k-header {\n background: white;\n border: none;\n padding: 16px 20px;\n border-radius: 12px 12px 0 0;\n color: #2c3e50;\n font-weight: 600;\n font-size: 16px;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item > .k-header:hover {\n background: #f8f9fa;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item.k-panelbar-expanded > .k-header {\n background: #2196f3;\n color: white;\n border-radius: 12px 12px 0 0;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item > .k-header .k-panelbar-toggle {\n position: absolute;\n right: 24px;\n color: inherit;\n font-size: 14px;\n transition: transform 0.2s ease;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item.k-panelbar-expanded > .k-header .k-panelbar-toggle {\n transform: rotate(180deg);\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item > .k-header .k-panelbar-toggle::before {\n content: '\\f107';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n}\n\n .analytics-content .k-panelbar > .k-panelbar-item > .k-content {\n padding: 0;\n border: none;\n background: white;\n border-radius: 0 0 12px 12px;\n}\n\n .analytics-content .k-panelbar .k-header .k-panelbar-icon {\n font-size: 18px;\n color: #2196f3;\n margin-right: 8px;\n}\n\n .analytics-content .k-panelbar .k-panelbar-expanded .k-header .k-panelbar-icon {\n color: white;\n}\n\n\n\n.charts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n\n\n.chart-card[_ngcontent-%COMP%] {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.chart-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: #f8f9fa;\n border-bottom: 1px solid #e9ecef;\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header[_ngcontent-%COMP%]:hover {\n background-color: #e9ecef;\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: #6c757d;\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: #6c757d;\n transition: color 0.2s;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: #495057;\n}\n\n.chart-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n background: white;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-card-body[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 400px;\n}\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.chart-container[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: #495057;\n}\n\n.chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n\n\n.chart-container[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total[_ngcontent-%COMP%] {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: #495057;\n}\n\n\n\n.detailed-metrics[_ngcontent-%COMP%] {\n margin-top: 20px;\n border-top: 1px solid #e9ecef;\n padding-top: 20px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.metrics-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.metrics-table[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: #f8f9fa;\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: #495057;\n border-bottom: 2px solid #dee2e6;\n}\n\n.metrics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid #dee2e6;\n}\n\n.metrics-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: #f8f9fa;\n}\n\n.success-rate[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.success-rate.high[_ngcontent-%COMP%] {\n color: #28a745;\n}\n\n.success-rate.medium[_ngcontent-%COMP%] {\n color: #ffc107;\n}\n\n.success-rate.low[_ngcontent-%COMP%] {\n color: #dc3545;\n}\n\n\n\n.error-analysis[_ngcontent-%COMP%] {\n margin-top: 30px;\n padding: 20px;\n background-color: #fff5f5;\n border-radius: 8px;\n border: 1px solid #f5c6cb;\n}\n\n.error-analysis[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n color: #721c24;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #856404;\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: white;\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count[_ngcontent-%COMP%] {\n background-color: #dc3545;\n color: white;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message[_ngcontent-%COMP%] {\n flex: 1;\n color: #495057;\n}\n\n\n\n.no-errors[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: #d4edda;\n border-radius: 8px;\n border: 1px solid #c3e6cb;\n color: #155724;\n}\n\n.no-errors[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: #28a745;\n}\n\n.no-errors[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.no-data-message[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: #6c757d;\n}\n\n.no-data-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: #dee2e6;\n}\n\n.no-data-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message[_ngcontent-%COMP%] p.small[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #adb5bd;\n}\n\n\n\n.model-comparison[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.model-comparison[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: #f8f9fa;\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: #495057;\n border-bottom: 2px solid #dee2e6;\n white-space: nowrap;\n}\n\n.model-comparison[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid #dee2e6;\n}\n\n.model-comparison[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: #f8f9fa;\n}\n\n\n\n.timeline-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: #f8f9fa;\n border-radius: 8px;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n color: #6c757d;\n margin-bottom: 8px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 32px;\n font-weight: 700;\n color: #212529;\n}\n\n.step-breakdown[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: #495057;\n}\n\n.step-type-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: #f8f9fa;\n border-radius: 6px;\n border: 1px solid #e9ecef;\n}\n\n.step-type-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 30px;\n text-align: center;\n color: #6c757d;\n}\n\n.type-name[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count[_ngcontent-%COMP%] {\n font-weight: 700;\n color: #212529;\n}\n\n.type-percentage[_ngcontent-%COMP%] {\n font-size: 13px;\n color: #6c757d;\n margin-left: 5px;\n}\n\n\n\n@media (max-width: 768px) {\n .summary-cards[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .charts-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }); }
2053
+ }
2054
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAgentRunAnalyticsComponent, [{
2055
+ type: Component,
2056
+ args: [{ selector: 'mj-ai-agent-run-analytics', template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n <div class=\"loading-state\" *ngIf=\"isLoading\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n\n <!-- Error State -->\n <div class=\"error-state\" *ngIf=\"error && !isLoading\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button kendoButton (click)=\"loadData()\">Retry</button>\n </div>\n\n <!-- Analytics Content -->\n <div class=\"analytics-content\" *ngIf=\"!isLoading && !error\">\n <kendo-panelbar>\n <!-- Summary Cards -->\n <kendo-panelbar-item [expanded]=\"true\">\n <ng-template kendoPanelBarItemTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <ng-template kendoPanelBarContent>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n <span class=\"failed\" *ngIf=\"promptMetrics.statusBreakdown.failed > 0\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n </div>\n </div>\n </div>\n\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n <span class=\"failed\" *ngIf=\"actionMetrics.statusBreakdown.failed > 0\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n </div>\n </div>\n </div>\n\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <div class=\"metric-value\">{{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n <div class=\"metric-detail\">\n <span>{{ promptMetrics.tokenUsage.totalInput + promptMetrics.tokenUsage.totalOutput }} tokens</span>\n </div>\n </div>\n </div>\n\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n </kendo-panelbar-item>\n\n <!-- Prompt Analytics -->\n <kendo-panelbar-item [expanded]=\"true\">\n <ng-template kendoPanelBarItemTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <ng-template kendoPanelBarContent>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n <div class=\"view-mode-toggle\" *ngIf=\"promptMetrics.totalCount > 0\">\n <button kendoButton \n fillMode=\"flat\" \n size=\"small\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n \n <!-- No prompts message -->\n <div class=\"no-data-message\" *ngIf=\"promptMetrics.totalCount === 0\">\n <i class=\"fas fa-info-circle\"></i>\n <p>No prompt executions found in this agent run.</p>\n <p class=\"small\">This agent run may have only executed actions without any AI prompts.</p>\n </div>\n\n <div class=\"charts-grid\" *ngIf=\"promptMetrics.totalCount > 0\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['modelDistribution'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"modelDistributionChart\" #modelDistributionChart></div>\n <div class=\"chart-legend\" *ngIf=\"promptMetrics.byModel.size > 0\">\n <div class=\"legend-item\" *ngFor=\"let item of promptMetrics.byModel | keyvalue\">\n <span class=\"legend-color\" [style.backgroundColor]=\"getModelColor(item.key)\"></span>\n <span class=\"legend-label\">{{ item.key }}: {{ item.value.count }} ({{ (item.value.count / promptMetrics.totalCount * 100).toFixed(1) }}%)</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Execution Time by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['executionTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('executionTime')\">\n <h3><i class=\"fas fa-clock\"></i> Average Execution Time by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['executionTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"executionTimeChart\" #executionTimeChart></div>\n </div>\n </div>\n </div>\n\n <!-- Cost by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['costByVendor']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('costByVendor')\">\n <h3><i class=\"fas fa-dollar-sign\"></i> Cost Distribution by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['costByVendor'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"costByVendorChart\" #costByVendorChart></div>\n <div class=\"chart-total\">Total: {{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n </div>\n </div>\n </div>\n\n <!-- Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['tokenUsage']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('tokenUsage')\">\n <h3><i class=\"fas fa-coins\"></i> Token Usage by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['tokenUsage'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"tokenUsageChart\" #tokenUsageChart></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Additional Prompt Analytics Charts -->\n <div class=\"charts-grid\" style=\"margin-top: 20px;\" *ngIf=\"promptMetrics.totalCount > 0\">\n <!-- Prompt Execution Time Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptTime')\">\n <h3><i class=\"fas fa-hourglass-half\"></i> Average Execution Time by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTimeDistributionChart\" #promptTimeDistributionChart></div>\n </div>\n </div>\n </div>\n\n <!-- Prompt Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptToken']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptToken')\">\n <h3><i class=\"fas fa-database\"></i> Token Usage by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptToken'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTokenDistributionChart\" #promptTokenDistributionChart></div>\n </div>\n </div>\n </div>\n\n <!-- Prompt Cost Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCost']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCost')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Cost Distribution by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCost'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCostDistributionChart\" #promptCostDistributionChart></div>\n </div>\n </div>\n </div>\n\n <!-- Prompt Count by Name -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCount']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCount')\">\n <h3><i class=\"fas fa-list-ol\"></i> Prompt Execution Count</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCount'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCountByNameChart\" #promptCountByNameChart></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Detailed Prompt Metrics -->\n <div class=\"detailed-metrics\">\n <button kendoButton \n fillMode=\"flat\" \n (click)=\"promptDetailsExpanded = !promptDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"promptDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Prompt Metrics\n </button>\n \n <div class=\"metrics-table\" *ngIf=\"promptDetailsExpanded\">\n <table>\n <thead>\n <tr>\n <th>Prompt Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Total Time</th>\n <th>Success Rate</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let prompt of promptMetrics.byPrompt | keyvalue\">\n <td>{{ prompt.key }}</td>\n <td>{{ prompt.value.count }}</td>\n <td>{{ formatDuration(prompt.value.avgTime) }}</td>\n <td>{{ formatDuration(prompt.value.totalTime) }}</td>\n <td>\n <span class=\"success-rate\">\n <!-- Calculate success rate for this prompt -->\n {{ calculatePromptSuccessRate(prompt.key) }}%\n </span>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </ng-template>\n </kendo-panelbar-item>\n\n <!-- Action Analytics -->\n <kendo-panelbar-item [expanded]=\"true\">\n <ng-template kendoPanelBarItemTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <ng-template kendoPanelBarContent>\n <div class=\"analytics-panel\">\n\n <div class=\"charts-grid\">\n <!-- Action Success Rate -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['actionSuccess']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('actionSuccess')\">\n <h3><i class=\"fas fa-chart-bar\"></i> Action Success Rate</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['actionSuccess'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"actionSuccessRateChart\" #actionSuccessRateChart></div>\n </div>\n </div>\n </div>\n\n <!-- Step Type Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['stepType']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('stepType')\">\n <h3><i class=\"fas fa-layer-group\"></i> Step Type Distribution</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['stepType'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"stepTypeChart\" #stepTypeChart></div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button kendoButton \n fillMode=\"flat\" \n (click)=\"actionDetailsExpanded = !actionDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"actionDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Action Metrics\n </button>\n \n <div class=\"metrics-table\" *ngIf=\"actionDetailsExpanded\">\n <table>\n <thead>\n <tr>\n <th>Action Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Success Rate</th>\n <th>Type</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let action of actionMetrics.byAction | keyvalue\">\n <td>{{ action.key }}</td>\n <td>{{ action.value.count }}</td>\n <td>{{ formatDuration(action.value.avgTime) }}</td>\n <td>\n <span class=\"success-rate\" [class.high]=\"action.value.successRate > 0.9\" \n [class.medium]=\"action.value.successRate > 0.7 && action.value.successRate <= 0.9\"\n [class.low]=\"action.value.successRate <= 0.7\">\n {{ (action.value.successRate * 100).toFixed(1) }}%\n </span>\n </td>\n <td>{{ getActionType(action.key) }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n <div class=\"error-analysis\" *ngIf=\"actionMetrics.errorAnalysis.size > 0\">\n <h3>\n <i class=\"fas fa-exclamation-triangle\"></i>\n Common Errors\n </h3>\n <p class=\"error-analysis-description\">\n This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention.\n </p>\n <div class=\"error-list\">\n <div class=\"error-item\" *ngFor=\"let error of getTopErrors()\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n </div>\n </div>\n <div class=\"no-errors\" *ngIf=\"actionMetrics.errorAnalysis.size === 0\">\n <i class=\"fas fa-check-circle\"></i>\n <p>No action errors detected in this run. All actions completed successfully!</p>\n </div>\n </div>\n </div>\n </ng-template>\n </kendo-panelbar-item>\n\n <!-- Model Performance Comparison -->\n <kendo-panelbar-item [expanded]=\"true\">\n <ng-template kendoPanelBarItemTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <ng-template kendoPanelBarContent>\n <div class=\"analytics-panel\">\n\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let model of getModelPerformanceData()\">\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </ng-template>\n </kendo-panelbar-item>\n\n <!-- Timeline Analysis -->\n <kendo-panelbar-item [expanded]=\"true\">\n <ng-template kendoPanelBarItemTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <ng-template kendoPanelBarContent>\n <div class=\"analytics-panel\">\n\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n <div class=\"step-type-item\" *ngFor=\"let type of timelineMetrics.stepsByType | keyvalue\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n </kendo-panelbar-item>\n </kendo-panelbar>\n </div>\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: #f8f9fa;\n}\n\n/* Loading and Error States */\n.loading-state,\n.error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: #6c757d;\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: #dc3545;\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: white;\n border-radius: 8px;\n padding: 20px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: white;\n}\n\n.card-icon.prompts {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n}\n\n.card-icon.actions {\n background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);\n}\n\n.card-icon.cost {\n background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);\n}\n\n.card-icon.time {\n background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: #212529;\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: #6c757d;\n}\n\n.metric-detail .success {\n color: #28a745;\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: #dc3545;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Kendo PanelBar Styling - Copied from AI Agent Form */\n::ng-deep .analytics-content .k-panelbar {\n border: none;\n background: transparent;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item {\n border: none;\n border-radius: 12px;\n margin-bottom: 12px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.06);\n background: white;\n overflow: hidden;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item > .k-header {\n background: white;\n border: none;\n padding: 16px 20px;\n border-radius: 12px 12px 0 0;\n color: #2c3e50;\n font-weight: 600;\n font-size: 16px;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item > .k-header:hover {\n background: #f8f9fa;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item.k-panelbar-expanded > .k-header {\n background: #2196f3;\n color: white;\n border-radius: 12px 12px 0 0;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item > .k-header .k-panelbar-toggle {\n position: absolute;\n right: 24px;\n color: inherit;\n font-size: 14px;\n transition: transform 0.2s ease;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item.k-panelbar-expanded > .k-header .k-panelbar-toggle {\n transform: rotate(180deg);\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item > .k-header .k-panelbar-toggle::before {\n content: '\\f107';\n font-family: 'Font Awesome 6 Free';\n font-weight: 900;\n}\n\n::ng-deep .analytics-content .k-panelbar > .k-panelbar-item > .k-content {\n padding: 0;\n border: none;\n background: white;\n border-radius: 0 0 12px 12px;\n}\n\n::ng-deep .analytics-content .k-panelbar .k-header .k-panelbar-icon {\n font-size: 18px;\n color: #2196f3;\n margin-right: 8px;\n}\n\n::ng-deep .analytics-content .k-panelbar .k-panelbar-expanded .k-header .k-panelbar-icon {\n color: white;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: #f8f9fa;\n border-bottom: 1px solid #e9ecef;\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: #e9ecef;\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: #495057;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: #6c757d;\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: #6c757d;\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: #495057;\n}\n\n.chart-card-body {\n padding: 16px;\n background: white;\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: #495057;\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: #495057;\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid #e9ecef;\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: #f8f9fa;\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: #495057;\n border-bottom: 2px solid #dee2e6;\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid #dee2e6;\n}\n\n.metrics-table tr:hover {\n background-color: #f8f9fa;\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: #28a745;\n}\n\n.success-rate.medium {\n color: #ffc107;\n}\n\n.success-rate.low {\n color: #dc3545;\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: #fff5f5;\n border-radius: 8px;\n border: 1px solid #f5c6cb;\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: #721c24;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: #856404;\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: white;\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: #dc3545;\n color: white;\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: #495057;\n}\n\n/* No errors state */\n.no-errors {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: #d4edda;\n border-radius: 8px;\n border: 1px solid #c3e6cb;\n color: #155724;\n}\n\n.no-errors i {\n font-size: 24px;\n color: #28a745;\n}\n\n.no-errors p {\n margin: 0;\n font-size: 14px;\n}\n\n/* No data message */\n.no-data-message {\n text-align: center;\n padding: 60px 20px;\n color: #6c757d;\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: #dee2e6;\n}\n\n.no-data-message p {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message p.small {\n font-size: 14px;\n color: #adb5bd;\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: #f8f9fa;\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: #495057;\n border-bottom: 2px solid #dee2e6;\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid #dee2e6;\n}\n\n.model-comparison tr:hover {\n background-color: #f8f9fa;\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: #f8f9fa;\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: #6c757d;\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: #212529;\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: #495057;\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: #f8f9fa;\n border-radius: 6px;\n border: 1px solid #e9ecef;\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: #6c757d;\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: #212529;\n}\n\n.type-percentage {\n font-size: 13px;\n color: #6c757d;\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
2057
+ }], () => [{ type: i0.ChangeDetectorRef }], { agentRunId: [{
2058
+ type: Input
2059
+ }], modelDistributionChart: [{
2060
+ type: ViewChild,
2061
+ args: ['modelDistributionChart', { static: false }]
2062
+ }], executionTimeChart: [{
2063
+ type: ViewChild,
2064
+ args: ['executionTimeChart', { static: false }]
2065
+ }], costByVendorChart: [{
2066
+ type: ViewChild,
2067
+ args: ['costByVendorChart', { static: false }]
2068
+ }], tokenUsageChart: [{
2069
+ type: ViewChild,
2070
+ args: ['tokenUsageChart', { static: false }]
2071
+ }], actionSuccessRateChart: [{
2072
+ type: ViewChild,
2073
+ args: ['actionSuccessRateChart', { static: false }]
2074
+ }], stepTypeChart: [{
2075
+ type: ViewChild,
2076
+ args: ['stepTypeChart', { static: false }]
2077
+ }], promptTimeDistributionChart: [{
2078
+ type: ViewChild,
2079
+ args: ['promptTimeDistributionChart', { static: false }]
2080
+ }], promptTokenDistributionChart: [{
2081
+ type: ViewChild,
2082
+ args: ['promptTokenDistributionChart', { static: false }]
2083
+ }], promptCostDistributionChart: [{
2084
+ type: ViewChild,
2085
+ args: ['promptCostDistributionChart', { static: false }]
2086
+ }], promptCountByNameChart: [{
2087
+ type: ViewChild,
2088
+ args: ['promptCountByNameChart', { static: false }]
2089
+ }] }); })();
2090
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 43 }); })();
2091
+ //# sourceMappingURL=ai-agent-run-analytics.component.js.map