@memberjunction/ng-core-entity-forms 5.39.0 → 5.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +14 -7
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts +7 -0
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js +583 -559
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +2 -2
- package/dist/lib/custom/Actions/action-form.component.js +2 -2
- package/dist/lib/custom/Entities/entity-form.component.js +4 -4
- package/dist/lib/custom/Entities/entity-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +117 -97
- 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-visualization.component.js +2 -2
- package/dist/lib/custom/ai-agent-run/ai-agent-run-visualization.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +59 -51
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js +28 -10
- package/dist/lib/generated/Entities/MJAIPromptRun/mjaipromptrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js +29 -21
- package/dist/lib/generated/Entities/MJAPIKey/mjapikey.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js +47 -11
- package/dist/lib/generated/Entities/MJApplication/mjapplication.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.js +24 -6
- package/dist/lib/generated/Entities/MJArtifact/mjartifact.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJArtifactVersion/mjartifactversion.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.js +93 -0
- package/dist/lib/generated/Entities/MJClusterAnalysis/mjclusteranalysis.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.js +66 -0
- package/dist/lib/generated/Entities/MJClusterAnalysisCluster/mjclusteranalysiscluster.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js +27 -9
- package/dist/lib/generated/Entities/MJCompany/mjcompany.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js +13 -3
- package/dist/lib/generated/Entities/MJContentItemTag/mjcontentitemtag.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js +29 -11
- package/dist/lib/generated/Entities/MJCredential/mjcredential.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js +100 -64
- package/dist/lib/generated/Entities/MJEntity/mjentity.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.js +173 -0
- package/dist/lib/generated/Entities/MJMagicLinkInvite/mjmagiclinkinvite.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedDomain/mjmagiclinkinvitealloweddomain.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteAllowedPath/mjmagiclinkinviteallowedpath.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteApplication/mjmagiclinkinviteapplication.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.js +58 -0
- package/dist/lib/generated/Entities/MJMagicLinkInviteRole/mjmagiclinkinviterole.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.js +68 -0
- package/dist/lib/generated/Entities/MJMagicLinkRedemption/mjmagiclinkredemption.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js +26 -8
- package/dist/lib/generated/Entities/MJResourceType/mjresourcetype.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js +52 -16
- package/dist/lib/generated/Entities/MJRole/mjrole.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.js +115 -0
- package/dist/lib/generated/Entities/MJSignatureAccount/mjsignatureaccount.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.js +101 -0
- package/dist/lib/generated/Entities/MJSignatureProvider/mjsignatureprovider.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.js +153 -0
- package/dist/lib/generated/Entities/MJSignatureRequest/mjsignaturerequest.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.js +78 -0
- package/dist/lib/generated/Entities/MJSignatureRequestDocument/mjsignaturerequestdocument.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.js +84 -0
- package/dist/lib/generated/Entities/MJSignatureRequestLog/mjsignaturerequestlog.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.js +88 -0
- package/dist/lib/generated/Entities/MJSignatureRequestRecipient/mjsignaturerequestrecipient.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js +156 -102
- package/dist/lib/generated/Entities/MJUser/mjuser.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js +34 -26
- package/dist/lib/generated/Entities/MJUserView/mjuserview.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.js +91 -0
- package/dist/lib/generated/Entities/MJViewType/mjviewtype.form.component.js.map +1 -0
- package/dist/lib/generated/generated-forms.module.d.ts +265 -250
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +224 -179
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/package.json +36 -36
|
@@ -42,7 +42,7 @@ function AIAgentRunAnalyticsComponent_Conditional_2_Template(rf, ctx) { if (rf &
|
|
|
42
42
|
i0.ɵɵtextInterpolate(ctx_r1.error);
|
|
43
43
|
} }
|
|
44
44
|
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
-
i0.ɵɵelement(0, "i",
|
|
45
|
+
i0.ɵɵelement(0, "i", 67);
|
|
46
46
|
i0.ɵɵtext(1, " Overview ");
|
|
47
47
|
} }
|
|
48
48
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_15_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -132,18 +132,18 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template(rf,
|
|
|
132
132
|
} }
|
|
133
133
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template(rf, ctx) { if (rf & 1) {
|
|
134
134
|
i0.ɵɵelementStart(0, "div", 39);
|
|
135
|
-
i0.ɵɵelement(1, "i",
|
|
135
|
+
i0.ɵɵelement(1, "i", 68);
|
|
136
136
|
i0.ɵɵelementStart(2, "p");
|
|
137
137
|
i0.ɵɵtext(3, "No prompt executions found in this agent run.");
|
|
138
138
|
i0.ɵɵelementEnd();
|
|
139
|
-
i0.ɵɵelementStart(4, "p",
|
|
139
|
+
i0.ɵɵelementStart(4, "p", 69);
|
|
140
140
|
i0.ɵɵtext(5, "This agent run may have only executed actions without any AI prompts.");
|
|
141
141
|
i0.ɵɵelementEnd()();
|
|
142
142
|
} }
|
|
143
143
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
144
|
-
i0.ɵɵelementStart(0, "div",
|
|
145
|
-
i0.ɵɵelement(1, "span",
|
|
146
|
-
i0.ɵɵelementStart(2, "span",
|
|
144
|
+
i0.ɵɵelementStart(0, "div", 78);
|
|
145
|
+
i0.ɵɵelement(1, "span", 79);
|
|
146
|
+
i0.ɵɵelementStart(2, "span", 80);
|
|
147
147
|
i0.ɵɵtext(3);
|
|
148
148
|
i0.ɵɵelementEnd()();
|
|
149
149
|
} if (rf & 2) {
|
|
@@ -155,8 +155,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_1
|
|
|
155
155
|
i0.ɵɵtextInterpolate3("", item_r6.key, ": ", item_r6.value.count, " (", (item_r6.value.count / ctx_r1.promptMetrics.totalCount * 100).toFixed(1), "%)");
|
|
156
156
|
} }
|
|
157
157
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
158
|
-
i0.ɵɵelementStart(0, "div",
|
|
159
|
-
i0.ɵɵrepeaterCreate(1, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template, 4, 5, "div",
|
|
158
|
+
i0.ɵɵelementStart(0, "div", 72);
|
|
159
|
+
i0.ɵɵrepeaterCreate(1, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template, 4, 5, "div", 78, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
160
160
|
i0.ɵɵpipe(3, "keyvalue");
|
|
161
161
|
i0.ɵɵelementEnd();
|
|
162
162
|
} if (rf & 2) {
|
|
@@ -169,15 +169,15 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
169
169
|
i0.ɵɵelementStart(0, "div", 40)(1, "div", 46)(2, "div", 47);
|
|
170
170
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
|
|
171
171
|
i0.ɵɵelementStart(3, "h3");
|
|
172
|
-
i0.ɵɵelement(4, "i",
|
|
172
|
+
i0.ɵɵelement(4, "i", 70);
|
|
173
173
|
i0.ɵɵtext(5, " Prompts by Model");
|
|
174
174
|
i0.ɵɵelementEnd();
|
|
175
175
|
i0.ɵɵelementStart(6, "button", 49);
|
|
176
|
-
i0.ɵɵelement(7, "i",
|
|
176
|
+
i0.ɵɵelement(7, "i", 50);
|
|
177
177
|
i0.ɵɵelementEnd()();
|
|
178
|
-
i0.ɵɵelementStart(8, "div",
|
|
179
|
-
i0.ɵɵelement(10, "div",
|
|
180
|
-
i0.ɵɵconditionalCreate(12, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template, 4, 2, "div",
|
|
178
|
+
i0.ɵɵelementStart(8, "div", 51)(9, "div", 52);
|
|
179
|
+
i0.ɵɵelement(10, "div", 71, 2);
|
|
180
|
+
i0.ɵɵconditionalCreate(12, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template, 4, 2, "div", 72);
|
|
181
181
|
i0.ɵɵelementEnd()()();
|
|
182
182
|
i0.ɵɵelementStart(13, "div", 46)(14, "div", 47);
|
|
183
183
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
|
|
@@ -186,10 +186,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
186
186
|
i0.ɵɵtext(17, " Average Execution Time by Vendor");
|
|
187
187
|
i0.ɵɵelementEnd();
|
|
188
188
|
i0.ɵɵelementStart(18, "button", 49);
|
|
189
|
-
i0.ɵɵelement(19, "i",
|
|
189
|
+
i0.ɵɵelement(19, "i", 50);
|
|
190
190
|
i0.ɵɵelementEnd()();
|
|
191
|
-
i0.ɵɵelementStart(20, "div",
|
|
192
|
-
i0.ɵɵelement(22, "div",
|
|
191
|
+
i0.ɵɵelementStart(20, "div", 51)(21, "div", 52);
|
|
192
|
+
i0.ɵɵelement(22, "div", 73, 3);
|
|
193
193
|
i0.ɵɵelementEnd()()();
|
|
194
194
|
i0.ɵɵelementStart(24, "div", 46)(25, "div", 47);
|
|
195
195
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
|
|
@@ -198,46 +198,54 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf,
|
|
|
198
198
|
i0.ɵɵtext(28, " Cost Distribution by Vendor");
|
|
199
199
|
i0.ɵɵelementEnd();
|
|
200
200
|
i0.ɵɵelementStart(29, "button", 49);
|
|
201
|
-
i0.ɵɵelement(30, "i",
|
|
201
|
+
i0.ɵɵelement(30, "i", 50);
|
|
202
202
|
i0.ɵɵelementEnd()();
|
|
203
|
-
i0.ɵɵelementStart(31, "div",
|
|
204
|
-
i0.ɵɵelement(33, "div",
|
|
205
|
-
i0.ɵɵelementStart(35, "div",
|
|
203
|
+
i0.ɵɵelementStart(31, "div", 51)(32, "div", 52);
|
|
204
|
+
i0.ɵɵelement(33, "div", 74, 4);
|
|
205
|
+
i0.ɵɵelementStart(35, "div", 75);
|
|
206
206
|
i0.ɵɵtext(36);
|
|
207
207
|
i0.ɵɵelementEnd()()()();
|
|
208
208
|
i0.ɵɵelementStart(37, "div", 46)(38, "div", 47);
|
|
209
209
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
|
|
210
210
|
i0.ɵɵelementStart(39, "h3");
|
|
211
|
-
i0.ɵɵelement(40, "i",
|
|
211
|
+
i0.ɵɵelement(40, "i", 76);
|
|
212
212
|
i0.ɵɵtext(41, " Token Usage by Model");
|
|
213
213
|
i0.ɵɵelementEnd();
|
|
214
214
|
i0.ɵɵelementStart(42, "button", 49);
|
|
215
|
-
i0.ɵɵelement(43, "i",
|
|
215
|
+
i0.ɵɵelement(43, "i", 50);
|
|
216
216
|
i0.ɵɵelementEnd()();
|
|
217
|
-
i0.ɵɵelementStart(44, "div",
|
|
218
|
-
i0.ɵɵelement(46, "div",
|
|
217
|
+
i0.ɵɵelementStart(44, "div", 51)(45, "div", 52);
|
|
218
|
+
i0.ɵɵelement(46, "div", 77, 5);
|
|
219
219
|
i0.ɵɵelementEnd()()()();
|
|
220
220
|
} if (rf & 2) {
|
|
221
221
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
222
222
|
i0.ɵɵadvance();
|
|
223
223
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["modelDistribution"]);
|
|
224
|
-
i0.ɵɵadvance(
|
|
224
|
+
i0.ɵɵadvance(5);
|
|
225
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["modelDistribution"] ? "Collapse Model Distribution chart" : "Expand Model Distribution chart");
|
|
226
|
+
i0.ɵɵadvance();
|
|
225
227
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["modelDistribution"] ? "fa-compress" : "fa-expand");
|
|
226
228
|
i0.ɵɵadvance(5);
|
|
227
229
|
i0.ɵɵconditional(ctx_r1.promptMetrics.byModel.size > 0 ? 12 : -1);
|
|
228
230
|
i0.ɵɵadvance();
|
|
229
231
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["executionTime"]);
|
|
230
|
-
i0.ɵɵadvance(
|
|
232
|
+
i0.ɵɵadvance(5);
|
|
233
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["executionTime"] ? "Collapse Average Execution Time by Vendor chart" : "Expand Average Execution Time by Vendor chart");
|
|
234
|
+
i0.ɵɵadvance();
|
|
231
235
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["executionTime"] ? "fa-compress" : "fa-expand");
|
|
232
236
|
i0.ɵɵadvance(5);
|
|
233
237
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["costByVendor"]);
|
|
234
|
-
i0.ɵɵadvance(
|
|
238
|
+
i0.ɵɵadvance(5);
|
|
239
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["costByVendor"] ? "Collapse Cost Distribution by Vendor chart" : "Expand Cost Distribution by Vendor chart");
|
|
240
|
+
i0.ɵɵadvance();
|
|
235
241
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["costByVendor"] ? "fa-compress" : "fa-expand");
|
|
236
242
|
i0.ɵɵadvance(6);
|
|
237
243
|
i0.ɵɵtextInterpolate1("Total: ", ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
|
|
238
244
|
i0.ɵɵadvance();
|
|
239
245
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["tokenUsage"]);
|
|
240
|
-
i0.ɵɵadvance(
|
|
246
|
+
i0.ɵɵadvance(5);
|
|
247
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["tokenUsage"] ? "Collapse Token Usage by Model chart" : "Expand Token Usage by Model chart");
|
|
248
|
+
i0.ɵɵadvance();
|
|
241
249
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["tokenUsage"] ? "fa-compress" : "fa-expand");
|
|
242
250
|
} }
|
|
243
251
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -245,68 +253,76 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf,
|
|
|
245
253
|
i0.ɵɵelementStart(0, "div", 41)(1, "div", 46)(2, "div", 47);
|
|
246
254
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptTime")); });
|
|
247
255
|
i0.ɵɵelementStart(3, "h3");
|
|
248
|
-
i0.ɵɵelement(4, "i",
|
|
256
|
+
i0.ɵɵelement(4, "i", 81);
|
|
249
257
|
i0.ɵɵtext(5, " Average Execution Time by Prompt");
|
|
250
258
|
i0.ɵɵelementEnd();
|
|
251
259
|
i0.ɵɵelementStart(6, "button", 49);
|
|
252
|
-
i0.ɵɵelement(7, "i",
|
|
260
|
+
i0.ɵɵelement(7, "i", 50);
|
|
253
261
|
i0.ɵɵelementEnd()();
|
|
254
|
-
i0.ɵɵelementStart(8, "div",
|
|
255
|
-
i0.ɵɵelement(10, "div",
|
|
262
|
+
i0.ɵɵelementStart(8, "div", 51)(9, "div", 52);
|
|
263
|
+
i0.ɵɵelement(10, "div", 82, 6);
|
|
256
264
|
i0.ɵɵelementEnd()()();
|
|
257
265
|
i0.ɵɵelementStart(12, "div", 46)(13, "div", 47);
|
|
258
266
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptToken")); });
|
|
259
267
|
i0.ɵɵelementStart(14, "h3");
|
|
260
|
-
i0.ɵɵelement(15, "i",
|
|
268
|
+
i0.ɵɵelement(15, "i", 83);
|
|
261
269
|
i0.ɵɵtext(16, " Token Usage by Prompt");
|
|
262
270
|
i0.ɵɵelementEnd();
|
|
263
271
|
i0.ɵɵelementStart(17, "button", 49);
|
|
264
|
-
i0.ɵɵelement(18, "i",
|
|
272
|
+
i0.ɵɵelement(18, "i", 50);
|
|
265
273
|
i0.ɵɵelementEnd()();
|
|
266
|
-
i0.ɵɵelementStart(19, "div",
|
|
267
|
-
i0.ɵɵelement(21, "div",
|
|
274
|
+
i0.ɵɵelementStart(19, "div", 51)(20, "div", 52);
|
|
275
|
+
i0.ɵɵelement(21, "div", 84, 7);
|
|
268
276
|
i0.ɵɵelementEnd()()();
|
|
269
277
|
i0.ɵɵelementStart(23, "div", 46)(24, "div", 47);
|
|
270
278
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_24_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCost")); });
|
|
271
279
|
i0.ɵɵelementStart(25, "h3");
|
|
272
|
-
i0.ɵɵelement(26, "i",
|
|
280
|
+
i0.ɵɵelement(26, "i", 70);
|
|
273
281
|
i0.ɵɵtext(27, " Cost Distribution by Prompt");
|
|
274
282
|
i0.ɵɵelementEnd();
|
|
275
283
|
i0.ɵɵelementStart(28, "button", 49);
|
|
276
|
-
i0.ɵɵelement(29, "i",
|
|
284
|
+
i0.ɵɵelement(29, "i", 50);
|
|
277
285
|
i0.ɵɵelementEnd()();
|
|
278
|
-
i0.ɵɵelementStart(30, "div",
|
|
279
|
-
i0.ɵɵelement(32, "div",
|
|
286
|
+
i0.ɵɵelementStart(30, "div", 51)(31, "div", 52);
|
|
287
|
+
i0.ɵɵelement(32, "div", 85, 8);
|
|
280
288
|
i0.ɵɵelementEnd()()();
|
|
281
289
|
i0.ɵɵelementStart(34, "div", 46)(35, "div", 47);
|
|
282
290
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template_div_click_35_listener() { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("promptCount")); });
|
|
283
291
|
i0.ɵɵelementStart(36, "h3");
|
|
284
|
-
i0.ɵɵelement(37, "i",
|
|
292
|
+
i0.ɵɵelement(37, "i", 86);
|
|
285
293
|
i0.ɵɵtext(38, " Prompt Execution Count");
|
|
286
294
|
i0.ɵɵelementEnd();
|
|
287
295
|
i0.ɵɵelementStart(39, "button", 49);
|
|
288
|
-
i0.ɵɵelement(40, "i",
|
|
296
|
+
i0.ɵɵelement(40, "i", 50);
|
|
289
297
|
i0.ɵɵelementEnd()();
|
|
290
|
-
i0.ɵɵelementStart(41, "div",
|
|
291
|
-
i0.ɵɵelement(43, "div",
|
|
298
|
+
i0.ɵɵelementStart(41, "div", 51)(42, "div", 52);
|
|
299
|
+
i0.ɵɵelement(43, "div", 87, 9);
|
|
292
300
|
i0.ɵɵelementEnd()()()();
|
|
293
301
|
} if (rf & 2) {
|
|
294
302
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
295
303
|
i0.ɵɵadvance();
|
|
296
304
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptTime"]);
|
|
297
|
-
i0.ɵɵadvance(
|
|
305
|
+
i0.ɵɵadvance(5);
|
|
306
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["promptTime"] ? "Collapse Average Execution Time by Prompt chart" : "Expand Average Execution Time by Prompt chart");
|
|
307
|
+
i0.ɵɵadvance();
|
|
298
308
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptTime"] ? "fa-compress" : "fa-expand");
|
|
299
309
|
i0.ɵɵadvance(5);
|
|
300
310
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptToken"]);
|
|
301
|
-
i0.ɵɵadvance(
|
|
311
|
+
i0.ɵɵadvance(5);
|
|
312
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["promptToken"] ? "Collapse Token Usage by Prompt chart" : "Expand Token Usage by Prompt chart");
|
|
313
|
+
i0.ɵɵadvance();
|
|
302
314
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptToken"] ? "fa-compress" : "fa-expand");
|
|
303
315
|
i0.ɵɵadvance(5);
|
|
304
316
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCost"]);
|
|
305
|
-
i0.ɵɵadvance(
|
|
317
|
+
i0.ɵɵadvance(5);
|
|
318
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["promptCost"] ? "Collapse Cost Distribution by Prompt chart" : "Expand Cost Distribution by Prompt chart");
|
|
319
|
+
i0.ɵɵadvance();
|
|
306
320
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCost"] ? "fa-compress" : "fa-expand");
|
|
307
321
|
i0.ɵɵadvance(5);
|
|
308
322
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCount"]);
|
|
309
|
-
i0.ɵɵadvance(
|
|
323
|
+
i0.ɵɵadvance(5);
|
|
324
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["promptCount"] ? "Collapse Prompt Execution Count chart" : "Expand Prompt Execution Count chart");
|
|
325
|
+
i0.ɵɵadvance();
|
|
310
326
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCount"] ? "fa-compress" : "fa-expand");
|
|
311
327
|
} }
|
|
312
328
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -322,7 +338,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Templa
|
|
|
322
338
|
i0.ɵɵelementStart(7, "td");
|
|
323
339
|
i0.ɵɵtext(8);
|
|
324
340
|
i0.ɵɵelementEnd();
|
|
325
|
-
i0.ɵɵelementStart(9, "td")(10, "span",
|
|
341
|
+
i0.ɵɵelementStart(9, "td")(10, "span", 88);
|
|
326
342
|
i0.ɵɵtext(11);
|
|
327
343
|
i0.ɵɵelementEnd()()();
|
|
328
344
|
} if (rf & 2) {
|
|
@@ -378,7 +394,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Templ
|
|
|
378
394
|
i0.ɵɵelementStart(5, "td");
|
|
379
395
|
i0.ɵɵtext(6);
|
|
380
396
|
i0.ɵɵelementEnd();
|
|
381
|
-
i0.ɵɵelementStart(7, "td")(8, "span",
|
|
397
|
+
i0.ɵɵelementStart(7, "td")(8, "span", 88);
|
|
382
398
|
i0.ɵɵtext(9);
|
|
383
399
|
i0.ɵɵelementEnd()();
|
|
384
400
|
i0.ɵɵelementStart(10, "td");
|
|
@@ -426,10 +442,10 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template(rf,
|
|
|
426
442
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.actionMetrics.byAction));
|
|
427
443
|
} }
|
|
428
444
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
429
|
-
i0.ɵɵelementStart(0, "div",
|
|
445
|
+
i0.ɵɵelementStart(0, "div", 92)(1, "span", 93);
|
|
430
446
|
i0.ɵɵtext(2);
|
|
431
447
|
i0.ɵɵelementEnd();
|
|
432
|
-
i0.ɵɵelementStart(3, "span",
|
|
448
|
+
i0.ɵɵelementStart(3, "span", 94);
|
|
433
449
|
i0.ɵɵtext(4);
|
|
434
450
|
i0.ɵɵelementEnd()();
|
|
435
451
|
} if (rf & 2) {
|
|
@@ -440,15 +456,15 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Templa
|
|
|
440
456
|
i0.ɵɵtextInterpolate(error_r10.message);
|
|
441
457
|
} }
|
|
442
458
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template(rf, ctx) { if (rf & 1) {
|
|
443
|
-
i0.ɵɵelementStart(0, "div",
|
|
444
|
-
i0.ɵɵelement(2, "i",
|
|
459
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "h3");
|
|
460
|
+
i0.ɵɵelement(2, "i", 89);
|
|
445
461
|
i0.ɵɵtext(3, " Common Errors ");
|
|
446
462
|
i0.ɵɵelementEnd();
|
|
447
|
-
i0.ɵɵelementStart(4, "p",
|
|
463
|
+
i0.ɵɵelementStart(4, "p", 90);
|
|
448
464
|
i0.ɵɵtext(5, " This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention. ");
|
|
449
465
|
i0.ɵɵelementEnd();
|
|
450
|
-
i0.ɵɵelementStart(6, "div",
|
|
451
|
-
i0.ɵɵrepeaterCreate(7, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template, 5, 2, "div",
|
|
466
|
+
i0.ɵɵelementStart(6, "div", 91);
|
|
467
|
+
i0.ɵɵrepeaterCreate(7, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template, 5, 2, "div", 92, i0.ɵɵcomponentInstance().trackByErrorMessage, true);
|
|
452
468
|
i0.ɵɵelementEnd()();
|
|
453
469
|
} if (rf & 2) {
|
|
454
470
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
@@ -456,14 +472,14 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template(rf,
|
|
|
456
472
|
i0.ɵɵrepeater(ctx_r1.getTopErrors());
|
|
457
473
|
} }
|
|
458
474
|
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template(rf, ctx) { if (rf & 1) {
|
|
459
|
-
i0.ɵɵelementStart(0, "div",
|
|
460
|
-
i0.ɵɵelement(1, "i",
|
|
475
|
+
i0.ɵɵelementStart(0, "div", 58);
|
|
476
|
+
i0.ɵɵelement(1, "i", 95);
|
|
461
477
|
i0.ɵɵelementStart(2, "p");
|
|
462
478
|
i0.ɵɵtext(3, "No action errors detected in this run. All actions completed successfully!");
|
|
463
479
|
i0.ɵɵelementEnd()();
|
|
464
480
|
} }
|
|
465
481
|
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template(rf, ctx) { if (rf & 1) {
|
|
466
|
-
i0.ɵɵelement(0, "i",
|
|
482
|
+
i0.ɵɵelement(0, "i", 96);
|
|
467
483
|
i0.ɵɵtext(1, " Model Performance Comparison ");
|
|
468
484
|
} }
|
|
469
485
|
function AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -514,19 +530,19 @@ function AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template(rf, ctx) {
|
|
|
514
530
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(18, 11, model_r11.outputTokens, "1.0-0"));
|
|
515
531
|
} }
|
|
516
532
|
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template(rf, ctx) { if (rf & 1) {
|
|
517
|
-
i0.ɵɵelement(0, "i",
|
|
533
|
+
i0.ɵɵelement(0, "i", 97);
|
|
518
534
|
i0.ɵɵtext(1, " Execution Timeline Analysis ");
|
|
519
535
|
} }
|
|
520
536
|
function AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template(rf, ctx) { if (rf & 1) {
|
|
521
|
-
i0.ɵɵelementStart(0, "div",
|
|
537
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
522
538
|
i0.ɵɵelement(1, "i", 44);
|
|
523
|
-
i0.ɵɵelementStart(2, "span",
|
|
539
|
+
i0.ɵɵelementStart(2, "span", 98);
|
|
524
540
|
i0.ɵɵtext(3);
|
|
525
541
|
i0.ɵɵelementEnd();
|
|
526
|
-
i0.ɵɵelementStart(4, "span",
|
|
542
|
+
i0.ɵɵelementStart(4, "span", 99);
|
|
527
543
|
i0.ɵɵtext(5);
|
|
528
544
|
i0.ɵɵelementEnd();
|
|
529
|
-
i0.ɵɵelementStart(6, "span",
|
|
545
|
+
i0.ɵɵelementStart(6, "span", 100);
|
|
530
546
|
i0.ɵɵtext(7);
|
|
531
547
|
i0.ɵɵelementEnd()();
|
|
532
548
|
} if (rf & 2) {
|
|
@@ -623,8 +639,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
623
639
|
i0.ɵɵelementStart(70, "div", 37);
|
|
624
640
|
i0.ɵɵconditionalCreate(71, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template, 4, 2, "div", 38);
|
|
625
641
|
i0.ɵɵconditionalCreate(72, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template, 6, 0, "div", 39);
|
|
626
|
-
i0.ɵɵconditionalCreate(73, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template, 48,
|
|
627
|
-
i0.ɵɵconditionalCreate(74, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template, 45,
|
|
642
|
+
i0.ɵɵconditionalCreate(73, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template, 48, 18, "div", 40);
|
|
643
|
+
i0.ɵɵconditionalCreate(74, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template, 45, 16, "div", 41);
|
|
628
644
|
i0.ɵɵelementStart(75, "div", 42)(76, "button", 43);
|
|
629
645
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_76_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.promptDetailsExpanded = !ctx_r1.promptDetailsExpanded); });
|
|
630
646
|
i0.ɵɵelement(77, "i", 44);
|
|
@@ -641,22 +657,22 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
641
657
|
i0.ɵɵtext(88, " Action Success Rate");
|
|
642
658
|
i0.ɵɵelementEnd();
|
|
643
659
|
i0.ɵɵelementStart(89, "button", 49);
|
|
644
|
-
i0.ɵɵelement(90, "i",
|
|
660
|
+
i0.ɵɵelement(90, "i", 50);
|
|
645
661
|
i0.ɵɵelementEnd()();
|
|
646
|
-
i0.ɵɵelementStart(91, "div",
|
|
647
|
-
i0.ɵɵelement(93, "div",
|
|
662
|
+
i0.ɵɵelementStart(91, "div", 51)(92, "div", 52);
|
|
663
|
+
i0.ɵɵelement(93, "div", 53, 0);
|
|
648
664
|
i0.ɵɵelementEnd()()();
|
|
649
665
|
i0.ɵɵelementStart(95, "div", 46)(96, "div", 47);
|
|
650
666
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_96_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("stepType")); });
|
|
651
667
|
i0.ɵɵelementStart(97, "h3");
|
|
652
|
-
i0.ɵɵelement(98, "i",
|
|
668
|
+
i0.ɵɵelement(98, "i", 54);
|
|
653
669
|
i0.ɵɵtext(99, " Step Type Distribution");
|
|
654
670
|
i0.ɵɵelementEnd();
|
|
655
671
|
i0.ɵɵelementStart(100, "button", 49);
|
|
656
|
-
i0.ɵɵelement(101, "i",
|
|
672
|
+
i0.ɵɵelement(101, "i", 50);
|
|
657
673
|
i0.ɵɵelementEnd()();
|
|
658
|
-
i0.ɵɵelementStart(102, "div",
|
|
659
|
-
i0.ɵɵelement(104, "div",
|
|
674
|
+
i0.ɵɵelementStart(102, "div", 51)(103, "div", 52);
|
|
675
|
+
i0.ɵɵelement(104, "div", 55, 1);
|
|
660
676
|
i0.ɵɵelementEnd()()()();
|
|
661
677
|
i0.ɵɵelementStart(106, "div", 42)(107, "button", 43);
|
|
662
678
|
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_button_click_107_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.actionDetailsExpanded = !ctx_r1.actionDetailsExpanded); });
|
|
@@ -665,13 +681,13 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
665
681
|
i0.ɵɵelementEnd();
|
|
666
682
|
i0.ɵɵconditionalCreate(110, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template, 18, 2, "div", 45);
|
|
667
683
|
i0.ɵɵelementEnd();
|
|
668
|
-
i0.ɵɵelementStart(111, "div",
|
|
669
|
-
i0.ɵɵconditionalCreate(112, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template, 9, 0, "div",
|
|
670
|
-
i0.ɵɵconditionalCreate(113, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template, 4, 0, "div",
|
|
684
|
+
i0.ɵɵelementStart(111, "div", 56);
|
|
685
|
+
i0.ɵɵconditionalCreate(112, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template, 9, 0, "div", 57);
|
|
686
|
+
i0.ɵɵconditionalCreate(113, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template, 4, 0, "div", 58);
|
|
671
687
|
i0.ɵɵelementEnd()()();
|
|
672
688
|
i0.ɵɵelementStart(114, "mj-accordion-panel", 17);
|
|
673
689
|
i0.ɵɵtemplate(115, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template, 2, 0, "ng-template", 18);
|
|
674
|
-
i0.ɵɵelementStart(116, "div", 37)(117, "div",
|
|
690
|
+
i0.ɵɵelementStart(116, "div", 37)(117, "div", 59)(118, "table")(119, "thead")(120, "tr")(121, "th");
|
|
675
691
|
i0.ɵɵtext(122, "Model");
|
|
676
692
|
i0.ɵɵelementEnd();
|
|
677
693
|
i0.ɵɵelementStart(123, "th");
|
|
@@ -700,35 +716,35 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
700
716
|
i0.ɵɵelementEnd()()()()();
|
|
701
717
|
i0.ɵɵelementStart(140, "mj-accordion-panel", 17);
|
|
702
718
|
i0.ɵɵtemplate(141, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template, 2, 0, "ng-template", 18);
|
|
703
|
-
i0.ɵɵelementStart(142, "div", 37)(143, "div",
|
|
719
|
+
i0.ɵɵelementStart(142, "div", 37)(143, "div", 60)(144, "div", 61)(145, "span", 62);
|
|
704
720
|
i0.ɵɵtext(146, "Total Steps");
|
|
705
721
|
i0.ɵɵelementEnd();
|
|
706
|
-
i0.ɵɵelementStart(147, "span",
|
|
722
|
+
i0.ɵɵelementStart(147, "span", 63);
|
|
707
723
|
i0.ɵɵtext(148);
|
|
708
724
|
i0.ɵɵelementEnd()();
|
|
709
|
-
i0.ɵɵelementStart(149, "div",
|
|
725
|
+
i0.ɵɵelementStart(149, "div", 61)(150, "span", 62);
|
|
710
726
|
i0.ɵɵtext(151, "Parallel Executions");
|
|
711
727
|
i0.ɵɵelementEnd();
|
|
712
|
-
i0.ɵɵelementStart(152, "span",
|
|
728
|
+
i0.ɵɵelementStart(152, "span", 63);
|
|
713
729
|
i0.ɵɵtext(153);
|
|
714
730
|
i0.ɵɵelementEnd()();
|
|
715
|
-
i0.ɵɵelementStart(154, "div",
|
|
731
|
+
i0.ɵɵelementStart(154, "div", 61)(155, "span", 62);
|
|
716
732
|
i0.ɵɵtext(156, "Max Nesting Depth");
|
|
717
733
|
i0.ɵɵelementEnd();
|
|
718
|
-
i0.ɵɵelementStart(157, "span",
|
|
734
|
+
i0.ɵɵelementStart(157, "span", 63);
|
|
719
735
|
i0.ɵɵtext(158);
|
|
720
736
|
i0.ɵɵelementEnd()();
|
|
721
|
-
i0.ɵɵelementStart(159, "div",
|
|
737
|
+
i0.ɵɵelementStart(159, "div", 61)(160, "span", 62);
|
|
722
738
|
i0.ɵɵtext(161, "Sub-Agent Runs");
|
|
723
739
|
i0.ɵɵelementEnd();
|
|
724
|
-
i0.ɵɵelementStart(162, "span",
|
|
740
|
+
i0.ɵɵelementStart(162, "span", 63);
|
|
725
741
|
i0.ɵɵtext(163);
|
|
726
742
|
i0.ɵɵelementEnd()()();
|
|
727
|
-
i0.ɵɵelementStart(164, "div",
|
|
743
|
+
i0.ɵɵelementStart(164, "div", 64)(165, "h3");
|
|
728
744
|
i0.ɵɵtext(166, "Steps by Type");
|
|
729
745
|
i0.ɵɵelementEnd();
|
|
730
|
-
i0.ɵɵelementStart(167, "div",
|
|
731
|
-
i0.ɵɵrepeaterCreate(168, AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template, 8, 4, "div",
|
|
746
|
+
i0.ɵɵelementStart(167, "div", 65);
|
|
747
|
+
i0.ɵɵrepeaterCreate(168, AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template, 8, 4, "div", 66, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
732
748
|
i0.ɵɵpipe(170, "keyvalue");
|
|
733
749
|
i0.ɵɵelementEnd()()()()();
|
|
734
750
|
} if (rf & 2) {
|
|
@@ -750,7 +766,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
750
766
|
i0.ɵɵadvance(8);
|
|
751
767
|
i0.ɵɵtextInterpolate(ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
|
|
752
768
|
i0.ɵɵadvance(3);
|
|
753
|
-
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(39,
|
|
769
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(39, 43, ctx_r1.totalTokensProcessed), " tokens");
|
|
754
770
|
i0.ɵɵadvance(2);
|
|
755
771
|
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 40 : -1);
|
|
756
772
|
i0.ɵɵadvance();
|
|
@@ -758,7 +774,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
758
774
|
i0.ɵɵadvance();
|
|
759
775
|
i0.ɵɵconditional(ctx_r1.cacheSavings > 0 ? 42 : -1);
|
|
760
776
|
i0.ɵɵadvance(8);
|
|
761
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(51,
|
|
777
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(51, 45, ctx_r1.promptMetrics.tokenUsage.totalCacheRead));
|
|
762
778
|
i0.ɵɵadvance(5);
|
|
763
779
|
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 55 : -1);
|
|
764
780
|
i0.ɵɵadvance();
|
|
@@ -785,11 +801,15 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
785
801
|
i0.ɵɵproperty("Expanded", true);
|
|
786
802
|
i0.ɵɵadvance(4);
|
|
787
803
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["actionSuccess"]);
|
|
788
|
-
i0.ɵɵadvance(
|
|
804
|
+
i0.ɵɵadvance(5);
|
|
805
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["actionSuccess"] ? "Collapse Action Success Rate chart" : "Expand Action Success Rate chart");
|
|
806
|
+
i0.ɵɵadvance();
|
|
789
807
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["actionSuccess"] ? "fa-compress" : "fa-expand");
|
|
790
808
|
i0.ɵɵadvance(5);
|
|
791
809
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["stepType"]);
|
|
792
|
-
i0.ɵɵadvance(
|
|
810
|
+
i0.ɵɵadvance(5);
|
|
811
|
+
i0.ɵɵattribute("aria-label", ctx_r1.expandedCharts["stepType"] ? "Collapse Step Type Distribution chart" : "Expand Step Type Distribution chart");
|
|
812
|
+
i0.ɵɵadvance();
|
|
793
813
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["stepType"] ? "fa-compress" : "fa-expand");
|
|
794
814
|
i0.ɵɵadvance(7);
|
|
795
815
|
i0.ɵɵproperty("ngClass", ctx_r1.actionDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
|
|
@@ -814,7 +834,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
814
834
|
i0.ɵɵadvance(5);
|
|
815
835
|
i0.ɵɵtextInterpolate(ctx_r1.subAgentRuns.length);
|
|
816
836
|
i0.ɵɵadvance(5);
|
|
817
|
-
i0.ɵɵrepeater(i0.ɵɵpipeBind1(170,
|
|
837
|
+
i0.ɵɵrepeater(i0.ɵɵpipeBind1(170, 47, ctx_r1.timelineMetrics.stepsByType));
|
|
818
838
|
} }
|
|
819
839
|
export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
820
840
|
/** Helper method to create tracked setTimeout calls */
|
|
@@ -2287,11 +2307,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2287
2307
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTokenDistributionChart = _t.first);
|
|
2288
2308
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCostDistributionChart = _t.first);
|
|
2289
2309
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCountByNameChart = _t.first);
|
|
2290
|
-
} }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], [1, "error-state"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["mjButton", "", 3, "click"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "metric-detail", "cache-detail"], [1, "card-icon", "cache"], [1, "fas", "fa-bolt"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], [1, "no-data-message"], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], [1, "no-errors"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2310
|
+
} }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], [1, "error-state"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["mjButton", "", 3, "click"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "metric-detail", "cache-detail"], [1, "card-icon", "cache"], [1, "fas", "fa-bolt"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], [1, "no-data-message"], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], ["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"], [1, "no-errors"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
2291
2311
|
i0.ɵɵelementStart(0, "div", 10);
|
|
2292
2312
|
i0.ɵɵconditionalCreate(1, AIAgentRunAnalyticsComponent_Conditional_1_Template, 4, 0, "div", 11);
|
|
2293
2313
|
i0.ɵɵconditionalCreate(2, AIAgentRunAnalyticsComponent_Conditional_2_Template, 6, 1, "div", 12);
|
|
2294
|
-
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 171,
|
|
2314
|
+
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 171, 49, "div", 13);
|
|
2295
2315
|
i0.ɵɵelementEnd();
|
|
2296
2316
|
} if (rf & 2) {
|
|
2297
2317
|
i0.ɵɵadvance();
|
|
@@ -2304,7 +2324,7 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2304
2324
|
}
|
|
2305
2325
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAgentRunAnalyticsComponent, [{
|
|
2306
2326
|
type: Component,
|
|
2307
|
-
args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button mjButton (click)=\"loadData()\">Retry</button>\n </div>\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <div class=\"metric-value\">{{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>{{ totalTokensProcessed | number }} tokens</span>\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>incl. {{ (promptMetrics.tokenUsage.totalCacheRead + promptMetrics.tokenUsage.totalCacheWrite) | number }} cached</span>\n }\n @if (inputCost > 0 || outputCost > 0) {\n <span>input {{ formatCost(inputCost) }} · output {{ formatCost(outputCost) }}</span>\n }\n @if (cacheSavings > 0) {\n <span class=\"success\">saved {{ formatCost(cacheSavings) }} ({{ cacheSavingsPct | number:'1.0-0' }}%) via cache</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cache\">\n <i class=\"fas fa-bolt\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Prompt Cache</h3>\n <div class=\"metric-value\">{{ promptMetrics.tokenUsage.totalCacheRead | number }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>tokens read from cache</span>\n @if (promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ promptMetrics.tokenUsage.totalCacheWrite | number }} written</span>\n }\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ cacheHitRatePct | number:'1.0-0' }}% hit rate</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n }\n <!-- No prompts message -->\n @if (promptMetrics.totalCount === 0) {\n <div class=\"no-data-message\">\n <i class=\"fas fa-info-circle\"></i>\n <p>No prompt executions found in this agent run.</p>\n <p class=\"small\">This agent run may have only executed actions without any AI prompts.</p>\n </div>\n }\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['modelDistribution'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"modelDistributionChart\" #modelDistributionChart></div>\n @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\n <span class=\"legend-color\" [style.backgroundColor]=\"getModelColor(item.key)\"></span>\n <span class=\"legend-label\">{{ item.key }}: {{ item.value.count }} ({{ (item.value.count / promptMetrics.totalCount * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Execution Time by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['executionTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('executionTime')\">\n <h3><i class=\"fas fa-clock\"></i> Average Execution Time by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['executionTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"executionTimeChart\" #executionTimeChart></div>\n </div>\n </div>\n </div>\n <!-- Cost by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['costByVendor']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('costByVendor')\">\n <h3><i class=\"fas fa-dollar-sign\"></i> Cost Distribution by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['costByVendor'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"costByVendorChart\" #costByVendorChart></div>\n <div class=\"chart-total\">Total: {{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n </div>\n </div>\n </div>\n <!-- Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['tokenUsage']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('tokenUsage')\">\n <h3><i class=\"fas fa-coins\"></i> Token Usage by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['tokenUsage'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"tokenUsageChart\" #tokenUsageChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Additional Prompt Analytics Charts -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\n <!-- Prompt Execution Time Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptTime')\">\n <h3><i class=\"fas fa-hourglass-half\"></i> Average Execution Time by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTimeDistributionChart\" #promptTimeDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptToken']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptToken')\">\n <h3><i class=\"fas fa-database\"></i> Token Usage by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptToken'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTokenDistributionChart\" #promptTokenDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Cost Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCost']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCost')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Cost Distribution by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCost'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCostDistributionChart\" #promptCostDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Count by Name -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCount']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCount')\">\n <h3><i class=\"fas fa-list-ol\"></i> Prompt Execution Count</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCount'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCountByNameChart\" #promptCountByNameChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Detailed Prompt Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"promptDetailsExpanded = !promptDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"promptDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Prompt Metrics\n </button>\n @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Prompt Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Total Time</th>\n <th>Success Rate</th>\n </tr>\n </thead>\n <tbody>\n @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\n <td>{{ prompt.key }}</td>\n <td>{{ prompt.value.count }}</td>\n <td>{{ formatDuration(prompt.value.avgTime) }}</td>\n <td>{{ formatDuration(prompt.value.totalTime) }}</td>\n <td>\n <span class=\"success-rate\">\n <!-- Calculate success rate for this prompt -->\n {{ calculatePromptSuccessRate(prompt.key) }}%\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"charts-grid\">\n <!-- Action Success Rate -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['actionSuccess']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('actionSuccess')\">\n <h3><i class=\"fas fa-chart-bar\"></i> Action Success Rate</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['actionSuccess'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"actionSuccessRateChart\" #actionSuccessRateChart></div>\n </div>\n </div>\n </div>\n <!-- Step Type Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['stepType']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('stepType')\">\n <h3><i class=\"fas fa-layer-group\"></i> Step Type Distribution</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['stepType'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"stepTypeChart\" #stepTypeChart></div>\n </div>\n </div>\n </div>\n </div>\n <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"actionDetailsExpanded = !actionDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"actionDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Action Metrics\n </button>\n @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Action Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Success Rate</th>\n <th>Type</th>\n </tr>\n </thead>\n <tbody>\n @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\n <td>{{ action.key }}</td>\n <td>{{ action.value.count }}</td>\n <td>{{ formatDuration(action.value.avgTime) }}</td>\n <td>\n <span class=\"success-rate\" [class.high]=\"action.value.successRate > 0.9\"\n [class.medium]=\"action.value.successRate > 0.7 && action.value.successRate <= 0.9\"\n [class.low]=\"action.value.successRate <= 0.7\">\n {{ (action.value.successRate * 100).toFixed(1) }}%\n </span>\n </td>\n <td>{{ getActionType(action.key) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\n <h3>\n <i class=\"fas fa-exclamation-triangle\"></i>\n Common Errors\n </h3>\n <p class=\"error-analysis-description\">\n This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention.\n </p>\n <div class=\"error-list\">\n @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <div class=\"no-errors\">\n <i class=\"fas fa-check-circle\"></i>\n <p>No action errors detected in this run. All actions completed successfully!</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Loading and Error States */\n.loading-state,\n.error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache {\n background: var(--mj-status-info);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Cache card stacks its facts (caption / written / hit rate) one per line. */\n.metric-detail.cache-detail span {\n display: block;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n/* No errors state */\n.no-errors {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors i {\n font-size: 24px;\n color: var(--mj-status-success);\n}\n\n.no-errors p {\n margin: 0;\n font-size: 14px;\n}\n\n/* No data message */\n.no-data-message {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\n}\n\n.no-data-message p {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message p.small {\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
|
|
2327
|
+
args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button mjButton (click)=\"loadData()\">Retry</button>\n </div>\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <div class=\"metric-value\">{{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>{{ totalTokensProcessed | number }} tokens</span>\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>incl. {{ (promptMetrics.tokenUsage.totalCacheRead + promptMetrics.tokenUsage.totalCacheWrite) | number }} cached</span>\n }\n @if (inputCost > 0 || outputCost > 0) {\n <span>input {{ formatCost(inputCost) }} · output {{ formatCost(outputCost) }}</span>\n }\n @if (cacheSavings > 0) {\n <span class=\"success\">saved {{ formatCost(cacheSavings) }} ({{ cacheSavingsPct | number:'1.0-0' }}%) via cache</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cache\">\n <i class=\"fas fa-bolt\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Prompt Cache</h3>\n <div class=\"metric-value\">{{ promptMetrics.tokenUsage.totalCacheRead | number }}</div>\n <div class=\"metric-detail cache-detail\">\n <span>tokens read from cache</span>\n @if (promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ promptMetrics.tokenUsage.totalCacheWrite | number }} written</span>\n }\n @if (promptMetrics.tokenUsage.totalCacheRead > 0 || promptMetrics.tokenUsage.totalCacheWrite > 0) {\n <span>{{ cacheHitRatePct | number:'1.0-0' }}% hit rate</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n }\n <!-- No prompts message -->\n @if (promptMetrics.totalCount === 0) {\n <div class=\"no-data-message\">\n <i class=\"fas fa-info-circle\"></i>\n <p>No prompt executions found in this agent run.</p>\n <p class=\"small\">This agent run may have only executed actions without any AI prompts.</p>\n </div>\n }\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\" [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 <div class=\"no-errors\">\n <i class=\"fas fa-check-circle\"></i>\n <p>No action errors detected in this run. All actions completed successfully!</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Loading and Error States */\n.loading-state,\n.error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache {\n background: var(--mj-status-info);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Cache card stacks its facts (caption / written / hit rate) one per line. */\n.metric-detail.cache-detail span {\n display: block;\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n/* No errors state */\n.no-errors {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors i {\n font-size: 24px;\n color: var(--mj-status-success);\n}\n\n.no-errors p {\n margin: 0;\n font-size: 14px;\n}\n\n/* No data message */\n.no-data-message {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\n}\n\n.no-data-message p {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message p.small {\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
|
|
2308
2328
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.AIAgentRunCostService }], { agentRunId: [{
|
|
2309
2329
|
type: Input
|
|
2310
2330
|
}], modelDistributionChart: [{
|