@memberjunction/ng-core-entity-forms 5.38.0 → 5.39.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 (45) hide show
  1. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +10 -0
  2. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
  3. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +645 -531
  4. package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
  5. package/dist/lib/custom/Queries/query-form.component.d.ts +13 -4
  6. package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
  7. package/dist/lib/custom/Queries/query-form.component.js +374 -326
  8. package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
  9. package/dist/lib/custom/Tests/test-form.component.js +2 -3
  10. package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
  11. package/dist/lib/custom/Tests/test-suite-form.component.js +1 -2
  12. package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
  13. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +24 -0
  14. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
  15. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +381 -224
  16. package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
  17. package/dist/lib/custom/custom-forms.module.d.ts +39 -41
  18. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
  19. package/dist/lib/custom/custom-forms.module.js +8 -9
  20. package/dist/lib/custom/custom-forms.module.js.map +1 -1
  21. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.d.ts.map +1 -1
  22. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +71 -73
  23. package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
  24. package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +3 -3
  25. package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
  26. package/dist/lib/generated/Entities/MJAIModelCost/mjaimodelcost.form.component.js +10 -6
  27. package/dist/lib/generated/Entities/MJAIModelCost/mjaimodelcost.form.component.js.map +1 -1
  28. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +3 -3
  29. package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
  30. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +47 -39
  31. package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
  32. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.d.ts.map +1 -1
  33. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js +58 -24
  34. package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js.map +1 -1
  35. package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js +10 -8
  36. package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js.map +1 -1
  37. package/dist/lib/generated/Entities/MJScheduledJob/mjscheduledjob.form.component.js +27 -25
  38. package/dist/lib/generated/Entities/MJScheduledJob/mjscheduledjob.form.component.js.map +1 -1
  39. package/dist/lib/generated/Entities/MJTagSynonym/mjtagsynonym.form.component.js +8 -6
  40. package/dist/lib/generated/Entities/MJTagSynonym/mjtagsynonym.form.component.js.map +1 -1
  41. package/package.json +36 -36
  42. package/dist/lib/custom/Queries/query-category-dialog.component.d.ts +0 -34
  43. package/dist/lib/custom/Queries/query-category-dialog.component.d.ts.map +0 -1
  44. package/dist/lib/custom/Queries/query-category-dialog.component.js +0 -203
  45. package/dist/lib/custom/Queries/query-category-dialog.component.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import { Component, Input, ViewChild, ChangeDetectionStrategy } from '@angular/core';
2
2
  import { Subject } from 'rxjs';
3
3
  import { RunView } from '@memberjunction/core';
4
- import { UUIDsEqual } from '@memberjunction/global';
4
+ import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
5
5
  import * as d3 from 'd3';
6
6
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
7
7
  import * as i0 from "@angular/core";
@@ -42,7 +42,7 @@ function AIAgentRunAnalyticsComponent_Conditional_2_Template(rf, ctx) { if (rf &
42
42
  i0.ɵɵtextInterpolate(ctx_r1.error);
43
43
  } }
44
44
  function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_2_Template(rf, ctx) { if (rf & 1) {
45
- i0.ɵɵelement(0, "i", 63);
45
+ i0.ɵɵelement(0, "i", 66);
46
46
  i0.ɵɵtext(1, " Overview ");
47
47
  } }
48
48
  function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_15_Template(rf, ctx) { if (rf & 1) {
@@ -63,15 +63,64 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_27_Template(rf,
63
63
  i0.ɵɵadvance();
64
64
  i0.ɵɵtextInterpolate1("", ctx_r1.actionMetrics.statusBreakdown.failed, " failed");
65
65
  } }
66
- function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_51_Template(rf, ctx) { if (rf & 1) {
66
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_40_Template(rf, ctx) { if (rf & 1) {
67
+ i0.ɵɵelementStart(0, "span");
68
+ i0.ɵɵtext(1);
69
+ i0.ɵɵpipe(2, "number");
70
+ i0.ɵɵelementEnd();
71
+ } if (rf & 2) {
72
+ const ctx_r1 = i0.ɵɵnextContext(2);
73
+ i0.ɵɵadvance();
74
+ i0.ɵɵtextInterpolate1("incl. ", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheRead + ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " cached");
75
+ } }
76
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template(rf, ctx) { if (rf & 1) {
77
+ i0.ɵɵelementStart(0, "span");
78
+ i0.ɵɵtext(1);
79
+ i0.ɵɵelementEnd();
80
+ } if (rf & 2) {
81
+ const ctx_r1 = i0.ɵɵnextContext(2);
82
+ i0.ɵɵadvance();
83
+ i0.ɵɵtextInterpolate2("input ", ctx_r1.formatCost(ctx_r1.inputCost), " \u00B7 output ", ctx_r1.formatCost(ctx_r1.outputCost));
84
+ } }
85
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template(rf, ctx) { if (rf & 1) {
86
+ i0.ɵɵelementStart(0, "span", 26);
87
+ i0.ɵɵtext(1);
88
+ i0.ɵɵpipe(2, "number");
89
+ i0.ɵɵelementEnd();
90
+ } if (rf & 2) {
91
+ const ctx_r1 = i0.ɵɵnextContext(2);
92
+ i0.ɵɵadvance();
93
+ i0.ɵɵtextInterpolate2("saved ", ctx_r1.formatCost(ctx_r1.cacheSavings), " (", i0.ɵɵpipeBind2(2, 2, ctx_r1.cacheSavingsPct, "1.0-0"), "%) via cache");
94
+ } }
95
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template(rf, ctx) { if (rf & 1) {
96
+ i0.ɵɵelementStart(0, "span");
97
+ i0.ɵɵtext(1);
98
+ i0.ɵɵpipe(2, "number");
99
+ i0.ɵɵelementEnd();
100
+ } if (rf & 2) {
101
+ const ctx_r1 = i0.ɵɵnextContext(2);
102
+ i0.ɵɵadvance();
103
+ i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " written");
104
+ } }
105
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf, ctx) { if (rf & 1) {
106
+ i0.ɵɵelementStart(0, "span");
107
+ i0.ɵɵtext(1);
108
+ i0.ɵɵpipe(2, "number");
109
+ i0.ɵɵelementEnd();
110
+ } if (rf & 2) {
111
+ const ctx_r1 = i0.ɵɵnextContext(2);
112
+ i0.ɵɵadvance();
113
+ i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(2, 1, ctx_r1.cacheHitRatePct, "1.0-0"), "% hit rate");
114
+ } }
115
+ function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_69_Template(rf, ctx) { if (rf & 1) {
67
116
  i0.ɵɵelement(0, "i", 22);
68
117
  i0.ɵɵtext(1, " Prompt Analytics ");
69
118
  } }
