@memberjunction/ng-core-entity-forms 5.38.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 +17 -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 +695 -557
- 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/Queries/query-form.component.d.ts +13 -4
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +374 -326
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-form.component.js +2 -3
- package/dist/lib/custom/Tests/test-form.component.js.map +1 -1
- package/dist/lib/custom/Tests/test-suite-form.component.js +1 -2
- package/dist/lib/custom/Tests/test-suite-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts +24 -0
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +411 -234
- 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/custom/custom-forms.module.d.ts +39 -41
- package/dist/lib/custom/custom-forms.module.d.ts.map +1 -1
- package/dist/lib/custom/custom-forms.module.js +8 -9
- package/dist/lib/custom/custom-forms.module.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js +75 -69
- package/dist/lib/generated/Entities/MJAIAgentRun/mjaiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js +3 -3
- package/dist/lib/generated/Entities/MJAIModel/mjaimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIModelCost/mjaimodelcost.form.component.js +10 -6
- package/dist/lib/generated/Entities/MJAIModelCost/mjaimodelcost.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.form.component.js +3 -3
- package/dist/lib/generated/Entities/MJAIPrompt/mjaiprompt.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 +65 -39
- 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/MJIntegrationObject/mjintegrationobject.form.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js +58 -24
- package/dist/lib/generated/Entities/MJIntegrationObject/mjintegrationobject.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.form.component.js +10 -8
- package/dist/lib/generated/Entities/MJIntegrationObjectField/mjintegrationobjectfield.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/MJScheduledJob/mjscheduledjob.form.component.js +27 -25
- package/dist/lib/generated/Entities/MJScheduledJob/mjscheduledjob.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/MJTagSynonym/mjtagsynonym.form.component.js +8 -6
- package/dist/lib/generated/Entities/MJTagSynonym/mjtagsynonym.form.component.js.map +1 -1
- 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
- package/dist/lib/custom/Queries/query-category-dialog.component.d.ts +0 -34
- package/dist/lib/custom/Queries/query-category-dialog.component.d.ts.map +0 -1
- package/dist/lib/custom/Queries/query-category-dialog.component.js +0 -203
- package/dist/lib/custom/Queries/query-category-dialog.component.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Component, Input, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
3
|
import { RunView } from '@memberjunction/core';
|
|
4
|
-
import { UUIDsEqual } from '@memberjunction/global';
|
|
4
|
+
import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
|
|
5
5
|
import * as d3 from 'd3';
|
|
6
6
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
7
7
|
import * as i0 from "@angular/core";
|
|
@@ -42,7 +42,7 @@ function AIAgentRunAnalyticsComponent_Conditional_2_Template(rf, ctx) { if (rf &
|
|
|
42
42
|
i0.ɵɵtextInterpolate(ctx_r1.error);
|
|
43
43
|
} }
|
|
44
44
|
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_2_Template(rf, ctx) { if (rf & 1) {
|
|
45
|
-
i0.ɵɵelement(0, "i",
|
|
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) {
|
|
@@ -63,15 +63,64 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_27_Template(rf,
|
|
|
63
63
|
i0.ɵɵadvance();
|
|
64
64
|
i0.ɵɵtextInterpolate1("", ctx_r1.actionMetrics.statusBreakdown.failed, " failed");
|
|
65
65
|
} }
|
|
66
|
-
function
|
|
66
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_40_Template(rf, ctx) { if (rf & 1) {
|
|
67
|
+
i0.ɵɵelementStart(0, "span");
|
|
68
|
+
i0.ɵɵtext(1);
|
|
69
|
+
i0.ɵɵpipe(2, "number");
|
|
70
|
+
i0.ɵɵelementEnd();
|
|
71
|
+
} if (rf & 2) {
|
|
72
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
73
|
+
i0.ɵɵadvance();
|
|
74
|
+
i0.ɵɵtextInterpolate1("incl. ", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheRead + ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " cached");
|
|
75
|
+
} }
|
|
76
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template(rf, ctx) { if (rf & 1) {
|
|
77
|
+
i0.ɵɵelementStart(0, "span");
|
|
78
|
+
i0.ɵɵtext(1);
|
|
79
|
+
i0.ɵɵelementEnd();
|
|
80
|
+
} if (rf & 2) {
|
|
81
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
82
|
+
i0.ɵɵadvance();
|
|
83
|
+
i0.ɵɵtextInterpolate2("input ", ctx_r1.formatCost(ctx_r1.inputCost), " \u00B7 output ", ctx_r1.formatCost(ctx_r1.outputCost));
|
|
84
|
+
} }
|
|
85
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵelementStart(0, "span", 26);
|
|
87
|
+
i0.ɵɵtext(1);
|
|
88
|
+
i0.ɵɵpipe(2, "number");
|
|
89
|
+
i0.ɵɵelementEnd();
|
|
90
|
+
} if (rf & 2) {
|
|
91
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
92
|
+
i0.ɵɵadvance();
|
|
93
|
+
i0.ɵɵtextInterpolate2("saved ", ctx_r1.formatCost(ctx_r1.cacheSavings), " (", i0.ɵɵpipeBind2(2, 2, ctx_r1.cacheSavingsPct, "1.0-0"), "%) via cache");
|
|
94
|
+
} }
|
|
95
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template(rf, ctx) { if (rf & 1) {
|
|
96
|
+
i0.ɵɵelementStart(0, "span");
|
|
97
|
+
i0.ɵɵtext(1);
|
|
98
|
+
i0.ɵɵpipe(2, "number");
|
|
99
|
+
i0.ɵɵelementEnd();
|
|
100
|
+
} if (rf & 2) {
|
|
101
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
102
|
+
i0.ɵɵadvance();
|
|
103
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(2, 1, ctx_r1.promptMetrics.tokenUsage.totalCacheWrite), " written");
|
|
104
|
+
} }
|
|
105
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template(rf, ctx) { if (rf & 1) {
|
|
106
|
+
i0.ɵɵelementStart(0, "span");
|
|
107
|
+
i0.ɵɵtext(1);
|
|
108
|
+
i0.ɵɵpipe(2, "number");
|
|
109
|
+
i0.ɵɵelementEnd();
|
|
110
|
+
} if (rf & 2) {
|
|
111
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
112
|
+
i0.ɵɵadvance();
|
|
113
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(2, 1, ctx_r1.cacheHitRatePct, "1.0-0"), "% hit rate");
|
|
114
|
+
} }
|
|
115
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_69_Template(rf, ctx) { if (rf & 1) {
|
|
67
116
|
i0.ɵɵelement(0, "i", 22);
|
|
68
117
|
i0.ɵɵtext(1, " Prompt Analytics ");
|
|
69
118
|
} }
|
|
70
|
-
function
|
|
119
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template(rf, ctx) { if (rf & 1) {
|
|
71
120
|
const _r4 = i0.ɵɵgetCurrentView();
|
|
72
|
-
i0.ɵɵelementStart(0, "div",
|
|
73
|
-
i0.ɵɵlistener("click", function
|
|
74
|
-
i0.ɵɵelement(2, "i",
|
|
121
|
+
i0.ɵɵelementStart(0, "div", 38)(1, "button", 43);
|
|
122
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template_button_click_1_listener() { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleViewMode()); });
|
|
123
|
+
i0.ɵɵelement(2, "i", 44);
|
|
75
124
|
i0.ɵɵtext(3);
|
|
76
125
|
i0.ɵɵelementEnd()();
|
|
77
126
|
} if (rf & 2) {
|
|
@@ -81,20 +130,20 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_53_Template(rf,
|
|
|
81
130
|
i0.ɵɵadvance();
|
|
82
131
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.viewMode === "grid" ? "Expand All" : "Collapse All", " ");
|
|
83
132
|
} }
|
|
84
|
-
function
|
|
85
|
-
i0.ɵɵelementStart(0, "div",
|
|
86
|
-
i0.ɵɵelement(1, "i",
|
|
133
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template(rf, ctx) { if (rf & 1) {
|
|
134
|
+
i0.ɵɵelementStart(0, "div", 39);
|
|
135
|
+
i0.ɵɵelement(1, "i", 68);
|
|
87
136
|
i0.ɵɵelementStart(2, "p");
|
|
88
137
|
i0.ɵɵtext(3, "No prompt executions found in this agent run.");
|
|
89
138
|
i0.ɵɵelementEnd();
|
|
90
|
-
i0.ɵɵelementStart(4, "p",
|
|
139
|
+
i0.ɵɵelementStart(4, "p", 69);
|
|
91
140
|
i0.ɵɵtext(5, "This agent run may have only executed actions without any AI prompts.");
|
|
92
141
|
i0.ɵɵelementEnd()();
|
|
93
142
|
} }
|
|
94
|
-
function
|
|
95
|
-
i0.ɵɵelementStart(0, "div",
|
|
96
|
-
i0.ɵɵelement(1, "span",
|
|
97
|
-
i0.ɵɵelementStart(2, "span",
|
|
143
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
144
|
+
i0.ɵɵelementStart(0, "div", 78);
|
|
145
|
+
i0.ɵɵelement(1, "span", 79);
|
|
146
|
+
i0.ɵɵelementStart(2, "span", 80);
|
|
98
147
|
i0.ɵɵtext(3);
|
|
99
148
|
i0.ɵɵelementEnd()();
|
|
100
149
|
} if (rf & 2) {
|
|
@@ -105,9 +154,9 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_1
|
|
|
105
154
|
i0.ɵɵadvance(2);
|
|
106
155
|
i0.ɵɵtextInterpolate3("", item_r6.key, ": ", item_r6.value.count, " (", (item_r6.value.count / ctx_r1.promptMetrics.totalCount * 100).toFixed(1), "%)");
|
|
107
156
|
} }
|
|
108
|
-
function
|
|
109
|
-
i0.ɵɵelementStart(0, "div",
|
|
110
|
-
i0.ɵɵrepeaterCreate(1,
|
|
157
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Conditional_12_Template(rf, ctx) { if (rf & 1) {
|
|
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);
|
|
111
160
|
i0.ɵɵpipe(3, "keyvalue");
|
|
112
161
|
i0.ɵɵelementEnd();
|
|
113
162
|
} if (rf & 2) {
|
|
@@ -115,152 +164,168 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Conditional_1
|
|
|
115
164
|
i0.ɵɵadvance();
|
|
116
165
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(3, 0, ctx_r1.promptMetrics.byModel));
|
|
117
166
|
} }
|
|
118
|
-
function
|
|
167
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template(rf, ctx) { if (rf & 1) {
|
|
119
168
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
120
|
-
i0.ɵɵelementStart(0, "div",
|
|
121
|
-
i0.ɵɵlistener("click", function
|
|
169
|
+
i0.ɵɵelementStart(0, "div", 40)(1, "div", 46)(2, "div", 47);
|
|
170
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_2_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("modelDistribution")); });
|
|
122
171
|
i0.ɵɵelementStart(3, "h3");
|
|
123
|
-
i0.ɵɵelement(4, "i",
|
|
172
|
+
i0.ɵɵelement(4, "i", 70);
|
|
124
173
|
i0.ɵɵtext(5, " Prompts by Model");
|
|
125
174
|
i0.ɵɵelementEnd();
|
|
126
|
-
i0.ɵɵelementStart(6, "button",
|
|
127
|
-
i0.ɵɵelement(7, "i",
|
|
175
|
+
i0.ɵɵelementStart(6, "button", 49);
|
|
176
|
+
i0.ɵɵelement(7, "i", 50);
|
|
128
177
|
i0.ɵɵelementEnd()();
|
|
129
|
-
i0.ɵɵelementStart(8, "div",
|
|
130
|
-
i0.ɵɵelement(10, "div",
|
|
131
|
-
i0.ɵɵconditionalCreate(12,
|
|
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);
|
|
132
181
|
i0.ɵɵelementEnd()()();
|
|
133
|
-
i0.ɵɵelementStart(13, "div",
|
|
134
|
-
i0.ɵɵlistener("click", function
|
|
182
|
+
i0.ɵɵelementStart(13, "div", 46)(14, "div", 47);
|
|
183
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_14_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("executionTime")); });
|
|
135
184
|
i0.ɵɵelementStart(15, "h3");
|
|
136
|
-
i0.ɵɵelement(16, "i",
|
|
185
|
+
i0.ɵɵelement(16, "i", 36);
|
|
137
186
|
i0.ɵɵtext(17, " Average Execution Time by Vendor");
|
|
138
187
|
i0.ɵɵelementEnd();
|
|
139
|
-
i0.ɵɵelementStart(18, "button",
|
|
140
|
-
i0.ɵɵelement(19, "i",
|
|
188
|
+
i0.ɵɵelementStart(18, "button", 49);
|
|
189
|
+
i0.ɵɵelement(19, "i", 50);
|
|
141
190
|
i0.ɵɵelementEnd()();
|
|
142
|
-
i0.ɵɵelementStart(20, "div",
|
|
143
|
-
i0.ɵɵelement(22, "div",
|
|
191
|
+
i0.ɵɵelementStart(20, "div", 51)(21, "div", 52);
|
|
192
|
+
i0.ɵɵelement(22, "div", 73, 3);
|
|
144
193
|
i0.ɵɵelementEnd()()();
|
|
145
|
-
i0.ɵɵelementStart(24, "div",
|
|
146
|
-
i0.ɵɵlistener("click", function
|
|
194
|
+
i0.ɵɵelementStart(24, "div", 46)(25, "div", 47);
|
|
195
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_25_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("costByVendor")); });
|
|
147
196
|
i0.ɵɵelementStart(26, "h3");
|
|
148
197
|
i0.ɵɵelement(27, "i", 31);
|
|
149
198
|
i0.ɵɵtext(28, " Cost Distribution by Vendor");
|
|
150
199
|
i0.ɵɵelementEnd();
|
|
151
|
-
i0.ɵɵelementStart(29, "button",
|
|
152
|
-
i0.ɵɵelement(30, "i",
|
|
200
|
+
i0.ɵɵelementStart(29, "button", 49);
|
|
201
|
+
i0.ɵɵelement(30, "i", 50);
|
|
153
202
|
i0.ɵɵelementEnd()();
|
|
154
|
-
i0.ɵɵelementStart(31, "div",
|
|
155
|
-
i0.ɵɵelement(33, "div",
|
|
156
|
-
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);
|
|
157
206
|
i0.ɵɵtext(36);
|
|
158
207
|
i0.ɵɵelementEnd()()()();
|
|
159
|
-
i0.ɵɵelementStart(37, "div",
|
|
160
|
-
i0.ɵɵlistener("click", function
|
|
208
|
+
i0.ɵɵelementStart(37, "div", 46)(38, "div", 47);
|
|
209
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_73_Template_div_click_38_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("tokenUsage")); });
|
|
161
210
|
i0.ɵɵelementStart(39, "h3");
|
|
162
|
-
i0.ɵɵelement(40, "i",
|
|
211
|
+
i0.ɵɵelement(40, "i", 76);
|
|
163
212
|
i0.ɵɵtext(41, " Token Usage by Model");
|
|
164
213
|
i0.ɵɵelementEnd();
|
|
165
|
-
i0.ɵɵelementStart(42, "button",
|
|
166
|
-
i0.ɵɵelement(43, "i",
|
|
214
|
+
i0.ɵɵelementStart(42, "button", 49);
|
|
215
|
+
i0.ɵɵelement(43, "i", 50);
|
|
167
216
|
i0.ɵɵelementEnd()();
|
|
168
|
-
i0.ɵɵelementStart(44, "div",
|
|
169
|
-
i0.ɵɵelement(46, "div",
|
|
217
|
+
i0.ɵɵelementStart(44, "div", 51)(45, "div", 52);
|
|
218
|
+
i0.ɵɵelement(46, "div", 77, 5);
|
|
170
219
|
i0.ɵɵelementEnd()()()();
|
|
171
220
|
} if (rf & 2) {
|
|
172
221
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
173
222
|
i0.ɵɵadvance();
|
|
174
223
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["modelDistribution"]);
|
|
175
|
-
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();
|
|
176
227
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["modelDistribution"] ? "fa-compress" : "fa-expand");
|
|
177
228
|
i0.ɵɵadvance(5);
|
|
178
229
|
i0.ɵɵconditional(ctx_r1.promptMetrics.byModel.size > 0 ? 12 : -1);
|
|
179
230
|
i0.ɵɵadvance();
|
|
180
231
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["executionTime"]);
|
|
181
|
-
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();
|
|
182
235
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["executionTime"] ? "fa-compress" : "fa-expand");
|
|
183
236
|
i0.ɵɵadvance(5);
|
|
184
237
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["costByVendor"]);
|
|
185
|
-
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();
|
|
186
241
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["costByVendor"] ? "fa-compress" : "fa-expand");
|
|
187
242
|
i0.ɵɵadvance(6);
|
|
188
243
|
i0.ɵɵtextInterpolate1("Total: ", ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
|
|
189
244
|
i0.ɵɵadvance();
|
|
190
245
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["tokenUsage"]);
|
|
191
|
-
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();
|
|
192
249
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["tokenUsage"] ? "fa-compress" : "fa-expand");
|
|
193
250
|
} }
|
|
194
|
-
function
|
|
251
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_74_Template(rf, ctx) { if (rf & 1) {
|
|
195
252
|
const _r7 = i0.ɵɵgetCurrentView();
|
|
196
|
-
i0.ɵɵelementStart(0, "div",
|
|
197
|
-
i0.ɵɵlistener("click", function
|
|
253
|
+
i0.ɵɵelementStart(0, "div", 41)(1, "div", 46)(2, "div", 47);
|
|
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")); });
|
|
198
255
|
i0.ɵɵelementStart(3, "h3");
|
|
199
|
-
i0.ɵɵelement(4, "i",
|
|
256
|
+
i0.ɵɵelement(4, "i", 81);
|
|
200
257
|
i0.ɵɵtext(5, " Average Execution Time by Prompt");
|
|
201
258
|
i0.ɵɵelementEnd();
|
|
202
|
-
i0.ɵɵelementStart(6, "button",
|
|
203
|
-
i0.ɵɵelement(7, "i",
|
|
259
|
+
i0.ɵɵelementStart(6, "button", 49);
|
|
260
|
+
i0.ɵɵelement(7, "i", 50);
|
|
204
261
|
i0.ɵɵelementEnd()();
|
|
205
|
-
i0.ɵɵelementStart(8, "div",
|
|
206
|
-
i0.ɵɵelement(10, "div",
|
|
262
|
+
i0.ɵɵelementStart(8, "div", 51)(9, "div", 52);
|
|
263
|
+
i0.ɵɵelement(10, "div", 82, 6);
|
|
207
264
|
i0.ɵɵelementEnd()()();
|
|
208
|
-
i0.ɵɵelementStart(12, "div",
|
|
209
|
-
i0.ɵɵlistener("click", function
|
|
265
|
+
i0.ɵɵelementStart(12, "div", 46)(13, "div", 47);
|
|
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")); });
|
|
210
267
|
i0.ɵɵelementStart(14, "h3");
|
|
211
|
-
i0.ɵɵelement(15, "i",
|
|
268
|
+
i0.ɵɵelement(15, "i", 83);
|
|
212
269
|
i0.ɵɵtext(16, " Token Usage by Prompt");
|
|
213
270
|
i0.ɵɵelementEnd();
|
|
214
|
-
i0.ɵɵelementStart(17, "button",
|
|
215
|
-
i0.ɵɵelement(18, "i",
|
|
271
|
+
i0.ɵɵelementStart(17, "button", 49);
|
|
272
|
+
i0.ɵɵelement(18, "i", 50);
|
|
216
273
|
i0.ɵɵelementEnd()();
|
|
217
|
-
i0.ɵɵelementStart(19, "div",
|
|
218
|
-
i0.ɵɵelement(21, "div",
|
|
274
|
+
i0.ɵɵelementStart(19, "div", 51)(20, "div", 52);
|
|
275
|
+
i0.ɵɵelement(21, "div", 84, 7);
|
|
219
276
|
i0.ɵɵelementEnd()()();
|
|
220
|
-
i0.ɵɵelementStart(23, "div",
|
|
221
|
-
i0.ɵɵlistener("click", function
|
|
277
|
+
i0.ɵɵelementStart(23, "div", 46)(24, "div", 47);
|
|
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")); });
|
|
222
279
|
i0.ɵɵelementStart(25, "h3");
|
|
223
|
-
i0.ɵɵelement(26, "i",
|
|
280
|
+
i0.ɵɵelement(26, "i", 70);
|
|
224
281
|
i0.ɵɵtext(27, " Cost Distribution by Prompt");
|
|
225
282
|
i0.ɵɵelementEnd();
|
|
226
|
-
i0.ɵɵelementStart(28, "button",
|
|
227
|
-
i0.ɵɵelement(29, "i",
|
|
283
|
+
i0.ɵɵelementStart(28, "button", 49);
|
|
284
|
+
i0.ɵɵelement(29, "i", 50);
|
|
228
285
|
i0.ɵɵelementEnd()();
|
|
229
|
-
i0.ɵɵelementStart(30, "div",
|
|
230
|
-
i0.ɵɵelement(32, "div",
|
|
286
|
+
i0.ɵɵelementStart(30, "div", 51)(31, "div", 52);
|
|
287
|
+
i0.ɵɵelement(32, "div", 85, 8);
|
|
231
288
|
i0.ɵɵelementEnd()()();
|
|
232
|
-
i0.ɵɵelementStart(34, "div",
|
|
233
|
-
i0.ɵɵlistener("click", function
|
|
289
|
+
i0.ɵɵelementStart(34, "div", 46)(35, "div", 47);
|
|
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")); });
|
|
234
291
|
i0.ɵɵelementStart(36, "h3");
|
|
235
|
-
i0.ɵɵelement(37, "i",
|
|
292
|
+
i0.ɵɵelement(37, "i", 86);
|
|
236
293
|
i0.ɵɵtext(38, " Prompt Execution Count");
|
|
237
294
|
i0.ɵɵelementEnd();
|
|
238
|
-
i0.ɵɵelementStart(39, "button",
|
|
239
|
-
i0.ɵɵelement(40, "i",
|
|
295
|
+
i0.ɵɵelementStart(39, "button", 49);
|
|
296
|
+
i0.ɵɵelement(40, "i", 50);
|
|
240
297
|
i0.ɵɵelementEnd()();
|
|
241
|
-
i0.ɵɵelementStart(41, "div",
|
|
242
|
-
i0.ɵɵelement(43, "div",
|
|
298
|
+
i0.ɵɵelementStart(41, "div", 51)(42, "div", 52);
|
|
299
|
+
i0.ɵɵelement(43, "div", 87, 9);
|
|
243
300
|
i0.ɵɵelementEnd()()()();
|
|
244
301
|
} if (rf & 2) {
|
|
245
302
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
246
303
|
i0.ɵɵadvance();
|
|
247
304
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptTime"]);
|
|
248
|
-
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();
|
|
249
308
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptTime"] ? "fa-compress" : "fa-expand");
|
|
250
309
|
i0.ɵɵadvance(5);
|
|
251
310
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptToken"]);
|
|
252
|
-
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();
|
|
253
314
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptToken"] ? "fa-compress" : "fa-expand");
|
|
254
315
|
i0.ɵɵadvance(5);
|
|
255
316
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCost"]);
|
|
256
|
-
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();
|
|
257
320
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCost"] ? "fa-compress" : "fa-expand");
|
|
258
321
|
i0.ɵɵadvance(5);
|
|
259
322
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["promptCount"]);
|
|
260
|
-
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();
|
|
261
326
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["promptCount"] ? "fa-compress" : "fa-expand");
|
|
262
327
|
} }
|
|
263
|
-
function
|
|
328
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
264
329
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
265
330
|
i0.ɵɵtext(2);
|
|
266
331
|
i0.ɵɵelementEnd();
|
|
@@ -273,7 +338,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Templa
|
|
|
273
338
|
i0.ɵɵelementStart(7, "td");
|
|
274
339
|
i0.ɵɵtext(8);
|
|
275
340
|
i0.ɵɵelementEnd();
|
|
276
|
-
i0.ɵɵelementStart(9, "td")(10, "span",
|
|
341
|
+
i0.ɵɵelementStart(9, "td")(10, "span", 88);
|
|
277
342
|
i0.ɵɵtext(11);
|
|
278
343
|
i0.ɵɵelementEnd()()();
|
|
279
344
|
} if (rf & 2) {
|
|
@@ -290,8 +355,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_For_16_Templa
|
|
|
290
355
|
i0.ɵɵadvance(3);
|
|
291
356
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.calculatePromptSuccessRate(prompt_r8.key), "% ");
|
|
292
357
|
} }
|
|
293
|
-
function
|
|
294
|
-
i0.ɵɵelementStart(0, "div",
|
|
358
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template(rf, ctx) { if (rf & 1) {
|
|
359
|
+
i0.ɵɵelementStart(0, "div", 45)(1, "table")(2, "thead")(3, "tr")(4, "th");
|
|
295
360
|
i0.ɵɵtext(5, "Prompt Name");
|
|
296
361
|
i0.ɵɵelementEnd();
|
|
297
362
|
i0.ɵɵelementStart(6, "th");
|
|
@@ -307,7 +372,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template(rf,
|
|
|
307
372
|
i0.ɵɵtext(13, "Success Rate");
|
|
308
373
|
i0.ɵɵelementEnd()()();
|
|
309
374
|
i0.ɵɵelementStart(14, "tbody");
|
|
310
|
-
i0.ɵɵrepeaterCreate(15,
|
|
375
|
+
i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_For_16_Template, 12, 5, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
311
376
|
i0.ɵɵpipe(17, "keyvalue");
|
|
312
377
|
i0.ɵɵelementEnd()()();
|
|
313
378
|
} if (rf & 2) {
|
|
@@ -315,11 +380,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_61_Template(rf,
|
|
|
315
380
|
i0.ɵɵadvance(15);
|
|
316
381
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.promptMetrics.byPrompt));
|
|
317
382
|
} }
|
|
318
|
-
function
|
|
383
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_81_Template(rf, ctx) { if (rf & 1) {
|
|
319
384
|
i0.ɵɵelement(0, "i", 29);
|
|
320
385
|
i0.ɵɵtext(1, " Action Analytics ");
|
|
321
386
|
} }
|
|
322
|
-
function
|
|
387
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Template(rf, ctx) { if (rf & 1) {
|
|
323
388
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
324
389
|
i0.ɵɵtext(2);
|
|
325
390
|
i0.ɵɵelementEnd();
|
|
@@ -329,7 +394,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Templa
|
|
|
329
394
|
i0.ɵɵelementStart(5, "td");
|
|
330
395
|
i0.ɵɵtext(6);
|
|
331
396
|
i0.ɵɵelementEnd();
|
|
332
|
-
i0.ɵɵelementStart(7, "td")(8, "span",
|
|
397
|
+
i0.ɵɵelementStart(7, "td")(8, "span", 88);
|
|
333
398
|
i0.ɵɵtext(9);
|
|
334
399
|
i0.ɵɵelementEnd()();
|
|
335
400
|
i0.ɵɵelementStart(10, "td");
|
|
@@ -351,8 +416,8 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_For_16_Templa
|
|
|
351
416
|
i0.ɵɵadvance(2);
|
|
352
417
|
i0.ɵɵtextInterpolate(ctx_r1.getActionType(action_r9.key));
|
|
353
418
|
} }
|
|
354
|
-
function
|
|
355
|
-
i0.ɵɵelementStart(0, "div",
|
|
419
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template(rf, ctx) { if (rf & 1) {
|
|
420
|
+
i0.ɵɵelementStart(0, "div", 45)(1, "table")(2, "thead")(3, "tr")(4, "th");
|
|
356
421
|
i0.ɵɵtext(5, "Action Name");
|
|
357
422
|
i0.ɵɵelementEnd();
|
|
358
423
|
i0.ɵɵelementStart(6, "th");
|
|
@@ -368,7 +433,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template(rf,
|
|
|
368
433
|
i0.ɵɵtext(13, "Type");
|
|
369
434
|
i0.ɵɵelementEnd()()();
|
|
370
435
|
i0.ɵɵelementStart(14, "tbody");
|
|
371
|
-
i0.ɵɵrepeaterCreate(15,
|
|
436
|
+
i0.ɵɵrepeaterCreate(15, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_For_16_Template, 12, 11, "tr", null, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
372
437
|
i0.ɵɵpipe(17, "keyvalue");
|
|
373
438
|
i0.ɵɵelementEnd()()();
|
|
374
439
|
} if (rf & 2) {
|
|
@@ -376,11 +441,11 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_92_Template(rf,
|
|
|
376
441
|
i0.ɵɵadvance(15);
|
|
377
442
|
i0.ɵɵrepeater(i0.ɵɵpipeBind1(17, 0, ctx_r1.actionMetrics.byAction));
|
|
378
443
|
} }
|
|
379
|
-
function
|
|
380
|
-
i0.ɵɵelementStart(0, "div",
|
|
444
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_For_8_Template(rf, ctx) { if (rf & 1) {
|
|
445
|
+
i0.ɵɵelementStart(0, "div", 92)(1, "span", 93);
|
|
381
446
|
i0.ɵɵtext(2);
|
|
382
447
|
i0.ɵɵelementEnd();
|
|
383
|
-
i0.ɵɵelementStart(3, "span",
|
|
448
|
+
i0.ɵɵelementStart(3, "span", 94);
|
|
384
449
|
i0.ɵɵtext(4);
|
|
385
450
|
i0.ɵɵelementEnd()();
|
|
386
451
|
} if (rf & 2) {
|
|
@@ -390,34 +455,34 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_94_For_8_Templat
|
|
|
390
455
|
i0.ɵɵadvance(2);
|
|
391
456
|
i0.ɵɵtextInterpolate(error_r10.message);
|
|
392
457
|
} }
|
|
393
|
-
function
|
|
394
|
-
i0.ɵɵelementStart(0, "div",
|
|
395
|
-
i0.ɵɵelement(2, "i",
|
|
458
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_112_Template(rf, ctx) { if (rf & 1) {
|
|
459
|
+
i0.ɵɵelementStart(0, "div", 57)(1, "h3");
|
|
460
|
+
i0.ɵɵelement(2, "i", 89);
|
|
396
461
|
i0.ɵɵtext(3, " Common Errors ");
|
|
397
462
|
i0.ɵɵelementEnd();
|
|
398
|
-
i0.ɵɵelementStart(4, "p",
|
|
463
|
+
i0.ɵɵelementStart(4, "p", 90);
|
|
399
464
|
i0.ɵɵtext(5, " This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention. ");
|
|
400
465
|
i0.ɵɵelementEnd();
|
|
401
|
-
i0.ɵɵelementStart(6, "div",
|
|
402
|
-
i0.ɵɵrepeaterCreate(7,
|
|
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);
|
|
403
468
|
i0.ɵɵelementEnd()();
|
|
404
469
|
} if (rf & 2) {
|
|
405
470
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
406
471
|
i0.ɵɵadvance(7);
|
|
407
472
|
i0.ɵɵrepeater(ctx_r1.getTopErrors());
|
|
408
473
|
} }
|
|
409
|
-
function
|
|
410
|
-
i0.ɵɵelementStart(0, "div",
|
|
411
|
-
i0.ɵɵelement(1, "i",
|
|
474
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_Conditional_113_Template(rf, ctx) { if (rf & 1) {
|
|
475
|
+
i0.ɵɵelementStart(0, "div", 58);
|
|
476
|
+
i0.ɵɵelement(1, "i", 95);
|
|
412
477
|
i0.ɵɵelementStart(2, "p");
|
|
413
478
|
i0.ɵɵtext(3, "No action errors detected in this run. All actions completed successfully!");
|
|
414
479
|
i0.ɵɵelementEnd()();
|
|
415
480
|
} }
|
|
416
|
-
function
|
|
417
|
-
i0.ɵɵelement(0, "i",
|
|
481
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template(rf, ctx) { if (rf & 1) {
|
|
482
|
+
i0.ɵɵelement(0, "i", 96);
|
|
418
483
|
i0.ɵɵtext(1, " Model Performance Comparison ");
|
|
419
484
|
} }
|
|
420
|
-
function
|
|
485
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template(rf, ctx) { if (rf & 1) {
|
|
421
486
|
i0.ɵɵelementStart(0, "tr")(1, "td");
|
|
422
487
|
i0.ɵɵtext(2);
|
|
423
488
|
i0.ɵɵelementEnd();
|
|
@@ -464,20 +529,20 @@ function AIAgentRunAnalyticsComponent_Conditional_3_For_121_Template(rf, ctx) {
|
|
|
464
529
|
i0.ɵɵadvance(3);
|
|
465
530
|
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind2(18, 11, model_r11.outputTokens, "1.0-0"));
|
|
466
531
|
} }
|
|
467
|
-
function
|
|
468
|
-
i0.ɵɵelement(0, "i",
|
|
532
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template(rf, ctx) { if (rf & 1) {
|
|
533
|
+
i0.ɵɵelement(0, "i", 97);
|
|
469
534
|
i0.ɵɵtext(1, " Execution Timeline Analysis ");
|
|
470
535
|
} }
|
|
471
|
-
function
|
|
472
|
-
i0.ɵɵelementStart(0, "div",
|
|
473
|
-
i0.ɵɵelement(1, "i",
|
|
474
|
-
i0.ɵɵelementStart(2, "span",
|
|
536
|
+
function AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template(rf, ctx) { if (rf & 1) {
|
|
537
|
+
i0.ɵɵelementStart(0, "div", 66);
|
|
538
|
+
i0.ɵɵelement(1, "i", 44);
|
|
539
|
+
i0.ɵɵelementStart(2, "span", 98);
|
|
475
540
|
i0.ɵɵtext(3);
|
|
476
541
|
i0.ɵɵelementEnd();
|
|
477
|
-
i0.ɵɵelementStart(4, "span",
|
|
542
|
+
i0.ɵɵelementStart(4, "span", 99);
|
|
478
543
|
i0.ɵɵtext(5);
|
|
479
544
|
i0.ɵɵelementEnd();
|
|
480
|
-
i0.ɵɵelementStart(6, "span",
|
|
545
|
+
i0.ɵɵelementStart(6, "span", 100);
|
|
481
546
|
i0.ɵɵtext(7);
|
|
482
547
|
i0.ɵɵelementEnd()();
|
|
483
548
|
} if (rf & 2) {
|
|
@@ -533,133 +598,154 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
533
598
|
i0.ɵɵelementStart(34, "div", 24);
|
|
534
599
|
i0.ɵɵtext(35);
|
|
535
600
|
i0.ɵɵelementEnd();
|
|
536
|
-
i0.ɵɵelementStart(36, "div",
|
|
601
|
+
i0.ɵɵelementStart(36, "div", 32)(37, "span");
|
|
537
602
|
i0.ɵɵtext(38);
|
|
538
|
-
i0.ɵɵ
|
|
539
|
-
i0.ɵɵ
|
|
540
|
-
i0.ɵɵ
|
|
603
|
+
i0.ɵɵpipe(39, "number");
|
|
604
|
+
i0.ɵɵelementEnd();
|
|
605
|
+
i0.ɵɵconditionalCreate(40, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_40_Template, 3, 3, "span");
|
|
606
|
+
i0.ɵɵconditionalCreate(41, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_41_Template, 2, 2, "span");
|
|
607
|
+
i0.ɵɵconditionalCreate(42, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_42_Template, 3, 5, "span", 26);
|
|
608
|
+
i0.ɵɵelementEnd()()();
|
|
609
|
+
i0.ɵɵelementStart(43, "div", 20)(44, "div", 33);
|
|
610
|
+
i0.ɵɵelement(45, "i", 34);
|
|
541
611
|
i0.ɵɵelementEnd();
|
|
542
|
-
i0.ɵɵelementStart(
|
|
543
|
-
i0.ɵɵtext(
|
|
612
|
+
i0.ɵɵelementStart(46, "div", 23)(47, "h3");
|
|
613
|
+
i0.ɵɵtext(48, "Prompt Cache");
|
|
544
614
|
i0.ɵɵelementEnd();
|
|
545
|
-
i0.ɵɵelementStart(
|
|
546
|
-
i0.ɵɵtext(
|
|
615
|
+
i0.ɵɵelementStart(49, "div", 24);
|
|
616
|
+
i0.ɵɵtext(50);
|
|
617
|
+
i0.ɵɵpipe(51, "number");
|
|
618
|
+
i0.ɵɵelementEnd();
|
|
619
|
+
i0.ɵɵelementStart(52, "div", 32)(53, "span");
|
|
620
|
+
i0.ɵɵtext(54, "tokens read from cache");
|
|
621
|
+
i0.ɵɵelementEnd();
|
|
622
|
+
i0.ɵɵconditionalCreate(55, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_55_Template, 3, 3, "span");
|
|
623
|
+
i0.ɵɵconditionalCreate(56, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_56_Template, 3, 4, "span");
|
|
624
|
+
i0.ɵɵelementEnd()()();
|
|
625
|
+
i0.ɵɵelementStart(57, "div", 20)(58, "div", 35);
|
|
626
|
+
i0.ɵɵelement(59, "i", 36);
|
|
547
627
|
i0.ɵɵelementEnd();
|
|
548
|
-
i0.ɵɵelementStart(
|
|
549
|
-
i0.ɵɵtext(
|
|
628
|
+
i0.ɵɵelementStart(60, "div", 23)(61, "h3");
|
|
629
|
+
i0.ɵɵtext(62, "Execution Time");
|
|
630
|
+
i0.ɵɵelementEnd();
|
|
631
|
+
i0.ɵɵelementStart(63, "div", 24);
|
|
632
|
+
i0.ɵɵtext(64);
|
|
633
|
+
i0.ɵɵelementEnd();
|
|
634
|
+
i0.ɵɵelementStart(65, "div", 25)(66, "span");
|
|
635
|
+
i0.ɵɵtext(67);
|
|
550
636
|
i0.ɵɵelementEnd()()()()()();
|
|
551
|
-
i0.ɵɵelementStart(
|
|
552
|
-
i0.ɵɵtemplate(
|
|
553
|
-
i0.ɵɵelementStart(
|
|
554
|
-
i0.ɵɵconditionalCreate(
|
|
555
|
-
i0.ɵɵconditionalCreate(
|
|
556
|
-
i0.ɵɵconditionalCreate(
|
|
557
|
-
i0.ɵɵconditionalCreate(
|
|
558
|
-
i0.ɵɵelementStart(
|
|
559
|
-
i0.ɵɵlistener("click", function
|
|
560
|
-
i0.ɵɵelement(
|
|
561
|
-
i0.ɵɵtext(
|
|
562
|
-
i0.ɵɵelementEnd();
|
|
563
|
-
i0.ɵɵconditionalCreate(
|
|
637
|
+
i0.ɵɵelementStart(68, "mj-accordion-panel", 17);
|
|
638
|
+
i0.ɵɵtemplate(69, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_69_Template, 2, 0, "ng-template", 18);
|
|
639
|
+
i0.ɵɵelementStart(70, "div", 37);
|
|
640
|
+
i0.ɵɵconditionalCreate(71, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_71_Template, 4, 2, "div", 38);
|
|
641
|
+
i0.ɵɵconditionalCreate(72, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_72_Template, 6, 0, "div", 39);
|
|
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);
|
|
644
|
+
i0.ɵɵelementStart(75, "div", 42)(76, "button", 43);
|
|
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); });
|
|
646
|
+
i0.ɵɵelement(77, "i", 44);
|
|
647
|
+
i0.ɵɵtext(78, " Detailed Prompt Metrics ");
|
|
648
|
+
i0.ɵɵelementEnd();
|
|
649
|
+
i0.ɵɵconditionalCreate(79, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_79_Template, 18, 2, "div", 45);
|
|
564
650
|
i0.ɵɵelementEnd()()();
|
|
565
|
-
i0.ɵɵelementStart(
|
|
566
|
-
i0.ɵɵtemplate(
|
|
567
|
-
i0.ɵɵelementStart(
|
|
568
|
-
i0.ɵɵlistener("click", function
|
|
569
|
-
i0.ɵɵelementStart(
|
|
570
|
-
i0.ɵɵelement(
|
|
571
|
-
i0.ɵɵtext(
|
|
572
|
-
i0.ɵɵelementEnd();
|
|
573
|
-
i0.ɵɵelementStart(
|
|
574
|
-
i0.ɵɵelement(
|
|
651
|
+
i0.ɵɵelementStart(80, "mj-accordion-panel", 17);
|
|
652
|
+
i0.ɵɵtemplate(81, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_81_Template, 2, 0, "ng-template", 18);
|
|
653
|
+
i0.ɵɵelementStart(82, "div", 37)(83, "div", 40)(84, "div", 46)(85, "div", 47);
|
|
654
|
+
i0.ɵɵlistener("click", function AIAgentRunAnalyticsComponent_Conditional_3_Template_div_click_85_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleChartExpansion("actionSuccess")); });
|
|
655
|
+
i0.ɵɵelementStart(86, "h3");
|
|
656
|
+
i0.ɵɵelement(87, "i", 48);
|
|
657
|
+
i0.ɵɵtext(88, " Action Success Rate");
|
|
658
|
+
i0.ɵɵelementEnd();
|
|
659
|
+
i0.ɵɵelementStart(89, "button", 49);
|
|
660
|
+
i0.ɵɵelement(90, "i", 50);
|
|
575
661
|
i0.ɵɵelementEnd()();
|
|
576
|
-
i0.ɵɵelementStart(
|
|
577
|
-
i0.ɵɵelement(
|
|
662
|
+
i0.ɵɵelementStart(91, "div", 51)(92, "div", 52);
|
|
663
|
+
i0.ɵɵelement(93, "div", 53, 0);
|
|
578
664
|
i0.ɵɵelementEnd()()();
|
|
579
|
-
i0.ɵɵelementStart(
|
|
580
|
-
i0.ɵɵlistener("click", function
|
|
581
|
-
i0.ɵɵelementStart(
|
|
582
|
-
i0.ɵɵelement(
|
|
583
|
-
i0.ɵɵtext(
|
|
584
|
-
i0.ɵɵelementEnd();
|
|
585
|
-
i0.ɵɵelementStart(
|
|
586
|
-
i0.ɵɵelement(
|
|
665
|
+
i0.ɵɵelementStart(95, "div", 46)(96, "div", 47);
|
|
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")); });
|
|
667
|
+
i0.ɵɵelementStart(97, "h3");
|
|
668
|
+
i0.ɵɵelement(98, "i", 54);
|
|
669
|
+
i0.ɵɵtext(99, " Step Type Distribution");
|
|
670
|
+
i0.ɵɵelementEnd();
|
|
671
|
+
i0.ɵɵelementStart(100, "button", 49);
|
|
672
|
+
i0.ɵɵelement(101, "i", 50);
|
|
587
673
|
i0.ɵɵelementEnd()();
|
|
588
|
-
i0.ɵɵelementStart(
|
|
589
|
-
i0.ɵɵelement(
|
|
674
|
+
i0.ɵɵelementStart(102, "div", 51)(103, "div", 52);
|
|
675
|
+
i0.ɵɵelement(104, "div", 55, 1);
|
|
590
676
|
i0.ɵɵelementEnd()()()();
|
|
591
|
-
i0.ɵɵelementStart(
|
|
592
|
-
i0.ɵɵlistener("click", function
|
|
593
|
-
i0.ɵɵelement(
|
|
594
|
-
i0.ɵɵtext(
|
|
677
|
+
i0.ɵɵelementStart(106, "div", 42)(107, "button", 43);
|
|
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); });
|
|
679
|
+
i0.ɵɵelement(108, "i", 44);
|
|
680
|
+
i0.ɵɵtext(109, " Detailed Action Metrics ");
|
|
595
681
|
i0.ɵɵelementEnd();
|
|
596
|
-
i0.ɵɵconditionalCreate(
|
|
682
|
+
i0.ɵɵconditionalCreate(110, AIAgentRunAnalyticsComponent_Conditional_3_Conditional_110_Template, 18, 2, "div", 45);
|
|
597
683
|
i0.ɵɵelementEnd();
|
|
598
|
-
i0.ɵɵelementStart(
|
|
599
|
-
i0.ɵɵconditionalCreate(
|
|
600
|
-
i0.ɵɵconditionalCreate(
|
|
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);
|
|
601
687
|
i0.ɵɵelementEnd()()();
|
|
602
|
-
i0.ɵɵelementStart(
|
|
603
|
-
i0.ɵɵtemplate(
|
|
604
|
-
i0.ɵɵelementStart(
|
|
605
|
-
i0.ɵɵtext(
|
|
688
|
+
i0.ɵɵelementStart(114, "mj-accordion-panel", 17);
|
|
689
|
+
i0.ɵɵtemplate(115, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_115_Template, 2, 0, "ng-template", 18);
|
|
690
|
+
i0.ɵɵelementStart(116, "div", 37)(117, "div", 59)(118, "table")(119, "thead")(120, "tr")(121, "th");
|
|
691
|
+
i0.ɵɵtext(122, "Model");
|
|
606
692
|
i0.ɵɵelementEnd();
|
|
607
|
-
i0.ɵɵelementStart(
|
|
608
|
-
i0.ɵɵtext(
|
|
693
|
+
i0.ɵɵelementStart(123, "th");
|
|
694
|
+
i0.ɵɵtext(124, "Vendor");
|
|
609
695
|
i0.ɵɵelementEnd();
|
|
610
|
-
i0.ɵɵelementStart(
|
|
611
|
-
i0.ɵɵtext(
|
|
696
|
+
i0.ɵɵelementStart(125, "th");
|
|
697
|
+
i0.ɵɵtext(126, "Prompts");
|
|
612
698
|
i0.ɵɵelementEnd();
|
|
613
|
-
i0.ɵɵelementStart(
|
|
614
|
-
i0.ɵɵtext(
|
|
699
|
+
i0.ɵɵelementStart(127, "th");
|
|
700
|
+
i0.ɵɵtext(128, "Avg Time");
|
|
615
701
|
i0.ɵɵelementEnd();
|
|
616
|
-
i0.ɵɵelementStart(
|
|
617
|
-
i0.ɵɵtext(
|
|
702
|
+
i0.ɵɵelementStart(129, "th");
|
|
703
|
+
i0.ɵɵtext(130, "Total Cost");
|
|
618
704
|
i0.ɵɵelementEnd();
|
|
619
|
-
i0.ɵɵelementStart(
|
|
620
|
-
i0.ɵɵtext(
|
|
705
|
+
i0.ɵɵelementStart(131, "th");
|
|
706
|
+
i0.ɵɵtext(132, "Avg Cost/Prompt");
|
|
621
707
|
i0.ɵɵelementEnd();
|
|
622
|
-
i0.ɵɵelementStart(
|
|
623
|
-
i0.ɵɵtext(
|
|
708
|
+
i0.ɵɵelementStart(133, "th");
|
|
709
|
+
i0.ɵɵtext(134, "Input Tokens");
|
|
624
710
|
i0.ɵɵelementEnd();
|
|
625
|
-
i0.ɵɵelementStart(
|
|
626
|
-
i0.ɵɵtext(
|
|
711
|
+
i0.ɵɵelementStart(135, "th");
|
|
712
|
+
i0.ɵɵtext(136, "Output Tokens");
|
|
627
713
|
i0.ɵɵelementEnd()()();
|
|
628
|
-
i0.ɵɵelementStart(
|
|
629
|
-
i0.ɵɵrepeaterCreate(
|
|
714
|
+
i0.ɵɵelementStart(137, "tbody");
|
|
715
|
+
i0.ɵɵrepeaterCreate(138, AIAgentRunAnalyticsComponent_Conditional_3_For_139_Template, 19, 14, "tr", null, i0.ɵɵcomponentInstance().trackByModelName, true);
|
|
630
716
|
i0.ɵɵelementEnd()()()()();
|
|
631
|
-
i0.ɵɵelementStart(
|
|
632
|
-
i0.ɵɵtemplate(
|
|
633
|
-
i0.ɵɵelementStart(
|
|
634
|
-
i0.ɵɵtext(
|
|
717
|
+
i0.ɵɵelementStart(140, "mj-accordion-panel", 17);
|
|
718
|
+
i0.ɵɵtemplate(141, AIAgentRunAnalyticsComponent_Conditional_3_ng_template_141_Template, 2, 0, "ng-template", 18);
|
|
719
|
+
i0.ɵɵelementStart(142, "div", 37)(143, "div", 60)(144, "div", 61)(145, "span", 62);
|
|
720
|
+
i0.ɵɵtext(146, "Total Steps");
|
|
635
721
|
i0.ɵɵelementEnd();
|
|
636
|
-
i0.ɵɵelementStart(
|
|
637
|
-
i0.ɵɵtext(
|
|
722
|
+
i0.ɵɵelementStart(147, "span", 63);
|
|
723
|
+
i0.ɵɵtext(148);
|
|
638
724
|
i0.ɵɵelementEnd()();
|
|
639
|
-
i0.ɵɵelementStart(
|
|
640
|
-
i0.ɵɵtext(
|
|
725
|
+
i0.ɵɵelementStart(149, "div", 61)(150, "span", 62);
|
|
726
|
+
i0.ɵɵtext(151, "Parallel Executions");
|
|
641
727
|
i0.ɵɵelementEnd();
|
|
642
|
-
i0.ɵɵelementStart(
|
|
643
|
-
i0.ɵɵtext(
|
|
728
|
+
i0.ɵɵelementStart(152, "span", 63);
|
|
729
|
+
i0.ɵɵtext(153);
|
|
644
730
|
i0.ɵɵelementEnd()();
|
|
645
|
-
i0.ɵɵelementStart(
|
|
646
|
-
i0.ɵɵtext(
|
|
731
|
+
i0.ɵɵelementStart(154, "div", 61)(155, "span", 62);
|
|
732
|
+
i0.ɵɵtext(156, "Max Nesting Depth");
|
|
647
733
|
i0.ɵɵelementEnd();
|
|
648
|
-
i0.ɵɵelementStart(
|
|
649
|
-
i0.ɵɵtext(
|
|
734
|
+
i0.ɵɵelementStart(157, "span", 63);
|
|
735
|
+
i0.ɵɵtext(158);
|
|
650
736
|
i0.ɵɵelementEnd()();
|
|
651
|
-
i0.ɵɵelementStart(
|
|
652
|
-
i0.ɵɵtext(
|
|
737
|
+
i0.ɵɵelementStart(159, "div", 61)(160, "span", 62);
|
|
738
|
+
i0.ɵɵtext(161, "Sub-Agent Runs");
|
|
653
739
|
i0.ɵɵelementEnd();
|
|
654
|
-
i0.ɵɵelementStart(
|
|
655
|
-
i0.ɵɵtext(
|
|
740
|
+
i0.ɵɵelementStart(162, "span", 63);
|
|
741
|
+
i0.ɵɵtext(163);
|
|
656
742
|
i0.ɵɵelementEnd()()();
|
|
657
|
-
i0.ɵɵelementStart(
|
|
658
|
-
i0.ɵɵtext(
|
|
743
|
+
i0.ɵɵelementStart(164, "div", 64)(165, "h3");
|
|
744
|
+
i0.ɵɵtext(166, "Steps by Type");
|
|
659
745
|
i0.ɵɵelementEnd();
|
|
660
|
-
i0.ɵɵelementStart(
|
|
661
|
-
i0.ɵɵrepeaterCreate(
|
|
662
|
-
i0.ɵɵpipe(
|
|
746
|
+
i0.ɵɵelementStart(167, "div", 65);
|
|
747
|
+
i0.ɵɵrepeaterCreate(168, AIAgentRunAnalyticsComponent_Conditional_3_For_169_Template, 8, 4, "div", 66, i0.ɵɵcomponentInstance().trackByKey, true);
|
|
748
|
+
i0.ɵɵpipe(170, "keyvalue");
|
|
663
749
|
i0.ɵɵelementEnd()()()()();
|
|
664
750
|
} if (rf & 2) {
|
|
665
751
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
@@ -680,7 +766,19 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
680
766
|
i0.ɵɵadvance(8);
|
|
681
767
|
i0.ɵɵtextInterpolate(ctx_r1.formatCost(ctx_r1.promptMetrics.costBreakdown.totalCost));
|
|
682
768
|
i0.ɵɵadvance(3);
|
|
683
|
-
i0.ɵɵtextInterpolate1("",
|
|
769
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind1(39, 43, ctx_r1.totalTokensProcessed), " tokens");
|
|
770
|
+
i0.ɵɵadvance(2);
|
|
771
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 40 : -1);
|
|
772
|
+
i0.ɵɵadvance();
|
|
773
|
+
i0.ɵɵconditional(ctx_r1.inputCost > 0 || ctx_r1.outputCost > 0 ? 41 : -1);
|
|
774
|
+
i0.ɵɵadvance();
|
|
775
|
+
i0.ɵɵconditional(ctx_r1.cacheSavings > 0 ? 42 : -1);
|
|
776
|
+
i0.ɵɵadvance(8);
|
|
777
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(51, 45, ctx_r1.promptMetrics.tokenUsage.totalCacheRead));
|
|
778
|
+
i0.ɵɵadvance(5);
|
|
779
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 55 : -1);
|
|
780
|
+
i0.ɵɵadvance();
|
|
781
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.tokenUsage.totalCacheRead > 0 || ctx_r1.promptMetrics.tokenUsage.totalCacheWrite > 0 ? 56 : -1);
|
|
684
782
|
i0.ɵɵadvance(8);
|
|
685
783
|
i0.ɵɵtextInterpolate(ctx_r1.formatDuration(ctx_r1.promptMetrics.totalExecutionTime + ctx_r1.actionMetrics.totalExecutionTime));
|
|
686
784
|
i0.ɵɵadvance(3);
|
|
@@ -688,35 +786,39 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
688
786
|
i0.ɵɵadvance();
|
|
689
787
|
i0.ɵɵproperty("Expanded", true);
|
|
690
788
|
i0.ɵɵadvance(3);
|
|
691
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ?
|
|
789
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 71 : -1);
|
|
692
790
|
i0.ɵɵadvance();
|
|
693
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ?
|
|
791
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount === 0 ? 72 : -1);
|
|
694
792
|
i0.ɵɵadvance();
|
|
695
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ?
|
|
793
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 73 : -1);
|
|
696
794
|
i0.ɵɵadvance();
|
|
697
|
-
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ?
|
|
795
|
+
i0.ɵɵconditional(ctx_r1.promptMetrics.totalCount > 0 ? 74 : -1);
|
|
698
796
|
i0.ɵɵadvance(3);
|
|
699
797
|
i0.ɵɵproperty("ngClass", ctx_r1.promptDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
|
|
700
798
|
i0.ɵɵadvance(2);
|
|
701
|
-
i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ?
|
|
799
|
+
i0.ɵɵconditional(ctx_r1.promptDetailsExpanded ? 79 : -1);
|
|
702
800
|
i0.ɵɵadvance();
|
|
703
801
|
i0.ɵɵproperty("Expanded", true);
|
|
704
802
|
i0.ɵɵadvance(4);
|
|
705
803
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["actionSuccess"]);
|
|
706
|
-
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();
|
|
707
807
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["actionSuccess"] ? "fa-compress" : "fa-expand");
|
|
708
808
|
i0.ɵɵadvance(5);
|
|
709
809
|
i0.ɵɵclassProp("expanded", ctx_r1.expandedCharts["stepType"]);
|
|
710
|
-
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();
|
|
711
813
|
i0.ɵɵproperty("ngClass", ctx_r1.expandedCharts["stepType"] ? "fa-compress" : "fa-expand");
|
|
712
814
|
i0.ɵɵadvance(7);
|
|
713
815
|
i0.ɵɵproperty("ngClass", ctx_r1.actionDetailsExpanded ? "fa-chevron-up" : "fa-chevron-down");
|
|
714
816
|
i0.ɵɵadvance(2);
|
|
715
|
-
i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ?
|
|
817
|
+
i0.ɵɵconditional(ctx_r1.actionDetailsExpanded ? 110 : -1);
|
|
716
818
|
i0.ɵɵadvance(2);
|
|
717
|
-
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ?
|
|
819
|
+
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size > 0 ? 112 : -1);
|
|
718
820
|
i0.ɵɵadvance();
|
|
719
|
-
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ?
|
|
821
|
+
i0.ɵɵconditional(ctx_r1.actionMetrics.errorAnalysis.size === 0 ? 113 : -1);
|
|
720
822
|
i0.ɵɵadvance();
|
|
721
823
|
i0.ɵɵproperty("Expanded", true);
|
|
722
824
|
i0.ɵɵadvance(24);
|
|
@@ -732,7 +834,7 @@ function AIAgentRunAnalyticsComponent_Conditional_3_Template(rf, ctx) { if (rf &
|
|
|
732
834
|
i0.ɵɵadvance(5);
|
|
733
835
|
i0.ɵɵtextInterpolate(ctx_r1.subAgentRuns.length);
|
|
734
836
|
i0.ɵɵadvance(5);
|
|
735
|
-
i0.ɵɵrepeater(i0.ɵɵpipeBind1(
|
|
837
|
+
i0.ɵɵrepeater(i0.ɵɵpipeBind1(170, 47, ctx_r1.timelineMetrics.stepsByType));
|
|
736
838
|
} }
|
|
737
839
|
export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
738
840
|
/** Helper method to create tracked setTimeout calls */
|
|
@@ -752,6 +854,9 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
752
854
|
this.activeTimeouts.splice(index, 1);
|
|
753
855
|
}
|
|
754
856
|
}
|
|
857
|
+
static { this.UNIT_DIVISORS = {
|
|
858
|
+
'Per Million Tokens': 1_000_000, 'Per Hundred Thousand Tokens': 100_000, 'Per Thousand Tokens': 1_000
|
|
859
|
+
}; }
|
|
755
860
|
constructor(cdr, costService) {
|
|
756
861
|
super();
|
|
757
862
|
this.cdr = cdr;
|
|
@@ -779,6 +884,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
779
884
|
// Data
|
|
780
885
|
this.agentRun = null;
|
|
781
886
|
this.allPromptRuns = [];
|
|
887
|
+
// Per model+vendor cache pricing (currency-per-token), loaded from AIModelCost for the cost split.
|
|
888
|
+
this.cacheRates = new Map();
|
|
782
889
|
this.allActionLogs = [];
|
|
783
890
|
this.allSteps = [];
|
|
784
891
|
this.subAgentRuns = [];
|
|
@@ -942,6 +1049,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
942
1049
|
}
|
|
943
1050
|
// Load all prompt runs for the agent run hierarchy
|
|
944
1051
|
this.allPromptRuns = await this.loadAllPromptRuns(agentRunIds);
|
|
1052
|
+
// Load cache pricing so cost can be split (input/output) and cache savings computed
|
|
1053
|
+
await this.loadCacheRates();
|
|
945
1054
|
if (results[2].Success) {
|
|
946
1055
|
const actionSteps = results[2].Results || [];
|
|
947
1056
|
// Now load the actual action logs
|
|
@@ -973,8 +1082,8 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
973
1082
|
byVendor: new Map(),
|
|
974
1083
|
byPrompt: new Map(),
|
|
975
1084
|
statusBreakdown: { success: 0, failed: 0, timeout: 0 },
|
|
976
|
-
costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map() },
|
|
977
|
-
tokenUsage: { totalInput: 0, totalOutput: 0, byModel: new Map() }
|
|
1085
|
+
costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map(), inputCost: 0, outputCost: 0, savings: 0, unratedCost: 0 },
|
|
1086
|
+
tokenUsage: { totalInput: 0, totalOutput: 0, totalCacheRead: 0, totalCacheWrite: 0, byModel: new Map() }
|
|
978
1087
|
};
|
|
979
1088
|
}
|
|
980
1089
|
initializeActionMetrics() {
|
|
@@ -997,6 +1106,33 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
997
1106
|
criticalPath: { steps: [], totalTime: 0 }
|
|
998
1107
|
};
|
|
999
1108
|
}
|
|
1109
|
+
/** Stable rate-map key for a model+vendor pair. */
|
|
1110
|
+
rateKey(modelID, vendorID) {
|
|
1111
|
+
return `${NormalizeUUID(modelID ?? '')}|${NormalizeUUID(vendorID ?? '')}`;
|
|
1112
|
+
}
|
|
1113
|
+
/** Load active realtime AIModelCost rates and normalize each to currency-per-token. */
|
|
1114
|
+
async loadCacheRates() {
|
|
1115
|
+
this.cacheRates.clear();
|
|
1116
|
+
const rv = RunView.FromMetadataProvider(this.ProviderToUse);
|
|
1117
|
+
const res = await rv.RunView({
|
|
1118
|
+
EntityName: 'MJ: AI Model Costs',
|
|
1119
|
+
ExtraFilter: `Status='Active' AND ProcessingType='Realtime'`,
|
|
1120
|
+
Fields: ['ModelID', 'VendorID', 'InputPricePerUnit', 'OutputPricePerUnit', 'CacheReadPricePerUnit', 'CacheWritePricePerUnit', 'UnitType'],
|
|
1121
|
+
ResultType: 'simple'
|
|
1122
|
+
});
|
|
1123
|
+
if (!res.Success)
|
|
1124
|
+
return;
|
|
1125
|
+
for (const row of res.Results || []) {
|
|
1126
|
+
const divisor = AIAgentRunAnalyticsComponent.UNIT_DIVISORS[row.UnitType ?? ''] ?? 1_000_000;
|
|
1127
|
+
const input = (row.InputPricePerUnit ?? 0) / divisor;
|
|
1128
|
+
this.cacheRates.set(this.rateKey(row.ModelID, row.VendorID), {
|
|
1129
|
+
inputRate: input,
|
|
1130
|
+
outputRate: (row.OutputPricePerUnit ?? 0) / divisor,
|
|
1131
|
+
cacheReadRate: (row.CacheReadPricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor,
|
|
1132
|
+
cacheWriteRate: (row.CacheWritePricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1000
1136
|
calculatePromptMetrics() {
|
|
1001
1137
|
const metrics = this.initializePromptMetrics();
|
|
1002
1138
|
for (const promptRun of this.allPromptRuns) {
|
|
@@ -1047,6 +1183,24 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
1047
1183
|
const outputTokens = promptRun.TokensCompletion || 0;
|
|
1048
1184
|
metrics.tokenUsage.totalInput += inputTokens;
|
|
1049
1185
|
metrics.tokenUsage.totalOutput += outputTokens;
|
|
1186
|
+
// Provider prompt-cache tokens (read = cache hits, write = cache creation). Summed from the
|
|
1187
|
+
// child prompt runs' persisted TokensCacheRead/TokensCacheWrite columns.
|
|
1188
|
+
const cacheReadTokens = promptRun.TokensCacheRead || 0;
|
|
1189
|
+
const cacheWriteTokens = promptRun.TokensCacheWrite || 0;
|
|
1190
|
+
metrics.tokenUsage.totalCacheRead += cacheReadTokens;
|
|
1191
|
+
metrics.tokenUsage.totalCacheWrite += cacheWriteTokens;
|
|
1192
|
+
// Rate-derived cost split + cache savings. inputCost folds uncached + cache read + cache write
|
|
1193
|
+
// (each at its own rate); savings = the discount vs. pricing all input at the full input rate.
|
|
1194
|
+
// Runs whose model+vendor has no rate row are tracked separately so the split isn't silently off.
|
|
1195
|
+
const rate = this.cacheRates.get(this.rateKey(promptRun.ModelID, promptRun.VendorID));
|
|
1196
|
+
if (rate) {
|
|
1197
|
+
metrics.costBreakdown.inputCost += inputTokens * rate.inputRate + cacheReadTokens * rate.cacheReadRate + cacheWriteTokens * rate.cacheWriteRate;
|
|
1198
|
+
metrics.costBreakdown.outputCost += outputTokens * rate.outputRate;
|
|
1199
|
+
metrics.costBreakdown.savings += cacheReadTokens * (rate.inputRate - rate.cacheReadRate) + cacheWriteTokens * (rate.inputRate - rate.cacheWriteRate);
|
|
1200
|
+
}
|
|
1201
|
+
else {
|
|
1202
|
+
metrics.costBreakdown.unratedCost += cost;
|
|
1203
|
+
}
|
|
1050
1204
|
const modelTokens = metrics.tokenUsage.byModel.get(model) || { input: 0, output: 0 };
|
|
1051
1205
|
modelTokens.input += inputTokens;
|
|
1052
1206
|
modelTokens.output += outputTokens;
|
|
@@ -1229,6 +1383,29 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
1229
1383
|
return `$${cost.toFixed(3)}`;
|
|
1230
1384
|
return `$${cost.toFixed(2)}`;
|
|
1231
1385
|
}
|
|
1386
|
+
/** Total tokens the models processed across this run, including cached input (true throughput). */
|
|
1387
|
+
get totalTokensProcessed() {
|
|
1388
|
+
const u = this.promptMetrics.tokenUsage;
|
|
1389
|
+
return u.totalInput + u.totalOutput + u.totalCacheRead + u.totalCacheWrite;
|
|
1390
|
+
}
|
|
1391
|
+
/** Rate-derived input-side dollars (uncached + cache read + cache write). */
|
|
1392
|
+
get inputCost() { return this.promptMetrics.costBreakdown.inputCost; }
|
|
1393
|
+
/** Rate-derived output dollars. */
|
|
1394
|
+
get outputCost() { return this.promptMetrics.costBreakdown.outputCost; }
|
|
1395
|
+
/** Net dollars saved by caching vs. pricing all input at the full input rate. */
|
|
1396
|
+
get cacheSavings() { return this.promptMetrics.costBreakdown.savings; }
|
|
1397
|
+
/** Savings as a % of what the run would have cost with no caching. */
|
|
1398
|
+
get cacheSavingsPct() {
|
|
1399
|
+
const cb = this.promptMetrics.costBreakdown;
|
|
1400
|
+
const fullPrice = cb.totalCost + cb.savings;
|
|
1401
|
+
return fullPrice > 0 ? (cb.savings / fullPrice) * 100 : 0;
|
|
1402
|
+
}
|
|
1403
|
+
/** Percentage of input tokens served from the provider's prompt cache across this agent run. */
|
|
1404
|
+
get cacheHitRatePct() {
|
|
1405
|
+
const u = this.promptMetrics.tokenUsage;
|
|
1406
|
+
const totalInput = u.totalInput + u.totalCacheRead + u.totalCacheWrite;
|
|
1407
|
+
return totalInput > 0 ? (u.totalCacheRead / totalInput) * 100 : 0;
|
|
1408
|
+
}
|
|
1232
1409
|
refresh() {
|
|
1233
1410
|
this.loadData();
|
|
1234
1411
|
}
|
|
@@ -2130,11 +2307,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2130
2307
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptTokenDistributionChart = _t.first);
|
|
2131
2308
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCostDistributionChart = _t.first);
|
|
2132
2309
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.promptCountByNameChart = _t.first);
|
|
2133
|
-
} }, inputs: { agentRunId: "agentRunId" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 3, consts: [["actionSuccessRateChart", ""], ["stepTypeChart", ""], ["modelDistributionChart", ""], ["executionTimeChart", ""], ["costByVendorChart", ""], ["tokenUsageChart", ""], ["promptTimeDistributionChart", ""], ["promptTokenDistributionChart", ""], ["promptCostDistributionChart", ""], ["promptCountByNameChart", ""], [1, "analytics-container"], [1, "loading-state"], [1, "error-state"], [1, "analytics-content"], [1, "fas", "fa-spinner", "fa-spin", "fa-2x"], [1, "fas", "fa-exclamation-triangle", "fa-2x"], ["mjButton", "", 3, "click"], [3, "Expanded"], ["mjAccordionTitle", ""], [1, "summary-cards"], [1, "summary-card"], [1, "card-icon", "prompts"], [1, "fas", "fa-microchip"], [1, "card-content"], [1, "metric-value"], [1, "metric-detail"], [1, "success"], [1, "failed"], [1, "card-icon", "actions"], [1, "fas", "fa-cog"], [1, "card-icon", "cost"], [1, "fas", "fa-dollar-sign"], [1, "card-icon", "time"], [1, "fas", "fa-clock"], [1, "analytics-panel"], [1, "view-mode-toggle"], [1, "no-data-message"], [1, "charts-grid"], [1, "charts-grid", 2, "margin-top", "20px"], [1, "detailed-metrics"], ["mjButton", "", "variant", "flat", 3, "click"], [1, "fas", 3, "ngClass"], [1, "metrics-table"], [1, "chart-card"], [1, "chart-card-header", 3, "click"], [1, "fas", "fa-chart-bar"], [1, "expand-btn"], [1, "chart-card-body"], [1, "chart-container"], ["id", "actionSuccessRateChart"], [1, "fas", "fa-layer-group"], ["id", "stepTypeChart"], [1, "error-analysis-section"], [1, "error-analysis"], [1, "no-errors"], [1, "model-comparison"], [1, "timeline-stats"], [1, "stat-item"], [1, "stat-label"], [1, "stat-value"], [1, "step-breakdown"], [1, "step-type-list"], [1, "step-type-item"], [1, "fas", "fa-tachometer-alt"], [1, "fas", "fa-info-circle"], [1, "small"], [1, "fas", "fa-chart-pie"], ["id", "modelDistributionChart"], [1, "chart-legend"], ["id", "executionTimeChart"], ["id", "costByVendorChart"], [1, "chart-total"], [1, "fas", "fa-coins"], ["id", "tokenUsageChart"], [1, "legend-item"], [1, "legend-color"], [1, "legend-label"], [1, "fas", "fa-hourglass-half"], ["id", "promptTimeDistributionChart"], [1, "fas", "fa-database"], ["id", "promptTokenDistributionChart"], ["id", "promptCostDistributionChart"], [1, "fas", "fa-list-ol"], ["id", "promptCountByNameChart"], [1, "success-rate"], [1, "fas", "fa-exclamation-triangle"], [1, "error-analysis-description"], [1, "error-list"], [1, "error-item"], [1, "error-count"], [1, "error-message"], [1, "fas", "fa-check-circle"], [1, "fas", "fa-chart-line"], [1, "fas", "fa-stream"], [1, "type-name"], [1, "type-count"], [1, "type-percentage"]], template: function AIAgentRunAnalyticsComponent_Template(rf, ctx) { if (rf & 1) {
|
|
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) {
|
|
2134
2311
|
i0.ɵɵelementStart(0, "div", 10);
|
|
2135
2312
|
i0.ɵɵconditionalCreate(1, AIAgentRunAnalyticsComponent_Conditional_1_Template, 4, 0, "div", 11);
|
|
2136
2313
|
i0.ɵɵconditionalCreate(2, AIAgentRunAnalyticsComponent_Conditional_2_Template, 6, 1, "div", 12);
|
|
2137
|
-
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template,
|
|
2314
|
+
i0.ɵɵconditionalCreate(3, AIAgentRunAnalyticsComponent_Conditional_3_Template, 171, 49, "div", 13);
|
|
2138
2315
|
i0.ɵɵelementEnd();
|
|
2139
2316
|
} if (rf & 2) {
|
|
2140
2317
|
i0.ɵɵadvance();
|
|
@@ -2143,11 +2320,11 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2143
2320
|
i0.ɵɵconditional(ctx.error && !ctx.isLoading ? 2 : -1);
|
|
2144
2321
|
i0.ɵɵadvance();
|
|
2145
2322
|
i0.ɵɵconditional(!ctx.isLoading && !ctx.error ? 3 : -1);
|
|
2146
|
-
} }, dependencies: [i2.NgClass, i3.MJButtonDirective, i3.MJAccordionPanelComponent, i3.MJAccordionTitleDirective, i2.DecimalPipe, i2.KeyValuePipe], styles: [".analytics-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.summary-cards[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.card-icon.time[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n}\n\n.card-content[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail[_ngcontent-%COMP%] .success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail[_ngcontent-%COMP%] .failed[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.analytics-panel[_ngcontent-%COMP%] {\n padding: 15px;\n}\n\n\n\n.analytics-content[_ngcontent-%COMP%] mj-accordion-panel[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 12px;\n}\n\n\n\n.charts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n\n\n.chart-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.chart-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-card-body[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 400px;\n}\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.chart-container[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n\n\n.chart-container[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total[_ngcontent-%COMP%] {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n\n.detailed-metrics[_ngcontent-%COMP%] {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.metrics-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.metrics-table[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.success-rate.high[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.error-analysis[_ngcontent-%COMP%] {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message[_ngcontent-%COMP%] {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n\n\n.no-errors[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.no-data-message[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.no-data-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\n}\n\n.no-data-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message[_ngcontent-%COMP%] p.small[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.model-comparison[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.model-comparison[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n\n\n.timeline-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count[_ngcontent-%COMP%] {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n\n\n@media (max-width: 768px) {\n .summary-cards[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .charts-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}"], changeDetection: 0 }); }
|
|
2323
|
+
} }, dependencies: [i2.NgClass, i3.MJButtonDirective, i3.MJAccordionPanelComponent, i3.MJAccordionTitleDirective, i2.DecimalPipe, i2.KeyValuePipe], styles: [".analytics-container[_ngcontent-%COMP%] {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n\n\n.loading-state[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%], \n.error-state[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.error-state[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.summary-cards[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card[_ngcontent-%COMP%]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon[_ngcontent-%COMP%] {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n}\n\n.card-icon.time[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n}\n\n.card-icon.cache[_ngcontent-%COMP%] {\n background: var(--mj-status-info);\n}\n\n.card-content[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value[_ngcontent-%COMP%] {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail[_ngcontent-%COMP%] .success[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail[_ngcontent-%COMP%] .failed[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.metric-detail.cache-detail[_ngcontent-%COMP%] span[_ngcontent-%COMP%] {\n display: block;\n}\n\n\n\n.analytics-panel[_ngcontent-%COMP%] {\n padding: 15px;\n}\n\n\n\n.analytics-content[_ngcontent-%COMP%] mj-accordion-panel[_ngcontent-%COMP%] {\n display: block;\n margin-bottom: 12px;\n}\n\n\n\n.charts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n\n\n.chart-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] {\n grid-column: 1 / -1;\n}\n\n.chart-card-header[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn[_ngcontent-%COMP%] {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn[_ngcontent-%COMP%]:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body[_ngcontent-%COMP%] {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-card-body[_ngcontent-%COMP%] {\n padding: 24px;\n}\n\n.chart-card.expanded[_ngcontent-%COMP%] .chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 400px;\n}\n\n\n\n.view-mode-toggle[_ngcontent-%COMP%] {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container[_ngcontent-%COMP%] {\n position: relative;\n}\n\n.chart-container[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n\n\n.chart-container[_ngcontent-%COMP%] svg[_ngcontent-%COMP%] {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend[_ngcontent-%COMP%] {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color[_ngcontent-%COMP%] {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total[_ngcontent-%COMP%] {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n\n\n.detailed-metrics[_ngcontent-%COMP%] {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n margin-bottom: 15px;\n}\n\n.detailed-metrics[_ngcontent-%COMP%] button[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n margin-right: 8px;\n}\n\n.metrics-table[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.metrics-table[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate[_ngcontent-%COMP%] {\n font-weight: 500;\n}\n\n.success-rate.high[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n}\n\n\n\n.error-analysis[_ngcontent-%COMP%] {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count[_ngcontent-%COMP%] {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message[_ngcontent-%COMP%] {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n\n\n.no-errors[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 24px;\n color: var(--mj-status-success);\n}\n\n.no-errors[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 14px;\n}\n\n\n\n.no-data-message[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.no-data-message[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\n}\n\n.no-data-message[_ngcontent-%COMP%] p[_ngcontent-%COMP%] {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message[_ngcontent-%COMP%] p.small[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n\n\n.model-comparison[_ngcontent-%COMP%] {\n overflow-x: auto;\n}\n\n.model-comparison[_ngcontent-%COMP%] table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n\n\n.timeline-stats[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label[_ngcontent-%COMP%] {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value[_ngcontent-%COMP%] {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name[_ngcontent-%COMP%] {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count[_ngcontent-%COMP%] {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n\n\n@media (max-width: 768px) {\n .summary-cards[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .charts-grid[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n}"], changeDetection: 0 }); }
|
|
2147
2324
|
}
|
|
2148
2325
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AIAgentRunAnalyticsComponent, [{
|
|
2149
2326
|
type: Component,
|
|
2150
|
-
args: [{ standalone: false, selector: 'mj-ai-agent-run-analytics', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"analytics-container\">\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-state\">\n <i class=\"fas fa-spinner fa-spin fa-2x\"></i>\n <p>Loading analytics data...</p>\n </div>\n }\n\n <!-- Error State -->\n @if (error && !isLoading) {\n <div class=\"error-state\">\n <i class=\"fas fa-exclamation-triangle fa-2x\"></i>\n <p>{{ error }}</p>\n <button mjButton (click)=\"loadData()\">Retry</button>\n </div>\n }\n\n <!-- Analytics Content -->\n @if (!isLoading && !error) {\n <div class=\"analytics-content\">\n <!-- Summary Cards -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-tachometer-alt\"></i> Overview\n </ng-template>\n <div class=\"summary-cards\">\n <div class=\"summary-card\">\n <div class=\"card-icon prompts\">\n <i class=\"fas fa-microchip\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Prompts</h3>\n <div class=\"metric-value\">{{ promptMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ promptMetrics.statusBreakdown.success }} successful</span>\n @if (promptMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ promptMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon actions\">\n <i class=\"fas fa-cog\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Actions</h3>\n <div class=\"metric-value\">{{ actionMetrics.totalCount }}</div>\n <div class=\"metric-detail\">\n <span class=\"success\">{{ actionMetrics.statusBreakdown.success }} successful</span>\n @if (actionMetrics.statusBreakdown.failed > 0) {\n <span class=\"failed\">{{ actionMetrics.statusBreakdown.failed }} failed</span>\n }\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon cost\">\n <i class=\"fas fa-dollar-sign\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Total Cost</h3>\n <div class=\"metric-value\">{{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n <div class=\"metric-detail\">\n <span>{{ promptMetrics.tokenUsage.totalInput + promptMetrics.tokenUsage.totalOutput }} tokens</span>\n </div>\n </div>\n </div>\n <div class=\"summary-card\">\n <div class=\"card-icon time\">\n <i class=\"fas fa-clock\"></i>\n </div>\n <div class=\"card-content\">\n <h3>Execution Time</h3>\n <div class=\"metric-value\">{{ formatDuration(promptMetrics.totalExecutionTime + actionMetrics.totalExecutionTime) }}</div>\n <div class=\"metric-detail\">\n <span>{{ timelineMetrics.totalSteps }} total steps</span>\n </div>\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Prompt Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-microchip\"></i> Prompt Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <!-- View Mode Toggle -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"view-mode-toggle\">\n <button mjButton\n variant=\"flat\"\n (click)=\"toggleViewMode()\">\n <i class=\"fas\" [ngClass]=\"viewMode === 'grid' ? 'fa-expand-arrows-alt' : 'fa-compress-arrows-alt'\"></i>\n {{ viewMode === 'grid' ? 'Expand All' : 'Collapse All' }}\n </button>\n </div>\n }\n <!-- No prompts message -->\n @if (promptMetrics.totalCount === 0) {\n <div class=\"no-data-message\">\n <i class=\"fas fa-info-circle\"></i>\n <p>No prompt executions found in this agent run.</p>\n <p class=\"small\">This agent run may have only executed actions without any AI prompts.</p>\n </div>\n }\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\">\n <!-- Model Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['modelDistribution']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('modelDistribution')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Prompts by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['modelDistribution'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"modelDistributionChart\" #modelDistributionChart></div>\n @if (promptMetrics.byModel.size > 0) {\n <div class=\"chart-legend\">\n @for (item of promptMetrics.byModel | keyvalue; track trackByKey($index, item)) {\n <div class=\"legend-item\">\n <span class=\"legend-color\" [style.backgroundColor]=\"getModelColor(item.key)\"></span>\n <span class=\"legend-label\">{{ item.key }}: {{ item.value.count }} ({{ (item.value.count / promptMetrics.totalCount * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Execution Time by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['executionTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('executionTime')\">\n <h3><i class=\"fas fa-clock\"></i> Average Execution Time by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['executionTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"executionTimeChart\" #executionTimeChart></div>\n </div>\n </div>\n </div>\n <!-- Cost by Vendor -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['costByVendor']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('costByVendor')\">\n <h3><i class=\"fas fa-dollar-sign\"></i> Cost Distribution by Vendor</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['costByVendor'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"costByVendorChart\" #costByVendorChart></div>\n <div class=\"chart-total\">Total: {{ formatCost(promptMetrics.costBreakdown.totalCost) }}</div>\n </div>\n </div>\n </div>\n <!-- Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['tokenUsage']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('tokenUsage')\">\n <h3><i class=\"fas fa-coins\"></i> Token Usage by Model</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['tokenUsage'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"tokenUsageChart\" #tokenUsageChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Additional Prompt Analytics Charts -->\n @if (promptMetrics.totalCount > 0) {\n <div class=\"charts-grid\" style=\"margin-top: 20px;\">\n <!-- Prompt Execution Time Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptTime']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptTime')\">\n <h3><i class=\"fas fa-hourglass-half\"></i> Average Execution Time by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptTime'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTimeDistributionChart\" #promptTimeDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Token Usage -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptToken']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptToken')\">\n <h3><i class=\"fas fa-database\"></i> Token Usage by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptToken'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptTokenDistributionChart\" #promptTokenDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Cost Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCost']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCost')\">\n <h3><i class=\"fas fa-chart-pie\"></i> Cost Distribution by Prompt</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCost'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCostDistributionChart\" #promptCostDistributionChart></div>\n </div>\n </div>\n </div>\n <!-- Prompt Count by Name -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['promptCount']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('promptCount')\">\n <h3><i class=\"fas fa-list-ol\"></i> Prompt Execution Count</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['promptCount'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"promptCountByNameChart\" #promptCountByNameChart></div>\n </div>\n </div>\n </div>\n </div>\n }\n <!-- Detailed Prompt Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"promptDetailsExpanded = !promptDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"promptDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Prompt Metrics\n </button>\n @if (promptDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Prompt Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Total Time</th>\n <th>Success Rate</th>\n </tr>\n </thead>\n <tbody>\n @for (prompt of promptMetrics.byPrompt | keyvalue; track trackByKey($index, prompt)) {\n <tr>\n <td>{{ prompt.key }}</td>\n <td>{{ prompt.value.count }}</td>\n <td>{{ formatDuration(prompt.value.avgTime) }}</td>\n <td>{{ formatDuration(prompt.value.totalTime) }}</td>\n <td>\n <span class=\"success-rate\">\n <!-- Calculate success rate for this prompt -->\n {{ calculatePromptSuccessRate(prompt.key) }}%\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Action Analytics -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-cog\"></i> Action Analytics\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"charts-grid\">\n <!-- Action Success Rate -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['actionSuccess']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('actionSuccess')\">\n <h3><i class=\"fas fa-chart-bar\"></i> Action Success Rate</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['actionSuccess'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"actionSuccessRateChart\" #actionSuccessRateChart></div>\n </div>\n </div>\n </div>\n <!-- Step Type Distribution -->\n <div class=\"chart-card\" [class.expanded]=\"expandedCharts['stepType']\">\n <div class=\"chart-card-header\" (click)=\"toggleChartExpansion('stepType')\">\n <h3><i class=\"fas fa-layer-group\"></i> Step Type Distribution</h3>\n <button class=\"expand-btn\">\n <i class=\"fas\" [ngClass]=\"expandedCharts['stepType'] ? 'fa-compress' : 'fa-expand'\"></i>\n </button>\n </div>\n <div class=\"chart-card-body\">\n <div class=\"chart-container\">\n <div id=\"stepTypeChart\" #stepTypeChart></div>\n </div>\n </div>\n </div>\n </div>\n <!-- Detailed Action Metrics -->\n <div class=\"detailed-metrics\">\n <button mjButton\n variant=\"flat\"\n (click)=\"actionDetailsExpanded = !actionDetailsExpanded\">\n <i class=\"fas\" [ngClass]=\"actionDetailsExpanded ? 'fa-chevron-up' : 'fa-chevron-down'\"></i>\n Detailed Action Metrics\n </button>\n @if (actionDetailsExpanded) {\n <div class=\"metrics-table\">\n <table>\n <thead>\n <tr>\n <th>Action Name</th>\n <th>Count</th>\n <th>Avg Time</th>\n <th>Success Rate</th>\n <th>Type</th>\n </tr>\n </thead>\n <tbody>\n @for (action of actionMetrics.byAction | keyvalue; track trackByKey($index, action)) {\n <tr>\n <td>{{ action.key }}</td>\n <td>{{ action.value.count }}</td>\n <td>{{ formatDuration(action.value.avgTime) }}</td>\n <td>\n <span class=\"success-rate\" [class.high]=\"action.value.successRate > 0.9\"\n [class.medium]=\"action.value.successRate > 0.7 && action.value.successRate <= 0.9\"\n [class.low]=\"action.value.successRate <= 0.7\">\n {{ (action.value.successRate * 100).toFixed(1) }}%\n </span>\n </td>\n <td>{{ getActionType(action.key) }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n <!-- Error Analysis -->\n <div class=\"error-analysis-section\">\n @if (actionMetrics.errorAnalysis.size > 0) {\n <div class=\"error-analysis\">\n <h3>\n <i class=\"fas fa-exclamation-triangle\"></i>\n Common Errors\n </h3>\n <p class=\"error-analysis-description\">\n This section shows the most frequent error messages from failed actions, helping identify systemic issues that may need attention.\n </p>\n <div class=\"error-list\">\n @for (error of getTopErrors(); track trackByErrorMessage($index, error)) {\n <div class=\"error-item\">\n <span class=\"error-count\">{{ error.count }}x</span>\n <span class=\"error-message\">{{ error.message }}</span>\n </div>\n }\n </div>\n </div>\n }\n @if (actionMetrics.errorAnalysis.size === 0) {\n <div class=\"no-errors\">\n <i class=\"fas fa-check-circle\"></i>\n <p>No action errors detected in this run. All actions completed successfully!</p>\n </div>\n }\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Model Performance Comparison -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-chart-line\"></i> Model Performance Comparison\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"model-comparison\">\n <table>\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th>Prompts</th>\n <th>Avg Time</th>\n <th>Total Cost</th>\n <th>Avg Cost/Prompt</th>\n <th>Input Tokens</th>\n <th>Output Tokens</th>\n </tr>\n </thead>\n <tbody>\n @for (model of getModelPerformanceData(); track trackByModelName($index, model)) {\n <tr>\n <td>{{ model.name }}</td>\n <td>{{ model.vendor }}</td>\n <td>{{ model.count }}</td>\n <td>{{ formatDuration(model.avgTime) }}</td>\n <td>{{ formatCost(model.totalCost) }}</td>\n <td>{{ formatCost(model.avgCost) }}</td>\n <td>{{ model.inputTokens | number:'1.0-0' }}</td>\n <td>{{ model.outputTokens | number:'1.0-0' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n </mj-accordion-panel>\n <!-- Timeline Analysis -->\n <mj-accordion-panel [Expanded]=\"true\">\n <ng-template mjAccordionTitle>\n <i class=\"fas fa-stream\"></i> Execution Timeline Analysis\n </ng-template>\n <div class=\"analytics-panel\">\n <div class=\"timeline-stats\">\n <div class=\"stat-item\">\n <span class=\"stat-label\">Total Steps</span>\n <span class=\"stat-value\">{{ timelineMetrics.totalSteps }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Parallel Executions</span>\n <span class=\"stat-value\">{{ timelineMetrics.parallelExecutions }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Max Nesting Depth</span>\n <span class=\"stat-value\">{{ timelineMetrics.deepestNesting }}</span>\n </div>\n <div class=\"stat-item\">\n <span class=\"stat-label\">Sub-Agent Runs</span>\n <span class=\"stat-value\">{{ subAgentRuns.length }}</span>\n </div>\n </div>\n <div class=\"step-breakdown\">\n <h3>Steps by Type</h3>\n <div class=\"step-type-list\">\n @for (type of timelineMetrics.stepsByType | keyvalue; track trackByKey($index, type)) {\n <div class=\"step-type-item\">\n <i class=\"fas\" [ngClass]=\"getStepTypeIcon(type.key)\"></i>\n <span class=\"type-name\">{{ type.key }}</span>\n <span class=\"type-count\">{{ type.value }}</span>\n <span class=\"type-percentage\">({{ (type.value / timelineMetrics.totalSteps * 100).toFixed(1) }}%)</span>\n </div>\n }\n </div>\n </div>\n </div>\n </mj-accordion-panel>\n </div>\n }\n</div>", styles: [".analytics-container {\n padding: 20px;\n height: 100%;\n overflow-y: auto;\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Loading and Error States */\n.loading-state,\n.error-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 300px;\n color: var(--mj-text-muted);\n}\n\n.loading-state i,\n.error-state i {\n margin-bottom: 15px;\n}\n\n.error-state {\n color: var(--mj-status-error);\n}\n\n/* Summary Cards */\n.summary-cards {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.summary-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n padding: 20px;\n box-shadow: var(--mj-shadow-sm);\n display: flex;\n align-items: center;\n transition: transform 0.2s, box-shadow 0.2s;\n}\n\n.summary-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);\n}\n\n.card-icon {\n width: 60px;\n height: 60px;\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin-right: 20px;\n font-size: 24px;\n color: var(--mj-text-inverse);\n}\n\n.card-icon.prompts {\n background: var(--mj-brand-primary);\n}\n\n.card-icon.actions {\n background: var(--mj-status-error);\n}\n\n.card-icon.cost {\n background: var(--mj-status-success);\n}\n\n.card-icon.time {\n background: var(--mj-status-warning);\n}\n\n.card-content h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n}\n\n.metric-value {\n font-size: 28px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.metric-detail {\n font-size: 13px;\n color: var(--mj-text-muted);\n}\n\n.metric-detail .success {\n color: var(--mj-status-success);\n margin-right: 10px;\n}\n\n.metric-detail .failed {\n color: var(--mj-status-error);\n}\n\n/* Analytics Panels */\n.analytics-panel {\n padding: 15px;\n}\n\n/* Accordion Panel Styling */\n.analytics-content mj-accordion-panel {\n display: block;\n margin-bottom: 12px;\n}\n\n/* Charts */\n.charts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));\n gap: 20px;\n margin-bottom: 20px;\n}\n\n/* Chart Cards */\n.chart-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-sm);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.chart-card.expanded {\n grid-column: 1 / -1;\n}\n\n.chart-card-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n background-color: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n}\n\n.chart-card-header:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.chart-card-header h3 {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.chart-card-header h3 i {\n font-size: 16px;\n color: var(--mj-text-muted);\n}\n\n.expand-btn {\n background: none;\n border: none;\n padding: 4px 8px;\n cursor: pointer;\n color: var(--mj-text-muted);\n transition: color 0.2s;\n}\n\n.expand-btn:hover {\n color: var(--mj-text-secondary);\n}\n\n.chart-card-body {\n padding: 16px;\n background: var(--mj-bg-surface-card);\n}\n\n.chart-card.expanded .chart-card-body {\n padding: 24px;\n}\n\n.chart-card.expanded .chart-container > div {\n min-height: 400px;\n}\n\n/* View Mode Toggle */\n.view-mode-toggle {\n display: flex;\n justify-content: flex-end;\n margin-bottom: 16px;\n}\n\n.view-mode-toggle button {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.chart-container {\n position: relative;\n}\n\n.chart-container h3 {\n margin: 0 0 10px 0;\n font-size: 15px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.chart-container > div {\n min-height: 220px;\n width: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n/* Ensure SVG charts are centered */\n.chart-container svg {\n display: block;\n margin: 0 auto;\n}\n\n.chart-legend {\n margin-top: 10px;\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.legend-item {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 13px;\n}\n\n.legend-color {\n width: 16px;\n height: 16px;\n border-radius: 3px;\n}\n\n.chart-total {\n text-align: center;\n margin-top: 10px;\n font-size: 14px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n/* Detailed Metrics */\n.detailed-metrics {\n margin-top: 20px;\n border-top: 1px solid var(--mj-border-default);\n padding-top: 20px;\n}\n\n.detailed-metrics button {\n margin-bottom: 15px;\n}\n\n.detailed-metrics button i {\n margin-right: 8px;\n}\n\n.metrics-table {\n overflow-x: auto;\n}\n\n.metrics-table table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.metrics-table th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n}\n\n.metrics-table td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.metrics-table tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n.success-rate {\n font-weight: 500;\n}\n\n.success-rate.high {\n color: var(--mj-status-success);\n}\n\n.success-rate.medium {\n color: var(--mj-status-warning);\n}\n\n.success-rate.low {\n color: var(--mj-status-error);\n}\n\n/* Error Analysis */\n.error-analysis {\n margin-top: 30px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-bg-surface));\n}\n\n.error-analysis h3 {\n margin: 0 0 15px 0;\n color: var(--mj-status-error);\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.error-analysis-description {\n font-size: 14px;\n color: var(--mj-text-secondary);\n margin-bottom: 20px;\n line-height: 1.5;\n}\n\n.error-list {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.error-item {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 10px;\n background-color: var(--mj-bg-surface);\n border-radius: 4px;\n font-size: 14px;\n}\n\n.error-count {\n background-color: var(--mj-status-error);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.error-message {\n flex: 1;\n color: var(--mj-text-secondary);\n}\n\n/* No errors state */\n.no-errors {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 20px;\n background-color: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n border-radius: 8px;\n border: 1px solid color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n}\n\n.no-errors i {\n font-size: 24px;\n color: var(--mj-status-success);\n}\n\n.no-errors p {\n margin: 0;\n font-size: 14px;\n}\n\n/* No data message */\n.no-data-message {\n text-align: center;\n padding: 60px 20px;\n color: var(--mj-text-muted);\n}\n\n.no-data-message i {\n font-size: 48px;\n margin-bottom: 20px;\n color: var(--mj-border-strong);\n}\n\n.no-data-message p {\n margin: 0 0 10px 0;\n font-size: 16px;\n}\n\n.no-data-message p.small {\n font-size: 14px;\n color: var(--mj-text-disabled);\n}\n\n/* Model Comparison Table */\n.model-comparison {\n overflow-x: auto;\n}\n\n.model-comparison table {\n width: 100%;\n border-collapse: collapse;\n}\n\n.model-comparison th {\n background-color: var(--mj-bg-surface-sunken);\n padding: 12px;\n text-align: left;\n font-weight: 600;\n color: var(--mj-text-secondary);\n border-bottom: 2px solid var(--mj-border-strong);\n white-space: nowrap;\n}\n\n.model-comparison td {\n padding: 12px;\n border-bottom: 1px solid var(--mj-border-strong);\n}\n\n.model-comparison tr:hover {\n background-color: var(--mj-bg-surface-sunken);\n}\n\n/* Timeline Analysis */\n.timeline-stats {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n margin-bottom: 30px;\n}\n\n.stat-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n padding: 20px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 8px;\n}\n\n.stat-label {\n font-size: 14px;\n color: var(--mj-text-muted);\n margin-bottom: 8px;\n}\n\n.stat-value {\n font-size: 32px;\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.step-breakdown h3 {\n margin: 0 0 15px 0;\n font-size: 16px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.step-type-list {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n gap: 12px;\n}\n\n.step-type-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 12px;\n background-color: var(--mj-bg-surface-sunken);\n border-radius: 6px;\n border: 1px solid var(--mj-border-default);\n}\n\n.step-type-item i {\n width: 30px;\n text-align: center;\n color: var(--mj-text-muted);\n}\n\n.type-name {\n flex: 1;\n font-weight: 500;\n}\n\n.type-count {\n font-weight: 700;\n color: var(--mj-text-primary);\n}\n\n.type-percentage {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-left: 5px;\n}\n\n/* Responsive */\n@media (max-width: 768px) {\n .summary-cards {\n grid-template-columns: 1fr;\n }\n \n .charts-grid {\n grid-template-columns: 1fr;\n }\n \n .timeline-stats {\n grid-template-columns: repeat(2, 1fr);\n }\n}"] }]
|
|
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}"] }]
|
|
2151
2328
|
}], () => [{ type: i0.ChangeDetectorRef }, { type: i1.AIAgentRunCostService }], { agentRunId: [{
|
|
2152
2329
|
type: Input
|
|
2153
2330
|
}], modelDistributionChart: [{
|
|
@@ -2181,5 +2358,5 @@ export class AIAgentRunAnalyticsComponent extends BaseAngularComponent {
|
|
|
2181
2358
|
type: ViewChild,
|
|
2182
2359
|
args: ['promptCountByNameChart', { static: false }]
|
|
2183
2360
|
}] }); })();
|
|
2184
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber:
|
|
2361
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 82 }); })();
|
|
2185
2362
|
//# sourceMappingURL=ai-agent-run-analytics.component.js.map
|