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