70
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_53_Template(rf, ctx) { if (rf & 1) {
119
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template(rf, ctx) { if (rf & 1) {
71
120
  const _r4 = i0.ɵɵgetCurrentView();
72
- i0.ɵɵelementStart(0, "div", 35)(1, "button", 40);
73
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_53_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
74
- i0.ɵɵelement(2, "i", 41);
121
+ i0.ɵɵelementStart(0, "div", 38)(1, "button", 43);
122
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
123
+ i0.ɵɵelement(2, "i", 44);
75
124
  i0.ɵɵtext(3);
76
125
  i0.ɵɵelementEnd()();
77
126
  } if (rf & 2) {
@@ -81,20 +130,20 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_53_Template(rf,
81
130
  i0.ɵɵadvance();
82
131
  i0.ɵɵtextInterpolate1(" ", ctx_r1.viewMode === "grid" ? "Expand All" : "Collapse All", " ");
83
132
  } }
84
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_54_Template(rf, ctx) { if (rf & 1) {
85
- i0.ɵɵelementStart(0, "div", 36);
86
- i0.ɵɵelement(1, "i", 64);
133
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template(rf, ctx) { if (rf & 1) {
134
+ i0.ɵɵelementStart(0, "div", 39);
135
+ i0.ɵɵelement(1, "i", 67);
87
136
  i0.ɵɵelementStart(2, "p");
88
137
  i0.ɵɵtext(3, "No prompt executions found in this agent run.");
89
138
  i0.ɵɵelementEnd();
90
- i0.ɵɵelementStart(4, "p", 65);
139
+ i0.ɵɵelementStart(4, "p", 68);
91
140
  i0.ɵɵtext(5, "This agent run may have only executed actions without any AI prompts.");
92
141
  i0.ɵɵelementEnd()();
93
142
  } }
94
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
95
- i0.ɵɵelementStart(0, "div", 74);
96
- i0.ɵɵelement(1, "span", 75);
97
- i0.ɵɵelementStart(2, "span", 76);
143
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
144
+ i0.ɵɵelementStart(0, "div", 77);
145
+ i0.ɵɵelement(1, "span", 78);
146
+ i0.ɵɵelementStart(2, "span", 79);
98
147
  i0.ɵɵtext(3);
99
148
  i0.ɵɵelementEnd()();
100
149
  } if (rf & 2) {
@@ -105,9 +154,9 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_1
105
154
  i0.ɵɵadvance(2);
106
155
  i0.ɵɵtextInterpolate3("", item_r6.key, ": ", item_r6.value.count, " (", (item_r6.value.count / ctx_r1.promptMetrics.totalCount * 100).toFixed(1), "%)");
107
156
  } }
108
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_12_Template(rf, ctx) { if (rf & 1) {
109
- i0.ɵɵelementStart(0, "div", 68);
110
- i0.ɵɵrepeaterCreate(1, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_12_For_2_Template, 4, 5, "div", 74, i0.ɵɵcomponentInstance().trackByKey, true);
157
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template(rf, ctx) { if (rf & 1) {
158
+ i0.ɵɵelementStart(0, "div", 71);
159
+ i0.ɵɵrepeaterCreate(1, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template, 4, 5, "div", 77, i0.ɵɵcomponentInstance().trackByKey, true);
111
160
  i0.ɵɵpipe(3, "keyvalue");
112
161
  i0.ɵɵelementEnd();
113
162
  } if (rf & 2) {
@@ -115,58 +164,58 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_1
115
164
  i0.ɵɵadvance();
116
165
  i0.ɵɵrepeater(i0.ɵɵpipeBind1(3, 0, ctx_r1.promptMetrics.byModel));
117
166
  } }
118
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template(rf, ctx) { if (rf & 1) {
167
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf, ctx) { if (rf & 1) {
119
168
  const _r5 = i0.ɵɵgetCurrentView();
120
- i0.ɵɵelementStart(0, "div", 37)(1, "div", 43)(2, "div", 44);
121
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
169
+ i0.ɵɵelementStart(0, "div", 40)(1, "div", 46)(2, "div", 47);
170
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
122
171
  i0.ɵɵelementStart(3, "h3");
123
- i0.ɵɵelement(4, "i", 66);
172
+ i0.ɵɵelement(4, "i", 69);
124
173
  i0.ɵɵtext(5, " Prompts by Model");
125
174
  i0.ɵɵelementEnd();
126
- i0.ɵɵelementStart(6, "button", 46);
127
- i0.ɵɵelement(7, "i", 41);
175
+ i0.ɵɵelementStart(6, "button", 49);
176
+ i0.ɵɵelement(7, "i", 44);
128
177
  i0.ɵɵelementEnd()();
129
- i0.ɵɵelementStart(8, "div", 47)(9, "div", 48);
130
- i0.ɵɵelement(10, "div", 67, 2);
131
- i0.ɵɵconditionalCreate(12, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_12_Template, 4, 2, "div", 68);
178
+ i0.ɵɵelementStart(8, "div", 50)(9, "div", 51);
179
+ i0.ɵɵelement(10, "div", 70, 2);
180
+ i0.ɵɵconditionalCreate(12, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template, 4, 2, "div", 71);
132
181
  i0.ɵɵelementEnd()()();
133
- i0.ɵɵelementStart(13, "div", 43)(14, "div", 44);
134
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
182
+ i0.ɵɵelementStart(13, "div", 46)(14, "div", 47);
183
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
135
184
  i0.ɵɵelementStart(15, "h3");
136
- i0.ɵɵelement(16, "i", 33);
185
+ i0.ɵɵelement(16, "i", 36);
137
186
  i0.ɵɵtext(17, " Average Execution Time by Vendor");
138
187
  i0.ɵɵelementEnd();
139
- i0.ɵɵelementStart(18, "button", 46);
140
- i0.ɵɵelement(19, "i", 41);
188
+ i0.ɵɵelementStart(18, "button", 49);
189
+ i0.ɵɵelement(19, "i", 44);
141
190
  i0.ɵɵelementEnd()();
142
- i0.ɵɵelementStart(20, "div", 47)(21, "div", 48);
143
- i0.ɵɵelement(22, "div", 69, 3);
191
+ i0.ɵɵelementStart(20, "div", 50)(21, "div", 51);
192
+ i0.ɵɵelement(22, "div", 72, 3);
144
193
  i0.ɵɵelementEnd()()();
145
- i0.ɵɵelementStart(24, "div", 43)(25, "div", 44);
146
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
194
+ i0.ɵɵelementStart(24, "div", 46)(25, "div", 47);
195
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
147
196
  i0.ɵɵelementStart(26, "h3");
148
197
  i0.ɵɵelement(27, "i", 31);
149
198
  i0.ɵɵtext(28, " Cost Distribution by Vendor");
150
199
  i0.ɵɵelementEnd();
151
- i0.ɵɵelementStart(29, "button", 46);
152
- i0.ɵɵelement(30, "i", 41);
200
+ i0.ɵɵelementStart(29, "button", 49);
201
+ i0.ɵɵelement(30, "i", 44);
153
202
  i0.ɵɵelementEnd()();
154
- i0.ɵɵelementStart(31, "div", 47)(32, "div", 48);
155
- i0.ɵɵelement(33, "div", 70, 4);
156
- i0.ɵɵelementStart(35, "div", 71);
203
+ i0.ɵɵelementStart(31, "div", 50)(32, "div", 51);
204
+ i0.ɵɵelement(33, "div", 73, 4);
205
+ i0.ɵɵelementStart(35, "div", 74);
157
206
  i0.ɵɵtext(36);
158
207
  i0.ɵɵelementEnd()()()();
159
- i0.ɵɵelementStart(37, "div", 43)(38, "div", 44);
160
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
208
+ i0.ɵɵelementStart(37, "div", 46)(38, "div", 47);
209
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
161
210
  i0.ɵɵelementStart(39, "h3");
162
- i0.ɵɵelement(40, "i", 72);
211
+ i0.ɵɵelement(40, "i", 75);
163
212
  i0.ɵɵtext(41, " Token Usage by Model");
164
213
  i0.ɵɵelementEnd();
165
- i0.ɵɵelementStart(42, "button", 46);
166
- i0.ɵɵelement(43, "i", 41);
214
+ i0.ɵɵelementStart(42, "button", 49);
215
+ i0.ɵɵelement(43, "i", 44);
167
216
  i0.ɵɵelementEnd()();
168
- i0.ɵɵelementStart(44, "div", 47)(45, "div", 48);
169
- i0.ɵɵelement(46, "div", 73, 5);
217
+ i0.ɵɵelementStart(44, "div", 50)(45, "div", 51);
218
+ i0.ɵɵelement(46, "div", 76, 5);
170
219
  i0.ɵɵelementEnd()()()();
171
220
  } if (rf & 2) {
172
221
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -191,55 +240,55 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template(rf,
191
240
  i0.ɵɵadvance(6);
192
241
  i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["tokenUsage"] ? "fa-compress" : "fa-expand");
193
242
  } }
194
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf, ctx) { if (rf & 1) {
243
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf, ctx) { if (rf & 1) {
195
244
  const _r7 = i0.ɵɵgetCurrentView();
196
- i0.ɵɵelementStart(0, "div", 38)(1, "div", 43)(2, "div", 44);
197
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptTime")); });
245
+ i0.ɵɵelementStart(0, "div", 41)(1, "div", 46)(2, "div", 47);
246
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptTime")); });
198
247
  i0.ɵɵelementStart(3, "h3");
199
- i0.ɵɵelement(4, "i", 77);
248
+ i0.ɵɵelement(4, "i", 80);
200
249
  i0.ɵɵtext(5, " Average Execution Time by Prompt");
201
250
  i0.ɵɵelementEnd();
202
- i0.ɵɵelementStart(6, "button", 46);
203
- i0.ɵɵelement(7, "i", 41);
251
+ i0.ɵɵelementStart(6, "button", 49);
252
+ i0.ɵɵelement(7, "i", 44);
204
253
  i0.ɵɵelementEnd()();
205
- i0.ɵɵelementStart(8, "div", 47)(9, "div", 48);
206
- i0.ɵɵelement(10, "div", 78, 6);
254
+ i0.ɵɵelementStart(8, "div", 50)(9, "div", 51);
255
+ i0.ɵɵelement(10, "div", 81, 6);
207
256
  i0.ɵɵelementEnd()()();
208
- i0.ɵɵelementStart(12, "div", 43)(13, "div", 44);
209
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptToken")); });
257
+ i0.ɵɵelementStart(12, "div", 46)(13, "div", 47);
258
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptToken")); });
210
259
  i0.ɵɵelementStart(14, "h3");
211
- i0.ɵɵelement(15, "i", 79);
260
+ i0.ɵɵelement(15, "i", 82);
212
261
  i0.ɵɵtext(16, " Token Usage by Prompt");
213
262
  i0.ɵɵelementEnd();
214
- i0.ɵɵelementStart(17, "button", 46);
215
- i0.ɵɵelement(18, "i", 41);
263
+ i0.ɵɵelementStart(17, "button", 49);
264
+ i0.ɵɵelement(18, "i", 44);
216
265
  i0.ɵɵelementEnd()();
217
- i0.ɵɵelementStart(19, "div", 47)(20, "div", 48);
218
- i0.ɵɵelement(21, "div", 80, 7);
266
+ i0.ɵɵelementStart(19, "div", 50)(20, "div", 51);
267
+ i0.ɵɵelement(21, "div", 83, 7);
219
268
  i0.ɵɵelementEnd()()();
220
- i0.ɵɵelementStart(23, "div", 43)(24, "div", 44);
221
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template_div_click_24_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCost")); });
269
+ i0.ɵɵelementStart(23, "div", 46)(24, "div", 47);
270
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_24_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCost")); });
222
271
  i0.ɵɵelementStart(25, "h3");
223
- i0.ɵɵelement(26, "i", 66);
272
+ i0.ɵɵelement(26, "i", 69);
224
273
  i0.ɵɵtext(27, " Cost Distribution by Prompt");
225
274
  i0.ɵɵelementEnd();
226
- i0.ɵɵelementStart(28, "button", 46);
227
- i0.ɵɵelement(29, "i", 41);
275
+ i0.ɵɵelementStart(28, "button", 49);
276
+ i0.ɵɵelement(29, "i", 44);
228
277
  i0.ɵɵelementEnd()();
229
- i0.ɵɵelementStart(30, "div", 47)(31, "div", 48);
230
- i0.ɵɵelement(32, "div", 81, 8);
278
+ i0.ɵɵelementStart(30, "div", 50)(31, "div", 51);
279
+ i0.ɵɵelement(32, "div", 84, 8);
231
280
  i0.ɵɵelementEnd()()();
232
- i0.ɵɵelementStart(34, "div", 43)(35, "div", 44);
233
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template_div_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCount")); });
281
+ i0.ɵɵelementStart(34, "div", 46)(35, "div", 47);
282
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCount")); });
234
283
  i0.ɵɵelementStart(36, "h3");
235
- i0.ɵɵelement(37, "i", 82);
284
+ i0.ɵɵelement(37, "i", 85);
236
285
  i0.ɵɵtext(38, " Prompt Execution Count");
237
286
  i0.ɵɵelementEnd();
238
- i0.ɵɵelementStart(39, "button", 46);
239
- i0.ɵɵelement(40, "i", 41);
287
+ i0.ɵɵelementStart(39, "button", 49);
288
+ i0.ɵɵelement(40, "i", 44);
240
289
  i0.ɵɵelementEnd()();
241
- i0.ɵɵelementStart(41, "div", 47)(42, "div", 48);
242
- i0.ɵɵelement(43, "div", 83, 9);
290
+ i0.ɵɵelementStart(41, "div", 50)(42, "div", 51);
291
+ i0.ɵɵelement(43, "div", 86, 9);
243
292
  i0.ɵɵelementEnd()()()();
244
293
  } if (rf & 2) {
245
294
  const ctx_r1 = i0.ɵɵnextContext(2);
@@ -260,7 +309,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf,
260
309
  i0.ɵɵadvance(6);
261
310
  i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCount"] ? "fa-compress" : "fa-expand");
262
311
  } }
263
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Template(rf, ctx) { if (rf & 1) {
312
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Template(rf, ctx) { if (rf & 1) {
264
313
  i0.ɵɵelementStart(0, "tr")(1, "td");
265
314
  i0.ɵɵtext(2);
266
315
  i0.ɵɵelementEnd();
@@ -273,7 +322,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Templa
273
322
  i0.ɵɵelementStart(7, "td");
274
323
  i0.ɵɵtext(8);
275
324
  i0.ɵɵelementEnd();
276
- i0.ɵɵelementStart(9, "td")(10, "span", 84);
325
+ i0.ɵɵelementStart(9, "td")(10, "span", 87);
277
326
  i0.ɵɵtext(11);
278
327
  i0.ɵɵelementEnd()()();
279
328
  } if (rf & 2) {
@@ -290,8 +339,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Templa
290
339
  i0.ɵɵadvance(3);
291
340
  i0.ɵɵtextInterpolate1(" ", ctx_r1.calculatePromptSuccessRate(prompt_r8.key), "% ");
292
341
  } }
293
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template(rf, ctx) { if (rf & 1) {
294
- i0.ɵɵelementStart(0, "div", 42)(1, "table")(2, "thead")(3, "tr")(4, "th");
342
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template(rf, ctx) { if (rf & 1) {
343
+ i0.ɵɵelementStart(0, "div", 45)(1, "table")(2, "thead")(3, "tr")(4, "th");
295
344
  i0.ɵɵtext(5, "Prompt Name");
296
345
  i0.ɵɵelementEnd();
297
346
  i0.ɵɵelementStart(6, "th");
@@ -307,7 +356,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template(rf,
307
356
  i0.ɵɵtext(13, "Success Rate");
308
357
  i0.ɵɵelementEnd()()();
309
358
  i0.ɵɵelementStart(14, "tbody");
310
- i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Template, 12, 5, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
359
+ i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Template, 12, 5, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
311
360
  i0.ɵɵpipe(17, "keyvalue");
312
361
  i0.ɵɵelementEnd()()();
313
362
  } if (rf & 2) {
@@ -315,11 +364,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template(rf,
315
364
  i0.ɵɵadvance(15);
316
365
  i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.promptMetrics.byPrompt));
317
366
  } }
318
- function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_63_Template(rf, ctx) { if (rf & 1) {
367
+ function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_81_Template(rf, ctx) { if (rf & 1) {
319
368
  i0.ɵɵelement(0, "i", 29);
320
369
  i0.ɵɵtext(1, " Action Analytics ");
321
370
  } }
322
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Template(rf, ctx) { if (rf & 1) {
371
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Template(rf, ctx) { if (rf & 1) {
323
372
  i0.ɵɵelementStart(0, "tr")(1, "td");
324
373
  i0.ɵɵtext(2);
325
374
  i0.ɵɵelementEnd();
@@ -329,7 +378,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Templa
329
378
  i0.ɵɵelementStart(5, "td");
330
379
  i0.ɵɵtext(6);
331
380
  i0.ɵɵelementEnd();
332
- i0.ɵɵelementStart(7, "td")(8, "span", 84);
381
+ i0.ɵɵelementStart(7, "td")(8, "span", 87);
333
382
  i0.ɵɵtext(9);
334
383
  i0.ɵɵelementEnd()();
335
384
  i0.ɵɵelementStart(10, "td");
@@ -351,8 +400,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Templa
351
400
  i0.ɵɵadvance(2);
352
401
  i0.ɵɵtextInterpolate(ctx_r1.getActionType(action_r9.key));
353
402
  } }
354
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template(rf, ctx) { if (rf & 1) {
355
- i0.ɵɵelementStart(0, "div", 42)(1, "table")(2, "thead")(3, "tr")(4, "th");
403
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template(rf, ctx) { if (rf & 1) {
404
+ i0.ɵɵelementStart(0, "div", 45)(1, "table")(2, "thead")(3, "tr")(4, "th");
356
405
  i0.ɵɵtext(5, "Action Name");
357
406
  i0.ɵɵelementEnd();
358
407
  i0.ɵɵelementStart(6, "th");
@@ -368,7 +417,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template(rf,
368
417
  i0.ɵɵtext(13, "Type");
369
418
  i0.ɵɵelementEnd()()();
370
419
  i0.ɵɵelementStart(14, "tbody");
371
- i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Template, 12, 11, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
420
+ i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Template, 12, 11, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
372
421
  i0.ɵɵpipe(17, "keyvalue");
373
422
  i0.ɵɵelementEnd()()();
374
423
  } if (rf & 2) {
@@ -376,11 +425,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template(rf,
376
425
  i0.ɵɵadvance(15);
377
426
  i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.actionMetrics.byAction));
378
427
  } }
379
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_For_8_Template(rf, ctx) { if (rf & 1) {
380
- i0.ɵɵelementStart(0, "div", 88)(1, "span", 89);
428
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template(rf, ctx) { if (rf & 1) {
429
+ i0.ɵɵelementStart(0, "div", 91)(1, "span", 92);
381
430
  i0.ɵɵtext(2);
382
431
  i0.ɵɵelementEnd();
383
- i0.ɵɵelementStart(3, "span", 90);
432
+ i0.ɵɵelementStart(3, "span", 93);
384
433
  i0.ɵɵtext(4);
385
434
  i0.ɵɵelementEnd()();
386
435
  } if (rf & 2) {
@@ -390,34 +439,34 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_For_8_Templat
390
439
  i0.ɵɵadvance(2);
391
440
  i0.ɵɵtextInterpolate(error_r10.message);
392
441
  } }
393
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_Template(rf, ctx) { if (rf & 1) {
394
- i0.ɵɵelementStart(0, "div", 53)(1, "h3");
395
- i0.ɵɵelement(2, "i", 85);
442
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template(rf, ctx) { if (rf & 1) {
443
+ i0.ɵɵelementStart(0, "div", 56)(1, "h3");
444
+ i0.ɵɵelement(2, "i", 88);
396
445
  i0.ɵɵtext(3, " Common Errors ");
397
446
  i0.ɵɵelementEnd();
398
- i0.ɵɵelementStart(4, "p", 86);
447
+ i0.ɵɵelementStart(4, "p", 89);
399
448
  i0.ɵɵtext(5, " This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention. ");
400
449
  i0.ɵɵelementEnd();
401
- i0.ɵɵelementStart(6, "div", 87);
402
- i0.ɵɵrepeaterCreate(7, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_For_8_Template, 5, 2, "div", 88, i0.ɵɵcomponentInstance().trackByErrorMessage, true);
450
+ i0.ɵɵelementStart(6, "div", 90);
451
+ i0.ɵɵrepeaterCreate(7, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template, 5, 2, "div", 91, i0.ɵɵcomponentInstance().trackByErrorMessage, true);
403
452
  i0.ɵɵelementEnd()();
404
453
  } if (rf & 2) {
405
454
  const ctx_r1 = i0.ɵɵnextContext(2);
406
455
  i0.ɵɵadvance(7);
407
456
  i0.ɵɵrepeater(ctx_r1.getTopErrors());
408
457
  } }
409
- function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_95_Template(rf, ctx) { if (rf & 1) {
410
- i0.ɵɵelementStart(0, "div", 54);
411
- i0.ɵɵelement(1, "i", 91);
458
+ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template(rf, ctx) { if (rf & 1) {
459
+ i0.ɵɵelementStart(0, "div", 57);
460
+ i0.ɵɵelement(1, "i", 94);
412
461
  i0.ɵɵelementStart(2, "p");
413
462
  i0.ɵɵtext(3, "No action errors detected in this run. All actions completed successfully!");
414
463
  i0.ɵɵelementEnd()();
415
464
  } }
416
- function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_97_Template(rf, ctx) { if (rf & 1) {
417
- i0.ɵɵelement(0, "i", 92);
465
+ function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template(rf, ctx) { if (rf & 1) {
466
+ i0.ɵɵelement(0, "i", 95);
418
467
  i0.ɵɵtext(1, " Model Performance Comparison ");
419
468
  } }
420
- function AIAgentRunAnalyticsComponent_Conditional_3_For_121_Template(rf, ctx) { if (rf & 1) {
469
+ function AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template(rf, ctx) { if (rf & 1) {
421
470
  i0.ɵɵelementStart(0, "tr")(1, "td");
422
471
  i0.ɵɵtext(2);
423
472
  i0.ɵɵelementEnd();
@@ -464,20 +513,20 @@ function AIAgentRunAnalyticsComponent_Conditional_3_For_121_Template(rf, ctx) {
464
513
  i0.ɵɵadvance(3);
465
514
  i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(18, 11, model_r11.outputTokens, "1.0-0"));
466
515
  } }
467
- function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_123_Template(rf, ctx) { if (rf & 1) {
468
- i0.ɵɵelement(0, "i", 93);
516
+ function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template(rf, ctx) { if (rf & 1) {
517
+ i0.ɵɵelement(0, "i", 96);
469
518
  i0.ɵɵtext(1, " Execution Timeline Analysis ");
470
519
  } }
471
- function AIAgentRunAnalyticsComponent_Conditional_3_For_151_Template(rf, ctx) { if (rf & 1) {
472
- i0.ɵɵelementStart(0, "div", 62);
473
- i0.ɵɵelement(1, "i", 41);
474
- i0.ɵɵelementStart(2, "span", 94);
520
+ function AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template(rf, ctx) { if (rf & 1) {
521
+ i0.ɵɵelementStart(0, "div", 65);
522
+ i0.ɵɵelement(1, "i", 44);
523
+ i0.ɵɵelementStart(2, "span", 97);
475
524
  i0.ɵɵtext(3);
476
525
  i0.ɵɵelementEnd();
477
- i0.ɵɵelementStart(4, "span", 95);
526
+ i0.ɵɵelementStart(4, "span", 98);
478
527
  i0.ɵɵtext(5);
479
528
  i0.ɵɵelementEnd();
480
- i0.ɵɵelementStart(6, "span", 96);
529
+ i0.ɵɵelementStart(6, "span", 99);
481
530
  i0.ɵɵtext(7);
482
531
  i0.ɵɵelementEnd()();
483
532
  } if (rf & 2) {
@@ -533,133 +582,154 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
533
582
  i0.ɵɵelementStart(34, "div", 24);
534
583
  i0.ɵɵtext(35);
535
584
  i0.ɵɵelementEnd();
536
- i0.ɵɵelementStart(36, "div", 25)(37, "span");
585
+ i0.ɵɵelementStart(36, "div", 32)(37, "span");
537
586
  i0.ɵɵtext(38);
538
- i0.ɵɵelementEnd()()()();
539
- i0.ɵɵelementStart(39, "div", 20)(40, "div", 32);
540
- i0.ɵɵelement(41, "i", 33);
587
+ i0.ɵɵpipe(39, "number");
588
+ i0.ɵɵelementEnd();
589
+ i0.ɵɵconditionalCreate(40, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_40_Template, 3, 3, "span");
590
+ i0.ɵɵconditionalCreate(41, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template, 2, 2, "span");
591
+ i0.ɵɵconditionalCreate(42, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template, 3, 5, "span", 26);
592
+ i0.ɵɵelementEnd()()();
593
+ i0.ɵɵelementStart(43, "div", 20)(44, "div", 33);
594
+ i0.ɵɵelement(45, "i", 34);
595
+ i0.ɵɵelementEnd();
596
+ i0.ɵɵelementStart(46, "div", 23)(47, "h3");
597
+ i0.ɵɵtext(48, "Prompt Cache");
598
+ i0.ɵɵelementEnd();
599
+ i0.ɵɵelementStart(49, "div", 24);
600
+ i0.ɵɵtext(50);
601
+ i0.ɵɵpipe(51, "number");
541
602
  i0.ɵɵelementEnd();
542
- i0.ɵɵelementStart(42, "div", 23)(43, "h3");
543
- i0.ɵɵtext(44, "Execution Time");
603
+ i0.ɵɵelementStart(52, "div", 32)(53, "span");
604
+ i0.ɵɵtext(54, "tokens read from cache");
544
605
  i0.ɵɵelementEnd();
545
- i0.ɵɵelementStart(45, "div", 24);
546
- i0.ɵɵtext(46);
606
+ i0.ɵɵconditionalCreate(55, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template, 3, 3, "span");
607
+ i0.ɵɵconditionalCreate(56, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template, 3, 4, "span");
608
+ i0.ɵɵelementEnd()()();
609
+ i0.ɵɵelementStart(57, "div", 20)(58, "div", 35);
610
+ i0.ɵɵelement(59, "i", 36);
611
+ i0.ɵɵelementEnd();
612
+ i0.ɵɵelementStart(60, "div", 23)(61, "h3");
613
+ i0.ɵɵtext(62, "Execution Time");
547
614
  i0.ɵɵelementEnd();
548
- i0.ɵɵelementStart(47, "div", 25)(48, "span");
549
- i0.ɵɵtext(49);
615
+ i0.ɵɵelementStart(63, "div", 24);
616
+ i0.ɵɵtext(64);
617
+ i0.ɵɵelementEnd();
618
+ i0.ɵɵelementStart(65, "div", 25)(66, "span");
619
+ i0.ɵɵtext(67);
550
620
  i0.ɵɵelementEnd()()()()()();
551
- i0.ɵɵelementStart(50, "mj-accordion-panel", 17);
552
- i0.ɵɵtemplate(51, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_51_Template, 2, 0, "ng-template", 18);
553
- i0.ɵɵelementStart(52, "div", 34);
554
- i0.ɵɵconditionalCreate(53, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_53_Template, 4, 2, "div", 35);
555
- i0.ɵɵconditionalCreate(54, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_54_Template, 6, 0, "div", 36);
556
- i0.ɵɵconditionalCreate(55, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template, 48, 14, "div", 37);
557
- i0.ɵɵconditionalCreate(56, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template, 45, 12, "div", 38);
558
- i0.ɵɵelementStart(57, "div", 39)(58, "button", 40);
559
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_58_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.promptDetailsExpanded = !ctx_r1.promptDetailsExpanded); });
560
- i0.ɵɵelement(59, "i", 41);
561
- i0.ɵɵtext(60, " Detailed Prompt Metrics ");
562
- i0.ɵɵelementEnd();
563
- i0.ɵɵconditionalCreate(61, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template, 18, 2, "div", 42);
621
+ i0.ɵɵelementStart(68, "mj-accordion-panel", 17);
622
+ i0.ɵɵtemplate(69, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_69_Template, 2, 0, "ng-template", 18);
623
+ i0.ɵɵelementStart(70, "div", 37);
624
+ i0.ɵɵconditionalCreate(71, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template, 4, 2, "div", 38);
625
+ i0.ɵɵconditionalCreate(72, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template, 6, 0, "div", 39);
626
+ i0.ɵɵconditionalCreate(73, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template, 48, 14, "div", 40);
627
+ i0.ɵɵconditionalCreate(74, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template, 45, 12, "div", 41);
628
+ i0.ɵɵelementStart(75, "div", 42)(76, "button", 43);
629
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_76_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.promptDetailsExpanded = !ctx_r1.promptDetailsExpanded); });
630
+ i0.ɵɵelement(77, "i", 44);
631
+ i0.ɵɵtext(78, " Detailed Prompt Metrics ");
632
+ i0.ɵɵelementEnd();
633
+ i0.ɵɵconditionalCreate(79, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template, 18, 2, "div", 45);
564
634
  i0.ɵɵelementEnd()()();
565
- i0.ɵɵelementStart(62, "mj-accordion-panel", 17);
566
- i0.ɵɵtemplate(63, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_63_Template, 2, 0, "ng-template", 18);
567
- i0.ɵɵelementStart(64, "div", 34)(65, "div", 37)(66, "div", 43)(67, "div", 44);
568
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_67_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("actionSuccess")); });
569
- i0.ɵɵelementStart(68, "h3");
570
- i0.ɵɵelement(69, "i", 45);
571
- i0.ɵɵtext(70, " Action Success Rate");
572
- i0.ɵɵelementEnd();
573
- i0.ɵɵelementStart(71, "button", 46);
574
- i0.ɵɵelement(72, "i", 41);
635
+ i0.ɵɵelementStart(80, "mj-accordion-panel", 17);
636
+ i0.ɵɵtemplate(81, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_81_Template, 2, 0, "ng-template", 18);
637
+ i0.ɵɵelementStart(82, "div", 37)(83, "div", 40)(84, "div", 46)(85, "div", 47);
638
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_85_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("actionSuccess")); });
639
+ i0.ɵɵelementStart(86, "h3");
640
+ i0.ɵɵelement(87, "i", 48);
641
+ i0.ɵɵtext(88, " Action Success Rate");
642
+ i0.ɵɵelementEnd();
643
+ i0.ɵɵelementStart(89, "button", 49);
644
+ i0.ɵɵelement(90, "i", 44);
575
645
  i0.ɵɵelementEnd()();
576
- i0.ɵɵelementStart(73, "div", 47)(74, "div", 48);
577
- i0.ɵɵelement(75, "div", 49, 0);
646
+ i0.ɵɵelementStart(91, "div", 50)(92, "div", 51);
647
+ i0.ɵɵelement(93, "div", 52, 0);
578
648
  i0.ɵɵelementEnd()()();
579
- i0.ɵɵelementStart(77, "div", 43)(78, "div", 44);
580
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_78_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("stepType")); });
581
- i0.ɵɵelementStart(79, "h3");
582
- i0.ɵɵelement(80, "i", 50);
583
- i0.ɵɵtext(81, " Step Type Distribution");
584
- i0.ɵɵelementEnd();
585
- i0.ɵɵelementStart(82, "button", 46);
586
- i0.ɵɵelement(83, "i", 41);
649
+ i0.ɵɵelementStart(95, "div", 46)(96, "div", 47);
650
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_96_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("stepType")); });
651
+ i0.ɵɵelementStart(97, "h3");
652
+ i0.ɵɵelement(98, "i", 53);
653
+ i0.ɵɵtext(99, " Step Type Distribution");
654
+ i0.ɵɵelementEnd();
655
+ i0.ɵɵelementStart(100, "button", 49);
656
+ i0.ɵɵelement(101, "i", 44);
587
657
  i0.ɵɵelementEnd()();
588
- i0.ɵɵelementStart(84, "div", 47)(85, "div", 48);
589
- i0.ɵɵelement(86, "div", 51, 1);
658
+ i0.ɵɵelementStart(102, "div", 50)(103, "div", 51);
659
+ i0.ɵɵelement(104, "div", 54, 1);
590
660
  i0.ɵɵelementEnd()()()();
591
- i0.ɵɵelementStart(88, "div", 39)(89, "button", 40);
592
- i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_89_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.actionDetailsExpanded = !ctx_r1.actionDetailsExpanded); });
593
- i0.ɵɵelement(90, "i", 41);
594
- i0.ɵɵtext(91, " Detailed Action Metrics ");
661
+ i0.ɵɵelementStart(106, "div", 42)(107, "button", 43);
662
+ i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_107_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.actionDetailsExpanded = !ctx_r1.actionDetailsExpanded); });
663
+ i0.ɵɵelement(108, "i", 44);
664
+ i0.ɵɵtext(109, " Detailed Action Metrics ");
595
665
  i0.ɵɵelementEnd();
596
- i0.ɵɵconditionalCreate(92, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template, 18, 2, "div", 42);
666
+ i0.ɵɵconditionalCreate(110, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template, 18, 2, "div", 45);
597
667
  i0.ɵɵelementEnd();
598
- i0.ɵɵelementStart(93, "div", 52);
599
- i0.ɵɵconditionalCreate(94, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_Template, 9, 0, "div", 53);
600
- i0.ɵɵconditionalCreate(95, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_95_Template, 4, 0, "div", 54);
668
+ i0.ɵɵelementStart(111, "div", 55);
669
+ i0.ɵɵconditionalCreate(112, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template, 9, 0, "div", 56);
670
+ i0.ɵɵconditionalCreate(113, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template, 4, 0, "div", 57);
601
671
  i0.ɵɵelementEnd()()();
602
- i0.ɵɵelementStart(96, "mj-accordion-panel", 17);
603
- i0.ɵɵtemplate(97, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_97_Template, 2, 0, "ng-template", 18);
604
- i0.ɵɵelementStart(98, "div", 34)(99, "div", 55)(100, "table")(101, "thead")(102, "tr")(103, "th");
605
- i0.ɵɵtext(104, "Model");
672
+ i0.ɵɵelementStart(114, "mj-accordion-panel", 17);
673
+ i0.ɵɵtemplate(115, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template, 2, 0, "ng-template", 18);
674
+ i0.ɵɵelementStart(116, "div", 37)(117, "div", 58)(118, "table")(119, "thead")(120, "tr")(121, "th");
675
+ i0.ɵɵtext(122, "Model");
606
676
  i0.ɵɵelementEnd();
607
- i0.ɵɵelementStart(105, "th");
608
- i0.ɵɵtext(106, "Vendor");
677
+ i0.ɵɵelementStart(123, "th");
678
+ i0.ɵɵtext(124, "Vendor");
609
679
  i0.ɵɵelementEnd();
610
- i0.ɵɵelementStart(107, "th");
611
- i0.ɵɵtext(108, "Prompts");
680
+ i0.ɵɵelementStart(125, "th");
681
+ i0.ɵɵtext(126, "Prompts");
612
682
  i0.ɵɵelementEnd();
613
- i0.ɵɵelementStart(109, "th");
614
- i0.ɵɵtext(110, "Avg Time");
683
+ i0.ɵɵelementStart(127, "th");
684
+ i0.ɵɵtext(128, "Avg Time");
615
685
  i0.ɵɵelementEnd();
616
- i0.ɵɵelementStart(111, "th");
617
- i0.ɵɵtext(112, "Total Cost");
686
+ i0.ɵɵelementStart(129, "th");
687
+ i0.ɵɵtext(130, "Total Cost");
618
688
  i0.ɵɵelementEnd();
619
- i0.ɵɵelementStart(113, "th");
620
- i0.ɵɵtext(114, "Avg Cost/Prompt");
689
+ i0.ɵɵelementStart(131, "th");
690
+ i0.ɵɵtext(132, "Avg Cost/Prompt");
621
691
  i0.ɵɵelementEnd();
622
- i0.ɵɵelementStart(115, "th");
623
- i0.ɵɵtext(116, "Input Tokens");
692
+ i0.ɵɵelementStart(133, "th");
693
+ i0.ɵɵtext(134, "Input Tokens");
624
694
  i0.ɵɵelementEnd();
625
- i0.ɵɵelementStart(117, "th");
626
- i0.ɵɵtext(118, "Output Tokens");
695
+ i0.ɵɵelementStart(135, "th");
696
+ i0.ɵɵtext(136, "Output Tokens");
627
697
  i0.ɵɵelementEnd()()();
628
- i0.ɵɵelementStart(119, "tbody");
629
- i0.ɵɵrepeaterCreate(120, AIAgentRunAnalyticsComponent_Conditional_3_For_121_Template, 19, 14, "tr", null, i0.ɵɵcomponentInstance().trackByModelName, true);
698
+ i0.ɵɵelementStart(137, "tbody");
699
+ i0.ɵɵrepeaterCreate(138, AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template, 19, 14, "tr", null, i0.ɵɵcomponentInstance().trackByModelName, true);
630
700
  i0.ɵɵelementEnd()()()()();
631
- i0.ɵɵelementStart(122, "mj-accordion-panel", 17);
632
- i0.ɵɵtemplate(123, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_123_Template, 2, 0, "ng-template", 18);
633
- i0.ɵɵelementStart(124, "div", 34)(125, "div", 56)(126, "div", 57)(127, "span", 58);
634
- i0.ɵɵtext(128, "Total Steps");
701
+ i0.ɵɵelementStart(140, "mj-accordion-panel", 17);
702
+ i0.ɵɵtemplate(141, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template, 2, 0, "ng-template", 18);
703
+ i0.ɵɵelementStart(142, "div", 37)(143, "div", 59)(144, "div", 60)(145, "span", 61);
704
+ i0.ɵɵtext(146, "Total Steps");
635
705
  i0.ɵɵelementEnd();
636
- i0.ɵɵelementStart(129, "span", 59);
637
- i0.ɵɵtext(130);
706
+ i0.ɵɵelementStart(147, "span", 62);
707
+ i0.ɵɵtext(148);
638
708
  i0.ɵɵelementEnd()();
639
- i0.ɵɵelementStart(131, "div", 57)(132, "span", 58);
640
- i0.ɵɵtext(133, "Parallel Executions");
709
+ i0.ɵɵelementStart(149, "div", 60)(150, "span", 61);
710
+ i0.ɵɵtext(151, "Parallel Executions");
641
711
  i0.ɵɵelementEnd();
642
- i0.ɵɵelementStart(134, "span", 59);
643
- i0.ɵɵtext(135);
712
+ i0.ɵɵelementStart(152, "span", 62);
713
+ i0.ɵɵtext(153);
644
714
  i0.ɵɵelementEnd()();
645
- i0.ɵɵelementStart(136, "div", 57)(137, "span", 58);
646
- i0.ɵɵtext(138, "Max Nesting Depth");
715
+ i0.ɵɵelementStart(154, "div", 60)(155, "span", 61);
716
+ i0.ɵɵtext(156, "Max Nesting Depth");
647
717
  i0.ɵɵelementEnd();
648
- i0.ɵɵelementStart(139, "span", 59);
649
- i0.ɵɵtext(140);
718
+ i0.ɵɵelementStart(157, "span", 62);
719
+ i0.ɵɵtext(158);
650
720
  i0.ɵɵelementEnd()();
651
- i0.ɵɵelementStart(141, "div", 57)(142, "span", 58);
652
- i0.ɵɵtext(143, "Sub-Agent Runs");
721
+ i0.ɵɵelementStart(159, "div", 60)(160, "span", 61);
722
+ i0.ɵɵtext(161, "Sub-Agent Runs");
653
723
  i0.ɵɵelementEnd();
654
- i0.ɵɵelementStart(144, "span", 59);
655
- i0.ɵɵtext(145);
724
+ i0.ɵɵelementStart(162, "span", 62);
725
+ i0.ɵɵtext(163);
656
726
  i0.ɵɵelementEnd()()();
657
- i0.ɵɵelementStart(146, "div", 60)(147, "h3");
658
- i0.ɵɵtext(148, "Steps by Type");
727
+ i0.ɵɵelementStart(164, "div", 63)(165, "h3");
728
+ i0.ɵɵtext(166, "Steps by Type");
659
729
  i0.ɵɵelementEnd();
660
- i0.ɵɵelementStart(149, "div", 61);
661
- i0.ɵɵrepeaterCreate(150, AIAgentRunAnalyticsComponent_Conditional_3_For_151_Template, 8, 4, "div", 62, i0.ɵɵcomponentInstance().trackByKey, true);
662
- i0.ɵɵpipe(152, "keyvalue");
730
+ i0.ɵɵelementStart(167, "div", 64);
731
+ i0.ɵɵrepeaterCreate(168, AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template, 8, 4, "div", 65, i0.ɵɵcomponentInstance().trackByKey, true);
732
+ i0.ɵɵpipe(170, "keyvalue");
663
733
  i0.ɵɵelementEnd()()()()();
664
734
  } if (rf & 2) {
665
735
  const ctx_r1 = i0.ɵɵnextContext();
@@ -680,7 +750,19 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
680
750
  i0.ɵɵadvance(8);
681
751
  i0.ɵɵtextInterpolate(ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
682
752
  i0.ɵɵadvance(3);
683
- i0.ɵɵtextInterpolate1("", ctx_r1.promptMetrics.tokenUsage.totalInput + ctx_r1.promptMetrics.tokenUsage.totalOutput, " tokens");
753
+ i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(39, 41, ctx_r1.totalTokensProcessed), " tokens");
754
+ i0.ɵɵadvance(2);
755
+ i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 40 : -1);
756
+ i0.ɵɵadvance();
757
+ i0.ɵɵconditional(ctx_r1.inputCost > 0 || ctx_r1.outputCost > 0 ? 41 : -1);
758
+ i0.ɵɵadvance();
759
+ i0.ɵɵconditional(ctx_r1.cacheSavings > 0 ? 42 : -1);
760
+ i0.ɵɵadvance(8);
761
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(51, 43, ctx_r1.promptMetrics.tokenUsage.totalCacheRead));
762
+ i0.ɵɵadvance(5);
763
+ i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 55 : -1);
764
+ i0.ɵɵadvance();
765
+ i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 56 : -1);
684
766
  i0.ɵɵadvance(8);
685
767
  i0.ɵɵtextInterpolate(ctx_r1.formatDuration(ctx_r1.promptMetrics.totalExecutionTime + ctx_r1.actionMetrics.totalExecutionTime));
686
768
  i0.ɵɵadvance(3);
@@ -688,17 +770,17 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
688
770
  i0.ɵɵadvance();
689
771
  i0.ɵɵproperty("Expanded", true);
690
772
  i0.ɵɵadvance(3);
691
- i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 53 : -1);
773
+ i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 71 : -1);
692
774
  i0.ɵɵadvance();
693
- i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ? 54 : -1);
775
+ i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ? 72 : -1);
694
776
  i0.ɵɵadvance();
