@memberjunction/ng-core-entity-forms 2.112.0 → 2.113.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/README.md +10 -10
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.js +45 -45
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-diagram.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js +7 -6
- package/dist/lib/custom/AIAgents/FlowAgentType/flow-agent-form-section.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js +32 -17
- package/dist/lib/custom/AIAgents/FlowAgentType/mj-integrated-flow-editor.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js +36 -37
- package/dist/lib/custom/AIAgents/add-action-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js +2 -2
- package/dist/lib/custom/AIAgents/agent-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.d.ts +1 -1
- package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.js +25 -18
- package/dist/lib/custom/AIAgents/agent-permissions-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js +11 -10
- package/dist/lib/custom/AIAgents/agent-prompt-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js +147 -159
- package/dist/lib/custom/AIAgents/ai-agent-form.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js +10 -11
- package/dist/lib/custom/AIAgents/create-prompt-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js +32 -36
- package/dist/lib/custom/AIAgents/create-sub-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js +5 -5
- package/dist/lib/custom/AIAgents/new-agent-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js +13 -15
- package/dist/lib/custom/AIAgents/prompt-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js +15 -13
- package/dist/lib/custom/AIAgents/sub-agent-advanced-settings-dialog.component.js.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js +23 -28
- package/dist/lib/custom/AIAgents/sub-agent-selector-dialog.component.js.map +1 -1
- 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 +12 -15
- package/dist/lib/custom/AIPromptRuns/ai-prompt-run-form.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js +86 -105
- package/dist/lib/custom/AIPrompts/ai-prompt-form.component.js.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js +20 -13
- package/dist/lib/custom/AIPrompts/template-selector-dialog.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-execution-log-form.component.js +7 -4
- package/dist/lib/custom/Actions/action-execution-log-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-form.component.js +80 -99
- package/dist/lib/custom/Actions/action-form.component.js.map +1 -1
- package/dist/lib/custom/Actions/action-test-harness.component.d.ts.map +1 -1
- package/dist/lib/custom/Actions/action-test-harness.component.js +17 -24
- package/dist/lib/custom/Actions/action-test-harness.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-category-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-category-dialog.component.js +8 -8
- package/dist/lib/custom/Queries/query-category-dialog.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.d.ts +2 -2
- package/dist/lib/custom/Queries/query-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-form.component.js +44 -32
- package/dist/lib/custom/Queries/query-form.component.js.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/Queries/query-run-dialog.component.js +22 -24
- package/dist/lib/custom/Queries/query-run-dialog.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-param-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/template-param-dialog.component.js +21 -15
- package/dist/lib/custom/Templates/template-param-dialog.component.js.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/template-params-grid.component.js +17 -29
- package/dist/lib/custom/Templates/template-params-grid.component.js.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.d.ts.map +1 -1
- package/dist/lib/custom/Templates/templates-form.component.js +26 -25
- package/dist/lib/custom/Templates/templates-form.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-analytics.component.js +274 -335
- 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-cost.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js +8 -8
- package/dist/lib/custom/ai-agent-run/ai-agent-run-cost.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js +28 -24
- package/dist/lib/custom/ai-agent-run/ai-agent-run-data.service.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js +30 -25
- package/dist/lib/custom/ai-agent-run/ai-agent-run-timeline.component.js.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.d.ts.map +1 -1
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js +21 -20
- package/dist/lib/custom/ai-agent-run/ai-agent-run.component.js.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.d.ts.map +1 -1
- package/dist/lib/custom/shared/entity-selector-dialog.component.js +7 -6
- package/dist/lib/custom/shared/entity-selector-dialog.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.js +33 -47
- package/dist/lib/generated/Entities/AIAgent/sections/aiagent-form-overview.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/sections/details.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgent/sections/details.component.js +31 -4
- package/dist/lib/generated/Entities/AIAgent/sections/details.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.js +33 -4
- package/dist/lib/generated/Entities/AIAgentExample/sections/details.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.js +33 -4
- package/dist/lib/generated/Entities/AIAgentNote/sections/details.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.d.ts.map +1 -1
- package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.js +22 -4
- package/dist/lib/generated/Entities/AIAgentRelationship/sections/details.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js +6 -6
- package/dist/lib/generated/Entities/AIAgentRun/aiagentrun.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js +8 -8
- package/dist/lib/generated/Entities/AIConfiguration/aiconfiguration.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js +34 -14
- package/dist/lib/generated/Entities/AIModel/aimodel.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.js +59 -0
- package/dist/lib/generated/Entities/ArtifactUse/artifactuse.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.d.ts +11 -0
- package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.js +129 -0
- package/dist/lib/generated/Entities/ArtifactUse/sections/details.component.js.map +1 -0
- package/dist/lib/generated/Entities/ArtifactVersion/artifactversion.form.component.js +24 -4
- package/dist/lib/generated/Entities/ArtifactVersion/artifactversion.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/CollectionArtifact/sections/details.component.js +10 -10
- package/dist/lib/generated/Entities/CollectionArtifact/sections/details.component.js.map +1 -1
- package/dist/lib/generated/Entities/ConversationArtifact/conversationartifact.form.component.js +6 -6
- package/dist/lib/generated/Entities/ConversationArtifact/conversationartifact.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js +18 -8
- package/dist/lib/generated/Entities/ConversationDetail/conversationdetail.form.component.js.map +1 -1
- package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.d.ts +10 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js +59 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/conversationdetailrating.form.component.js.map +1 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.d.ts +11 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.d.ts.map +1 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.js +120 -0
- package/dist/lib/generated/Entities/ConversationDetailRating/sections/details.component.js.map +1 -0
- package/dist/lib/generated/Entities/User/user.form.component.js +49 -29
- package/dist/lib/generated/Entities/User/user.form.component.js.map +1 -1
- package/dist/lib/generated/generated-forms.module.d.ts +336 -327
- package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
- package/dist/lib/generated/generated-forms.module.js +199 -126
- package/dist/lib/generated/generated-forms.module.js.map +1 -1
- package/dist/lib/shared/components/template-editor.component.d.ts.map +1 -1
- package/dist/lib/shared/components/template-editor.component.js +27 -26
- package/dist/lib/shared/components/template-editor.component.js.map +1 -1
- package/package.json +17 -16
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Component, Input, ViewChild, ChangeDetectionStrategy
|
|
1
|
+
import { Component, Input, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
|
2
2
|
import { Subject } from 'rxjs';
|
|
3
|
-
import { RunView } from '@memberjunction/
|
|
3
|
+
import { RunView } from '@memberjunction/core';
|
|
4
4
|
import * as d3 from 'd3';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
import * as i1 from "./ai-agent-run-cost.service";
|
|
@@ -791,7 +791,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
791
791
|
promptCost: false,
|
|
792
792
|
promptCount: false,
|
|
793
793
|
actionSuccess: false,
|
|
794
|
-
stepType: false
|
|
794
|
+
stepType: false
|
|
795
795
|
};
|
|
796
796
|
this.viewMode = 'grid';
|
|
797
797
|
// Loading state
|
|
@@ -816,7 +816,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
816
816
|
prompts: true,
|
|
817
817
|
actions: true,
|
|
818
818
|
models: true,
|
|
819
|
-
timeline: true
|
|
819
|
+
timeline: true
|
|
820
820
|
};
|
|
821
821
|
}
|
|
822
822
|
ngOnInit() {
|
|
@@ -829,7 +829,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
829
829
|
this.destroy$.next();
|
|
830
830
|
this.destroy$.complete();
|
|
831
831
|
// Clear all active timeouts
|
|
832
|
-
this.activeTimeouts.forEach(
|
|
832
|
+
this.activeTimeouts.forEach(timeoutId => {
|
|
833
833
|
clearTimeout(timeoutId);
|
|
834
834
|
});
|
|
835
835
|
this.activeTimeouts.length = 0;
|
|
@@ -849,54 +849,31 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
849
849
|
this.promptTimeDistributionChart,
|
|
850
850
|
this.promptTokenDistributionChart,
|
|
851
851
|
this.promptCostDistributionChart,
|
|
852
|
-
this.promptCountByNameChart
|
|
852
|
+
this.promptCountByNameChart
|
|
853
853
|
];
|
|
854
854
|
// More comprehensive D3 cleanup
|
|
855
|
-
chartRefs.forEach(
|
|
855
|
+
chartRefs.forEach(chartRef => {
|
|
856
856
|
if (chartRef?.nativeElement) {
|
|
857
857
|
const element = chartRef.nativeElement;
|
|
858
858
|
const d3Element = d3.select(element);
|
|
859
859
|
// Remove ALL possible event listeners (comprehensive list)
|
|
860
860
|
const allEventTypes = [
|
|
861
|
-
'click',
|
|
862
|
-
'
|
|
863
|
-
'
|
|
864
|
-
'
|
|
865
|
-
'
|
|
866
|
-
'
|
|
867
|
-
'mousemove',
|
|
868
|
-
'mouseenter',
|
|
869
|
-
'mouseleave',
|
|
870
|
-
'contextmenu',
|
|
871
|
-
'touchstart',
|
|
872
|
-
'touchend',
|
|
873
|
-
'touchmove',
|
|
874
|
-
'touchcancel',
|
|
875
|
-
'wheel',
|
|
876
|
-
'scroll',
|
|
877
|
-
'resize',
|
|
878
|
-
'focus',
|
|
879
|
-
'blur',
|
|
880
|
-
'keydown',
|
|
881
|
-
'keyup',
|
|
882
|
-
'keypress',
|
|
883
|
-
'drag',
|
|
884
|
-
'dragstart',
|
|
885
|
-
'dragend',
|
|
886
|
-
'dragover',
|
|
887
|
-
'dragenter',
|
|
888
|
-
'dragleave',
|
|
889
|
-
'drop',
|
|
861
|
+
'click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout',
|
|
862
|
+
'mousemove', 'mouseenter', 'mouseleave', 'contextmenu',
|
|
863
|
+
'touchstart', 'touchend', 'touchmove', 'touchcancel',
|
|
864
|
+
'wheel', 'scroll', 'resize', 'focus', 'blur',
|
|
865
|
+
'keydown', 'keyup', 'keypress',
|
|
866
|
+
'drag', 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'drop'
|
|
890
867
|
];
|
|
891
868
|
// Remove event listeners from all child elements
|
|
892
869
|
d3Element.selectAll('*').each(function () {
|
|
893
870
|
const node = d3.select(this);
|
|
894
|
-
allEventTypes.forEach(
|
|
871
|
+
allEventTypes.forEach(eventType => {
|
|
895
872
|
node.on(eventType, null);
|
|
896
873
|
});
|
|
897
874
|
});
|
|
898
875
|
// Remove event listeners from the main element too
|
|
899
|
-
allEventTypes.forEach(
|
|
876
|
+
allEventTypes.forEach(eventType => {
|
|
900
877
|
d3Element.on(eventType, null);
|
|
901
878
|
});
|
|
902
879
|
// Cancel any ongoing transitions
|
|
@@ -975,7 +952,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
975
952
|
{
|
|
976
953
|
EntityName: 'MJ: AI Agent Run Steps',
|
|
977
954
|
ExtraFilter: `AgentRunID IN ('${agentRunIds.join("','")}')`,
|
|
978
|
-
}
|
|
955
|
+
}
|
|
979
956
|
]);
|
|
980
957
|
// Process results
|
|
981
958
|
if (results[0].Success && results[0].Results && results[0].Results.length > 0) {
|
|
@@ -990,11 +967,13 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
990
967
|
const actionSteps = results[2].Results || [];
|
|
991
968
|
// Now load the actual action logs
|
|
992
969
|
if (actionSteps.length > 0) {
|
|
993
|
-
const actionLogIds = actionSteps
|
|
970
|
+
const actionLogIds = actionSteps
|
|
971
|
+
.map(s => s.TargetLogID)
|
|
972
|
+
.filter(id => id != null);
|
|
994
973
|
if (actionLogIds.length > 0) {
|
|
995
974
|
const actionResult = await rv.RunView({
|
|
996
975
|
EntityName: 'Action Execution Logs',
|
|
997
|
-
ExtraFilter: `ID IN ('${actionLogIds.join("','")}')
|
|
976
|
+
ExtraFilter: `ID IN ('${actionLogIds.join("','")}')`
|
|
998
977
|
});
|
|
999
978
|
if (actionResult.Success) {
|
|
1000
979
|
this.allActionLogs = actionResult.Results || [];
|
|
@@ -1016,7 +995,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1016
995
|
byPrompt: new Map(),
|
|
1017
996
|
statusBreakdown: { success: 0, failed: 0, timeout: 0 },
|
|
1018
997
|
costBreakdown: { totalCost: 0, byModel: new Map(), byVendor: new Map() },
|
|
1019
|
-
tokenUsage: { totalInput: 0, totalOutput: 0, byModel: new Map() }
|
|
998
|
+
tokenUsage: { totalInput: 0, totalOutput: 0, byModel: new Map() }
|
|
1020
999
|
};
|
|
1021
1000
|
}
|
|
1022
1001
|
initializeActionMetrics() {
|
|
@@ -1027,7 +1006,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1027
1006
|
byAction: new Map(),
|
|
1028
1007
|
byType: new Map(),
|
|
1029
1008
|
statusBreakdown: { success: 0, failed: 0, timeout: 0 },
|
|
1030
|
-
errorAnalysis: new Map()
|
|
1009
|
+
errorAnalysis: new Map()
|
|
1031
1010
|
};
|
|
1032
1011
|
}
|
|
1033
1012
|
initializeTimelineMetrics() {
|
|
@@ -1036,7 +1015,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1036
1015
|
stepsByType: new Map(),
|
|
1037
1016
|
parallelExecutions: 0,
|
|
1038
1017
|
deepestNesting: 0,
|
|
1039
|
-
criticalPath: { steps: [], totalTime: 0 }
|
|
1018
|
+
criticalPath: { steps: [], totalTime: 0 }
|
|
1040
1019
|
};
|
|
1041
1020
|
}
|
|
1042
1021
|
calculatePromptMetrics() {
|
|
@@ -1115,7 +1094,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1115
1094
|
actionMetric.avgTime = actionMetric.totalTime / actionMetric.count;
|
|
1116
1095
|
// Track success rate
|
|
1117
1096
|
if (actionLog.ResultCode === 'Success') {
|
|
1118
|
-
const successCount = actionMetric.successRate * (actionMetric.count - 1) + 1;
|
|
1097
|
+
const successCount = (actionMetric.successRate * (actionMetric.count - 1) + 1);
|
|
1119
1098
|
actionMetric.successRate = successCount / actionMetric.count;
|
|
1120
1099
|
}
|
|
1121
1100
|
else {
|
|
@@ -1174,35 +1153,29 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1174
1153
|
// Model distribution pie chart
|
|
1175
1154
|
this.modelDistributionChartData = {
|
|
1176
1155
|
labels: Array.from(this.promptMetrics.byModel.keys()),
|
|
1177
|
-
datasets: [
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
},
|
|
1182
|
-
],
|
|
1156
|
+
datasets: [{
|
|
1157
|
+
data: Array.from(this.promptMetrics.byModel.values()).map(m => m.count),
|
|
1158
|
+
backgroundColor: this.generateColors(this.promptMetrics.byModel.size)
|
|
1159
|
+
}]
|
|
1183
1160
|
};
|
|
1184
1161
|
// Execution time by vendor bar chart
|
|
1185
1162
|
this.executionTimeChartData = {
|
|
1186
1163
|
labels: Array.from(this.promptMetrics.byVendor.keys()),
|
|
1187
|
-
datasets: [
|
|
1188
|
-
{
|
|
1164
|
+
datasets: [{
|
|
1189
1165
|
label: 'Average Execution Time (ms)',
|
|
1190
|
-
data: Array.from(this.promptMetrics.byVendor.values()).map(
|
|
1166
|
+
data: Array.from(this.promptMetrics.byVendor.values()).map(v => v.avgTime),
|
|
1191
1167
|
backgroundColor: 'rgba(54, 162, 235, 0.5)',
|
|
1192
1168
|
borderColor: 'rgba(54, 162, 235, 1)',
|
|
1193
|
-
borderWidth: 1
|
|
1194
|
-
}
|
|
1195
|
-
],
|
|
1169
|
+
borderWidth: 1
|
|
1170
|
+
}]
|
|
1196
1171
|
};
|
|
1197
1172
|
// Cost by vendor doughnut chart
|
|
1198
1173
|
this.costByVendorChartData = {
|
|
1199
1174
|
labels: Array.from(this.promptMetrics.costBreakdown.byVendor.keys()),
|
|
1200
|
-
datasets: [
|
|
1201
|
-
{
|
|
1175
|
+
datasets: [{
|
|
1202
1176
|
data: Array.from(this.promptMetrics.costBreakdown.byVendor.values()),
|
|
1203
|
-
backgroundColor: this.generateColors(this.promptMetrics.costBreakdown.byVendor.size)
|
|
1204
|
-
}
|
|
1205
|
-
],
|
|
1177
|
+
backgroundColor: this.generateColors(this.promptMetrics.costBreakdown.byVendor.size)
|
|
1178
|
+
}]
|
|
1206
1179
|
};
|
|
1207
1180
|
// Token usage stacked bar chart
|
|
1208
1181
|
const tokenModels = Array.from(this.promptMetrics.tokenUsage.byModel.keys());
|
|
@@ -1211,38 +1184,34 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1211
1184
|
datasets: [
|
|
1212
1185
|
{
|
|
1213
1186
|
label: 'Input Tokens',
|
|
1214
|
-
data: tokenModels.map(
|
|
1215
|
-
backgroundColor: 'rgba(255, 99, 132, 0.5)'
|
|
1187
|
+
data: tokenModels.map(m => this.promptMetrics.tokenUsage.byModel.get(m)?.input || 0),
|
|
1188
|
+
backgroundColor: 'rgba(255, 99, 132, 0.5)'
|
|
1216
1189
|
},
|
|
1217
1190
|
{
|
|
1218
1191
|
label: 'Output Tokens',
|
|
1219
|
-
data: tokenModels.map(
|
|
1220
|
-
backgroundColor: 'rgba(75, 192, 192, 0.5)'
|
|
1221
|
-
}
|
|
1222
|
-
]
|
|
1192
|
+
data: tokenModels.map(m => this.promptMetrics.tokenUsage.byModel.get(m)?.output || 0),
|
|
1193
|
+
backgroundColor: 'rgba(75, 192, 192, 0.5)'
|
|
1194
|
+
}
|
|
1195
|
+
]
|
|
1223
1196
|
};
|
|
1224
1197
|
// Action success rate bar chart
|
|
1225
1198
|
this.actionSuccessRateChartData = {
|
|
1226
1199
|
labels: Array.from(this.actionMetrics.byAction.keys()),
|
|
1227
|
-
datasets: [
|
|
1228
|
-
{
|
|
1200
|
+
datasets: [{
|
|
1229
1201
|
label: 'Success Rate (%)',
|
|
1230
|
-
data: Array.from(this.actionMetrics.byAction.values()).map(
|
|
1202
|
+
data: Array.from(this.actionMetrics.byAction.values()).map(a => a.successRate * 100),
|
|
1231
1203
|
backgroundColor: 'rgba(75, 192, 192, 0.5)',
|
|
1232
1204
|
borderColor: 'rgba(75, 192, 192, 1)',
|
|
1233
|
-
borderWidth: 1
|
|
1234
|
-
}
|
|
1235
|
-
],
|
|
1205
|
+
borderWidth: 1
|
|
1206
|
+
}]
|
|
1236
1207
|
};
|
|
1237
1208
|
// Step type distribution pie chart
|
|
1238
1209
|
this.stepTypeDistributionChartData = {
|
|
1239
1210
|
labels: Array.from(this.timelineMetrics.stepsByType.keys()),
|
|
1240
|
-
datasets: [
|
|
1241
|
-
{
|
|
1211
|
+
datasets: [{
|
|
1242
1212
|
data: Array.from(this.timelineMetrics.stepsByType.values()),
|
|
1243
|
-
backgroundColor: this.generateColors(this.timelineMetrics.stepsByType.size)
|
|
1244
|
-
}
|
|
1245
|
-
],
|
|
1213
|
+
backgroundColor: this.generateColors(this.timelineMetrics.stepsByType.size)
|
|
1214
|
+
}]
|
|
1246
1215
|
};
|
|
1247
1216
|
}
|
|
1248
1217
|
generateColors(count) {
|
|
@@ -1256,7 +1225,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1256
1225
|
'rgba(199, 199, 199, 0.5)',
|
|
1257
1226
|
'rgba(83, 102, 255, 0.5)',
|
|
1258
1227
|
'rgba(255, 99, 255, 0.5)',
|
|
1259
|
-
'rgba(99, 255, 132, 0.5)'
|
|
1228
|
+
'rgba(99, 255, 132, 0.5)'
|
|
1260
1229
|
];
|
|
1261
1230
|
// Repeat colors if needed
|
|
1262
1231
|
const result = [];
|
|
@@ -1303,7 +1272,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1303
1272
|
const element = this.modelDistributionChart.nativeElement;
|
|
1304
1273
|
const data = Array.from(this.promptMetrics.byModel.entries()).map(([name, metrics]) => ({
|
|
1305
1274
|
name,
|
|
1306
|
-
value: metrics.count
|
|
1275
|
+
value: metrics.count
|
|
1307
1276
|
}));
|
|
1308
1277
|
if (data.length === 0)
|
|
1309
1278
|
return;
|
|
@@ -1313,37 +1282,37 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1313
1282
|
const width = isExpanded ? 500 : 300;
|
|
1314
1283
|
const height = isExpanded ? 400 : 220;
|
|
1315
1284
|
const radius = Math.min(width, height) / 2 - 40;
|
|
1316
|
-
const svg = d3
|
|
1317
|
-
.select(element)
|
|
1285
|
+
const svg = d3.select(element)
|
|
1318
1286
|
.append('svg')
|
|
1319
1287
|
.attr('width', width)
|
|
1320
1288
|
.attr('height', height)
|
|
1321
1289
|
.append('g')
|
|
1322
1290
|
.attr('transform', `translate(${width / 2}, ${height / 2})`);
|
|
1323
1291
|
const color = d3.scaleOrdinal(d3.schemeCategory10);
|
|
1324
|
-
const pie = d3
|
|
1325
|
-
.
|
|
1326
|
-
.value((d) => d.value)
|
|
1292
|
+
const pie = d3.pie()
|
|
1293
|
+
.value(d => d.value)
|
|
1327
1294
|
.sort(null);
|
|
1328
|
-
const arc = d3.arc()
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1295
|
+
const arc = d3.arc()
|
|
1296
|
+
.innerRadius(0)
|
|
1297
|
+
.outerRadius(radius);
|
|
1298
|
+
const arcs = svg.selectAll('arc')
|
|
1299
|
+
.data(pie(data))
|
|
1300
|
+
.enter()
|
|
1301
|
+
.append('g');
|
|
1302
|
+
arcs.append('path')
|
|
1332
1303
|
.attr('d', arc)
|
|
1333
1304
|
.attr('fill', (d, i) => color(i.toString()))
|
|
1334
1305
|
.attr('stroke', 'white')
|
|
1335
1306
|
.style('stroke-width', '2px');
|
|
1336
1307
|
// Add labels
|
|
1337
|
-
arcs
|
|
1338
|
-
.append('text')
|
|
1308
|
+
arcs.append('text')
|
|
1339
1309
|
.attr('transform', (d) => `translate(${arc.centroid(d)})`)
|
|
1340
1310
|
.attr('text-anchor', 'middle')
|
|
1341
1311
|
.style('font-size', '12px')
|
|
1342
1312
|
.style('fill', 'white')
|
|
1343
|
-
.text((d) =>
|
|
1313
|
+
.text((d) => d.data.value > 0 ? d.data.value : '');
|
|
1344
1314
|
// Add title
|
|
1345
|
-
svg
|
|
1346
|
-
.append('text')
|
|
1315
|
+
svg.append('text')
|
|
1347
1316
|
.attr('x', 0)
|
|
1348
1317
|
.attr('y', -radius - 25)
|
|
1349
1318
|
.attr('text-anchor', 'middle')
|
|
@@ -1355,7 +1324,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1355
1324
|
const element = this.executionTimeChart.nativeElement;
|
|
1356
1325
|
const data = Array.from(this.promptMetrics.byVendor.entries()).map(([name, metrics]) => ({
|
|
1357
1326
|
name,
|
|
1358
|
-
value: metrics.avgTime
|
|
1327
|
+
value: metrics.avgTime
|
|
1359
1328
|
}));
|
|
1360
1329
|
if (data.length === 0)
|
|
1361
1330
|
return;
|
|
@@ -1365,47 +1334,41 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1365
1334
|
const margin = { top: 40, right: 20, bottom: 70, left: 60 };
|
|
1366
1335
|
const width = (isExpanded ? 600 : 320) - margin.left - margin.right;
|
|
1367
1336
|
const height = (isExpanded ? 350 : 200) - margin.top - margin.bottom;
|
|
1368
|
-
const svg = d3
|
|
1369
|
-
.select(element)
|
|
1337
|
+
const svg = d3.select(element)
|
|
1370
1338
|
.append('svg')
|
|
1371
1339
|
.attr('width', width + margin.left + margin.right)
|
|
1372
1340
|
.attr('height', height + margin.top + margin.bottom)
|
|
1373
1341
|
.append('g')
|
|
1374
1342
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
1375
|
-
const x = d3
|
|
1376
|
-
.scaleBand()
|
|
1343
|
+
const x = d3.scaleBand()
|
|
1377
1344
|
.range([0, width])
|
|
1378
|
-
.domain(data.map(
|
|
1345
|
+
.domain(data.map(d => d.name))
|
|
1379
1346
|
.padding(0.1);
|
|
1380
|
-
const y = d3
|
|
1381
|
-
.
|
|
1382
|
-
.domain([0, d3.max(data, (d) => d.value) || 0])
|
|
1347
|
+
const y = d3.scaleLinear()
|
|
1348
|
+
.domain([0, d3.max(data, d => d.value) || 0])
|
|
1383
1349
|
.range([height, 0]);
|
|
1384
1350
|
// Add bars
|
|
1385
|
-
svg
|
|
1386
|
-
.selectAll('.bar')
|
|
1351
|
+
svg.selectAll('.bar')
|
|
1387
1352
|
.data(data)
|
|
1388
|
-
.enter()
|
|
1389
|
-
.append('rect')
|
|
1353
|
+
.enter().append('rect')
|
|
1390
1354
|
.attr('class', 'bar')
|
|
1391
|
-
.attr('x',
|
|
1355
|
+
.attr('x', d => x(d.name) || 0)
|
|
1392
1356
|
.attr('width', x.bandwidth())
|
|
1393
|
-
.attr('y',
|
|
1394
|
-
.attr('height',
|
|
1357
|
+
.attr('y', d => y(d.value))
|
|
1358
|
+
.attr('height', d => height - y(d.value))
|
|
1395
1359
|
.attr('fill', '#36a2eb');
|
|
1396
1360
|
// Add x axis
|
|
1397
|
-
svg
|
|
1398
|
-
.append('g')
|
|
1361
|
+
svg.append('g')
|
|
1399
1362
|
.attr('transform', `translate(0,${height})`)
|
|
1400
1363
|
.call(d3.axisBottom(x))
|
|
1401
1364
|
.selectAll('text')
|
|
1402
1365
|
.attr('transform', 'rotate(-45)')
|
|
1403
1366
|
.style('text-anchor', 'end');
|
|
1404
1367
|
// Add y axis
|
|
1405
|
-
svg.append('g')
|
|
1368
|
+
svg.append('g')
|
|
1369
|
+
.call(d3.axisLeft(y).tickFormat(d => `${d}ms`));
|
|
1406
1370
|
// Add title
|
|
1407
|
-
svg
|
|
1408
|
-
.append('text')
|
|
1371
|
+
svg.append('text')
|
|
1409
1372
|
.attr('x', width / 2)
|
|
1410
1373
|
.attr('y', -20)
|
|
1411
1374
|
.attr('text-anchor', 'middle')
|
|
@@ -1417,7 +1380,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1417
1380
|
const element = this.costByVendorChart.nativeElement;
|
|
1418
1381
|
const data = Array.from(this.promptMetrics.costBreakdown.byVendor.entries()).map(([name, cost]) => ({
|
|
1419
1382
|
name,
|
|
1420
|
-
value: cost
|
|
1383
|
+
value: cost
|
|
1421
1384
|
}));
|
|
1422
1385
|
if (data.length === 0)
|
|
1423
1386
|
return;
|
|
@@ -1426,32 +1389,30 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1426
1389
|
const width = 300;
|
|
1427
1390
|
const height = 220;
|
|
1428
1391
|
const radius = Math.min(width, height) / 2 - 40;
|
|
1429
|
-
const svg = d3
|
|
1430
|
-
.select(element)
|
|
1392
|
+
const svg = d3.select(element)
|
|
1431
1393
|
.append('svg')
|
|
1432
1394
|
.attr('width', width)
|
|
1433
1395
|
.attr('height', height)
|
|
1434
1396
|
.append('g')
|
|
1435
1397
|
.attr('transform', `translate(${width / 2}, ${height / 2})`);
|
|
1436
1398
|
const color = d3.scaleOrdinal(d3.schemeSet2);
|
|
1437
|
-
const pie = d3
|
|
1438
|
-
.
|
|
1439
|
-
.value((d) => d.value)
|
|
1399
|
+
const pie = d3.pie()
|
|
1400
|
+
.value(d => d.value)
|
|
1440
1401
|
.sort(null);
|
|
1441
|
-
const arc = d3
|
|
1442
|
-
.arc()
|
|
1402
|
+
const arc = d3.arc()
|
|
1443
1403
|
.innerRadius(radius * 0.5) // Doughnut chart
|
|
1444
1404
|
.outerRadius(radius);
|
|
1445
|
-
const arcs = svg.selectAll('arc')
|
|
1446
|
-
|
|
1447
|
-
.
|
|
1405
|
+
const arcs = svg.selectAll('arc')
|
|
1406
|
+
.data(pie(data))
|
|
1407
|
+
.enter()
|
|
1408
|
+
.append('g');
|
|
1409
|
+
arcs.append('path')
|
|
1448
1410
|
.attr('d', arc)
|
|
1449
1411
|
.attr('fill', (d, i) => color(i.toString()))
|
|
1450
1412
|
.attr('stroke', 'white')
|
|
1451
1413
|
.style('stroke-width', '2px');
|
|
1452
1414
|
// Add title
|
|
1453
|
-
svg
|
|
1454
|
-
.append('text')
|
|
1415
|
+
svg.append('text')
|
|
1455
1416
|
.attr('x', 0)
|
|
1456
1417
|
.attr('y', -radius - 25)
|
|
1457
1418
|
.attr('text-anchor', 'middle')
|
|
@@ -1462,15 +1423,15 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1462
1423
|
renderTokenUsageChart() {
|
|
1463
1424
|
const element = this.tokenUsageChart.nativeElement;
|
|
1464
1425
|
const models = Array.from(this.promptMetrics.tokenUsage.byModel.keys());
|
|
1465
|
-
const inputData = models.map(
|
|
1426
|
+
const inputData = models.map(model => ({
|
|
1466
1427
|
model,
|
|
1467
1428
|
type: 'Input',
|
|
1468
|
-
value: this.promptMetrics.tokenUsage.byModel.get(model)?.input || 0
|
|
1429
|
+
value: this.promptMetrics.tokenUsage.byModel.get(model)?.input || 0
|
|
1469
1430
|
}));
|
|
1470
|
-
const outputData = models.map(
|
|
1431
|
+
const outputData = models.map(model => ({
|
|
1471
1432
|
model,
|
|
1472
1433
|
type: 'Output',
|
|
1473
|
-
value: this.promptMetrics.tokenUsage.byModel.get(model)?.output || 0
|
|
1434
|
+
value: this.promptMetrics.tokenUsage.byModel.get(model)?.output || 0
|
|
1474
1435
|
}));
|
|
1475
1436
|
const data = [...inputData, ...outputData];
|
|
1476
1437
|
if (data.length === 0)
|
|
@@ -1480,73 +1441,71 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1480
1441
|
const margin = { top: 40, right: 100, bottom: 70, left: 60 };
|
|
1481
1442
|
const width = 320 - margin.left - margin.right;
|
|
1482
1443
|
const height = 200 - margin.top - margin.bottom;
|
|
1483
|
-
const svg = d3
|
|
1484
|
-
.select(element)
|
|
1444
|
+
const svg = d3.select(element)
|
|
1485
1445
|
.append('svg')
|
|
1486
1446
|
.attr('width', width + margin.left + margin.right)
|
|
1487
1447
|
.attr('height', height + margin.top + margin.bottom)
|
|
1488
1448
|
.append('g')
|
|
1489
1449
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
1490
|
-
const x0 = d3.scaleBand()
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
.
|
|
1450
|
+
const x0 = d3.scaleBand()
|
|
1451
|
+
.rangeRound([0, width])
|
|
1452
|
+
.paddingInner(0.1)
|
|
1453
|
+
.domain(models);
|
|
1454
|
+
const x1 = d3.scaleBand()
|
|
1455
|
+
.padding(0.05)
|
|
1456
|
+
.domain(['Input', 'Output'])
|
|
1457
|
+
.rangeRound([0, x0.bandwidth()]);
|
|
1458
|
+
const y = d3.scaleLinear()
|
|
1494
1459
|
.rangeRound([height, 0])
|
|
1495
|
-
.domain([0, d3.max(data,
|
|
1496
|
-
const color = d3.scaleOrdinal()
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1460
|
+
.domain([0, d3.max(data, d => d.value) || 0]);
|
|
1461
|
+
const color = d3.scaleOrdinal()
|
|
1462
|
+
.domain(['Input', 'Output'])
|
|
1463
|
+
.range(['#ff6384', '#4bc0c0']);
|
|
1464
|
+
const grouped = d3.group(data, d => d.model);
|
|
1465
|
+
svg.append('g')
|
|
1500
1466
|
.selectAll('g')
|
|
1501
1467
|
.data(grouped)
|
|
1502
|
-
.enter()
|
|
1503
|
-
.
|
|
1504
|
-
.attr('transform', (d) => `translate(${x0(d[0]) || 0},0)`)
|
|
1468
|
+
.enter().append('g')
|
|
1469
|
+
.attr('transform', d => `translate(${x0(d[0]) || 0},0)`)
|
|
1505
1470
|
.selectAll('rect')
|
|
1506
|
-
.data(
|
|
1507
|
-
.enter()
|
|
1508
|
-
.
|
|
1509
|
-
.attr('
|
|
1510
|
-
.attr('y', (d) => y(d.value))
|
|
1471
|
+
.data(d => d[1])
|
|
1472
|
+
.enter().append('rect')
|
|
1473
|
+
.attr('x', d => x1(d.type) || 0)
|
|
1474
|
+
.attr('y', d => y(d.value))
|
|
1511
1475
|
.attr('width', x1.bandwidth())
|
|
1512
|
-
.attr('height',
|
|
1513
|
-
.attr('fill',
|
|
1476
|
+
.attr('height', d => height - y(d.value))
|
|
1477
|
+
.attr('fill', d => color(d.type));
|
|
1514
1478
|
// Add x axis
|
|
1515
|
-
svg
|
|
1516
|
-
.append('g')
|
|
1479
|
+
svg.append('g')
|
|
1517
1480
|
.attr('transform', `translate(0,${height})`)
|
|
1518
1481
|
.call(d3.axisBottom(x0))
|
|
1519
1482
|
.selectAll('text')
|
|
1520
1483
|
.attr('transform', 'rotate(-45)')
|
|
1521
1484
|
.style('text-anchor', 'end');
|
|
1522
1485
|
// Add y axis
|
|
1523
|
-
svg.append('g')
|
|
1486
|
+
svg.append('g')
|
|
1487
|
+
.call(d3.axisLeft(y));
|
|
1524
1488
|
// Add legend
|
|
1525
|
-
const legend = svg
|
|
1526
|
-
.append('g')
|
|
1489
|
+
const legend = svg.append('g')
|
|
1527
1490
|
.attr('font-family', 'sans-serif')
|
|
1528
1491
|
.attr('font-size', 10)
|
|
1529
1492
|
.attr('text-anchor', 'end')
|
|
1530
1493
|
.selectAll('g')
|
|
1531
1494
|
.data(['Input', 'Output'])
|
|
1532
|
-
.enter()
|
|
1533
|
-
.append('g')
|
|
1495
|
+
.enter().append('g')
|
|
1534
1496
|
.attr('transform', (d, i) => `translate(0,${i * 20})`);
|
|
1535
|
-
legend
|
|
1536
|
-
.append('rect')
|
|
1497
|
+
legend.append('rect')
|
|
1537
1498
|
.attr('x', width + 70)
|
|
1538
1499
|
.attr('width', 19)
|
|
1539
1500
|
.attr('height', 19)
|
|
1540
|
-
.attr('fill',
|
|
1541
|
-
legend
|
|
1542
|
-
.append('text')
|
|
1501
|
+
.attr('fill', d => color(d));
|
|
1502
|
+
legend.append('text')
|
|
1543
1503
|
.attr('x', width + 65)
|
|
1544
1504
|
.attr('y', 9.5)
|
|
1545
1505
|
.attr('dy', '0.32em')
|
|
1546
|
-
.text(
|
|
1506
|
+
.text(d => d);
|
|
1547
1507
|
// Add title
|
|
1548
|
-
svg
|
|
1549
|
-
.append('text')
|
|
1508
|
+
svg.append('text')
|
|
1550
1509
|
.attr('x', width / 2)
|
|
1551
1510
|
.attr('y', -20)
|
|
1552
1511
|
.attr('text-anchor', 'middle')
|
|
@@ -1558,7 +1517,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1558
1517
|
const element = this.actionSuccessRateChart.nativeElement;
|
|
1559
1518
|
const data = Array.from(this.actionMetrics.byAction.entries()).map(([name, metrics]) => ({
|
|
1560
1519
|
name,
|
|
1561
|
-
value: metrics.successRate * 100
|
|
1520
|
+
value: metrics.successRate * 100
|
|
1562
1521
|
}));
|
|
1563
1522
|
if (data.length === 0)
|
|
1564
1523
|
return;
|
|
@@ -1567,44 +1526,41 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1567
1526
|
const margin = { top: 40, right: 20, bottom: 100, left: 60 };
|
|
1568
1527
|
const width = 320 - margin.left - margin.right;
|
|
1569
1528
|
const height = 200 - margin.top - margin.bottom;
|
|
1570
|
-
const svg = d3
|
|
1571
|
-
.select(element)
|
|
1529
|
+
const svg = d3.select(element)
|
|
1572
1530
|
.append('svg')
|
|
1573
1531
|
.attr('width', width + margin.left + margin.right)
|
|
1574
1532
|
.attr('height', height + margin.top + margin.bottom)
|
|
1575
1533
|
.append('g')
|
|
1576
1534
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
1577
|
-
const x = d3
|
|
1578
|
-
.scaleBand()
|
|
1535
|
+
const x = d3.scaleBand()
|
|
1579
1536
|
.range([0, width])
|
|
1580
|
-
.domain(data.map(
|
|
1537
|
+
.domain(data.map(d => d.name))
|
|
1581
1538
|
.padding(0.1);
|
|
1582
|
-
const y = d3.scaleLinear()
|
|
1539
|
+
const y = d3.scaleLinear()
|
|
1540
|
+
.domain([0, 100])
|
|
1541
|
+
.range([height, 0]);
|
|
1583
1542
|
// Add bars with color based on success rate
|
|
1584
|
-
svg
|
|
1585
|
-
.selectAll('.bar')
|
|
1543
|
+
svg.selectAll('.bar')
|
|
1586
1544
|
.data(data)
|
|
1587
|
-
.enter()
|
|
1588
|
-
.append('rect')
|
|
1545
|
+
.enter().append('rect')
|
|
1589
1546
|
.attr('class', 'bar')
|
|
1590
|
-
.attr('x',
|
|
1547
|
+
.attr('x', d => x(d.name) || 0)
|
|
1591
1548
|
.attr('width', x.bandwidth())
|
|
1592
|
-
.attr('y',
|
|
1593
|
-
.attr('height',
|
|
1594
|
-
.attr('fill',
|
|
1549
|
+
.attr('y', d => y(d.value))
|
|
1550
|
+
.attr('height', d => height - y(d.value))
|
|
1551
|
+
.attr('fill', d => d.value > 90 ? '#4bc0c0' : d.value > 70 ? '#ffce56' : '#ff6384');
|
|
1595
1552
|
// Add x axis
|
|
1596
|
-
svg
|
|
1597
|
-
.append('g')
|
|
1553
|
+
svg.append('g')
|
|
1598
1554
|
.attr('transform', `translate(0,${height})`)
|
|
1599
1555
|
.call(d3.axisBottom(x))
|
|
1600
1556
|
.selectAll('text')
|
|
1601
1557
|
.attr('transform', 'rotate(-45)')
|
|
1602
1558
|
.style('text-anchor', 'end');
|
|
1603
1559
|
// Add y axis
|
|
1604
|
-
svg.append('g')
|
|
1560
|
+
svg.append('g')
|
|
1561
|
+
.call(d3.axisLeft(y).tickFormat(d => `${d}%`));
|
|
1605
1562
|
// Add title
|
|
1606
|
-
svg
|
|
1607
|
-
.append('text')
|
|
1563
|
+
svg.append('text')
|
|
1608
1564
|
.attr('x', width / 2)
|
|
1609
1565
|
.attr('y', -20)
|
|
1610
1566
|
.attr('text-anchor', 'middle')
|
|
@@ -1616,7 +1572,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1616
1572
|
const element = this.stepTypeChart.nativeElement;
|
|
1617
1573
|
const data = Array.from(this.timelineMetrics.stepsByType.entries()).map(([name, value]) => ({
|
|
1618
1574
|
name,
|
|
1619
|
-
value
|
|
1575
|
+
value
|
|
1620
1576
|
}));
|
|
1621
1577
|
if (data.length === 0)
|
|
1622
1578
|
return;
|
|
@@ -1625,29 +1581,30 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1625
1581
|
const width = 300;
|
|
1626
1582
|
const height = 220;
|
|
1627
1583
|
const radius = Math.min(width, height) / 2 - 40;
|
|
1628
|
-
const svg = d3
|
|
1629
|
-
.select(element)
|
|
1584
|
+
const svg = d3.select(element)
|
|
1630
1585
|
.append('svg')
|
|
1631
1586
|
.attr('width', width)
|
|
1632
1587
|
.attr('height', height)
|
|
1633
1588
|
.append('g')
|
|
1634
1589
|
.attr('transform', `translate(${width / 2}, ${height / 2})`);
|
|
1635
1590
|
const color = d3.scaleOrdinal(d3.schemeSet3);
|
|
1636
|
-
const pie = d3
|
|
1637
|
-
.
|
|
1638
|
-
.value((d) => d.value)
|
|
1591
|
+
const pie = d3.pie()
|
|
1592
|
+
.value(d => d.value)
|
|
1639
1593
|
.sort(null);
|
|
1640
|
-
const arc = d3.arc()
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1594
|
+
const arc = d3.arc()
|
|
1595
|
+
.innerRadius(0)
|
|
1596
|
+
.outerRadius(radius);
|
|
1597
|
+
const arcs = svg.selectAll('arc')
|
|
1598
|
+
.data(pie(data))
|
|
1599
|
+
.enter()
|
|
1600
|
+
.append('g');
|
|
1601
|
+
arcs.append('path')
|
|
1644
1602
|
.attr('d', arc)
|
|
1645
1603
|
.attr('fill', (d, i) => color(i.toString()))
|
|
1646
1604
|
.attr('stroke', 'white')
|
|
1647
1605
|
.style('stroke-width', '2px');
|
|
1648
1606
|
// Add labels
|
|
1649
|
-
arcs
|
|
1650
|
-
.append('text')
|
|
1607
|
+
arcs.append('text')
|
|
1651
1608
|
.attr('transform', (d) => {
|
|
1652
1609
|
const centroid = arc.centroid(d);
|
|
1653
1610
|
return `translate(${centroid})`;
|
|
@@ -1655,10 +1612,9 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1655
1612
|
.attr('text-anchor', 'middle')
|
|
1656
1613
|
.style('font-size', '12px')
|
|
1657
1614
|
.style('fill', 'white')
|
|
1658
|
-
.text((d) =>
|
|
1615
|
+
.text((d) => d.data.value > 0 ? d.data.value : '');
|
|
1659
1616
|
// Add title
|
|
1660
|
-
svg
|
|
1661
|
-
.append('text')
|
|
1617
|
+
svg.append('text')
|
|
1662
1618
|
.attr('x', 0)
|
|
1663
1619
|
.attr('y', -radius - 25)
|
|
1664
1620
|
.attr('text-anchor', 'middle')
|
|
@@ -1667,8 +1623,8 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1667
1623
|
.text('Step Type Distribution');
|
|
1668
1624
|
}
|
|
1669
1625
|
calculatePromptSuccessRate(promptName) {
|
|
1670
|
-
const successfulRuns = this.allPromptRuns.filter(
|
|
1671
|
-
const totalRuns = this.allPromptRuns.filter(
|
|
1626
|
+
const successfulRuns = this.allPromptRuns.filter(run => run.Prompt === promptName && run.Success === true).length;
|
|
1627
|
+
const totalRuns = this.allPromptRuns.filter(run => run.Prompt === promptName).length;
|
|
1672
1628
|
if (totalRuns === 0)
|
|
1673
1629
|
return '0';
|
|
1674
1630
|
return ((successfulRuns / totalRuns) * 100).toFixed(1);
|
|
@@ -1684,14 +1640,14 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1684
1640
|
if (this.viewMode === 'grid') {
|
|
1685
1641
|
this.viewMode = 'expanded';
|
|
1686
1642
|
// Expand all charts
|
|
1687
|
-
Object.keys(this.expandedCharts).forEach(
|
|
1643
|
+
Object.keys(this.expandedCharts).forEach(key => {
|
|
1688
1644
|
this.expandedCharts[key] = true;
|
|
1689
1645
|
});
|
|
1690
1646
|
}
|
|
1691
1647
|
else {
|
|
1692
1648
|
this.viewMode = 'grid';
|
|
1693
1649
|
// Collapse all charts
|
|
1694
|
-
Object.keys(this.expandedCharts).forEach(
|
|
1650
|
+
Object.keys(this.expandedCharts).forEach(key => {
|
|
1695
1651
|
this.expandedCharts[key] = false;
|
|
1696
1652
|
});
|
|
1697
1653
|
}
|
|
@@ -1737,7 +1693,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1737
1693
|
totalCost: 0,
|
|
1738
1694
|
avgCost: 0,
|
|
1739
1695
|
inputTokens: 0,
|
|
1740
|
-
outputTokens: 0
|
|
1696
|
+
outputTokens: 0
|
|
1741
1697
|
});
|
|
1742
1698
|
}
|
|
1743
1699
|
const data = modelData.get(key);
|
|
@@ -1754,14 +1710,14 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1754
1710
|
}
|
|
1755
1711
|
getStepTypeIcon(stepType) {
|
|
1756
1712
|
const iconMap = {
|
|
1757
|
-
Prompts: 'fa-microchip',
|
|
1758
|
-
Actions: 'fa-cog',
|
|
1713
|
+
'Prompts': 'fa-microchip',
|
|
1714
|
+
'Actions': 'fa-cog',
|
|
1759
1715
|
'Sub-Agent': 'fa-robot',
|
|
1760
|
-
Start: 'fa-play-circle',
|
|
1761
|
-
End: 'fa-stop-circle',
|
|
1762
|
-
Decision: 'fa-code-branch',
|
|
1763
|
-
Loop: 'fa-sync',
|
|
1764
|
-
Error: 'fa-exclamation-triangle'
|
|
1716
|
+
'Start': 'fa-play-circle',
|
|
1717
|
+
'End': 'fa-stop-circle',
|
|
1718
|
+
'Decision': 'fa-code-branch',
|
|
1719
|
+
'Loop': 'fa-sync',
|
|
1720
|
+
'Error': 'fa-exclamation-triangle'
|
|
1765
1721
|
};
|
|
1766
1722
|
return iconMap[stepType] || 'fa-circle';
|
|
1767
1723
|
}
|
|
@@ -1777,7 +1733,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1777
1733
|
'rgba(199, 199, 199, 0.5)',
|
|
1778
1734
|
'rgba(83, 102, 255, 0.5)',
|
|
1779
1735
|
'rgba(255, 99, 255, 0.5)',
|
|
1780
|
-
'rgba(99, 255, 132, 0.5)'
|
|
1736
|
+
'rgba(99, 255, 132, 0.5)'
|
|
1781
1737
|
];
|
|
1782
1738
|
// Use a simple hash of the model name to consistently pick a color
|
|
1783
1739
|
let hash = 0;
|
|
@@ -1791,7 +1747,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1791
1747
|
const data = Array.from(this.promptMetrics.byPrompt.entries())
|
|
1792
1748
|
.map(([name, metrics]) => ({
|
|
1793
1749
|
name: name.length > 20 ? name.substring(0, 20) + '...' : name,
|
|
1794
|
-
value: metrics.avgTime
|
|
1750
|
+
value: metrics.avgTime
|
|
1795
1751
|
}))
|
|
1796
1752
|
.sort((a, b) => b.value - a.value)
|
|
1797
1753
|
.slice(0, 10); // Top 10 prompts by avg time
|
|
@@ -1802,37 +1758,31 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1802
1758
|
const margin = { top: 40, right: 20, bottom: 120, left: 80 };
|
|
1803
1759
|
const width = 320 - margin.left - margin.right;
|
|
1804
1760
|
const height = 200 - margin.top - margin.bottom;
|
|
1805
|
-
const svg = d3
|
|
1806
|
-
.select(element)
|
|
1761
|
+
const svg = d3.select(element)
|
|
1807
1762
|
.append('svg')
|
|
1808
1763
|
.attr('width', width + margin.left + margin.right)
|
|
1809
1764
|
.attr('height', height + margin.top + margin.bottom)
|
|
1810
1765
|
.append('g')
|
|
1811
1766
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
1812
|
-
const x = d3
|
|
1813
|
-
.scaleBand()
|
|
1767
|
+
const x = d3.scaleBand()
|
|
1814
1768
|
.range([0, width])
|
|
1815
|
-
.domain(data.map(
|
|
1769
|
+
.domain(data.map(d => d.name))
|
|
1816
1770
|
.padding(0.1);
|
|
1817
|
-
const y = d3
|
|
1818
|
-
.
|
|
1819
|
-
.domain([0, d3.max(data, (d) => d.value) || 0])
|
|
1771
|
+
const y = d3.scaleLinear()
|
|
1772
|
+
.domain([0, d3.max(data, d => d.value) || 0])
|
|
1820
1773
|
.range([height, 0]);
|
|
1821
1774
|
// Add bars
|
|
1822
|
-
svg
|
|
1823
|
-
.selectAll('.bar')
|
|
1775
|
+
svg.selectAll('.bar')
|
|
1824
1776
|
.data(data)
|
|
1825
|
-
.enter()
|
|
1826
|
-
.append('rect')
|
|
1777
|
+
.enter().append('rect')
|
|
1827
1778
|
.attr('class', 'bar')
|
|
1828
|
-
.attr('x',
|
|
1779
|
+
.attr('x', d => x(d.name) || 0)
|
|
1829
1780
|
.attr('width', x.bandwidth())
|
|
1830
|
-
.attr('y',
|
|
1831
|
-
.attr('height',
|
|
1781
|
+
.attr('y', d => y(d.value))
|
|
1782
|
+
.attr('height', d => height - y(d.value))
|
|
1832
1783
|
.attr('fill', '#667eea');
|
|
1833
1784
|
// Add x axis
|
|
1834
|
-
svg
|
|
1835
|
-
.append('g')
|
|
1785
|
+
svg.append('g')
|
|
1836
1786
|
.attr('transform', `translate(0,${height})`)
|
|
1837
1787
|
.call(d3.axisBottom(x))
|
|
1838
1788
|
.selectAll('text')
|
|
@@ -1840,10 +1790,10 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1840
1790
|
.style('text-anchor', 'end')
|
|
1841
1791
|
.style('font-size', '10px');
|
|
1842
1792
|
// Add y axis
|
|
1843
|
-
svg.append('g')
|
|
1793
|
+
svg.append('g')
|
|
1794
|
+
.call(d3.axisLeft(y).tickFormat(d => `${d}ms`));
|
|
1844
1795
|
// Add title
|
|
1845
|
-
svg
|
|
1846
|
-
.append('text')
|
|
1796
|
+
svg.append('text')
|
|
1847
1797
|
.attr('x', width / 2)
|
|
1848
1798
|
.attr('y', -20)
|
|
1849
1799
|
.attr('text-anchor', 'middle')
|
|
@@ -1863,18 +1813,18 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1863
1813
|
promptTokenData.set(promptName, existing);
|
|
1864
1814
|
}
|
|
1865
1815
|
const topPrompts = Array.from(promptTokenData.entries())
|
|
1866
|
-
.sort((a, b) => b[1].input + b[1].output - (a[1].input + a[1].output))
|
|
1816
|
+
.sort((a, b) => (b[1].input + b[1].output) - (a[1].input + a[1].output))
|
|
1867
1817
|
.slice(0, 8)
|
|
1868
1818
|
.map(([name]) => name);
|
|
1869
|
-
const inputData = topPrompts.map(
|
|
1819
|
+
const inputData = topPrompts.map(prompt => ({
|
|
1870
1820
|
prompt: prompt.length > 15 ? prompt.substring(0, 15) + '...' : prompt,
|
|
1871
1821
|
type: 'Input',
|
|
1872
|
-
value: promptTokenData.get(prompt)?.input || 0
|
|
1822
|
+
value: promptTokenData.get(prompt)?.input || 0
|
|
1873
1823
|
}));
|
|
1874
|
-
const outputData = topPrompts.map(
|
|
1824
|
+
const outputData = topPrompts.map(prompt => ({
|
|
1875
1825
|
prompt: prompt.length > 15 ? prompt.substring(0, 15) + '...' : prompt,
|
|
1876
1826
|
type: 'Output',
|
|
1877
|
-
value: promptTokenData.get(prompt)?.output || 0
|
|
1827
|
+
value: promptTokenData.get(prompt)?.output || 0
|
|
1878
1828
|
}));
|
|
1879
1829
|
const data = [...inputData, ...outputData];
|
|
1880
1830
|
if (data.length === 0)
|
|
@@ -1884,44 +1834,42 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1884
1834
|
const margin = { top: 40, right: 100, bottom: 100, left: 80 };
|
|
1885
1835
|
const width = 320 - margin.left - margin.right;
|
|
1886
1836
|
const height = 200 - margin.top - margin.bottom;
|
|
1887
|
-
const svg = d3
|
|
1888
|
-
.select(element)
|
|
1837
|
+
const svg = d3.select(element)
|
|
1889
1838
|
.append('svg')
|
|
1890
1839
|
.attr('width', width + margin.left + margin.right)
|
|
1891
1840
|
.attr('height', height + margin.top + margin.bottom)
|
|
1892
1841
|
.append('g')
|
|
1893
1842
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
1894
|
-
const x0 = d3
|
|
1895
|
-
.scaleBand()
|
|
1843
|
+
const x0 = d3.scaleBand()
|
|
1896
1844
|
.rangeRound([0, width])
|
|
1897
1845
|
.paddingInner(0.1)
|
|
1898
|
-
.domain(topPrompts.map(
|
|
1899
|
-
const x1 = d3.scaleBand()
|
|
1900
|
-
|
|
1901
|
-
.
|
|
1846
|
+
.domain(topPrompts.map(p => p.length > 15 ? p.substring(0, 15) + '...' : p));
|
|
1847
|
+
const x1 = d3.scaleBand()
|
|
1848
|
+
.padding(0.05)
|
|
1849
|
+
.domain(['Input', 'Output'])
|
|
1850
|
+
.rangeRound([0, x0.bandwidth()]);
|
|
1851
|
+
const y = d3.scaleLinear()
|
|
1902
1852
|
.rangeRound([height, 0])
|
|
1903
|
-
.domain([0, d3.max(data,
|
|
1904
|
-
const color = d3.scaleOrdinal()
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1853
|
+
.domain([0, d3.max(data, d => d.value) || 0]);
|
|
1854
|
+
const color = d3.scaleOrdinal()
|
|
1855
|
+
.domain(['Input', 'Output'])
|
|
1856
|
+
.range(['#764ba2', '#667eea']);
|
|
1857
|
+
const grouped = d3.group(data, d => d.prompt);
|
|
1858
|
+
svg.append('g')
|
|
1908
1859
|
.selectAll('g')
|
|
1909
1860
|
.data(grouped)
|
|
1910
|
-
.enter()
|
|
1911
|
-
.
|
|
1912
|
-
.attr('transform', (d) => `translate(${x0(d[0]) || 0},0)`)
|
|
1861
|
+
.enter().append('g')
|
|
1862
|
+
.attr('transform', d => `translate(${x0(d[0]) || 0},0)`)
|
|
1913
1863
|
.selectAll('rect')
|
|
1914
|
-
.data(
|
|
1915
|
-
.enter()
|
|
1916
|
-
.
|
|
1917
|
-
.attr('
|
|
1918
|
-
.attr('y', (d) => y(d.value))
|
|
1864
|
+
.data(d => d[1])
|
|
1865
|
+
.enter().append('rect')
|
|
1866
|
+
.attr('x', d => x1(d.type) || 0)
|
|
1867
|
+
.attr('y', d => y(d.value))
|
|
1919
1868
|
.attr('width', x1.bandwidth())
|
|
1920
|
-
.attr('height',
|
|
1921
|
-
.attr('fill',
|
|
1869
|
+
.attr('height', d => height - y(d.value))
|
|
1870
|
+
.attr('fill', d => color(d.type));
|
|
1922
1871
|
// Add x axis
|
|
1923
|
-
svg
|
|
1924
|
-
.append('g')
|
|
1872
|
+
svg.append('g')
|
|
1925
1873
|
.attr('transform', `translate(0,${height})`)
|
|
1926
1874
|
.call(d3.axisBottom(x0))
|
|
1927
1875
|
.selectAll('text')
|
|
@@ -1929,33 +1877,29 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1929
1877
|
.style('text-anchor', 'end')
|
|
1930
1878
|
.style('font-size', '10px');
|
|
1931
1879
|
// Add y axis
|
|
1932
|
-
svg.append('g')
|
|
1880
|
+
svg.append('g')
|
|
1881
|
+
.call(d3.axisLeft(y).tickFormat(d => d3.format('.2s')(d)));
|
|
1933
1882
|
// Add legend
|
|
1934
|
-
const legend = svg
|
|
1935
|
-
.append('g')
|
|
1883
|
+
const legend = svg.append('g')
|
|
1936
1884
|
.attr('font-family', 'sans-serif')
|
|
1937
1885
|
.attr('font-size', 10)
|
|
1938
1886
|
.attr('text-anchor', 'end')
|
|
1939
1887
|
.selectAll('g')
|
|
1940
1888
|
.data(['Input', 'Output'])
|
|
1941
|
-
.enter()
|
|
1942
|
-
.append('g')
|
|
1889
|
+
.enter().append('g')
|
|
1943
1890
|
.attr('transform', (d, i) => `translate(0,${i * 20})`);
|
|
1944
|
-
legend
|
|
1945
|
-
.append('rect')
|
|
1891
|
+
legend.append('rect')
|
|
1946
1892
|
.attr('x', width + 70)
|
|
1947
1893
|
.attr('width', 19)
|
|
1948
1894
|
.attr('height', 19)
|
|
1949
|
-
.attr('fill',
|
|
1950
|
-
legend
|
|
1951
|
-
.append('text')
|
|
1895
|
+
.attr('fill', d => color(d));
|
|
1896
|
+
legend.append('text')
|
|
1952
1897
|
.attr('x', width + 65)
|
|
1953
1898
|
.attr('y', 9.5)
|
|
1954
1899
|
.attr('dy', '0.32em')
|
|
1955
|
-
.text(
|
|
1900
|
+
.text(d => d);
|
|
1956
1901
|
// Add title
|
|
1957
|
-
svg
|
|
1958
|
-
.append('text')
|
|
1902
|
+
svg.append('text')
|
|
1959
1903
|
.attr('x', width / 2)
|
|
1960
1904
|
.attr('y', -20)
|
|
1961
1905
|
.attr('text-anchor', 'middle')
|
|
@@ -1976,7 +1920,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1976
1920
|
.filter(([_, cost]) => cost > 0)
|
|
1977
1921
|
.map(([name, cost]) => ({
|
|
1978
1922
|
name: name.length > 20 ? name.substring(0, 20) + '...' : name,
|
|
1979
|
-
value: cost
|
|
1923
|
+
value: cost
|
|
1980
1924
|
}))
|
|
1981
1925
|
.sort((a, b) => b.value - a.value)
|
|
1982
1926
|
.slice(0, 10); // Top 10 prompts by cost
|
|
@@ -1987,32 +1931,30 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
1987
1931
|
const width = 300;
|
|
1988
1932
|
const height = 220;
|
|
1989
1933
|
const radius = Math.min(width, height) / 2 - 40;
|
|
1990
|
-
const svg = d3
|
|
1991
|
-
.select(element)
|
|
1934
|
+
const svg = d3.select(element)
|
|
1992
1935
|
.append('svg')
|
|
1993
1936
|
.attr('width', width)
|
|
1994
1937
|
.attr('height', height)
|
|
1995
1938
|
.append('g')
|
|
1996
1939
|
.attr('transform', `translate(${width / 2}, ${height / 2})`);
|
|
1997
1940
|
const color = d3.scaleOrdinal(d3.schemePurples[9].slice(2));
|
|
1998
|
-
const pie = d3
|
|
1999
|
-
.
|
|
2000
|
-
.value((d) => d.value)
|
|
1941
|
+
const pie = d3.pie()
|
|
1942
|
+
.value(d => d.value)
|
|
2001
1943
|
.sort((a, b) => b.value - a.value);
|
|
2002
|
-
const arc = d3
|
|
2003
|
-
.arc()
|
|
1944
|
+
const arc = d3.arc()
|
|
2004
1945
|
.innerRadius(radius * 0.5)
|
|
2005
1946
|
.outerRadius(radius);
|
|
2006
|
-
const arcs = svg.selectAll('arc')
|
|
2007
|
-
|
|
2008
|
-
.
|
|
1947
|
+
const arcs = svg.selectAll('arc')
|
|
1948
|
+
.data(pie(data))
|
|
1949
|
+
.enter()
|
|
1950
|
+
.append('g');
|
|
1951
|
+
arcs.append('path')
|
|
2009
1952
|
.attr('d', arc)
|
|
2010
1953
|
.attr('fill', (d, i) => color(i.toString()))
|
|
2011
1954
|
.attr('stroke', 'white')
|
|
2012
1955
|
.style('stroke-width', '2px');
|
|
2013
1956
|
// Add title
|
|
2014
|
-
svg
|
|
2015
|
-
.append('text')
|
|
1957
|
+
svg.append('text')
|
|
2016
1958
|
.attr('x', 0)
|
|
2017
1959
|
.attr('y', -radius - 25)
|
|
2018
1960
|
.attr('text-anchor', 'middle')
|
|
@@ -2020,15 +1962,13 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2020
1962
|
.style('font-weight', 'bold')
|
|
2021
1963
|
.text('Cost Distribution by Prompt');
|
|
2022
1964
|
// Add total cost in center
|
|
2023
|
-
svg
|
|
2024
|
-
.append('text')
|
|
1965
|
+
svg.append('text')
|
|
2025
1966
|
.attr('text-anchor', 'middle')
|
|
2026
1967
|
.attr('dy', '-0.5em')
|
|
2027
1968
|
.style('font-size', '14px')
|
|
2028
1969
|
.style('font-weight', 'bold')
|
|
2029
1970
|
.text('Total Cost');
|
|
2030
|
-
svg
|
|
2031
|
-
.append('text')
|
|
1971
|
+
svg.append('text')
|
|
2032
1972
|
.attr('text-anchor', 'middle')
|
|
2033
1973
|
.attr('dy', '1em')
|
|
2034
1974
|
.style('font-size', '18px')
|
|
@@ -2040,7 +1980,7 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2040
1980
|
const data = Array.from(this.promptMetrics.byPrompt.entries())
|
|
2041
1981
|
.map(([name, metrics]) => ({
|
|
2042
1982
|
name: name.length > 20 ? name.substring(0, 20) + '...' : name,
|
|
2043
|
-
value: metrics.count
|
|
1983
|
+
value: metrics.count
|
|
2044
1984
|
}))
|
|
2045
1985
|
.sort((a, b) => b.value - a.value)
|
|
2046
1986
|
.slice(0, 10); // Top 10 prompts by count
|
|
@@ -2051,61 +1991,58 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2051
1991
|
const margin = { top: 40, right: 20, bottom: 120, left: 60 };
|
|
2052
1992
|
const width = 320 - margin.left - margin.right;
|
|
2053
1993
|
const height = 200 - margin.top - margin.bottom;
|
|
2054
|
-
const svg = d3
|
|
2055
|
-
.select(element)
|
|
1994
|
+
const svg = d3.select(element)
|
|
2056
1995
|
.append('svg')
|
|
2057
1996
|
.attr('width', width + margin.left + margin.right)
|
|
2058
1997
|
.attr('height', height + margin.top + margin.bottom)
|
|
2059
1998
|
.append('g')
|
|
2060
1999
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
2061
|
-
const x = d3
|
|
2062
|
-
.scaleBand()
|
|
2000
|
+
const x = d3.scaleBand()
|
|
2063
2001
|
.range([0, width])
|
|
2064
|
-
.domain(data.map(
|
|
2002
|
+
.domain(data.map(d => d.name))
|
|
2065
2003
|
.padding(0.1);
|
|
2066
|
-
const y = d3
|
|
2067
|
-
.
|
|
2068
|
-
.domain([0, d3.max(data, (d) => d.value) || 0])
|
|
2004
|
+
const y = d3.scaleLinear()
|
|
2005
|
+
.domain([0, d3.max(data, d => d.value) || 0])
|
|
2069
2006
|
.range([height, 0]);
|
|
2070
2007
|
// Create gradient
|
|
2071
|
-
const gradient = svg
|
|
2072
|
-
.append('defs')
|
|
2008
|
+
const gradient = svg.append('defs')
|
|
2073
2009
|
.append('linearGradient')
|
|
2074
2010
|
.attr('id', 'promptCountGradient')
|
|
2075
2011
|
.attr('x1', '0%')
|
|
2076
2012
|
.attr('y1', '0%')
|
|
2077
2013
|
.attr('x2', '0%')
|
|
2078
2014
|
.attr('y2', '100%');
|
|
2079
|
-
gradient.append('stop')
|
|
2080
|
-
|
|
2015
|
+
gradient.append('stop')
|
|
2016
|
+
.attr('offset', '0%')
|
|
2017
|
+
.attr('stop-color', '#667eea')
|
|
2018
|
+
.attr('stop-opacity', 1);
|
|
2019
|
+
gradient.append('stop')
|
|
2020
|
+
.attr('offset', '100%')
|
|
2021
|
+
.attr('stop-color', '#764ba2')
|
|
2022
|
+
.attr('stop-opacity', 1);
|
|
2081
2023
|
// Add bars
|
|
2082
|
-
svg
|
|
2083
|
-
.selectAll('.bar')
|
|
2024
|
+
svg.selectAll('.bar')
|
|
2084
2025
|
.data(data)
|
|
2085
|
-
.enter()
|
|
2086
|
-
.append('rect')
|
|
2026
|
+
.enter().append('rect')
|
|
2087
2027
|
.attr('class', 'bar')
|
|
2088
|
-
.attr('x',
|
|
2028
|
+
.attr('x', d => x(d.name) || 0)
|
|
2089
2029
|
.attr('width', x.bandwidth())
|
|
2090
|
-
.attr('y',
|
|
2091
|
-
.attr('height',
|
|
2030
|
+
.attr('y', d => y(d.value))
|
|
2031
|
+
.attr('height', d => height - y(d.value))
|
|
2092
2032
|
.attr('fill', 'url(#promptCountGradient)');
|
|
2093
2033
|
// Add value labels on bars
|
|
2094
|
-
svg
|
|
2095
|
-
.selectAll('.bar-label')
|
|
2034
|
+
svg.selectAll('.bar-label')
|
|
2096
2035
|
.data(data)
|
|
2097
|
-
.enter()
|
|
2098
|
-
.append('text')
|
|
2036
|
+
.enter().append('text')
|
|
2099
2037
|
.attr('class', 'bar-label')
|
|
2100
|
-
.attr('x',
|
|
2101
|
-
.attr('y',
|
|
2038
|
+
.attr('x', d => (x(d.name) || 0) + x.bandwidth() / 2)
|
|
2039
|
+
.attr('y', d => y(d.value) - 5)
|
|
2102
2040
|
.attr('text-anchor', 'middle')
|
|
2103
2041
|
.style('font-size', '12px')
|
|
2104
2042
|
.style('font-weight', 'bold')
|
|
2105
|
-
.text(
|
|
2043
|
+
.text(d => d.value);
|
|
2106
2044
|
// Add x axis
|
|
2107
|
-
svg
|
|
2108
|
-
.append('g')
|
|
2045
|
+
svg.append('g')
|
|
2109
2046
|
.attr('transform', `translate(0,${height})`)
|
|
2110
2047
|
.call(d3.axisBottom(x))
|
|
2111
2048
|
.selectAll('text')
|
|
@@ -2113,10 +2050,10 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2113
2050
|
.style('text-anchor', 'end')
|
|
2114
2051
|
.style('font-size', '10px');
|
|
2115
2052
|
// Add y axis
|
|
2116
|
-
svg.append('g')
|
|
2053
|
+
svg.append('g')
|
|
2054
|
+
.call(d3.axisLeft(y));
|
|
2117
2055
|
// Add title
|
|
2118
|
-
svg
|
|
2119
|
-
.append('text')
|
|
2056
|
+
svg.append('text')
|
|
2120
2057
|
.attr('x', width / 2)
|
|
2121
2058
|
.attr('y', -20)
|
|
2122
2059
|
.attr('text-anchor', 'middle')
|
|
@@ -2160,13 +2097,15 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2160
2097
|
const stepsResult = await rv.RunView({
|
|
2161
2098
|
EntityName: 'MJ: AI Agent Run Steps',
|
|
2162
2099
|
ExtraFilter: `AgentRunID IN ('${agentRunIds.join("','")}') AND StepType = 'Prompt'`,
|
|
2163
|
-
ResultType: 'simple'
|
|
2100
|
+
ResultType: 'simple'
|
|
2164
2101
|
});
|
|
2165
2102
|
if (!stepsResult.Success || !stepsResult.Results || stepsResult.Results.length === 0) {
|
|
2166
2103
|
return [];
|
|
2167
2104
|
}
|
|
2168
2105
|
// Extract the TargetLogID values (these are the prompt run IDs)
|
|
2169
|
-
const promptRunIds = stepsResult.Results
|
|
2106
|
+
const promptRunIds = stepsResult.Results
|
|
2107
|
+
.map(step => step.TargetLogID)
|
|
2108
|
+
.filter(id => id); // Remove any null/undefined values
|
|
2170
2109
|
if (promptRunIds.length === 0) {
|
|
2171
2110
|
return [];
|
|
2172
2111
|
}
|
|
@@ -2175,9 +2114,9 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2175
2114
|
EntityName: 'MJ: AI Prompt Runs',
|
|
2176
2115
|
ExtraFilter: `ID IN ('${promptRunIds.join("','")}')`,
|
|
2177
2116
|
OrderBy: 'RunAt',
|
|
2178
|
-
ResultType: 'simple'
|
|
2117
|
+
ResultType: 'simple'
|
|
2179
2118
|
});
|
|
2180
|
-
return promptResult.Success ? promptResult.Results || [] : [];
|
|
2119
|
+
return promptResult.Success ? (promptResult.Results || []) : [];
|
|
2181
2120
|
}
|
|
2182
2121
|
/**
|
|
2183
2122
|
* TrackBy function for keyvalue pipe
|
|
@@ -2270,5 +2209,5 @@ export class AIAgentRunAnalyticsComponent {
|
|
|
2270
2209
|
type: ViewChild,
|
|
2271
2210
|
args: ['promptCountByNameChart', { static: false }]
|
|
2272
2211
|
}] }); })();
|
|
2273
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber:
|
|
2212
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AIAgentRunAnalyticsComponent, { className: "AIAgentRunAnalyticsComponent", filePath: "src/lib/custom/ai-agent-run/ai-agent-run-analytics.component.ts", lineNumber: 69 }); })();
|
|
2274
2213
|
//# sourceMappingURL=ai-agent-run-analytics.component.js.map
|