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