695
- i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 55 : -1);
777
+ i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 73 : -1);
696
778
  i0.ɵɵadvance();
697
- i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 56 : -1);
779
+ i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 74 : -1);
698
780
  i0.ɵɵadvance(3);
699
781
  i0.ɵɵproperty("ngClass", ctx_r1.promptDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
700
782
  i0.ɵɵadvance(2);
701
- i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ? 61 : -1);
783
+ i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ? 79 : -1);
702
784
  i0.ɵɵadvance();
703
785
  i0.ɵɵproperty("Expanded", true);
704
786
  i0.ɵɵadvance(4);
@@ -712,11 +794,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
712
794
  i0.ɵɵadvance(7);
713
795
  i0.ɵɵproperty("ngClass", ctx_r1.actionDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
714
796
  i0.ɵɵadvance(2);
715
- i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ? 92 : -1);
797
+ i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ? 110 : -1);
716
798
  i0.ɵɵadvance(2);
717
- i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ? 94 : -1);
799
+ i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ? 112 : -1);
718
800
  i0.ɵɵadvance();
719
- i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ? 95 : -1);
801
+ i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ? 113 : -1);
720
802
  i0.ɵɵadvance();
721
803
  i0.ɵɵproperty("Expanded", true);
722
804
  i0.ɵɵadvance(24);
