@memberjunction/ng-core-entity-forms 6.1.0-edge.1 → 6.1.0-edge.2
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/FlowAgentType/flow-agent-form-section.component.d.ts +19 -2
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js +50 -9
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-form-tabs.d.ts +59 -0
- package/dist/lib/custom/AIAgents/agent-form-tabs.d.ts.map +1 -0
- package/dist/lib/custom/AIAgents/agent-form-tabs.js +53 -0
- package/dist/lib/custom/AIAgents/agent-form-tabs.js.map +1 -0
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts +54 -0
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +1300 -1143
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +25 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +228 -170
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts +31 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js +229 -157
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-detail.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts +9 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-step-node.component.js +86 -51
- 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 +73 -4
- 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 +133 -7
- 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 +49 -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 +383 -264
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts +10 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js +25 -3
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts +21 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js +11 -0
- package/dist/lib/custom/ai-agent-run/flow/agent-run-flow.model.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts +28 -0
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.d.ts.map +1 -0
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js +120 -0
- package/dist/lib/custom/ai-agent-run/flow/run-tree-flow-projection.js.map +1 -0
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.d.ts +90 -0
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.d.ts.map +1 -0
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js +326 -0
- package/dist/lib/custom/ai-agent-run/run-tree-timeline-projection.js.map +1 -0
- package/dist/lib/custom/custom-forms.module.d.ts +1 -1
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +4 -1
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRequest/mjaiagentrequest.form.component.js +8 -6
- package/dist/lib/generated/Entities/MJAIAgentRequest/mjaiagentrequest.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +171 -169
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModelType/mjaimodeltype.form.component.js +25 -23
- package/dist/lib/generated/Entities/MJAIModelType/mjaimodeltype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModelVendor/mjaimodelvendor.form.component.js +15 -13
- package/dist/lib/generated/Entities/MJAIModelVendor/mjaimodelvendor.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +43 -25
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js +35 -17
- package/dist/lib/generated/Entities/MJAction/mjaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJActionExecutionLog/mjactionexecutionlog.form.component.js +11 -11
- package/dist/lib/generated/Entities/MJActionExecutionLog/mjactionexecutionlog.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityAction/mjentityaction.form.component.js +38 -36
- package/dist/lib/generated/Entities/MJEntityAction/mjentityaction.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntityActionParam/mjentityactionparam.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntityActionParam/mjentityactionparam.form.component.js +7 -13
- package/dist/lib/generated/Entities/MJEntityActionParam/mjentityactionparam.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js +52 -26
- package/dist/lib/generated/Entities/MJTask/mjtask.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJTaskDependency/mjtaskdependency.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJTaskDependency/mjtaskdependency.form.component.js +16 -4
- package/dist/lib/generated/Entities/MJTaskDependency/mjtaskdependency.form.component.js.map +1 -1
- package/package.json +40 -40
|
@@ -2,6 +2,7 @@ import { Component, Input, ViewChild, ChangeDetectionStrategy } from '@angular/c
|
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
3
|
import { RunView } from '@memberjunction/core';
|
|
4
4
|
import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
|
|
5
|
+
import { WalkAgentRunTree } from '@memberjunction/ai-core-plus';
|
|
5
6
|
import * as d3 from 'd3';
|
|
6
7
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
7
8
|
import * as i0 from "@angular/core";
|
|
@@ -56,7 +57,21 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_27_Template(rf,
|
|
|
56
57
|
i0.ɵɵadvance();
|
|
57
58
|
i0.ɵɵtextInterpolate1("", ctx_r1.actionMetrics.statusBreakdown.failed, " failed");
|
|
58
59
|
} }
|
|
59
|
-
function
|
|
60
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_36_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
+
i0.ɵɵelementStart(0, "div", 31)(1, "span");
|
|
62
|
+
i0.ɵɵtext(2);
|
|
63
|
+
i0.ɵɵelementEnd();
|
|
64
|
+
i0.ɵɵelementStart(3, "span");
|
|
65
|
+
i0.ɵɵtext(4);
|
|
66
|
+
i0.ɵɵelementEnd()();
|
|
67
|
+
} if (rf & 2) {
|
|
68
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
69
|
+
i0.ɵɵadvance(2);
|
|
70
|
+
i0.ɵɵtextInterpolate1("", ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost), " this run");
|
|
71
|
+
i0.ɵɵadvance(2);
|
|
72
|
+
i0.ɵɵtextInterpolate3("+ ", ctx_r1.formatCost(ctx_r1.DispatchedCost.Cost), " across ", ctx_r1.DispatchedCost.NodeCount, " workflow step", ctx_r1.DispatchedCost.NodeCount === 1 ? "" : "s");
|
|
73
|
+
} }
|
|
74
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template(rf, ctx) { if (rf & 1) {
|
|
60
75
|
i0.ɵɵelementStart(0, "span");
|
|
61
76
|
i0.ɵɵtext(1);
|
|
62
77
|
i0.ɵɵpipe(2, "number");
|
|
@@ -66,7 +81,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_40_Template(rf,
|
|
|
66
81
|
i0.ɵɵadvance();
|
|
67
82
|
i0.ɵɵtextInterpolate1("incl. ", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheRead + ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " cached");
|
|
68
83
|
} }
|
|
69
|
-
function
|
|
84
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template(rf, ctx) { if (rf & 1) {
|
|
70
85
|
i0.ɵɵelementStart(0, "span");
|
|
71
86
|
i0.ɵɵtext(1);
|
|
72
87
|
i0.ɵɵelementEnd();
|
|
@@ -75,7 +90,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template(rf,
|
|
|
75
90
|
i0.ɵɵadvance();
|
|
76
91
|
i0.ɵɵtextInterpolate2("input ", ctx_r1.formatCost(ctx_r1.inputCost), " \u00B7 output ", ctx_r1.formatCost(ctx_r1.outputCost));
|
|
77
92
|
} }
|
|
78
|
-
function
|
|
93
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_43_Template(rf, ctx) { if (rf & 1) {
|
|
79
94
|
i0.ɵɵelementStart(0, "span", 25);
|
|
80
95
|
i0.ɵɵtext(1);
|
|
81
96
|
i0.ɵɵpipe(2, "number");
|
|
@@ -85,7 +100,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template(rf,
|
|
|
85
100
|
i0.ɵɵadvance();
|
|
86
101
|
i0.ɵɵtextInterpolate2("saved ", ctx_r1.formatCost(ctx_r1.cacheSavings), " (", i0.ɵɵpipeBind2(2, 2, ctx_r1.cacheSavingsPct, "1.0-0"), "%) via cache");
|
|
87
102
|
} }
|
|
88
|
-
function
|
|
103
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
89
104
|
i0.ɵɵelementStart(0, "span");
|
|
90
105
|
i0.ɵɵtext(1);
|
|
91
106
|
i0.ɵɵpipe(2, "number");
|
|
@@ -95,7 +110,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template(rf,
|
|
|
95
110
|
i0.ɵɵadvance();
|
|
96
111
|
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " written");
|
|
97
112
|
} }
|
|
98
|
-
function
|
|
113
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_57_Template(rf, ctx) { if (rf & 1) {
|
|
99
114
|
i0.ɵɵelementStart(0, "span");
|
|
100
115
|
i0.ɵɵtext(1);
|
|
101
116
|
i0.ɵɵpipe(2, "number");
|
|
@@ -105,14 +120,14 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf,
|
|
|
105
120
|
i0.ɵɵadvance();
|
|
106
121
|
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(2, 1, ctx_r1.cacheHitRatePct, "1.0-0"), "% hit rate");
|
|
107
122
|
} }
|
|
108
|
-
function
|
|
123
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_70_Template(rf, ctx) { if (rf & 1) {
|
|
109
124
|
i0.ɵɵelement(0, "i", 21);
|
|
110
125
|
i0.ɵɵtext(1, " Prompt Analytics ");
|
|
111
126
|
} }
|
|
112
|
-
function
|
|
127
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template(rf, ctx) { if (rf & 1) {
|
|
113
128
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
114
129
|
i0.ɵɵelementStart(0, "div", 37)(1, "button", 42);
|
|
115
|
-
i0.ɵɵlistener("click", function
|
|
130
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
|
|
116
131
|
i0.ɵɵelement(2, "i", 43);
|
|
117
132
|
i0.ɵɵtext(3);
|
|
118
133
|
i0.ɵɵelementEnd()();
|
|
@@ -123,10 +138,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template(rf,
|
|
|
123
138
|
i0.ɵɵadvance();
|
|
124
139
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.viewMode === "grid" ? "Expand All" : "Collapse All", " ");
|
|
125
140
|
} }
|
|
126
|
-
function
|
|
141
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf, ctx) { if (rf & 1) {
|
|
127
142
|
i0.ɵɵelement(0, "mj-empty-state", 38);
|
|
128
143
|
} }
|
|
129
|
-
function
|
|
144
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
130
145
|
i0.ɵɵelementStart(0, "div", 75);
|
|
131
146
|
i0.ɵɵelement(1, "span", 76);
|
|
132
147
|
i0.ɵɵelementStart(2, "span", 77);
|
|
@@ -140,9 +155,9 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_1
|
|
|
140
155
|
i0.ɵɵadvance(2);
|
|
141
156
|
i0.ɵɵtextInterpolate3("", item_r6.key, ": ", item_r6.value.count, " (", (item_r6.value.count / ctx_r1.promptMetrics.totalCount * 100).toFixed(1), "%)");
|
|
142
157
|
} }
|
|
143
|
-
function
|
|
158
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
144
159
|
i0.ɵɵelementStart(0, "div", 69);
|
|
145
|
-
i0.ɵɵrepeaterCreate(1,
|
|
160
|
+
i0.ɵɵrepeaterCreate(1, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Conditional_12_For_2_Template, 4, 5, "div", 75, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
146
161
|
i0.ɵɵpipe(3, "keyvalue");
|
|
147
162
|
i0.ɵɵelementEnd();
|
|
148
163
|
} if (rf & 2) {
|
|
@@ -150,10 +165,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_1
|
|
|
150
165
|
i0.ɵɵadvance();
|
|
151
166
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(3, 0, ctx_r1.promptMetrics.byModel));
|
|
152
167
|
} }
|
|
153
|
-
function
|
|
168
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
154
169
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
155
170
|
i0.ɵɵelementStart(0, "div", 39)(1, "div", 45)(2, "div", 46);
|
|
156
|
-
i0.ɵɵlistener("click", function
|
|
171
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
|
|
157
172
|
i0.ɵɵelementStart(3, "h3");
|
|
158
173
|
i0.ɵɵelement(4, "i", 67);
|
|
159
174
|
i0.ɵɵtext(5, " Prompts by Model");
|
|
@@ -163,10 +178,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
163
178
|
i0.ɵɵelementEnd()();
|
|
164
179
|
i0.ɵɵelementStart(8, "div", 50)(9, "div", 51);
|
|
165
180
|
i0.ɵɵelement(10, "div", 68, 2);
|
|
166
|
-
i0.ɵɵconditionalCreate(12,
|
|
181
|
+
i0.ɵɵconditionalCreate(12, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Conditional_12_Template, 4, 2, "div", 69);
|
|
167
182
|
i0.ɵɵelementEnd()()();
|
|
168
183
|
i0.ɵɵelementStart(13, "div", 45)(14, "div", 46);
|
|
169
|
-
i0.ɵɵlistener("click", function
|
|
184
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
|
|
170
185
|
i0.ɵɵelementStart(15, "h3");
|
|
171
186
|
i0.ɵɵelement(16, "i", 35);
|
|
172
187
|
i0.ɵɵtext(17, " Average Execution Time by Vendor");
|
|
@@ -178,7 +193,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
178
193
|
i0.ɵɵelement(22, "div", 70, 3);
|
|
179
194
|
i0.ɵɵelementEnd()()();
|
|
180
195
|
i0.ɵɵelementStart(24, "div", 45)(25, "div", 46);
|
|
181
|
-
i0.ɵɵlistener("click", function
|
|
196
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
|
|
182
197
|
i0.ɵɵelementStart(26, "h3");
|
|
183
198
|
i0.ɵɵelement(27, "i", 30);
|
|
184
199
|
i0.ɵɵtext(28, " Cost Distribution by Vendor");
|
|
@@ -192,7 +207,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
192
207
|
i0.ɵɵtext(36);
|
|
193
208
|
i0.ɵɵelementEnd()()()();
|
|
194
209
|
i0.ɵɵelementStart(37, "div", 45)(38, "div", 46);
|
|
195
|
-
i0.ɵɵlistener("click", function
|
|
210
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
|
|
196
211
|
i0.ɵɵelementStart(39, "h3");
|
|
197
212
|
i0.ɵɵelement(40, "i", 73);
|
|
198
213
|
i0.ɵɵtext(41, " Token Usage by Model");
|
|
@@ -234,10 +249,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
234
249
|
i0.ɵɵadvance();
|
|
235
250
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["tokenUsage"] ? "fa-compress" : "fa-expand");
|
|
236
251
|
} }
|
|
237
|
-
function
|
|
252
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template(rf, ctx) { if (rf & 1) {
|
|
238
253
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
239
254
|
i0.ɵɵelementStart(0, "div", 40)(1, "div", 45)(2, "div", 46);
|
|
240
|
-
i0.ɵɵlistener("click", function
|
|
255
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptTime")); });
|
|
241
256
|
i0.ɵɵelementStart(3, "h3");
|
|
242
257
|
i0.ɵɵelement(4, "i", 78);
|
|
243
258
|
i0.ɵɵtext(5, " Average Execution Time by Prompt");
|
|
@@ -249,7 +264,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf,
|
|
|
249
264
|
i0.ɵɵelement(10, "div", 79, 6);
|
|
250
265
|
i0.ɵɵelementEnd()()();
|
|
251
266
|
i0.ɵɵelementStart(12, "div", 45)(13, "div", 46);
|
|
252
|
-
i0.ɵɵlistener("click", function
|
|
267
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptToken")); });
|
|
253
268
|
i0.ɵɵelementStart(14, "h3");
|
|
254
269
|
i0.ɵɵelement(15, "i", 80);
|
|
255
270
|
i0.ɵɵtext(16, " Token Usage by Prompt");
|
|
@@ -261,7 +276,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf,
|
|
|
261
276
|
i0.ɵɵelement(21, "div", 81, 7);
|
|
262
277
|
i0.ɵɵelementEnd()()();
|
|
263
278
|
i0.ɵɵelementStart(23, "div", 45)(24, "div", 46);
|
|
264
|
-
i0.ɵɵlistener("click", function
|
|
279
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template_div_click_24_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCost")); });
|
|
265
280
|
i0.ɵɵelementStart(25, "h3");
|
|
266
281
|
i0.ɵɵelement(26, "i", 67);
|
|
267
282
|
i0.ɵɵtext(27, " Cost Distribution by Prompt");
|
|
@@ -273,7 +288,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf,
|
|
|
273
288
|
i0.ɵɵelement(32, "div", 82, 8);
|
|
274
289
|
i0.ɵɵelementEnd()()();
|
|
275
290
|
i0.ɵɵelementStart(34, "div", 45)(35, "div", 46);
|
|
276
|
-
i0.ɵɵlistener("click", function
|
|
291
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template_div_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCount")); });
|
|
277
292
|
i0.ɵɵelementStart(36, "h3");
|
|
278
293
|
i0.ɵɵelement(37, "i", 83);
|
|
279
294
|
i0.ɵɵtext(38, " Prompt Execution Count");
|
|
@@ -311,7 +326,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf,
|
|
|
311
326
|
i0.ɵɵadvance();
|
|
312
327
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCount"] ? "fa-compress" : "fa-expand");
|
|
313
328
|
} }
|
|
314
|
-
function
|
|
329
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_80_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
315
330
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
316
331
|
i0.ɵɵtext(2);
|
|
317
332
|
i0.ɵɵelementEnd();
|
|
@@ -341,7 +356,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Templa
|
|
|
341
356
|
i0.ɵɵadvance(3);
|
|
342
357
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.calculatePromptSuccessRate(prompt_r8.key), "% ");
|
|
343
358
|
} }
|
|
344
|
-
function
|
|
359
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_80_Template(rf, ctx) { if (rf & 1) {
|
|
345
360
|
i0.ɵɵelementStart(0, "div", 44)(1, "table")(2, "thead")(3, "tr")(4, "th");
|
|
346
361
|
i0.ɵɵtext(5, "Prompt Name");
|
|
347
362
|
i0.ɵɵelementEnd();
|
|
@@ -358,7 +373,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template(rf,
|
|
|
358
373
|
i0.ɵɵtext(13, "Success Rate");
|
|
359
374
|
i0.ɵɵelementEnd()()();
|
|
360
375
|
i0.ɵɵelementStart(14, "tbody");
|
|
361
|
-
i0.ɵɵrepeaterCreate(15,
|
|
376
|
+
i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_80_For_16_Template, 12, 5, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
362
377
|
i0.ɵɵpipe(17, "keyvalue");
|
|
363
378
|
i0.ɵɵelementEnd()()();
|
|
364
379
|
} if (rf & 2) {
|
|
@@ -366,11 +381,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template(rf,
|
|
|
366
381
|
i0.ɵɵadvance(15);
|
|
367
382
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.promptMetrics.byPrompt));
|
|
368
383
|
} }
|
|
369
|
-
function
|
|
384
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_82_Template(rf, ctx) { if (rf & 1) {
|
|
370
385
|
i0.ɵɵelement(0, "i", 28);
|
|
371
386
|
i0.ɵɵtext(1, " Action Analytics ");
|
|
372
387
|
} }
|
|
373
|
-
function
|
|
388
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_111_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
374
389
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
375
390
|
i0.ɵɵtext(2);
|
|
376
391
|
i0.ɵɵelementEnd();
|
|
@@ -402,7 +417,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Templ
|
|
|
402
417
|
i0.ɵɵadvance(2);
|
|
403
418
|
i0.ɵɵtextInterpolate(ctx_r1.getActionType(action_r9.key));
|
|
404
419
|
} }
|
|
405
|
-
function
|
|
420
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_111_Template(rf, ctx) { if (rf & 1) {
|
|
406
421
|
i0.ɵɵelementStart(0, "div", 44)(1, "table")(2, "thead")(3, "tr")(4, "th");
|
|
407
422
|
i0.ɵɵtext(5, "Action Name");
|
|
408
423
|
i0.ɵɵelementEnd();
|
|
@@ -419,7 +434,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template(rf,
|
|
|
419
434
|
i0.ɵɵtext(13, "Type");
|
|
420
435
|
i0.ɵɵelementEnd()()();
|
|
421
436
|
i0.ɵɵelementStart(14, "tbody");
|
|
422
|
-
i0.ɵɵrepeaterCreate(15,
|
|
437
|
+
i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_111_For_16_Template, 12, 11, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
423
438
|
i0.ɵɵpipe(17, "keyvalue");
|
|
424
439
|
i0.ɵɵelementEnd()()();
|
|
425
440
|
} if (rf & 2) {
|
|
@@ -427,7 +442,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template(rf,
|
|
|
427
442
|
i0.ɵɵadvance(15);
|
|
428
443
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.actionMetrics.byAction));
|
|
429
444
|
} }
|
|
430
|
-
function
|
|
445
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
431
446
|
i0.ɵɵelementStart(0, "div", 89)(1, "span", 90);
|
|
432
447
|
i0.ɵɵtext(2);
|
|
433
448
|
i0.ɵɵelementEnd();
|
|
@@ -441,7 +456,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Templa
|
|
|
441
456
|
i0.ɵɵadvance(2);
|
|
442
457
|
i0.ɵɵtextInterpolate(error_r10.message);
|
|
443
458
|
} }
|
|
444
|
-
function
|
|
459
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template(rf, ctx) { if (rf & 1) {
|
|
445
460
|
i0.ɵɵelementStart(0, "div", 56)(1, "h3");
|
|
446
461
|
i0.ɵɵelement(2, "i", 86);
|
|
447
462
|
i0.ɵɵtext(3, " Common Errors ");
|
|
@@ -450,21 +465,21 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template(rf,
|
|
|
450
465
|
i0.ɵɵtext(5, " This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention. ");
|
|
451
466
|
i0.ɵɵelementEnd();
|
|
452
467
|
i0.ɵɵelementStart(6, "div", 88);
|
|
453
|
-
i0.ɵɵrepeaterCreate(7,
|
|
468
|
+
i0.ɵɵrepeaterCreate(7, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_For_8_Template, 5, 2, "div", 89, i0.ɵɵcomponentInstance().trackByErrorMessage, true);
|
|
454
469
|
i0.ɵɵelementEnd()();
|
|
455
470
|
} if (rf & 2) {
|
|
456
471
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
457
472
|
i0.ɵɵadvance(7);
|
|
458
473
|
i0.ɵɵrepeater(ctx_r1.getTopErrors());
|
|
459
474
|
} }
|
|
460
|
-
function
|
|
475
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_114_Template(rf, ctx) { if (rf & 1) {
|
|
461
476
|
i0.ɵɵelement(0, "mj-empty-state", 57);
|
|
462
477
|
} }
|
|
463
|
-
function
|
|
478
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_116_Template(rf, ctx) { if (rf & 1) {
|
|
464
479
|
i0.ɵɵelement(0, "i", 92);
|
|
465
480
|
i0.ɵɵtext(1, " Model Performance Comparison ");
|
|
466
481
|
} }
|
|
467
|
-
function
|
|
482
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_For_140_Template(rf, ctx) { if (rf & 1) {
|
|
468
483
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
469
484
|
i0.ɵɵtext(2);
|
|
470
485
|
i0.ɵɵelementEnd();
|
|
@@ -511,11 +526,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template(rf, ctx) {
|
|
|
511
526
|
i0.ɵɵadvance(3);
|
|
512
527
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(18, 11, model_r11.outputTokens, "1.0-0"));
|
|
513
528
|
} }
|
|
514
|
-
function
|
|
529
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_142_Template(rf, ctx) { if (rf & 1) {
|
|
515
530
|
i0.ɵɵelement(0, "i", 93);
|
|
516
531
|
i0.ɵɵtext(1, " Execution Timeline Analysis ");
|
|
517
532
|
} }
|
|
518
|
-
function
|
|
533
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_For_170_Template(rf, ctx) { if (rf & 1) {
|
|
519
534
|
i0.ɵɵelementStart(0, "div", 65);
|
|
520
535
|
i0.ɵɵelement(1, "i", 43);
|
|
521
536
|
i0.ɵɵelementStart(2, "span", 94);
|
|
@@ -580,154 +595,155 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
580
595
|
i0.ɵɵelementStart(34, "div", 23);
|
|
581
596
|
i0.ɵɵtext(35);
|
|
582
597
|
i0.ɵɵelementEnd();
|
|
583
|
-
i0.ɵɵ
|
|
584
|
-
i0.ɵɵ
|
|
585
|
-
i0.ɵɵ
|
|
598
|
+
i0.ɵɵconditionalCreate(36, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_36_Template, 5, 4, "div", 31);
|
|
599
|
+
i0.ɵɵelementStart(37, "div", 31)(38, "span");
|
|
600
|
+
i0.ɵɵtext(39);
|
|
601
|
+
i0.ɵɵpipe(40, "number");
|
|
586
602
|
i0.ɵɵelementEnd();
|
|
587
|
-
i0.ɵɵconditionalCreate(
|
|
588
|
-
i0.ɵɵconditionalCreate(
|
|
589
|
-
i0.ɵɵconditionalCreate(
|
|
603
|
+
i0.ɵɵconditionalCreate(41, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template, 3, 3, "span");
|
|
604
|
+
i0.ɵɵconditionalCreate(42, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template, 2, 2, "span");
|
|
605
|
+
i0.ɵɵconditionalCreate(43, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_43_Template, 3, 5, "span", 25);
|
|
590
606
|
i0.ɵɵelementEnd()()();
|
|
591
|
-
i0.ɵɵelementStart(
|
|
592
|
-
i0.ɵɵelement(
|
|
607
|
+
i0.ɵɵelementStart(44, "div", 19)(45, "div", 32);
|
|
608
|
+
i0.ɵɵelement(46, "i", 33);
|
|
593
609
|
i0.ɵɵelementEnd();
|
|
594
|
-
i0.ɵɵelementStart(
|
|
595
|
-
i0.ɵɵtext(
|
|
610
|
+
i0.ɵɵelementStart(47, "div", 22)(48, "h3");
|
|
611
|
+
i0.ɵɵtext(49, "Prompt Cache");
|
|
596
612
|
i0.ɵɵelementEnd();
|
|
597
|
-
i0.ɵɵelementStart(
|
|
598
|
-
i0.ɵɵtext(
|
|
599
|
-
i0.ɵɵpipe(
|
|
613
|
+
i0.ɵɵelementStart(50, "div", 23);
|
|
614
|
+
i0.ɵɵtext(51);
|
|
615
|
+
i0.ɵɵpipe(52, "number");
|
|
600
616
|
i0.ɵɵelementEnd();
|
|
601
|
-
i0.ɵɵelementStart(
|
|
602
|
-
i0.ɵɵtext(
|
|
617
|
+
i0.ɵɵelementStart(53, "div", 31)(54, "span");
|
|
618
|
+
i0.ɵɵtext(55, "tokens read from cache");
|
|
603
619
|
i0.ɵɵelementEnd();
|
|
604
|
-
i0.ɵɵconditionalCreate(
|
|
605
|
-
i0.ɵɵconditionalCreate(
|
|
620
|
+
i0.ɵɵconditionalCreate(56, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template, 3, 3, "span");
|
|
621
|
+
i0.ɵɵconditionalCreate(57, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_57_Template, 3, 4, "span");
|
|
606
622
|
i0.ɵɵelementEnd()()();
|
|
607
|
-
i0.ɵɵelementStart(
|
|
608
|
-
i0.ɵɵelement(
|
|
623
|
+
i0.ɵɵelementStart(58, "div", 19)(59, "div", 34);
|
|
624
|
+
i0.ɵɵelement(60, "i", 35);
|
|
609
625
|
i0.ɵɵelementEnd();
|
|
610
|
-
i0.ɵɵelementStart(
|
|
611
|
-
i0.ɵɵtext(
|
|
626
|
+
i0.ɵɵelementStart(61, "div", 22)(62, "h3");
|
|
627
|
+
i0.ɵɵtext(63, "Execution Time");
|
|
612
628
|
i0.ɵɵelementEnd();
|
|
613
|
-
i0.ɵɵelementStart(
|
|
614
|
-
i0.ɵɵtext(
|
|
629
|
+
i0.ɵɵelementStart(64, "div", 23);
|
|
630
|
+
i0.ɵɵtext(65);
|
|
615
631
|
i0.ɵɵelementEnd();
|
|
616
|
-
i0.ɵɵelementStart(
|
|
617
|
-
i0.ɵɵtext(
|
|
632
|
+
i0.ɵɵelementStart(66, "div", 24)(67, "span");
|
|
633
|
+
i0.ɵɵtext(68);
|
|
618
634
|
i0.ɵɵelementEnd()()()()()();
|
|
619
|
-
i0.ɵɵelementStart(
|
|
620
|
-
i0.ɵɵtemplate(
|
|
621
|
-
i0.ɵɵelementStart(
|
|
622
|
-
i0.ɵɵconditionalCreate(
|
|
623
|
-
i0.ɵɵconditionalCreate(
|
|
624
|
-
i0.ɵɵconditionalCreate(
|
|
625
|
-
i0.ɵɵconditionalCreate(
|
|
626
|
-
i0.ɵɵelementStart(
|
|
627
|
-
i0.ɵɵlistener("click", function
|
|
628
|
-
i0.ɵɵelement(
|
|
629
|
-
i0.ɵɵtext(
|
|
630
|
-
i0.ɵɵelementEnd();
|
|
631
|
-
i0.ɵɵconditionalCreate(
|
|
635
|
+
i0.ɵɵelementStart(69, "mj-accordion-panel", 16);
|
|
636
|
+
i0.ɵɵtemplate(70, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_70_Template, 2, 0, "ng-template", 17);
|
|
637
|
+
i0.ɵɵelementStart(71, "div", 36);
|
|
638
|
+
i0.ɵɵconditionalCreate(72, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template, 4, 2, "div", 37);
|
|
639
|
+
i0.ɵɵconditionalCreate(73, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template, 1, 0, "mj-empty-state", 38);
|
|
640
|
+
i0.ɵɵconditionalCreate(74, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template, 48, 18, "div", 39);
|
|
641
|
+
i0.ɵɵconditionalCreate(75, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_75_Template, 45, 16, "div", 40);
|
|
642
|
+
i0.ɵɵelementStart(76, "div", 41)(77, "button", 42);
|
|
643
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_77_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.promptDetailsExpanded = !ctx_r1.promptDetailsExpanded); });
|
|
644
|
+
i0.ɵɵelement(78, "i", 43);
|
|
645
|
+
i0.ɵɵtext(79, " Detailed Prompt Metrics ");
|
|
646
|
+
i0.ɵɵelementEnd();
|
|
647
|
+
i0.ɵɵconditionalCreate(80, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_80_Template, 18, 2, "div", 44);
|
|
632
648
|
i0.ɵɵelementEnd()()();
|
|
633
|
-
i0.ɵɵelementStart(
|
|
634
|
-
i0.ɵɵtemplate(
|
|
635
|
-
i0.ɵɵelementStart(
|
|
636
|
-
i0.ɵɵlistener("click", function
|
|
637
|
-
i0.ɵɵelementStart(
|
|
638
|
-
i0.ɵɵelement(
|
|
639
|
-
i0.ɵɵtext(
|
|
640
|
-
i0.ɵɵelementEnd();
|
|
641
|
-
i0.ɵɵelementStart(
|
|
642
|
-
i0.ɵɵelement(
|
|
649
|
+
i0.ɵɵelementStart(81, "mj-accordion-panel", 16);
|
|
650
|
+
i0.ɵɵtemplate(82, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_82_Template, 2, 0, "ng-template", 17);
|
|
651
|
+
i0.ɵɵelementStart(83, "div", 36)(84, "div", 39)(85, "div", 45)(86, "div", 46);
|
|
652
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_86_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("actionSuccess")); });
|
|
653
|
+
i0.ɵɵelementStart(87, "h3");
|
|
654
|
+
i0.ɵɵelement(88, "i", 47);
|
|
655
|
+
i0.ɵɵtext(89, " Action Success Rate");
|
|
656
|
+
i0.ɵɵelementEnd();
|
|
657
|
+
i0.ɵɵelementStart(90, "button", 48);
|
|
658
|
+
i0.ɵɵelement(91, "i", 49);
|
|
643
659
|
i0.ɵɵelementEnd()();
|
|
644
|
-
i0.ɵɵelementStart(
|
|
645
|
-
i0.ɵɵelement(
|
|
660
|
+
i0.ɵɵelementStart(92, "div", 50)(93, "div", 51);
|
|
661
|
+
i0.ɵɵelement(94, "div", 52, 0);
|
|
646
662
|
i0.ɵɵelementEnd()()();
|
|
647
|
-
i0.ɵɵelementStart(
|
|
648
|
-
i0.ɵɵlistener("click", function
|
|
649
|
-
i0.ɵɵelementStart(
|
|
650
|
-
i0.ɵɵelement(
|
|
651
|
-
i0.ɵɵtext(
|
|
652
|
-
i0.ɵɵelementEnd();
|
|
653
|
-
i0.ɵɵelementStart(
|
|
654
|
-
i0.ɵɵelement(
|
|
663
|
+
i0.ɵɵelementStart(96, "div", 45)(97, "div", 46);
|
|
664
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_97_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("stepType")); });
|
|
665
|
+
i0.ɵɵelementStart(98, "h3");
|
|
666
|
+
i0.ɵɵelement(99, "i", 53);
|
|
667
|
+
i0.ɵɵtext(100, " Step Type Distribution");
|
|
668
|
+
i0.ɵɵelementEnd();
|
|
669
|
+
i0.ɵɵelementStart(101, "button", 48);
|
|
670
|
+
i0.ɵɵelement(102, "i", 49);
|
|
655
671
|
i0.ɵɵelementEnd()();
|
|
656
|
-
i0.ɵɵelementStart(
|
|
657
|
-
i0.ɵɵelement(
|
|
672
|
+
i0.ɵɵelementStart(103, "div", 50)(104, "div", 51);
|
|
673
|
+
i0.ɵɵelement(105, "div", 54, 1);
|
|
658
674
|
i0.ɵɵelementEnd()()()();
|
|
659
|
-
i0.ɵɵelementStart(
|
|
660
|
-
i0.ɵɵlistener("click", function
|
|
661
|
-
i0.ɵɵelement(
|
|
662
|
-
i0.ɵɵtext(
|
|
675
|
+
i0.ɵɵelementStart(107, "div", 41)(108, "button", 42);
|
|
676
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_108_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.actionDetailsExpanded = !ctx_r1.actionDetailsExpanded); });
|
|
677
|
+
i0.ɵɵelement(109, "i", 43);
|
|
678
|
+
i0.ɵɵtext(110, " Detailed Action Metrics ");
|
|
663
679
|
i0.ɵɵelementEnd();
|
|
664
|
-
i0.ɵɵconditionalCreate(
|
|
680
|
+
i0.ɵɵconditionalCreate(111, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_111_Template, 18, 2, "div", 44);
|
|
665
681
|
i0.ɵɵelementEnd();
|
|
666
|
-
i0.ɵɵelementStart(
|
|
667
|
-
i0.ɵɵconditionalCreate(
|
|
668
|
-
i0.ɵɵconditionalCreate(
|
|
682
|
+
i0.ɵɵelementStart(112, "div", 55);
|
|
683
|
+
i0.ɵɵconditionalCreate(113, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template, 9, 0, "div", 56);
|
|
684
|
+
i0.ɵɵconditionalCreate(114, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_114_Template, 1, 0, "mj-empty-state", 57);
|
|
669
685
|
i0.ɵɵelementEnd()()();
|
|
670
|
-
i0.ɵɵelementStart(
|
|
671
|
-
i0.ɵɵtemplate(
|
|
672
|
-
i0.ɵɵelementStart(
|
|
673
|
-
i0.ɵɵtext(
|
|
686
|
+
i0.ɵɵelementStart(115, "mj-accordion-panel", 16);
|
|
687
|
+
i0.ɵɵtemplate(116, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_116_Template, 2, 0, "ng-template", 17);
|
|
688
|
+
i0.ɵɵelementStart(117, "div", 36)(118, "div", 58)(119, "table")(120, "thead")(121, "tr")(122, "th");
|
|
689
|
+
i0.ɵɵtext(123, "Model");
|
|
674
690
|
i0.ɵɵelementEnd();
|
|
675
|
-
i0.ɵɵelementStart(
|
|
676
|
-
i0.ɵɵtext(
|
|
691
|
+
i0.ɵɵelementStart(124, "th");
|
|
692
|
+
i0.ɵɵtext(125, "Vendor");
|
|
677
693
|
i0.ɵɵelementEnd();
|
|
678
|
-
i0.ɵɵelementStart(
|
|
679
|
-
i0.ɵɵtext(
|
|
694
|
+
i0.ɵɵelementStart(126, "th");
|
|
695
|
+
i0.ɵɵtext(127, "Prompts");
|
|
680
696
|
i0.ɵɵelementEnd();
|
|
681
|
-
i0.ɵɵelementStart(
|
|
682
|
-
i0.ɵɵtext(
|
|
697
|
+
i0.ɵɵelementStart(128, "th");
|
|
698
|
+
i0.ɵɵtext(129, "Avg Time");
|
|
683
699
|
i0.ɵɵelementEnd();
|
|
684
|
-
i0.ɵɵelementStart(
|
|
685
|
-
i0.ɵɵtext(
|
|
700
|
+
i0.ɵɵelementStart(130, "th");
|
|
701
|
+
i0.ɵɵtext(131, "Total Cost");
|
|
686
702
|
i0.ɵɵelementEnd();
|
|
687
|
-
i0.ɵɵelementStart(
|
|
688
|
-
i0.ɵɵtext(
|
|
703
|
+
i0.ɵɵelementStart(132, "th");
|
|
704
|
+
i0.ɵɵtext(133, "Avg Cost/Prompt");
|
|
689
705
|
i0.ɵɵelementEnd();
|
|
690
|
-
i0.ɵɵelementStart(
|
|
691
|
-
i0.ɵɵtext(
|
|
706
|
+
i0.ɵɵelementStart(134, "th");
|
|
707
|
+
i0.ɵɵtext(135, "Input Tokens");
|
|
692
708
|
i0.ɵɵelementEnd();
|
|
693
|
-
i0.ɵɵelementStart(
|
|
694
|
-
i0.ɵɵtext(
|
|
709
|
+
i0.ɵɵelementStart(136, "th");
|
|
710
|
+
i0.ɵɵtext(137, "Output Tokens");
|
|
695
711
|
i0.ɵɵelementEnd()()();
|
|
696
|
-
i0.ɵɵelementStart(
|
|
697
|
-
i0.ɵɵrepeaterCreate(
|
|
712
|
+
i0.ɵɵelementStart(138, "tbody");
|
|
713
|
+
i0.ɵɵrepeaterCreate(139, AIAgentRunAnalyticsComponent_Conditional_3_For_140_Template, 19, 14, "tr", null, i0.ɵɵcomponentInstance().trackByModelName, true);
|
|
698
714
|
i0.ɵɵelementEnd()()()()();
|
|
699
|
-
i0.ɵɵelementStart(
|
|
700
|
-
i0.ɵɵtemplate(
|
|
701
|
-
i0.ɵɵelementStart(
|
|
702
|
-
i0.ɵɵtext(
|
|
715
|
+
i0.ɵɵelementStart(141, "mj-accordion-panel", 16);
|
|
716
|
+
i0.ɵɵtemplate(142, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_142_Template, 2, 0, "ng-template", 17);
|
|
717
|
+
i0.ɵɵelementStart(143, "div", 36)(144, "div", 59)(145, "div", 60)(146, "span", 61);
|
|
718
|
+
i0.ɵɵtext(147, "Total Steps");
|
|
703
719
|
i0.ɵɵelementEnd();
|
|
704
|
-
i0.ɵɵelementStart(
|
|
705
|
-
i0.ɵɵtext(
|
|
720
|
+
i0.ɵɵelementStart(148, "span", 62);
|
|
721
|
+
i0.ɵɵtext(149);
|
|
706
722
|
i0.ɵɵelementEnd()();
|
|
707
|
-
i0.ɵɵelementStart(
|
|
708
|
-
i0.ɵɵtext(
|
|
723
|
+
i0.ɵɵelementStart(150, "div", 60)(151, "span", 61);
|
|
724
|
+
i0.ɵɵtext(152, "Parallel Executions");
|
|
709
725
|
i0.ɵɵelementEnd();
|
|
710
|
-
i0.ɵɵelementStart(
|
|
711
|
-
i0.ɵɵtext(
|
|
726
|
+
i0.ɵɵelementStart(153, "span", 62);
|
|
727
|
+
i0.ɵɵtext(154);
|
|
712
728
|
i0.ɵɵelementEnd()();
|
|
713
|
-
i0.ɵɵelementStart(
|
|
714
|
-
i0.ɵɵtext(
|
|
729
|
+
i0.ɵɵelementStart(155, "div", 60)(156, "span", 61);
|
|
730
|
+
i0.ɵɵtext(157, "Max Nesting Depth");
|
|
715
731
|
i0.ɵɵelementEnd();
|
|
716
|
-
i0.ɵɵelementStart(
|
|
717
|
-
i0.ɵɵtext(
|
|
732
|
+
i0.ɵɵelementStart(158, "span", 62);
|
|
733
|
+
i0.ɵɵtext(159);
|
|
718
734
|
i0.ɵɵelementEnd()();
|
|
719
|
-
i0.ɵɵelementStart(
|
|
720
|
-
i0.ɵɵtext(
|
|
735
|
+
i0.ɵɵelementStart(160, "div", 60)(161, "span", 61);
|
|
736
|
+
i0.ɵɵtext(162, "Sub-Agent Runs");
|
|
721
737
|
i0.ɵɵelementEnd();
|
|
722
|
-
i0.ɵɵelementStart(
|
|
723
|
-
i0.ɵɵtext(
|
|
738
|
+
i0.ɵɵelementStart(163, "span", 62);
|
|
739
|
+
i0.ɵɵtext(164);
|
|
724
740
|
i0.ɵɵelementEnd()()();
|
|
725
|
-
i0.ɵɵelementStart(
|
|
726
|
-
i0.ɵɵtext(
|
|
741
|
+
i0.ɵɵelementStart(165, "div", 63)(166, "h3");
|
|
742
|
+
i0.ɵɵtext(167, "Steps by Type");
|
|
727
743
|
i0.ɵɵelementEnd();
|
|
728
|
-
i0.ɵɵelementStart(
|
|
729
|
-
i0.ɵɵrepeaterCreate(
|
|
730
|
-
i0.ɵɵpipe(
|
|
744
|
+
i0.ɵɵelementStart(168, "div", 64);
|
|
745
|
+
i0.ɵɵrepeaterCreate(169, AIAgentRunAnalyticsComponent_Conditional_3_For_170_Template, 8, 4, "div", 65, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
746
|
+
i0.ɵɵpipe(171, "keyvalue");
|
|
731
747
|
i0.ɵɵelementEnd()()()()();
|
|
732
748
|
} if (rf & 2) {
|
|
733
749
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -746,21 +762,23 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
746
762
|
i0.ɵɵadvance();
|
|
747
763
|
i0.ɵɵconditional(ctx_r1.actionMetrics.statusBreakdown.failed > 0 ? 27 : -1);
|
|
748
764
|
i0.ɵɵadvance(8);
|
|
749
|
-
i0.ɵɵ
|
|
765
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost + ctx_r1.DispatchedCost.Cost), " ");
|
|
766
|
+
i0.ɵɵadvance();
|
|
767
|
+
i0.ɵɵconditional(ctx_r1.HasDispatchedWork ? 36 : -1);
|
|
750
768
|
i0.ɵɵadvance(3);
|
|
751
|
-
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(
|
|
769
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(40, 44, ctx_r1.totalTokensProcessed), " tokens");
|
|
752
770
|
i0.ɵɵadvance(2);
|
|
753
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ?
|
|
771
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 41 : -1);
|
|
754
772
|
i0.ɵɵadvance();
|
|
755
|
-
i0.ɵɵconditional(ctx_r1.inputCost > 0 || ctx_r1.outputCost > 0 ?
|
|
773
|
+
i0.ɵɵconditional(ctx_r1.inputCost > 0 || ctx_r1.outputCost > 0 ? 42 : -1);
|
|
756
774
|
i0.ɵɵadvance();
|
|
757
|
-
i0.ɵɵconditional(ctx_r1.cacheSavings > 0 ?
|
|
775
|
+
i0.ɵɵconditional(ctx_r1.cacheSavings > 0 ? 43 : -1);
|
|
758
776
|
i0.ɵɵadvance(8);
|
|
759
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(
|
|
777
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(52, 46, ctx_r1.promptMetrics.tokenUsage.totalCacheRead));
|
|
760
778
|
i0.ɵɵadvance(5);
|
|
761
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ?
|
|
779
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 56 : -1);
|
|
762
780
|
i0.ɵɵadvance();
|
|
763
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ?
|
|
781
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 57 : -1);
|
|
764
782
|
i0.ɵɵadvance(8);
|
|
765
783
|
i0.ɵɵtextInterpolate(ctx_r1.formatDuration(ctx_r1.promptMetrics.totalExecutionTime + ctx_r1.actionMetrics.totalExecutionTime));
|
|
766
784
|
i0.ɵɵadvance(3);
|
|
@@ -768,17 +786,17 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
768
786
|
i0.ɵɵadvance();
|
|
769
787
|
i0.ɵɵproperty("Expanded", true);
|
|
770
788
|
i0.ɵɵadvance(3);
|
|
771
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ?
|
|
772
|
-
i0.ɵɵadvance();
|
|
773
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ? 72 : -1);
|
|
789
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 72 : -1);
|
|
774
790
|
i0.ɵɵadvance();
|
|
775
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount
|
|
791
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ? 73 : -1);
|
|
776
792
|
i0.ɵɵadvance();
|
|
777
793
|
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 74 : -1);
|
|
794
|
+
i0.ɵɵadvance();
|
|
795
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 75 : -1);
|
|
778
796
|
i0.ɵɵadvance(3);
|
|
779
797
|
i0.ɵɵproperty("ngClass", ctx_r1.promptDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
|
|
780
798
|
i0.ɵɵadvance(2);
|
|
781
|
-
i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ?
|
|
799
|
+
i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ? 80 : -1);
|
|
782
800
|
i0.ɵɵadvance();
|
|
783
801
|
i0.ɵɵproperty("Expanded", true);
|
|
784
802
|
i0.ɵɵadvance(4);
|
|
@@ -796,11 +814,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
796
814
|
i0.ɵɵadvance(7);
|
|
797
815
|
i0.ɵɵproperty("ngClass", ctx_r1.actionDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
|
|
798
816
|
i0.ɵɵadvance(2);
|
|
799
|
-
i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ?
|
|
817
|
+
i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ? 111 : -1);
|
|
800
818
|
i0.ɵɵadvance(2);
|
|
801
|
-
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ?
|
|
819
|
+
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ? 113 : -1);
|
|
802
820
|
i0.ɵɵadvance();
|
|
803
|
-
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ?
|
|
821
|
+
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ? 114 : -1);
|
|
804
822
|
i0.ɵɵadvance();
|
|
805
823
|
i0.ɵɵproperty("Expanded", true);
|
|
806
824
|
i0.ɵɵadvance(24);
|
|
@@ -816,9 +834,46 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
816
834
|
i0.ɵɵadvance(5);
|
|
817
835
|
i0.ɵɵtextInterpolate(ctx_r1.subAgentRuns.length);
|
|
818
836
|
i0.ɵɵadvance(5);
|
|
819
|
-
i0.ɵɵrepeater(i0.ɵɵpipeBind1(
|
|
837
|
+
i0.ɵɵrepeater(i0.ɵɵpipeBind1(171, 48, ctx_r1.timelineMetrics.stepsByType));
|
|
820
838
|
} }
|
|
821
839
|
export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
840
|
+
/**
|
|
841
|
+
* The run's execution tree, loaded once by the form and shared with every tab.
|
|
842
|
+
*
|
|
843
|
+
* **This is what makes the totals honest.** Analytics derives cost from prompt runs reached
|
|
844
|
+
* through the run's own STEPS, which cannot see work the run dispatched: a task-graph's spend
|
|
845
|
+
* lives on Task rows and on prompt runs those tasks produced, so a workflow's cost was simply
|
|
846
|
+
* missing from every figure on this tab. Each tree node reports its OWN cost — never a rollup —
|
|
847
|
+
* so a total is an honest sum rather than a double-count.
|
|
848
|
+
*/
|
|
849
|
+
set RunTree(value) {
|
|
850
|
+
this.runTree = value;
|
|
851
|
+
this.cdr.markForCheck();
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* What the dispatched work cost, from the tree — the part the step-based figures cannot see.
|
|
855
|
+
*
|
|
856
|
+
* Zero when there is no graph, so a run that dispatched nothing reads exactly as it did before.
|
|
857
|
+
*/
|
|
858
|
+
get DispatchedCost() {
|
|
859
|
+
if (!this.runTree)
|
|
860
|
+
return { Cost: 0, Tokens: 0, NodeCount: 0 };
|
|
861
|
+
let cost = 0, tokens = 0, nodeCount = 0;
|
|
862
|
+
for (const node of WalkAgentRunTree(this.runTree)) {
|
|
863
|
+
// Only nodes the RUN's own step list cannot reach. Counting the run's steps here as well
|
|
864
|
+
// would double every figure this tab already shows correctly.
|
|
865
|
+
if (node.NodeType !== 'Task' && node.NodeType !== 'TaskGraph')
|
|
866
|
+
continue;
|
|
867
|
+
nodeCount++;
|
|
868
|
+
cost += node.Cost ?? 0;
|
|
869
|
+
tokens += node.Tokens ?? 0;
|
|
870
|
+
}
|
|
871
|
+
return { Cost: cost, Tokens: tokens, NodeCount: nodeCount };
|
|
872
|
+
}
|
|
873
|
+
/** True when this run dispatched a workflow, so the tab can show the extra figures at all. */
|
|
874
|
+
get HasDispatchedWork() {
|
|
875
|
+
return this.DispatchedCost.NodeCount > 0;
|
|
876
|
+
}
|
|
822
877
|
/** Helper method to create tracked setTimeout calls */
|
|
823
878
|
setTrackedTimeout(callback, delay = 0) {
|
|
824
879
|
const timeoutId = setTimeout(() => {
|
|
@@ -843,6 +898,7 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
843
898
|
super();
|
|
844
899
|
this.cdr = cdr;
|
|
845
900
|
this.costService = costService;
|
|
901
|
+
this.runTree = null;
|
|
846
902
|
this.destroy$ = new Subject();
|
|
847
903
|
/** Track active timeouts for cleanup */
|
|
848
904
|
this.activeTimeouts = [];
|
|
@@ -2289,11 +2345,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2289
2345
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTokenDistributionChart = _t.first);
|
|
2290
2346
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCostDistributionChart = _t.first);
|
|
2291
2347
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCountByNameChart = _t.first);
|
|
2292
|
-
} }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], ["Variant", "error", "ActionText", "Retry", "ActionIcon", "fa-solid fa-arrows-rotate", 3, "Message"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], ["Variant", "error", "ActionText", "Retry", "ActionIcon", "fa-solid fa-arrows-rotate", 3, "Action", "Message"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "metric-detail", "cache-detail"], [1, "card-icon", "cache"], [1, "fas", "fa-bolt"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], ["Icon", "fa-solid fa-circle-info", "Title", "No prompt executions found in this agent run.", "Message", "This agent run may have only executed actions without any AI prompts."], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], ["aria-hidden", "true", 1, "fas", 3, "ngClass"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], ["Variant", "success", "Message", "No action errors detected in this run. All actions completed successfully!"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2348
|
+
} }, inputs: { agentRunId: "agentRunId", RunTree: "RunTree" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], ["Variant", "error", "ActionText", "Retry", "ActionIcon", "fa-solid fa-arrows-rotate", 3, "Message"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], ["Variant", "error", "ActionText", "Retry", "ActionIcon", "fa-solid fa-arrows-rotate", 3, "Action", "Message"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "metric-detail", "cache-detail"], [1, "card-icon", "cache"], [1, "fas", "fa-bolt"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], ["Icon", "fa-solid fa-circle-info", "Title", "No prompt executions found in this agent run.", "Message", "This agent run may have only executed actions without any AI prompts."], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], ["aria-hidden", "true", 1, "fas", 3, "ngClass"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], ["Variant", "success", "Message", "No action errors detected in this run. All actions completed successfully!"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2293
2349
|
i0.ɵɵelementStart(0, "div", 10);
|
|
2294
2350
|
i0.ɵɵconditionalCreate(1, AIAgentRunAnalyticsComponent_Conditional_1_Template, 4, 0, "div", 11);
|
|
2295
2351
|
i0.ɵɵconditionalCreate(2, AIAgentRunAnalyticsComponent_Conditional_2_Template, 1, 1, "mj-empty-state", 12);
|
|
2296
|
-
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template,
|
|
2352
|
+
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 172, 50, "div", 13);
|
|
2297
2353
|
i0.ɵɵelementEnd();
|
|
2298
2354
|
} if (rf & 2) {
|
|
2299
2355
|
i0.ɵɵadvance();
|
|
@@ -2306,9 +2362,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2306
2362
|
}
|
|
2307
2363
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAgentRunAnalyticsComponent, [{
|
|
2308
2364
|
type: Component,
|
|
2309
|
-
args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <mj-empty-state\n Variant=\"error\"\n [Message]=\"error\"\n ActionText=\"Retry\"\n ActionIcon=\"fa-solid fa-arrows-rotate\"\n (Action)=\"loadData()\" />\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <div class=\"metric-value\">{{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>{{ totalTokensProcessed | number }} tokens</span>\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>incl. {{ (promptMetrics.tokenUsage.totalCacheRead + promptMetrics.tokenUsage.totalCacheWrite) | number }} cached</span>\n }\n @if (inputCost > 0 || outputCost > 0) {\n <span>input {{ formatCost(inputCost) }} · output {{ formatCost(outputCost) }}</span>\n }\n @if (cacheSavings > 0) {\n <span class=\"success\">saved {{ formatCost(cacheSavings) }} ({{ cacheSavingsPct | number:'1.0-0' }}%) via cache</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cache\">\n <i class=\"fas fa-bolt\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Prompt Cache</h3>\n <div class=\"metric-value\">{{ promptMetrics.tokenUsage.totalCacheRead | number }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>tokens read from cache</span>\n @if (promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ promptMetrics.tokenUsage.totalCacheWrite | number }} written</span>\n }\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ cacheHitRatePct | number:'1.0-0' }}% hit rate</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n }\n <!-- No prompts message -->\n @if (promptMetrics.totalCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-circle-info\"\n Title=\"No prompt executions found in this agent run.\"\n Message=\"This agent run may have only executed actions without any AI prompts.\" />\n }\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['modelDistribution'] ? 'Collapse Model Distribution chart' : 'Expand Model Distribution chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['modelDistribution'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"modelDistributionChart\" #modelDistributionChart></div>\n @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\n <span class=\"legend-color\" [style.backgroundColor]=\"getModelColor(item.key)\"></span>\n <span class=\"legend-label\">{{ item.key }}: {{ item.value.count }} ({{ (item.value.count / promptMetrics.totalCount * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Execution Time by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['executionTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('executionTime')\">\n <h3><i class=\"fas fa-clock\"></i> Average Execution Time by Vendor</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['executionTime'] ? 'Collapse Average Execution Time by Vendor chart' : 'Expand Average Execution Time by Vendor chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['executionTime'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"executionTimeChart\" #executionTimeChart></div>\n </div>\n </div>\n </div>\n <!-- Cost by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['costByVendor']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('costByVendor')\">\n <h3><i class=\"fas fa-dollar-sign\"></i> Cost Distribution by Vendor</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['costByVendor'] ? 'Collapse Cost Distribution by Vendor chart' : 'Expand Cost Distribution by Vendor chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['costByVendor'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"costByVendorChart\" #costByVendorChart></div>\n <div class=\"chart-total\">Total: {{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n </div>\n </div>\n </div>\n <!-- Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['tokenUsage']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('tokenUsage')\">\n <h3><i class=\"fas fa-coins\"></i> Token Usage by Model</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['tokenUsage'] ? 'Collapse Token Usage by Model chart' : 'Expand Token Usage by Model chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['tokenUsage'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"tokenUsageChart\" #tokenUsageChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Additional Prompt Analytics Charts -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\n <!-- Prompt Execution Time Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptTime')\">\n <h3><i class=\"fas fa-hourglass-half\"></i> Average Execution Time by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptTime'] ? 'Collapse Average Execution Time by Prompt chart' : 'Expand Average Execution Time by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptTime'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTimeDistributionChart\" #promptTimeDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptToken']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptToken')\">\n <h3><i class=\"fas fa-database\"></i> Token Usage by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptToken'] ? 'Collapse Token Usage by Prompt chart' : 'Expand Token Usage by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptToken'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTokenDistributionChart\" #promptTokenDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Cost Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCost']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCost')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Cost Distribution by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptCost'] ? 'Collapse Cost Distribution by Prompt chart' : 'Expand Cost Distribution by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCost'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCostDistributionChart\" #promptCostDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Count by Name -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCount']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCount')\">\n <h3><i class=\"fas fa-list-ol\"></i> Prompt Execution Count</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptCount'] ? 'Collapse Prompt Execution Count chart' : 'Expand Prompt Execution Count chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCount'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCountByNameChart\" #promptCountByNameChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Detailed Prompt Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"promptDetailsExpanded = !promptDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"promptDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Prompt Metrics\n </button>\n @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Prompt Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Total Time</th>\n <th>Success Rate</th>\n </tr>\n </thead>\n <tbody>\n @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\n <td>{{ prompt.key }}</td>\n <td>{{ prompt.value.count }}</td>\n <td>{{ formatDuration(prompt.value.avgTime) }}</td>\n <td>{{ formatDuration(prompt.value.totalTime) }}</td>\n <td>\n <span class=\"success-rate\">\n <!-- Calculate success rate for this prompt -->\n {{ calculatePromptSuccessRate(prompt.key) }}%\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"charts-grid\">\n <!-- Action Success Rate -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['actionSuccess']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('actionSuccess')\">\n <h3><i class=\"fas fa-chart-bar\"></i> Action Success Rate</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['actionSuccess'] ? 'Collapse Action Success Rate chart' : 'Expand Action Success Rate chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['actionSuccess'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"actionSuccessRateChart\" #actionSuccessRateChart></div>\n </div>\n </div>\n </div>\n <!-- Step Type Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['stepType']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('stepType')\">\n <h3><i class=\"fas fa-layer-group\"></i> Step Type Distribution</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['stepType'] ? 'Collapse Step Type Distribution chart' : 'Expand Step Type Distribution chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['stepType'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"stepTypeChart\" #stepTypeChart></div>\n </div>\n </div>\n </div>\n </div>\n <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"actionDetailsExpanded = !actionDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"actionDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Action Metrics\n </button>\n @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Action Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Success Rate</th>\n <th>Type</th>\n </tr>\n </thead>\n <tbody>\n @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\n <td>{{ action.key }}</td>\n <td>{{ action.value.count }}</td>\n <td>{{ formatDuration(action.value.avgTime) }}</td>\n <td>\n <span class=\"success-rate\" [class.high]=\"action.value.successRate > 0.9\"\n [class.medium]=\"action.value.successRate > 0.7 && action.value.successRate <= 0.9\"\n [class.low]=\"action.value.successRate <= 0.7\">\n {{ (action.value.successRate * 100).toFixed(1) }}%\n </span>\n </td>\n <td>{{ getActionType(action.key) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\n <h3>\n <i class=\"fas fa-exclamation-triangle\"></i>\n Common Errors\n </h3>\n <p class=\"error-analysis-description\">\n This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention.\n </p>\n <div class=\"error-list\">\n @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <mj-empty-state\n Variant=\"success\"\n Message=\"No action errors detected in this run. All actions completed successfully!\" />\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Loading State */\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i {\n margin-bottom: 15px;\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache {\n background: var(--mj-status-info);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Cache card stacks its facts (caption / written / hit rate) one per line. */\n.metric-detail.cache-detail span {\n display: block;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
|
|
2365
|
+
args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <mj-empty-state\n Variant=\"error\"\n [Message]=\"error\"\n ActionText=\"Retry\"\n ActionIcon=\"fa-solid fa-arrows-rotate\"\n (Action)=\"loadData()\" />\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <!-- The run's OWN spend plus anything it dispatched. A workflow's cost lives on\n Task rows and the prompt runs those tasks produced, which the run's step list\n cannot reach \u2014 so before this the headline figure silently omitted the most\n expensive thing many runs do. -->\n <div class=\"metric-value\">\n {{ formatCost(promptMetrics.costBreakdown.totalCost + DispatchedCost.Cost) }}\n </div>\n @if (HasDispatchedWork) {\n <div class=\"metric-detail cache-detail\">\n <span>{{ formatCost(promptMetrics.costBreakdown.totalCost) }} this run</span>\n <span>+ {{ formatCost(DispatchedCost.Cost) }} across\n {{ DispatchedCost.NodeCount }} workflow step{{ DispatchedCost.NodeCount === 1 ? '' : 's' }}</span>\n </div>\n }\n <div class=\"metric-detail cache-detail\">\n <span>{{ totalTokensProcessed | number }} tokens</span>\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>incl. {{ (promptMetrics.tokenUsage.totalCacheRead + promptMetrics.tokenUsage.totalCacheWrite) | number }} cached</span>\n }\n @if (inputCost > 0 || outputCost > 0) {\n <span>input {{ formatCost(inputCost) }} · output {{ formatCost(outputCost) }}</span>\n }\n @if (cacheSavings > 0) {\n <span class=\"success\">saved {{ formatCost(cacheSavings) }} ({{ cacheSavingsPct | number:'1.0-0' }}%) via cache</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cache\">\n <i class=\"fas fa-bolt\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Prompt Cache</h3>\n <div class=\"metric-value\">{{ promptMetrics.tokenUsage.totalCacheRead | number }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>tokens read from cache</span>\n @if (promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ promptMetrics.tokenUsage.totalCacheWrite | number }} written</span>\n }\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ cacheHitRatePct | number:'1.0-0' }}% hit rate</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n }\n <!-- No prompts message -->\n @if (promptMetrics.totalCount === 0) {\n <mj-empty-state\n Icon=\"fa-solid fa-circle-info\"\n Title=\"No prompt executions found in this agent run.\"\n Message=\"This agent run may have only executed actions without any AI prompts.\" />\n }\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['modelDistribution'] ? 'Collapse Model Distribution chart' : 'Expand Model Distribution chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['modelDistribution'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"modelDistributionChart\" #modelDistributionChart></div>\n @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\n <span class=\"legend-color\" [style.backgroundColor]=\"getModelColor(item.key)\"></span>\n <span class=\"legend-label\">{{ item.key }}: {{ item.value.count }} ({{ (item.value.count / promptMetrics.totalCount * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Execution Time by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['executionTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('executionTime')\">\n <h3><i class=\"fas fa-clock\"></i> Average Execution Time by Vendor</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['executionTime'] ? 'Collapse Average Execution Time by Vendor chart' : 'Expand Average Execution Time by Vendor chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['executionTime'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"executionTimeChart\" #executionTimeChart></div>\n </div>\n </div>\n </div>\n <!-- Cost by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['costByVendor']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('costByVendor')\">\n <h3><i class=\"fas fa-dollar-sign\"></i> Cost Distribution by Vendor</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['costByVendor'] ? 'Collapse Cost Distribution by Vendor chart' : 'Expand Cost Distribution by Vendor chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['costByVendor'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"costByVendorChart\" #costByVendorChart></div>\n <div class=\"chart-total\">Total: {{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n </div>\n </div>\n </div>\n <!-- Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['tokenUsage']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('tokenUsage')\">\n <h3><i class=\"fas fa-coins\"></i> Token Usage by Model</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['tokenUsage'] ? 'Collapse Token Usage by Model chart' : 'Expand Token Usage by Model chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['tokenUsage'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"tokenUsageChart\" #tokenUsageChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Additional Prompt Analytics Charts -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\n <!-- Prompt Execution Time Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptTime')\">\n <h3><i class=\"fas fa-hourglass-half\"></i> Average Execution Time by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptTime'] ? 'Collapse Average Execution Time by Prompt chart' : 'Expand Average Execution Time by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptTime'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTimeDistributionChart\" #promptTimeDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptToken']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptToken')\">\n <h3><i class=\"fas fa-database\"></i> Token Usage by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptToken'] ? 'Collapse Token Usage by Prompt chart' : 'Expand Token Usage by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptToken'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTokenDistributionChart\" #promptTokenDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Cost Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCost']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCost')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Cost Distribution by Prompt</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptCost'] ? 'Collapse Cost Distribution by Prompt chart' : 'Expand Cost Distribution by Prompt chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCost'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCostDistributionChart\" #promptCostDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Count by Name -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCount']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCount')\">\n <h3><i class=\"fas fa-list-ol\"></i> Prompt Execution Count</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['promptCount'] ? 'Collapse Prompt Execution Count chart' : 'Expand Prompt Execution Count chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCount'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCountByNameChart\" #promptCountByNameChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Detailed Prompt Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"promptDetailsExpanded = !promptDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"promptDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Prompt Metrics\n </button>\n @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Prompt Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Total Time</th>\n <th>Success Rate</th>\n </tr>\n </thead>\n <tbody>\n @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\n <td>{{ prompt.key }}</td>\n <td>{{ prompt.value.count }}</td>\n <td>{{ formatDuration(prompt.value.avgTime) }}</td>\n <td>{{ formatDuration(prompt.value.totalTime) }}</td>\n <td>\n <span class=\"success-rate\">\n <!-- Calculate success rate for this prompt -->\n {{ calculatePromptSuccessRate(prompt.key) }}%\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"charts-grid\">\n <!-- Action Success Rate -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['actionSuccess']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('actionSuccess')\">\n <h3><i class=\"fas fa-chart-bar\"></i> Action Success Rate</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['actionSuccess'] ? 'Collapse Action Success Rate chart' : 'Expand Action Success Rate chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['actionSuccess'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"actionSuccessRateChart\" #actionSuccessRateChart></div>\n </div>\n </div>\n </div>\n <!-- Step Type Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['stepType']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('stepType')\">\n <h3><i class=\"fas fa-layer-group\"></i> Step Type Distribution</h3>\n <button class=\"expand-btn\" [attr.aria-label]=\"expandedCharts['stepType'] ? 'Collapse Step Type Distribution chart' : 'Expand Step Type Distribution chart'\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['stepType'] ? 'fa-compress' : 'fa-expand'\" aria-hidden=\"true\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"stepTypeChart\" #stepTypeChart></div>\n </div>\n </div>\n </div>\n </div>\n <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"actionDetailsExpanded = !actionDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"actionDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Action Metrics\n </button>\n @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Action Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Success Rate</th>\n <th>Type</th>\n </tr>\n </thead>\n <tbody>\n @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\n <td>{{ action.key }}</td>\n <td>{{ action.value.count }}</td>\n <td>{{ formatDuration(action.value.avgTime) }}</td>\n <td>\n <span class=\"success-rate\" [class.high]=\"action.value.successRate > 0.9\"\n [class.medium]=\"action.value.successRate > 0.7 && action.value.successRate <= 0.9\"\n [class.low]=\"action.value.successRate <= 0.7\">\n {{ (action.value.successRate * 100).toFixed(1) }}%\n </span>\n </td>\n <td>{{ getActionType(action.key) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\n <h3>\n <i class=\"fas fa-exclamation-triangle\"></i>\n Common Errors\n </h3>\n <p class=\"error-analysis-description\">\n This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention.\n </p>\n <div class=\"error-list\">\n @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <mj-empty-state\n Variant=\"success\"\n Message=\"No action errors detected in this run. All actions completed successfully!\" />\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Loading State */\n.loading-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i {\n margin-bottom: 15px;\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache {\n background: var(--mj-status-info);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Cache card stacks its facts (caption / written / hit rate) one per line. */\n.metric-detail.cache-detail span {\n display: block;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
|
|
2310
2366
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.AIAgentRunCostService }], { agentRunId: [{
|
|
2311
2367
|
type: Input
|
|
2368
|
+
}], RunTree: [{
|
|
2369
|
+
type: Input
|
|
2312
2370
|
}], modelDistributionChart: [{
|
|
2313
2371
|
type: ViewChild,
|
|
2314
2372
|
args: ['modelDistributionChart', { static: false }]
|
|
@@ -2340,5 +2398,5 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2340
2398
|
type: ViewChild,
|
|
2341
2399
|
args: ['promptCountByNameChart', { static: false }]
|
|
2342
2400
|
}] }); })();
|
|
2343
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber:
|
|
2401
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 83 }); })();
|
|
2344
2402
|
//# sourceMappingURL=ai-agent-run-analytics.component.js.map
|