@@ -732,7 +814,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
732
814
  i0.ɵɵadvance(5);
733
815
  i0.ɵɵtextInterpolate(ctx_r1.subAgentRuns.length);
734
816
  i0.ɵɵadvance(5);
735
- i0.ɵɵrepeater(i0.ɵɵpipeBind1(152, 35, ctx_r1.timelineMetrics.stepsByType));
817
+ i0.ɵɵrepeater(i0.ɵɵpipeBind1(170, 45, ctx_r1.timelineMetrics.stepsByType));
736
818
  } }
737
819
  export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
738
820
  /** Helper method to create tracked setTimeout calls */
@@ -752,6 +834,9 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
752
834
  this.activeTimeouts.splice(index, 1);
753
835
  }
754
836
  }
837
+ static { this.UNIT_DIVISORS = {
838
+ 'Per Million Tokens': 1_000_000, 'Per Hundred Thousand Tokens': 100_000, 'Per Thousand Tokens': 1_000
839
+ }; }
755
840
  constructor(cdr, costService) {
756
841
  super();
757
842
  this.cdr = cdr;
@@ -779,6 +864,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
779
864
  // Data
780
865
  this.agentRun = null;
781
866
  this.allPromptRuns = [];
867
+ // Per model+vendor cache pricing (currency-per-token), loaded from AIModelCost for the cost split.
868
+ this.cacheRates = new Map();
782
869
  this.allActionLogs = [];
783
870
  this.allSteps = [];
784
871
  this.subAgentRuns = [];
@@ -942,6 +1029,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
942
1029
  }
943
1030
  // Load all prompt runs for the agent run hierarchy
944
1031
  this.allPromptRuns = await this.loadAllPromptRuns(agentRunIds);
1032
+ // Load cache pricing so cost can be split (input/output) and cache savings computed
1033
+ await this.loadCacheRates();
945
1034
  if (results[2].Success) {
946
1035
  const actionSteps = results[2].Results || [];
947
1036
  // Now load the actual action logs
@@ -973,8 +1062,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
973
1062
  byVendor: new Map(),
974
1063
  byPrompt: new Map(),
975
1064
  statusBreakdown: { success: 0, failed: 0, timeout: 0 },
976
- costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map() },
977
- tokenUsage: { totalInput: 0, totalOutput: 0, byModel: new Map() }
1065
+ costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map(), inputCost: 0, outputCost: 0, savings: 0, unratedCost: 0 },
1066
+ tokenUsage: { totalInput: 0, totalOutput: 0, totalCacheRead: 0, totalCacheWrite: 0, byModel: new Map() }
978
1067
  };
979
1068
  }
980
1069
  initializeActionMetrics() {
@@ -997,6 +1086,33 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
997
1086
  criticalPath: { steps: [], totalTime: 0 }
998
1087
  };
999
1088
  }
1089
+ /** Stable rate-map key for a model+vendor pair. */
1090
+ rateKey(modelID, vendorID) {
1091
+ return `${NormalizeUUID(modelID ?? '')}|${NormalizeUUID(vendorID ?? '')}`;
1092
+ }
1093
+ /** Load active realtime AIModelCost rates and normalize each to currency-per-token. */
1094
+ async loadCacheRates() {
1095
+ this.cacheRates.clear();
1096
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
1097
+ const res = await rv.RunView({
1098
+ EntityName: 'MJ: AI Model Costs',
1099
+ ExtraFilter: `Status='Active' AND ProcessingType='Realtime'`,
1100
+ Fields: ['ModelID', 'VendorID', 'InputPricePerUnit', 'OutputPricePerUnit', 'CacheReadPricePerUnit', 'CacheWritePricePerUnit', 'UnitType'],
1101
+ ResultType: 'simple'
1102
+ });
1103
+ if (!res.Success)
1104
+ return;
1105
+ for (const row of res.Results || []) {
1106
+ const divisor = AIAgentRunAnalyticsComponent.UNIT_DIVISORS[row.UnitType ?? ''] ?? 1_000_000;
1107
+ const input = (row.InputPricePerUnit ?? 0) / divisor;
1108
+ this.cacheRates.set(this.rateKey(row.ModelID, row.VendorID), {
1109
+ inputRate: input,
1110
+ outputRate: (row.OutputPricePerUnit ?? 0) / divisor,
1111
+ cacheReadRate: (row.CacheReadPricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor,
1112
+ cacheWriteRate: (row.CacheWritePricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor
1113
+ });
1114
+ }
1115
+ }
1000
1116
  calculatePromptMetrics() {
1001
1117
  const metrics = this.initializePromptMetrics();
1002
1118
  for (const promptRun of this.allPromptRuns) {
@@ -1047,6 +1163,24 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
1047
1163
  const outputTokens = promptRun.TokensCompletion || 0;
1048
1164
  metrics.tokenUsage.totalInput += inputTokens;
1049
1165
  metrics.tokenUsage.totalOutput += outputTokens;
1166
+ // Provider prompt-cache tokens (read = cache hits, write = cache creation). Summed from the
1167
+ // child prompt runs' persisted TokensCacheRead/TokensCacheWrite columns.
1168
+ const cacheReadTokens = promptRun.TokensCacheRead || 0;
1169
+ const cacheWriteTokens = promptRun.TokensCacheWrite || 0;
1170
+ metrics.tokenUsage.totalCacheRead += cacheReadTokens;
1171
+ metrics.tokenUsage.totalCacheWrite += cacheWriteTokens;
1172
+ // Rate-derived cost split + cache savings. inputCost folds uncached + cache read + cache write
1173
+ // (each at its own rate); savings = the discount vs. pricing all input at the full input rate.
1174
+ // Runs whose model+vendor has no rate row are tracked separately so the split isn't silently off.
1175
+ const rate = this.cacheRates.get(this.rateKey(promptRun.ModelID, promptRun.VendorID));
1176
+ if (rate) {
1177
+ metrics.costBreakdown.inputCost += inputTokens * rate.inputRate + cacheReadTokens * rate.cacheReadRate + cacheWriteTokens * rate.cacheWriteRate;
1178
+ metrics.costBreakdown.outputCost += outputTokens * rate.outputRate;
1179
+ metrics.costBreakdown.savings += cacheReadTokens * (rate.inputRate - rate.cacheReadRate) + cacheWriteTokens * (rate.inputRate - rate.cacheWriteRate);
1180
+ }
1181
+ else {
1182
+ metrics.costBreakdown.unratedCost += cost;
1183
+ }
1050
1184
  const modelTokens = metrics.tokenUsage.byModel.get(model) || { input: 0, output: 0 };
1051
1185
  modelTokens.input += inputTokens;
1052
1186
  modelTokens.output += outputTokens;
@@ -1229,6 +1363,29 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
1229
1363
  return `$${cost.toFixed(3)}`;
1230
1364
  return `$${cost.toFixed(2)}`;
1231
1365
  }
1366
+ /** Total tokens the models processed across this run, including cached input (true throughput). */
1367
+ get totalTokensProcessed() {
1368
+ const u = this.promptMetrics.tokenUsage;
1369
+ return u.totalInput + u.totalOutput + u.totalCacheRead + u.totalCacheWrite;
1370
+ }
1371
+ /** Rate-derived input-side dollars (uncached + cache read + cache write). */
1372
+ get inputCost() { return this.promptMetrics.costBreakdown.inputCost; }
1373
+ /** Rate-derived output dollars. */
1374
+ get outputCost() { return this.promptMetrics.costBreakdown.outputCost; }
1375
+ /** Net dollars saved by caching vs. pricing all input at the full input rate. */
1376
+ get cacheSavings() { return this.promptMetrics.costBreakdown.savings; }
1377
+ /** Savings as a % of what the run would have cost with no caching. */
1378
+ get cacheSavingsPct() {
1379
+ const cb = this.promptMetrics.costBreakdown;
1380
+ const fullPrice = cb.totalCost + cb.savings;
1381
+ return fullPrice > 0 ? (cb.savings / fullPrice) * 100 : 0;
1382
+ }
1383
+ /** Percentage of input tokens served from the provider's prompt cache across this agent run. */
1384
+ get cacheHitRatePct() {
1385
+ const u = this.promptMetrics.tokenUsage;
1386
+ const totalInput = u.totalInput + u.totalCacheRead + u.totalCacheWrite;
1387
+ return totalInput > 0 ? (u.totalCacheRead / totalInput) * 100 : 0;
1388
+ }
1232
1389
  refresh() {
1233
1390
  this.loadData();
1234
1391
  }
@@ -2130,11 +2287,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
2130
2287
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTokenDistributionChart = _t.first);
2131
2288
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCostDistributionChart = _t.first);
2132
2289
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCountByNameChart = _t.first);
2133
- } }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], [1, "error-state"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["mjButton", "", 3, "click"], [3, "Expanded"], ["mjAccordionTitle", ""], [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"], [1, "failed"], [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, "analytics-panel"], [1, "view-mode-toggle"], [1, "no-data-message"], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], [1, "no-errors"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
2290
+ } }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], [1, "error-state"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["mjButton", "", 3, "click"], [3, "Expanded"], ["mjAccordionTitle", ""], [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"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "metric-detail", "cache-detail"], [1, "card-icon", "cache"], [1, "fas", "fa-bolt"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], [1, "no-data-message"], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], [1, "no-errors"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
2134
2291
  i0.ɵɵelementStart(0, "div", 10);
2135
2292
  i0.ɵɵconditionalCreate(1, AIAgentRunAnalyticsComponent_Conditional_1_Template, 4, 0, "div", 11);
2136
2293
  i0.ɵɵconditionalCreate(2, AIAgentRunAnalyticsComponent_Conditional_2_Template, 6, 1, "div", 12);
2137
- i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 153, 37, "div", 13);
2294
+ i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 171, 47, "div", 13);
2138
2295
  i0.ɵɵelementEnd();
2139
2296
  } if (rf & 2) {
2140
2297
  i0.ɵɵadvance();
@@ -2143,11 +2300,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
2143
2300
  i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 2 : -1);
2144
2301
  i0.ɵɵadvance();
2145
2302
  i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 3 : -1);
2146
- } }, dependencies: [i2.NgClass, i3.MJButtonDirective, i3.MJAccordionPanelComponent, i3.MJAccordionTitleDirective, i2.DecimalPipe, i2.KeyValuePipe], styles: [".analytics-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-text-inverse);\n}\n\n.card-icon.prompts[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.card-icon.time[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\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: var(--mj-text-muted);\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: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail[_ngcontent-%COMP%] .success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail[_ngcontent-%COMP%] .failed[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.analytics-panel[_ngcontent-%COMP%] {\n padding: 15px;\n}\n\n\n\n.analytics-content[_ngcontent-%COMP%] mj-accordion-panel[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 12px;\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\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: var(--mj-text-secondary);\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: var(--mj-text-secondary);\n}\n\n\n\n.detailed-metrics[_ngcontent-%COMP%] {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.success-rate.high[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.error-analysis[_ngcontent-%COMP%] {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-success);\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: var(--mj-text-muted);\n}\n\n.no-data-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\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: var(--mj-text-secondary);\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: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\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: var(--mj-text-primary);\n}\n\n.type-percentage[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\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}"], changeDetection: 0 }); }
2303
+ } }, dependencies: [i2.NgClass, i3.MJButtonDirective, i3.MJAccordionPanelComponent, i3.MJAccordionTitleDirective, i2.DecimalPipe, i2.KeyValuePipe], styles: [".analytics-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-text-muted);\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: var(--mj-status-error);\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-text-inverse);\n}\n\n.card-icon.prompts[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.card-icon.time[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache[_ngcontent-%COMP%] {\n background: var(--mj-status-info);\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: var(--mj-text-muted);\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: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail[_ngcontent-%COMP%] .success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail[_ngcontent-%COMP%] .failed[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.metric-detail.cache-detail[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: block;\n}\n\n\n\n.analytics-panel[_ngcontent-%COMP%] {\n padding: 15px;\n}\n\n\n\n.analytics-content[_ngcontent-%COMP%] mj-accordion-panel[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 12px;\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\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: var(--mj-text-muted);\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\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: var(--mj-text-secondary);\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: var(--mj-text-secondary);\n}\n\n\n\n.detailed-metrics[_ngcontent-%COMP%] {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.success-rate.high[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.error-analysis[_ngcontent-%COMP%] {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-success);\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: var(--mj-text-muted);\n}\n\n.no-data-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\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: var(--mj-text-secondary);\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: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\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: var(--mj-text-primary);\n}\n\n.type-percentage[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\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}"], changeDetection: 0 }); }
2147
2304
  }
2148
2305
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAgentRunAnalyticsComponent, [{
2149
2306
  type: Component,
2150
- args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button mjButton (click)=\"loadData()\">Retry</button>\n </div>\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\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 @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\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 @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\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 <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 </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\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 @if (promptMetrics.totalCount === 0) {\n <div class=\"no-data-message\">\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 @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\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 @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\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 }\n </div>\n }\n </div>\n </div>\n </div>\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 <!-- 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 <!-- 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 @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\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 <!-- 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 <!-- 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 <!-- 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 mjButton\n variant=\"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 @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\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 @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\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 <!-- 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 <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"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 @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\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 @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\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 @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <div class=\"no-errors\">\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 }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\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 @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\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 <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\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 }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-text-muted);\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: var(--mj-status-error);\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\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: var(--mj-text-secondary);\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: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors i {\n font-size: 24px;\n color: var(--mj-status-success);\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: var(--mj-text-muted);\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\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}"] }]
2307
+ args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button mjButton (click)=\"loadData()\">Retry</button>\n </div>\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\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 @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\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 @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\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 cache-detail\">\n <span>{{ totalTokensProcessed | number }} tokens</span>\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>incl. {{ (promptMetrics.tokenUsage.totalCacheRead + promptMetrics.tokenUsage.totalCacheWrite) | number }} cached</span>\n }\n @if (inputCost > 0 || outputCost > 0) {\n <span>input {{ formatCost(inputCost) }} &middot; output {{ formatCost(outputCost) }}</span>\n }\n @if (cacheSavings > 0) {\n <span class=\"success\">saved {{ formatCost(cacheSavings) }} ({{ cacheSavingsPct | number:'1.0-0' }}%) via cache</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cache\">\n <i class=\"fas fa-bolt\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Prompt Cache</h3>\n <div class=\"metric-value\">{{ promptMetrics.tokenUsage.totalCacheRead | number }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>tokens read from cache</span>\n @if (promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ promptMetrics.tokenUsage.totalCacheWrite | number }} written</span>\n }\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ cacheHitRatePct | number:'1.0-0' }}% hit rate</span>\n }\n </div>\n </div>\n </div>\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 </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\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 @if (promptMetrics.totalCount === 0) {\n <div class=\"no-data-message\">\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 @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\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 @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\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 }\n </div>\n }\n </div>\n </div>\n </div>\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 <!-- 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 <!-- 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 @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\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 <!-- 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 <!-- 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 <!-- 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 mjButton\n variant=\"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 @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\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 @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\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 <!-- 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 <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"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 @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\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 @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\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 @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <div class=\"no-errors\">\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 }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\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 @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\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 }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\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 <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\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 }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-text-muted);\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: var(--mj-status-error);\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache {\n background: var(--mj-status-info);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Cache card stacks its facts (caption / written / hit rate) one per line. */\n.metric-detail.cache-detail span {\n display: block;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\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: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\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: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\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: var(--mj-text-secondary);\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: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\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: var(--mj-text-secondary);\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: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors i {\n font-size: 24px;\n color: var(--mj-status-success);\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: var(--mj-text-muted);\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\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: var(--mj-text-disabled);\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: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\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: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\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: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\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}"] }]
2151
2308
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i1.AIAgentRunCostService }], { agentRunId: [{
2152
2309
  type: Input
2153
2310
  }], modelDistributionChart: [{
@@ -2181,5 +2338,5 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
2181
2338
  type: ViewChild,
2182
2339
  args: ['promptCountByNameChart', { static: false }]
2183
2340
  }] }); })();
2184
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 72 }); })();
2341
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 82 }); })();
2185
2342
  //# sourceMappingURL=ai-agent-run-analytics.component.js.map