@memberjunction/ng-dashboards 5.38.0 → 5.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/README.md +14 -7
  2. package/dist/AI/components/agents/agent-configuration.component.js +199 -198
  3. package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
  4. package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
  5. package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
  6. package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
  7. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
  8. package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
  9. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
  10. package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
  11. package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
  12. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
  13. package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
  14. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
  15. package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
  16. package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
  17. package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
  18. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
  19. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
  20. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
  21. package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
  22. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
  23. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
  24. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
  25. package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
  26. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +217 -860
  27. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
  28. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1717 -7802
  29. package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
  30. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts +56 -0
  31. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.d.ts.map +1 -0
  32. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js +423 -0
  33. package/dist/AI/components/autotagging/components/classify-item-drilldown.component.js.map +1 -0
  34. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts +70 -0
  35. package/dist/AI/components/autotagging/components/classify-item-grid.component.d.ts.map +1 -0
  36. package/dist/AI/components/autotagging/components/classify-item-grid.component.js +308 -0
  37. package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -0
  38. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts +29 -0
  39. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -0
  40. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +186 -0
  41. package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -0
  42. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts +69 -0
  43. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.d.ts.map +1 -0
  44. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js +278 -0
  45. package/dist/AI/components/autotagging/components/classify-overview-analytics.component.js.map +1 -0
  46. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts +73 -0
  47. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.d.ts.map +1 -0
  48. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js +393 -0
  49. package/dist/AI/components/autotagging/components/classify-seed-taxonomy.component.js.map +1 -0
  50. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts +122 -0
  51. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.d.ts.map +1 -0
  52. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js +908 -0
  53. package/dist/AI/components/autotagging/dialogs/classify-setup-wizard.component.js.map +1 -0
  54. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
  55. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
  56. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
  57. package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
  58. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
  59. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
  60. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
  61. package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
  62. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
  63. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
  64. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
  65. package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
  66. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +333 -0
  67. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
  68. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +2125 -0
  69. package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
  70. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
  71. package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
  72. package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
  73. package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
  74. package/dist/AI/components/autotagging/shared/classify.format.d.ts +58 -0
  75. package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
  76. package/dist/AI/components/autotagging/shared/classify.format.js +260 -0
  77. package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
  78. package/dist/AI/components/autotagging/shared/classify.types.d.ts +319 -0
  79. package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
  80. package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
  81. package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
  82. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
  83. package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
  84. package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
  85. package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
  86. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +77 -0
  87. package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
  88. package/dist/AI/components/autotagging/tabs/history-tab.component.js +519 -0
  89. package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
  90. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
  91. package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
  92. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
  93. package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
  94. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +131 -0
  95. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
  96. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +813 -0
  97. package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
  98. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +177 -0
  99. package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
  100. package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1465 -0
  101. package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
  102. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +78 -0
  103. package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
  104. package/dist/AI/components/autotagging/tabs/tags-tab.component.js +492 -0
  105. package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
  106. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
  107. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
  108. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
  109. package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
  110. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +56 -0
  111. package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
  112. package/dist/AI/components/autotagging/tabs/types-tab.component.js +271 -0
  113. package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
  114. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +3 -0
  115. package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
  116. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +306 -290
  117. package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
  118. package/dist/AI/components/execution-monitoring.component.js +1 -1
  119. package/dist/AI/components/execution-monitoring.component.js.map +1 -1
  120. package/dist/AI/components/models/model-management.component.js +209 -208
  121. package/dist/AI/components/models/model-management.component.js.map +1 -1
  122. package/dist/AI/components/prompts/prompt-management.component.js +130 -128
  123. package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
  124. package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
  125. package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
  126. package/dist/AI/components/system/system-configuration.component.js +17 -17
  127. package/dist/AI/components/system/system-configuration.component.js.map +1 -1
  128. package/dist/AI/components/tags/tags-resource.component.d.ts +1 -0
  129. package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
  130. package/dist/AI/components/tags/tags-resource.component.js +578 -538
  131. package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
  132. package/dist/AI/components/vectors/vector-management-resource.component.d.ts +3 -0
  133. package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
  134. package/dist/AI/components/vectors/vector-management-resource.component.js +331 -303
  135. package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
  136. package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
  137. package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
  138. package/dist/AI/services/ai-instrumentation.service.js +14 -2
  139. package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
  140. package/dist/AI/services/cache-metrics.d.ts +50 -0
  141. package/dist/AI/services/cache-metrics.d.ts.map +1 -0
  142. package/dist/AI/services/cache-metrics.js +43 -0
  143. package/dist/AI/services/cache-metrics.js.map +1 -0
  144. package/dist/APIKeys/api-applications-panel.component.js +2 -2
  145. package/dist/APIKeys/api-key-create-dialog.component.js +2 -2
  146. package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
  147. package/dist/APIKeys/api-keys-resource.component.js +132 -131
  148. package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
  149. package/dist/Actions/components/actions-overview.component.js +141 -141
  150. package/dist/Actions/components/actions-overview.component.js.map +1 -1
  151. package/dist/Actions/components/execution-monitoring.component.js +15 -15
  152. package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
  153. package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
  154. package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
  155. package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
  156. package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
  157. package/dist/Admin/admin-data-schema.component.js +2 -2
  158. package/dist/Admin/admin-data-schema.component.js.map +1 -1
  159. package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
  160. package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
  161. package/dist/Admin/admin-identity-access.component.js +2 -2
  162. package/dist/Admin/admin-identity-access.component.js.map +1 -1
  163. package/dist/Admin/admin-monitoring.component.js +2 -2
  164. package/dist/Admin/admin-monitoring.component.js.map +1 -1
  165. package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
  166. package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
  167. package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
  168. package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
  169. package/dist/Communication/communication-logs-resource.component.js +72 -50
  170. package/dist/Communication/communication-logs-resource.component.js.map +1 -1
  171. package/dist/Communication/communication-monitor-resource.component.js +103 -102
  172. package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
  173. package/dist/Communication/communication-providers-resource.component.js +52 -51
  174. package/dist/Communication/communication-providers-resource.component.js.map +1 -1
  175. package/dist/Communication/communication-runs-resource.component.js +39 -38
  176. package/dist/Communication/communication-runs-resource.component.js.map +1 -1
  177. package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
  178. package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
  179. package/dist/Communication/communication-templates-resource.component.js +92 -89
  180. package/dist/Communication/communication-templates-resource.component.js.map +1 -1
  181. package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
  182. package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
  183. package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
  184. package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
  185. package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
  186. package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
  187. package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
  188. package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
  189. package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
  190. package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
  191. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +31 -340
  192. package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
  193. package/dist/DataExplorer/data-explorer-dashboard.component.js +468 -1958
  194. package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
  195. package/dist/DataExplorer/data-explorer-resource.component.d.ts.map +1 -1
  196. package/dist/DataExplorer/data-explorer-resource.component.js +10 -0
  197. package/dist/DataExplorer/data-explorer-resource.component.js.map +1 -1
  198. package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
  199. package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
  200. package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
  201. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
  202. package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
  203. package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
  204. package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
  205. package/dist/DevTools/app-state-inspector.component.js +18 -17
  206. package/dist/DevTools/app-state-inspector.component.js.map +1 -1
  207. package/dist/DevTools/class-registry.component.js +88 -85
  208. package/dist/DevTools/class-registry.component.js.map +1 -1
  209. package/dist/DevTools/event-monitor.component.js +155 -150
  210. package/dist/DevTools/event-monitor.component.js.map +1 -1
  211. package/dist/DevTools/graphql-console.component.js +245 -243
  212. package/dist/DevTools/graphql-console.component.js.map +1 -1
  213. package/dist/DevTools/layout-inspector.component.js +18 -17
  214. package/dist/DevTools/layout-inspector.component.js.map +1 -1
  215. package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
  216. package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
  217. package/dist/Home/home-dashboard.component.js +2 -2
  218. package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
  219. package/dist/Integration/components/activity/activity.component.js +236 -229
  220. package/dist/Integration/components/activity/activity.component.js.map +1 -1
  221. package/dist/Integration/components/connections/connections.component.js +390 -389
  222. package/dist/Integration/components/connections/connections.component.js.map +1 -1
  223. package/dist/Integration/components/overview/overview.component.js +2 -2
  224. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.d.ts.map +1 -1
  225. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +14 -11
  226. package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
  227. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts +27 -2
  228. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.d.ts.map +1 -1
  229. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +244 -119
  230. package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
  231. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
  232. package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
  233. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
  234. package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
  235. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts +65 -0
  236. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.d.ts.map +1 -0
  237. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js +176 -0
  238. package/dist/KnowledgeHub/components/visualize/record-drilldown/record-drilldown.component.js.map +1 -0
  239. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts +81 -0
  240. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.d.ts.map +1 -0
  241. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js +308 -0
  242. package/dist/KnowledgeHub/components/visualize/tag-cloud/tag-cloud.component.js.map +1 -0
  243. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts +85 -0
  244. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.d.ts.map +1 -0
  245. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js +362 -0
  246. package/dist/KnowledgeHub/components/visualize/visualize-resource.component.js.map +1 -0
  247. package/dist/KnowledgeHub/index.d.ts +3 -0
  248. package/dist/KnowledgeHub/index.d.ts.map +1 -1
  249. package/dist/KnowledgeHub/index.js +3 -0
  250. package/dist/KnowledgeHub/index.js.map +1 -1
  251. package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
  252. package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
  253. package/dist/Lists/components/lists-browse-resource.component.js +525 -566
  254. package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
  255. package/dist/Lists/components/lists-categories-resource.component.js +135 -134
  256. package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
  257. package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
  258. package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
  259. package/dist/MCP/components/mcp-server-dialog.component.js +2 -2
  260. package/dist/MCP/mcp-dashboard.component.js +443 -438
  261. package/dist/MCP/mcp-dashboard.component.js.map +1 -1
  262. package/dist/QueryBrowser/query-browser-resource.component.js +1 -1
  263. package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
  264. package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
  265. package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
  266. package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
  267. package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
  268. package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
  269. package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
  270. package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
  271. package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
  272. package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
  273. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
  274. package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
  275. package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
  276. package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
  277. package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
  278. package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
  279. package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
  280. package/dist/Testing/components/testing-explorer.component.js +436 -427
  281. package/dist/Testing/components/testing-explorer.component.js.map +1 -1
  282. package/dist/Testing/components/testing-runs-resource.component.js +1 -1
  283. package/dist/Testing/components/testing-runs.component.js +116 -115
  284. package/dist/Testing/components/testing-runs.component.js.map +1 -1
  285. package/dist/Testing/testing-dashboard.component.js +6 -7
  286. package/dist/Testing/testing-dashboard.component.js.map +1 -1
  287. package/dist/VersionHistory/components/labels-resource.component.js +173 -172
  288. package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
  289. package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
  290. package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
  291. package/dist/VersionHistory/components/restore-resource.component.js +116 -92
  292. package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
  293. package/dist/ai-dashboards.module.d.ts +57 -35
  294. package/dist/ai-dashboards.module.d.ts.map +1 -1
  295. package/dist/ai-dashboards.module.js +80 -1
  296. package/dist/ai-dashboards.module.js.map +1 -1
  297. package/dist/communication-dashboards.module.d.ts +1 -1
  298. package/dist/communication-dashboards.module.d.ts.map +1 -1
  299. package/dist/communication-dashboards.module.js +7 -1
  300. package/dist/communication-dashboards.module.js.map +1 -1
  301. package/dist/data-explorer-dashboards.module.d.ts +12 -14
  302. package/dist/data-explorer-dashboards.module.d.ts.map +1 -1
  303. package/dist/data-explorer-dashboards.module.js +5 -14
  304. package/dist/data-explorer-dashboards.module.js.map +1 -1
  305. package/dist/public-api.d.ts +3 -0
  306. package/dist/public-api.d.ts.map +1 -1
  307. package/dist/public-api.js +3 -0
  308. package/dist/public-api.js.map +1 -1
  309. package/dist/testing-dashboards.module.d.ts +4 -5
  310. package/dist/testing-dashboards.module.d.ts.map +1 -1
  311. package/dist/testing-dashboards.module.js +7 -5
  312. package/dist/testing-dashboards.module.js.map +1 -1
  313. package/package.json +57 -54
  314. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts +0 -79
  315. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.d.ts.map +0 -1
  316. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js +0 -195
  317. package/dist/DataExplorer/components/filter-dialog/filter-dialog.component.js.map +0 -1
  318. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts +0 -226
  319. package/dist/DataExplorer/components/view-selector/view-selector.component.d.ts.map +0 -1
  320. package/dist/DataExplorer/components/view-selector/view-selector.component.js +0 -861
  321. package/dist/DataExplorer/components/view-selector/view-selector.component.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cost-budget.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/cost-budget/cost-budget.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Cost & Budget Analytics -- Option B.\n *\n * Displays cost KPIs with period deltas, a daily cost bar chart with anomaly detection,\n * a cost breakdown treemap, and a detailed cost-by-model table with CSV export.\n */\n\nimport {\n Component, Input, Output, EventEmitter,\n OnInit, OnDestroy, ChangeDetectorRef, inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RunView } from '@memberjunction/core';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { GlobalFilterState } from '../../../interfaces/analytics-preferences.interface';\n\n// ── Interfaces ──\n\ninterface PromptRunRecord {\n ID: string;\n RunAt: string;\n Cost: number | null;\n TotalCost: number | null;\n TokensPrompt: number | null;\n TokensCompletion: number | null;\n TokensUsed: number | null;\n ModelID: string | null;\n Model: string | null;\n VendorID: string | null;\n Vendor: string | null;\n Success: boolean;\n}\n\ninterface CostKpi {\n Label: string;\n Value: string;\n Delta: number | null;\n DeltaDirection: 'up' | 'down' | 'stable';\n Highlighted: boolean;\n Icon: string;\n}\n\ninterface DailyBar {\n Date: string;\n Label: string;\n Cost: number;\n HeightPercent: number;\n IsAnomaly: boolean;\n}\n\ninterface TreemapCell {\n Label: string;\n Cost: number;\n Percent: number;\n Color: string;\n GridArea: string;\n}\n\ninterface CostByModelRow {\n Model: string;\n Vendor: string;\n Runs: number;\n InputTokens: number;\n OutputTokens: number;\n InputCost: number;\n OutputCost: number;\n TotalCost: number;\n PercentOfTotal: number;\n}\n\nconst FIELDS = [\n 'ID', 'RunAt', 'Cost', 'TotalCost', 'TokensPrompt', 'TokensCompletion',\n 'TokensUsed', 'ModelID', 'Model', 'VendorID', 'Vendor', 'Success'\n];\n\nconst TIME_RANGE_OPTIONS = ['Today', '7d', '30d', 'MTD'];\n\nconst TREEMAP_COLORS = [\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-accent, var(--mj-brand-primary-hover))',\n 'var(--mj-status-info)',\n 'var(--mj-status-success)',\n 'var(--mj-status-warning)',\n 'var(--mj-text-disabled)'\n];\n\n@Component({\n standalone: false,\n selector: 'app-analytics-cost-budget',\n template: `\n\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading cost data...\"></mj-loading>\n </div>\n } @else {\n <!-- Cost KPI Row -->\n <div class=\"kpi-row\">\n @for (kpi of CostKpis; track kpi.Label) {\n <div class=\"kpi-card\" [class.kpi-card--highlighted]=\"kpi.Highlighted\">\n <div class=\"kpi-icon\">\n <i [class]=\"kpi.Icon\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-label\">{{ kpi.Label }}</div>\n <div class=\"kpi-value\">{{ kpi.Value }}</div>\n @if (kpi.Delta != null) {\n <div class=\"kpi-delta\"\n [class.kpi-delta--up]=\"kpi.DeltaDirection === 'up'\"\n [class.kpi-delta--down]=\"kpi.DeltaDirection === 'down'\">\n @if (kpi.DeltaDirection === 'up') {\n <i class=\"fa-solid fa-arrow-up\"></i>\n } @else if (kpi.DeltaDirection === 'down') {\n <i class=\"fa-solid fa-arrow-down\"></i>\n }\n {{ kpi.Delta | number:'1.1-1' }}% vs prev\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Two-Column Layout -->\n <div class=\"two-col\">\n <!-- Daily Cost Trend -->\n <div class=\"panel panel-chart\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-column panel-header__icon\"></i>\n Daily Cost Trend\n </div>\n </div>\n <div class=\"chart-body\">\n @if (DailyBars.length === 0) {\n <div class=\"panel-empty\">No cost data for selected period</div>\n } @else {\n <div class=\"bar-chart\">\n <div class=\"bar-chart-area\">\n @if (AvgLinePercent > 0) {\n <div class=\"avg-line\" [style.bottom.%]=\"AvgLinePercent\">\n <span class=\"avg-label\">avg</span>\n </div>\n }\n @for (bar of DailyBars; track bar.Date) {\n <div class=\"bar-col\" [title]=\"bar.Label + ': ' + FormatCurrency(bar.Cost)\">\n <div\n class=\"bar\"\n [class.bar--anomaly]=\"bar.IsAnomaly\"\n [style.height.%]=\"bar.HeightPercent\"\n ></div>\n <div class=\"bar-label\">{{ bar.Label }}</div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Cost Breakdown Treemap -->\n <div class=\"panel panel-treemap\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-pie panel-header__icon\"></i>\n Cost by Vendor\n </div>\n </div>\n <div class=\"treemap-body\">\n @if (TreemapCells.length === 0) {\n <div class=\"panel-empty\">No vendor cost data</div>\n } @else {\n <div class=\"treemap-grid\">\n @for (cell of TreemapCells; track cell.Label) {\n <div\n class=\"treemap-cell\"\n [style.background]=\"cell.Color\"\n [style.flex-basis.%]=\"cell.Percent\"\n [title]=\"cell.Label + ': ' + FormatCurrency(cell.Cost) + ' (' + (cell.Percent | number:'1.0-0') + '%)'\">\n <span class=\"treemap-label\">{{ cell.Label }}</span>\n <span class=\"treemap-value\">{{ FormatCurrency(cell.Cost) }}</span>\n <span class=\"treemap-pct\">{{ cell.Percent | number:'1.0-0' }}%</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Cost by Model Table -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-table panel-header__icon\"></i>\n Cost by Model\n </div>\n <button class=\"export-btn\" (click)=\"ExportCSV()\">\n <i class=\"fa-solid fa-download\"></i>\n Export CSV\n </button>\n </div>\n <div class=\"table-wrapper\">\n <table class=\"data-table\">\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th class=\"col-numeric\">Runs</th>\n <th class=\"col-numeric\">Input Tokens</th>\n <th class=\"col-numeric\">Output Tokens</th>\n <th class=\"col-numeric\">Input Cost</th>\n <th class=\"col-numeric\">Output Cost</th>\n <th class=\"col-numeric\">Total Cost</th>\n <th class=\"col-numeric\">% of Total</th>\n </tr>\n </thead>\n <tbody>\n @if (CostByModelRows.length === 0) {\n <tr><td colspan=\"9\" class=\"empty-row\">No data available</td></tr>\n }\n @for (row of CostByModelRows; track row.Model) {\n <tr>\n <td class=\"cell-model\">{{ row.Model }}</td>\n <td class=\"cell-vendor\">{{ row.Vendor }}</td>\n <td class=\"cell-numeric\">{{ row.Runs | number }}</td>\n <td class=\"cell-numeric\">{{ row.InputTokens | number }}</td>\n <td class=\"cell-numeric\">{{ row.OutputTokens | number }}</td>\n <td class=\"cell-numeric\">{{ FormatCurrency(row.InputCost, 4) }}</td>\n <td class=\"cell-numeric\">{{ FormatCurrency(row.OutputCost, 4) }}</td>\n <td class=\"cell-numeric cell-cost\">{{ FormatCurrency(row.TotalCost) }}</td>\n <td class=\"cell-numeric\">{{ row.PercentOfTotal | number:'1.1-1' }}%</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n `,\n styles: [`\n :host { display: block; }\n\n .loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n /* ── KPI Row ── */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n margin: 16px 0;\n }\n\n .kpi-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 16px;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n\n .kpi-card--highlighted {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n }\n\n .kpi-icon {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n }\n\n .kpi-card--highlighted .kpi-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n }\n\n .kpi-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kpi-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 2px 0;\n letter-spacing: -0.02em;\n }\n\n .kpi-delta {\n font-size: 11px;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 3px;\n }\n\n .kpi-delta--up {\n color: var(--mj-status-error);\n }\n\n .kpi-delta--down {\n color: var(--mj-status-success);\n }\n\n /* ── Two-Column Layout ── */\n .two-col {\n display: grid;\n grid-template-columns: 3fr 2fr;\n gap: 16px;\n margin-bottom: 16px;\n }\n\n /* ── Panel ── */\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n margin-bottom: 16px;\n }\n\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .panel-header__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .panel-header__icon {\n font-size: 13px;\n color: var(--mj-brand-primary);\n }\n\n .panel-empty {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n .export-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n\n .export-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n /* ── Bar Chart ── */\n .chart-body {\n padding: 16px 18px;\n }\n\n .bar-chart {\n width: 100%;\n }\n\n .bar-chart-area {\n display: flex;\n align-items: flex-end;\n gap: 4px;\n height: 180px;\n position: relative;\n padding-bottom: 24px;\n }\n\n .bar-col {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n justify-content: flex-end;\n }\n\n .bar {\n width: 100%;\n max-width: 32px;\n border-radius: 4px 4px 0 0;\n background: var(--mj-brand-primary);\n transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 2px;\n }\n\n .bar--anomaly {\n background: var(--mj-status-error);\n }\n\n .bar-label {\n font-size: 10px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n white-space: nowrap;\n }\n\n .avg-line {\n position: absolute;\n left: 0;\n right: 0;\n border-top: 2px dashed var(--mj-text-disabled);\n z-index: 1;\n pointer-events: none;\n }\n\n .avg-label {\n position: absolute;\n right: 0;\n top: -14px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 600;\n }\n\n /* ── Treemap ── */\n .treemap-body {\n padding: 16px 18px;\n }\n\n .treemap-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n min-height: 160px;\n }\n\n .treemap-cell {\n border-radius: 8px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-width: 80px;\n min-height: 70px;\n flex-grow: 1;\n color: var(--mj-text-inverse, white);\n transition: opacity 0.2s;\n }\n\n .treemap-cell:hover {\n opacity: 0.85;\n }\n\n .treemap-label {\n font-size: 12px;\n font-weight: 600;\n opacity: 0.95;\n }\n\n .treemap-value {\n font-size: 16px;\n font-weight: 700;\n margin-top: 2px;\n }\n\n .treemap-pct {\n font-size: 11px;\n opacity: 0.8;\n }\n\n /* ── Table ── */\n .table-wrapper {\n overflow-x: auto;\n }\n\n .data-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table th,\n .data-table td {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table th {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: var(--mj-bg-surface-card);\n position: sticky;\n top: 0;\n white-space: nowrap;\n }\n\n .col-numeric { text-align: right; }\n\n .data-table tbody tr {\n transition: background 0.15s;\n }\n\n .data-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n .cell-model {\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .cell-vendor {\n color: var(--mj-text-secondary);\n }\n\n .cell-numeric {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-cost {\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* ── Responsive ── */\n @media (max-width: 1200px) {\n .two-col {\n grid-template-columns: 1fr;\n }\n }\n\n @media (max-width: 768px) {\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .kpi-value {\n font-size: 18px;\n }\n }\n `]\n})\nexport class AnalyticsCostBudgetComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private _timeRange = '7d';\n @Input()\n set TimeRange(value: string) {\n const prev = this._timeRange;\n this._timeRange = value;\n if (prev !== value && this.initialized) this.LoadData();\n }\n get TimeRange(): string { return this._timeRange; }\n\n private _filters: GlobalFilterState = { Models: [], Agents: [], Prompts: [], Statuses: [] };\n @Input()\n set Filters(value: GlobalFilterState) {\n const next = value ?? { Models: [], Agents: [], Prompts: [], Statuses: [] };\n const changed = !this.shallowFiltersEqual(this._filters, next);\n this._filters = next;\n if (changed && this.initialized) this.LoadData();\n }\n get Filters(): GlobalFilterState { return this._filters; }\n\n private shallowFiltersEqual(a: GlobalFilterState, b: GlobalFilterState): boolean {\n const sameArr = (x: string[], y: string[]) => x.length === y.length && x.every((v, i) => v === y[i]);\n return sameArr(a.Models, b.Models) && sameArr(a.Agents, b.Agents) && sameArr(a.Prompts, b.Prompts) && sameArr(a.Statuses, b.Statuses);\n }\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<GlobalFilterState>();\n\n private initialized = false;\n\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n\n public IsLoading = false;\n public TimeRangeOptionsList = TIME_RANGE_OPTIONS;\n\n public CostKpis: CostKpi[] = [];\n public DailyBars: DailyBar[] = [];\n public AvgLinePercent = 0;\n public TreemapCells: TreemapCell[] = [];\n public CostByModelRows: CostByModelRow[] = [];\n\n private allRuns: PromptRunRecord[] = [];\n private previousPeriodRuns: PromptRunRecord[] = [];\n\n ngOnInit(): void {\n this.initialized = true;\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ── Public Handlers ──\n\n public OnTimeRangeChange(range: string): void {\n this.TimeRange = range;\n this.TimeRangeChange.emit(range);\n this.LoadData();\n }\n\n public OnFiltersChange(filters: GlobalFilterState): void {\n this.Filters = filters;\n this.FiltersChange.emit(filters);\n this.LoadData();\n }\n\n public FormatCurrency(value: number, decimals = 2): string {\n if (value === 0) return '$0.00';\n if (value < 0.01 && decimals < 4) decimals = 4;\n return '$' + value.toFixed(decimals);\n }\n\n public ExportCSV(): void {\n const header = 'Model,Vendor,Runs,Input Tokens,Output Tokens,Input Cost,Output Cost,Total Cost,% of Total';\n const rows = this.CostByModelRows.map(r =>\n `\"${r.Model}\",\"${r.Vendor}\",${r.Runs},${r.InputTokens},${r.OutputTokens},${r.InputCost.toFixed(6)},${r.OutputCost.toFixed(6)},${r.TotalCost.toFixed(6)},${r.PercentOfTotal.toFixed(1)}`\n );\n const csv = [header, ...rows].join('\\n');\n this.downloadCSV(csv, 'cost-by-model.csv');\n }\n\n // ── Data Loading ──\n\n private async LoadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const { currentStart, previousStart } = this.getDateBounds();\n const now = new Date();\n const modelFilter = this.buildModelFilter();\n const currentFilter = this.combineDateAndModelFilter(currentStart, now, modelFilter);\n const prevFilter = this.combineDateAndModelFilter(previousStart, currentStart, modelFilter);\n\n const [currentResult, prevResult] = await rv.RunViews([\n {\n EntityName: 'MJ: AI Prompt Runs',\n ExtraFilter: currentFilter,\n Fields: FIELDS,\n OrderBy: 'RunAt ASC',\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: AI Prompt Runs',\n ExtraFilter: prevFilter,\n Fields: FIELDS,\n OrderBy: 'RunAt ASC',\n ResultType: 'simple'\n }\n ]);\n\n this.allRuns = (currentResult?.Results ?? []) as PromptRunRecord[];\n this.previousPeriodRuns = (prevResult?.Results ?? []) as PromptRunRecord[];\n\n this.computeKpis();\n this.computeDailyBars();\n this.computeTreemap();\n this.computeCostByModel();\n } catch (e) {\n console.error('Cost & Budget load error:', e);\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n // ── Computations ──\n\n private computeKpis(): void {\n const now = new Date();\n const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const weekStart = new Date(todayStart.getTime() - 6 * 86400000);\n const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);\n\n const todaySpend = this.sumCostInRange(this.allRuns, todayStart, now);\n const weekSpend = this.sumCostInRange(this.allRuns, weekStart, now);\n const monthSpend = this.sumCostInRange(this.allRuns, monthStart, now);\n\n const prevTotalCost = this.previousPeriodRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n const currentTotalCost = this.allRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n // Project monthly cost based on current daily average\n const daysIntoMonth = Math.max(1, now.getDate());\n const projectedMonthly = (monthSpend / daysIntoMonth) * new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();\n\n const delta = prevTotalCost > 0 ? ((currentTotalCost - prevTotalCost) / prevTotalCost) * 100 : null;\n\n this.CostKpis = [\n {\n Label: \"Today's Spend\",\n Value: this.FormatCurrency(todaySpend),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar-day'\n },\n {\n Label: 'This Week',\n Value: this.FormatCurrency(weekSpend),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar-week'\n },\n {\n Label: 'This Month',\n Value: this.FormatCurrency(monthSpend),\n Delta: delta,\n DeltaDirection: delta != null ? (delta > 0 ? 'up' : delta < 0 ? 'down' : 'stable') : 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar'\n },\n {\n Label: 'Projected Monthly',\n Value: this.FormatCurrency(projectedMonthly),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: true,\n Icon: 'fa-solid fa-chart-line'\n }\n ];\n }\n\n private computeDailyBars(): void {\n const buckets = new Map<string, number>();\n for (const run of this.allRuns) {\n const date = new Date(run.RunAt);\n const key = date.toISOString().slice(0, 10);\n buckets.set(key, (buckets.get(key) ?? 0) + (run.Cost ?? run.TotalCost ?? 0));\n }\n\n const sortedKeys = Array.from(buckets.keys()).sort();\n const values = sortedKeys.map(k => buckets.get(k) ?? 0);\n const maxVal = Math.max(...values, 0.001);\n\n // Anomaly detection: > 2 standard deviations from mean\n const mean = values.length > 0 ? values.reduce((s, v) => s + v, 0) / values.length : 0;\n const variance = values.length > 1\n ? values.reduce((s, v) => s + Math.pow(v - mean, 2), 0) / values.length\n : 0;\n const stdDev = Math.sqrt(variance);\n const anomalyThreshold = mean + 2 * stdDev;\n\n this.DailyBars = sortedKeys.map((key, i) => ({\n Date: key,\n Label: this.formatBarLabel(key),\n Cost: values[i],\n HeightPercent: maxVal > 0 ? (values[i] / maxVal) * 100 : 0,\n IsAnomaly: stdDev > 0 && values[i] > anomalyThreshold\n }));\n\n this.AvgLinePercent = maxVal > 0 ? (mean / maxVal) * 100 : 0;\n }\n\n private computeTreemap(): void {\n const vendorCosts = new Map<string, number>();\n for (const run of this.allRuns) {\n const vendor = run.Vendor ?? 'Other';\n vendorCosts.set(vendor, (vendorCosts.get(vendor) ?? 0) + (run.Cost ?? run.TotalCost ?? 0));\n }\n\n const total = Array.from(vendorCosts.values()).reduce((s, v) => s + v, 0);\n const sorted = Array.from(vendorCosts.entries()).sort((a, b) => b[1] - a[1]);\n\n this.TreemapCells = sorted.map(([vendor, cost], i) => ({\n Label: vendor,\n Cost: cost,\n Percent: total > 0 ? (cost / total) * 100 : 0,\n Color: TREEMAP_COLORS[i % TREEMAP_COLORS.length],\n GridArea: ''\n }));\n }\n\n private computeCostByModel(): void {\n const groups = new Map<string, PromptRunRecord[]>();\n for (const run of this.allRuns) {\n const key = run.ModelID ?? 'unknown';\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(run);\n }\n\n const totalCost = this.allRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n const rows: CostByModelRow[] = [];\n for (const [, modelRuns] of groups) {\n const inputTokens = modelRuns.reduce((s, r) => s + (r.TokensPrompt ?? 0), 0);\n const outputTokens = modelRuns.reduce((s, r) => s + (r.TokensCompletion ?? 0), 0);\n const cost = modelRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n // Approximate input/output cost split based on token ratio\n const totalTk = inputTokens + outputTokens;\n const inputCost = totalTk > 0 ? cost * (inputTokens / totalTk) : 0;\n const outputCost = totalTk > 0 ? cost * (outputTokens / totalTk) : 0;\n\n rows.push({\n Model: modelRuns[0].Model ?? 'Unknown',\n Vendor: modelRuns[0].Vendor ?? 'Unknown',\n Runs: modelRuns.length,\n InputTokens: inputTokens,\n OutputTokens: outputTokens,\n InputCost: inputCost,\n OutputCost: outputCost,\n TotalCost: cost,\n PercentOfTotal: totalCost > 0 ? (cost / totalCost) * 100 : 0\n });\n }\n\n this.CostByModelRows = rows.sort((a, b) => b.TotalCost - a.TotalCost);\n }\n\n // ── Helpers ──\n\n private sumCostInRange(runs: PromptRunRecord[], start: Date, end: Date): number {\n return runs\n .filter(r => {\n const d = new Date(r.RunAt);\n return d >= start && d <= end;\n })\n .reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n }\n\n private getDateBounds(): { currentStart: Date; previousStart: Date } {\n const now = new Date();\n const msMap: Record<string, number> = {\n 'Today': 86400000,\n '7d': 604800000,\n '30d': 2592000000,\n 'MTD': now.getDate() * 86400000\n };\n const ms = msMap[this.TimeRange] ?? 604800000;\n const currentStart = new Date(now.getTime() - ms);\n const previousStart = new Date(currentStart.getTime() - ms);\n return { currentStart, previousStart };\n }\n\n private buildModelFilter(): string {\n if (this.Filters.Models.length === 0) return '';\n const ids = this.Filters.Models.map(id => `'${id}'`).join(',');\n return `ModelID IN (${ids})`;\n }\n\n private combineDateAndModelFilter(start: Date, end: Date, modelFilter: string): string {\n const parts = [\n `RunAt >= '${start.toISOString()}'`,\n `RunAt <= '${end.toISOString()}'`\n ];\n if (modelFilter) parts.push(modelFilter);\n return parts.join(' AND ');\n }\n\n private formatBarLabel(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00');\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n return months[d.getMonth()] + ' ' + d.getDate();\n }\n\n private downloadCSV(csv: string, filename: string): void {\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.click();\n URL.revokeObjectURL(url);\n }\n}\n\nexport function LoadAnalyticsCostBudget() { /* tree-shaking prevention */ }\n"]}
1
+ {"version":3,"file":"cost-budget.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/cost-budget/cost-budget.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Cost & Budget Analytics -- Option B.\n *\n * Displays cost KPIs with period deltas, a daily cost bar chart with anomaly detection,\n * a cost breakdown treemap, and a detailed cost-by-model table with CSV export.\n */\n\nimport {\n Component, Input, Output, EventEmitter,\n OnInit, OnDestroy, ChangeDetectorRef, inject\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { RunView } from '@memberjunction/core';\nimport { NormalizeUUID } from '@memberjunction/global';\nimport { CacheRate, CacheTokenTotals, cacheHitRate, hasCacheActivity, netCacheSavings } from '../../../services/cache-metrics';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { GlobalFilterState } from '../../../interfaces/analytics-preferences.interface';\n\n// ── Interfaces ──\n\ninterface PromptRunRecord {\n ID: string;\n RunAt: string;\n Cost: number | null;\n TotalCost: number | null;\n TokensPrompt: number | null;\n TokensCompletion: number | null;\n TokensUsed: number | null;\n TokensCacheRead: number | null;\n TokensCacheWrite: number | null;\n ModelID: string | null;\n Model: string | null;\n VendorID: string | null;\n Vendor: string | null;\n Success: boolean;\n}\n\ninterface CostKpi {\n Label: string;\n Value: string;\n Delta: number | null;\n DeltaDirection: 'up' | 'down' | 'stable';\n Highlighted: boolean;\n Icon: string;\n}\n\ninterface DailyBar {\n Date: string;\n Label: string;\n Cost: number;\n HeightPercent: number;\n IsAnomaly: boolean;\n}\n\ninterface TreemapCell {\n Label: string;\n Cost: number;\n Percent: number;\n Color: string;\n GridArea: string;\n}\n\ninterface CostByModelRow {\n Model: string;\n Vendor: string;\n Runs: number;\n InputTokens: number;\n OutputTokens: number;\n CacheReadTokens: number;\n CacheWriteTokens: number;\n CacheHitRate: number;\n CacheSavings: number;\n InputCost: number;\n OutputCost: number;\n TotalCost: number;\n PercentOfTotal: number;\n}\n\nconst FIELDS = [\n 'ID', 'RunAt', 'Cost', 'TotalCost', 'TokensPrompt', 'TokensCompletion',\n 'TokensUsed', 'TokensCacheRead', 'TokensCacheWrite', 'ModelID', 'Model', 'VendorID', 'Vendor', 'Success'\n];\n\ninterface ModelCostRow {\n ModelID: string | null;\n VendorID: string | null;\n InputPricePerUnit: number | null;\n OutputPricePerUnit: number | null;\n CacheReadPricePerUnit: number | null;\n CacheWritePricePerUnit: number | null;\n UnitType: string | null;\n}\n\n// AIModelCost UnitType name -> token divisor, matching the BasePriceUnitType driver classes.\nconst UNIT_DIVISORS: Record<string, number> = {\n 'Per Million Tokens': 1_000_000,\n 'Per Hundred Thousand Tokens': 100_000,\n 'Per Thousand Tokens': 1_000\n};\n\nconst TIME_RANGE_OPTIONS = ['Today', '7d', '30d', 'MTD'];\n\nconst TREEMAP_COLORS = [\n 'var(--mj-brand-primary)',\n 'var(--mj-brand-accent, var(--mj-brand-primary-hover))',\n 'var(--mj-status-info)',\n 'var(--mj-status-success)',\n 'var(--mj-status-warning)',\n 'var(--mj-text-disabled)'\n];\n\n@Component({\n standalone: false,\n selector: 'app-analytics-cost-budget',\n template: `\n\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading cost data...\"></mj-loading>\n </div>\n } @else {\n <!-- Cost KPI Row -->\n <div class=\"kpi-row\">\n @for (kpi of CostKpis; track kpi.Label) {\n <div class=\"kpi-card\" [class.kpi-card--highlighted]=\"kpi.Highlighted\">\n <div class=\"kpi-icon\">\n <i [class]=\"kpi.Icon\"></i>\n </div>\n <div class=\"kpi-content\">\n <div class=\"kpi-label\">{{ kpi.Label }}</div>\n <div class=\"kpi-value\">{{ kpi.Value }}</div>\n @if (kpi.Delta != null) {\n <div class=\"kpi-delta\"\n [class.kpi-delta--up]=\"kpi.DeltaDirection === 'up'\"\n [class.kpi-delta--down]=\"kpi.DeltaDirection === 'down'\">\n @if (kpi.DeltaDirection === 'up') {\n <i class=\"fa-solid fa-arrow-up\"></i>\n } @else if (kpi.DeltaDirection === 'down') {\n <i class=\"fa-solid fa-arrow-down\"></i>\n }\n {{ kpi.Delta | number:'1.1-1' }}% vs prev\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Two-Column Layout -->\n <div class=\"two-col\">\n <!-- Daily Cost Trend -->\n <div class=\"panel panel-chart\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-column panel-header__icon\"></i>\n Daily Cost Trend\n </div>\n </div>\n <div class=\"chart-body\">\n @if (DailyBars.length === 0) {\n <div class=\"panel-empty\">No cost data for selected period</div>\n } @else {\n <div class=\"bar-chart\">\n <div class=\"bar-chart-area\">\n @if (AvgLinePercent > 0) {\n <div class=\"avg-line\" [style.bottom.%]=\"AvgLinePercent\">\n <span class=\"avg-label\">avg</span>\n </div>\n }\n @for (bar of DailyBars; track bar.Date) {\n <div class=\"bar-col\" [title]=\"bar.Label + ': ' + FormatCurrency(bar.Cost)\">\n <div\n class=\"bar\"\n [class.bar--anomaly]=\"bar.IsAnomaly\"\n [style.height.%]=\"bar.HeightPercent\"\n ></div>\n <div class=\"bar-label\">{{ bar.Label }}</div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Cost Breakdown Treemap -->\n <div class=\"panel panel-treemap\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-pie panel-header__icon\"></i>\n Cost by Vendor\n </div>\n </div>\n <div class=\"treemap-body\">\n @if (TreemapCells.length === 0) {\n <div class=\"panel-empty\">No vendor cost data</div>\n } @else {\n <div class=\"treemap-grid\">\n @for (cell of TreemapCells; track cell.Label) {\n <div\n class=\"treemap-cell\"\n [style.background]=\"cell.Color\"\n [style.flex-basis.%]=\"cell.Percent\"\n [title]=\"cell.Label + ': ' + FormatCurrency(cell.Cost) + ' (' + (cell.Percent | number:'1.0-0') + '%)'\">\n <span class=\"treemap-label\">{{ cell.Label }}</span>\n <span class=\"treemap-value\">{{ FormatCurrency(cell.Cost) }}</span>\n <span class=\"treemap-pct\">{{ cell.Percent | number:'1.0-0' }}%</span>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n\n <!-- Cost by Model Table -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-table panel-header__icon\"></i>\n Cost by Model\n </div>\n <button class=\"export-btn\" (click)=\"ExportCSV()\">\n <i class=\"fa-solid fa-download\"></i>\n Export CSV\n </button>\n </div>\n <div class=\"table-wrapper\">\n <table class=\"data-table\">\n <thead>\n <tr>\n <th>Model</th>\n <th>Vendor</th>\n <th class=\"col-numeric\">Runs</th>\n <th class=\"col-numeric\">Input Tokens</th>\n <th class=\"col-numeric\">Output Tokens</th>\n <th class=\"col-numeric\" title=\"Share of input tokens served from the provider's prompt cache\">Cache Hit</th>\n <th class=\"col-numeric\">Input Cost</th>\n <th class=\"col-numeric\">Output Cost</th>\n <th class=\"col-numeric\">Total Cost</th>\n <th class=\"col-numeric\" title=\"Net dollars saved by caching vs. full input pricing (requires cache rates on AI Model Costs)\">Cache Saved</th>\n <th class=\"col-numeric\">% of Total</th>\n </tr>\n </thead>\n <tbody>\n @if (CostByModelRows.length === 0) {\n <tr><td colspan=\"11\" class=\"empty-row\">No data available</td></tr>\n }\n @for (row of CostByModelRows; track row.Model) {\n <tr>\n <td class=\"cell-model\">{{ row.Model }}</td>\n <td class=\"cell-vendor\">{{ row.Vendor }}</td>\n <td class=\"cell-numeric\">{{ row.Runs | number }}</td>\n <td class=\"cell-numeric\">{{ row.InputTokens | number }}</td>\n <td class=\"cell-numeric\">{{ row.OutputTokens | number }}</td>\n <td class=\"cell-numeric\">{{ (row.CacheReadTokens + row.CacheWriteTokens) > 0 ? ((row.CacheHitRate * 100 | number:'1.0-0') + '%') : '—' }}</td>\n <td class=\"cell-numeric\">{{ FormatCurrency(row.InputCost, 4) }}</td>\n <td class=\"cell-numeric\">{{ FormatCurrency(row.OutputCost, 4) }}</td>\n <td class=\"cell-numeric cell-cost\">{{ FormatCurrency(row.TotalCost) }}</td>\n <td class=\"cell-numeric\">{{ row.CacheSavings > 0 ? FormatCurrency(row.CacheSavings, 4) : '—' }}</td>\n <td class=\"cell-numeric\">{{ row.PercentOfTotal | number:'1.1-1' }}%</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n </div>\n }\n `,\n styles: [`\n :host { display: block; }\n\n .loading-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n /* ── KPI Row ── */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 12px;\n margin: 16px 0;\n }\n\n .kpi-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 16px;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n\n .kpi-card--highlighted {\n border-color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 5%, var(--mj-bg-surface));\n }\n\n .kpi-icon {\n width: 36px;\n height: 36px;\n border-radius: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n font-size: 14px;\n flex-shrink: 0;\n }\n\n .kpi-card--highlighted .kpi-icon {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n }\n\n .kpi-label {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kpi-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 2px 0;\n letter-spacing: -0.02em;\n }\n\n .kpi-delta {\n font-size: 11px;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 3px;\n }\n\n .kpi-delta--up {\n color: var(--mj-status-error);\n }\n\n .kpi-delta--down {\n color: var(--mj-status-success);\n }\n\n /* ── Two-Column Layout ── */\n .two-col {\n display: grid;\n grid-template-columns: 3fr 2fr;\n gap: 16px;\n margin-bottom: 16px;\n }\n\n /* ── Panel ── */\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n margin-bottom: 16px;\n }\n\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .panel-header__title {\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .panel-header__icon {\n font-size: 13px;\n color: var(--mj-brand-primary);\n }\n\n .panel-empty {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n .export-btn {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n cursor: pointer;\n transition: background 0.15s, color 0.15s;\n }\n\n .export-btn:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n /* ── Bar Chart ── */\n .chart-body {\n padding: 16px 18px;\n }\n\n .bar-chart {\n width: 100%;\n }\n\n .bar-chart-area {\n display: flex;\n align-items: flex-end;\n gap: 4px;\n height: 180px;\n position: relative;\n padding-bottom: 24px;\n }\n\n .bar-col {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n height: 100%;\n justify-content: flex-end;\n }\n\n .bar {\n width: 100%;\n max-width: 32px;\n border-radius: 4px 4px 0 0;\n background: var(--mj-brand-primary);\n transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n min-height: 2px;\n }\n\n .bar--anomaly {\n background: var(--mj-status-error);\n }\n\n .bar-label {\n font-size: 10px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n white-space: nowrap;\n }\n\n .avg-line {\n position: absolute;\n left: 0;\n right: 0;\n border-top: 2px dashed var(--mj-text-disabled);\n z-index: 1;\n pointer-events: none;\n }\n\n .avg-label {\n position: absolute;\n right: 0;\n top: -14px;\n font-size: 10px;\n color: var(--mj-text-disabled);\n font-weight: 600;\n }\n\n /* ── Treemap ── */\n .treemap-body {\n padding: 16px 18px;\n }\n\n .treemap-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n min-height: 160px;\n }\n\n .treemap-cell {\n border-radius: 8px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-width: 80px;\n min-height: 70px;\n flex-grow: 1;\n color: var(--mj-text-inverse, white);\n transition: opacity 0.2s;\n }\n\n .treemap-cell:hover {\n opacity: 0.85;\n }\n\n .treemap-label {\n font-size: 12px;\n font-weight: 600;\n opacity: 0.95;\n }\n\n .treemap-value {\n font-size: 16px;\n font-weight: 700;\n margin-top: 2px;\n }\n\n .treemap-pct {\n font-size: 11px;\n opacity: 0.8;\n }\n\n /* ── Table ── */\n .table-wrapper {\n overflow-x: auto;\n }\n\n .data-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table th,\n .data-table td {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table th {\n font-size: 11px;\n font-weight: 600;\n color: var(--mj-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.4px;\n background: var(--mj-bg-surface-card);\n position: sticky;\n top: 0;\n white-space: nowrap;\n }\n\n .col-numeric { text-align: right; }\n\n .data-table tbody tr {\n transition: background 0.15s;\n }\n\n .data-table tbody tr:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n .cell-model {\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .cell-vendor {\n color: var(--mj-text-secondary);\n }\n\n .cell-numeric {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-cost {\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* ── Responsive ── */\n @media (max-width: 1200px) {\n .two-col {\n grid-template-columns: 1fr;\n }\n }\n\n @media (max-width: 768px) {\n .kpi-row {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .kpi-value {\n font-size: 18px;\n }\n }\n `]\n})\nexport class AnalyticsCostBudgetComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n private _timeRange = '7d';\n @Input()\n set TimeRange(value: string) {\n const prev = this._timeRange;\n this._timeRange = value;\n if (prev !== value && this.initialized) this.LoadData();\n }\n get TimeRange(): string { return this._timeRange; }\n\n private _filters: GlobalFilterState = { Models: [], Agents: [], Prompts: [], Statuses: [] };\n @Input()\n set Filters(value: GlobalFilterState) {\n const next = value ?? { Models: [], Agents: [], Prompts: [], Statuses: [] };\n const changed = !this.shallowFiltersEqual(this._filters, next);\n this._filters = next;\n if (changed && this.initialized) this.LoadData();\n }\n get Filters(): GlobalFilterState { return this._filters; }\n\n private shallowFiltersEqual(a: GlobalFilterState, b: GlobalFilterState): boolean {\n const sameArr = (x: string[], y: string[]) => x.length === y.length && x.every((v, i) => v === y[i]);\n return sameArr(a.Models, b.Models) && sameArr(a.Agents, b.Agents) && sameArr(a.Prompts, b.Prompts) && sameArr(a.Statuses, b.Statuses);\n }\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<GlobalFilterState>();\n\n private initialized = false;\n\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n\n public IsLoading = false;\n public TimeRangeOptionsList = TIME_RANGE_OPTIONS;\n\n public CostKpis: CostKpi[] = [];\n public DailyBars: DailyBar[] = [];\n public AvgLinePercent = 0;\n public TreemapCells: TreemapCell[] = [];\n public CostByModelRows: CostByModelRow[] = [];\n\n private allRuns: PromptRunRecord[] = [];\n private previousPeriodRuns: PromptRunRecord[] = [];\n\n // Per model+vendor cache pricing (rates already normalized to currency-per-token). Empty until\n // AIModelCost cache rates are configured — savings then stays 0 (surfaced as \"Set rates\").\n private cacheRates = new Map<string, CacheRate>();\n\n ngOnInit(): void {\n this.initialized = true;\n this.LoadData();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ── Public Handlers ──\n\n public OnTimeRangeChange(range: string): void {\n this.TimeRange = range;\n this.TimeRangeChange.emit(range);\n this.LoadData();\n }\n\n public OnFiltersChange(filters: GlobalFilterState): void {\n this.Filters = filters;\n this.FiltersChange.emit(filters);\n this.LoadData();\n }\n\n public FormatCurrency(value: number, decimals = 2): string {\n if (value === 0) return '$0.00';\n if (value < 0.01 && decimals < 4) decimals = 4;\n return '$' + value.toFixed(decimals);\n }\n\n public ExportCSV(): void {\n const header = 'Model,Vendor,Runs,Input Tokens,Output Tokens,Cache Read Tokens,Cache Write Tokens,Cache Hit Rate %,Input Cost,Output Cost,Total Cost,Cache Saved,% of Total';\n const rows = this.CostByModelRows.map(r =>\n `\"${r.Model}\",\"${r.Vendor}\",${r.Runs},${r.InputTokens},${r.OutputTokens},${r.CacheReadTokens},${r.CacheWriteTokens},${(r.CacheHitRate * 100).toFixed(1)},${r.InputCost.toFixed(6)},${r.OutputCost.toFixed(6)},${r.TotalCost.toFixed(6)},${r.CacheSavings.toFixed(6)},${r.PercentOfTotal.toFixed(1)}`\n );\n const csv = [header, ...rows].join('\\n');\n this.downloadCSV(csv, 'cost-by-model.csv');\n }\n\n // ── Data Loading ──\n\n private async LoadData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.detectChanges();\n\n try {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const { currentStart, previousStart } = this.getDateBounds();\n const now = new Date();\n const modelFilter = this.buildModelFilter();\n const currentFilter = this.combineDateAndModelFilter(currentStart, now, modelFilter);\n const prevFilter = this.combineDateAndModelFilter(previousStart, currentStart, modelFilter);\n\n const [currentResult, prevResult, rateResult] = await rv.RunViews([\n {\n EntityName: 'MJ: AI Prompt Runs',\n ExtraFilter: currentFilter,\n Fields: FIELDS,\n OrderBy: 'RunAt ASC',\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: AI Prompt Runs',\n ExtraFilter: prevFilter,\n Fields: FIELDS,\n OrderBy: 'RunAt ASC',\n ResultType: 'simple'\n },\n {\n EntityName: 'MJ: AI Model Costs',\n ExtraFilter: `Status='Active' AND ProcessingType='Realtime'`,\n Fields: ['ModelID', 'VendorID', 'InputPricePerUnit', 'OutputPricePerUnit', 'CacheReadPricePerUnit', 'CacheWritePricePerUnit', 'UnitType'],\n ResultType: 'simple'\n }\n ]);\n\n this.allRuns = (currentResult?.Results ?? []) as PromptRunRecord[];\n this.previousPeriodRuns = (prevResult?.Results ?? []) as PromptRunRecord[];\n this.buildCacheRateMap(rateResult?.Results ?? []);\n\n this.computeKpis();\n this.computeDailyBars();\n this.computeTreemap();\n this.computeCostByModel();\n } catch (e) {\n console.error('Cost & Budget load error:', e);\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n // ── Cache pricing ──\n\n /** Stable map key for a model+vendor pair (UUIDs normalized for case-insensitive matching). */\n private rateKey(modelID: string | null, vendorID: string | null): string {\n return `${NormalizeUUID(modelID ?? '')}|${NormalizeUUID(vendorID ?? '')}`;\n }\n\n /** The cache rate for a run's model+vendor, or undefined when no active cost row is configured. */\n private rateFor(run: PromptRunRecord): CacheRate | undefined {\n return this.cacheRates.get(this.rateKey(run.ModelID, run.VendorID));\n }\n\n /** Build the per-model+vendor rate lookup, normalizing each per-unit price to currency-per-token. */\n private buildCacheRateMap(rows: ModelCostRow[]): void {\n this.cacheRates.clear();\n for (const row of rows) {\n const divisor = UNIT_DIVISORS[row.UnitType ?? ''] ?? 1_000_000;\n const inputRate = (row.InputPricePerUnit ?? 0) / divisor;\n // Cache read/write fall back to the input rate when no distinct rate is recorded — exactly\n // as the server-side cost calculator does — which makes the corresponding savings term 0.\n const cacheReadRate = (row.CacheReadPricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor;\n const cacheWriteRate = (row.CacheWritePricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor;\n this.cacheRates.set(this.rateKey(row.ModelID, row.VendorID), { inputRate, cacheReadRate, cacheWriteRate });\n }\n }\n\n /** Sum net cache savings across a set of runs using each run's model+vendor rate. */\n private sumCacheSavings(runs: PromptRunRecord[]): number {\n return runs.reduce((total, run) => total + netCacheSavings({\n uncachedInputTokens: 0,\n cacheReadTokens: run.TokensCacheRead ?? 0,\n cacheWriteTokens: run.TokensCacheWrite ?? 0\n }, this.rateFor(run)), 0);\n }\n\n // ── Computations ──\n\n private computeKpis(): void {\n const now = new Date();\n const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const weekStart = new Date(todayStart.getTime() - 6 * 86400000);\n const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);\n\n const todaySpend = this.sumCostInRange(this.allRuns, todayStart, now);\n const weekSpend = this.sumCostInRange(this.allRuns, weekStart, now);\n const monthSpend = this.sumCostInRange(this.allRuns, monthStart, now);\n\n const prevTotalCost = this.previousPeriodRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n const currentTotalCost = this.allRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n // Project monthly cost based on current daily average\n const daysIntoMonth = Math.max(1, now.getDate());\n const projectedMonthly = (monthSpend / daysIntoMonth) * new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();\n\n const delta = prevTotalCost > 0 ? ((currentTotalCost - prevTotalCost) / prevTotalCost) * 100 : null;\n\n this.CostKpis = [\n {\n Label: \"Today's Spend\",\n Value: this.FormatCurrency(todaySpend),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar-day'\n },\n {\n Label: 'This Week',\n Value: this.FormatCurrency(weekSpend),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar-week'\n },\n {\n Label: 'This Month',\n Value: this.FormatCurrency(monthSpend),\n Delta: delta,\n DeltaDirection: delta != null ? (delta > 0 ? 'up' : delta < 0 ? 'down' : 'stable') : 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-calendar'\n },\n {\n Label: 'Projected Monthly',\n Value: this.FormatCurrency(projectedMonthly),\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: true,\n Icon: 'fa-solid fa-chart-line'\n }\n ];\n\n this.appendCacheKpis();\n }\n\n /** Append the cache hit-rate and cache-savings KPIs (computed from the current-period runs). */\n private appendCacheKpis(): void {\n const totals: CacheTokenTotals = { uncachedInputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };\n for (const r of this.allRuns) {\n totals.uncachedInputTokens += r.TokensPrompt ?? 0;\n totals.cacheReadTokens += r.TokensCacheRead ?? 0;\n totals.cacheWriteTokens += r.TokensCacheWrite ?? 0;\n }\n const savings = this.sumCacheSavings(this.allRuns);\n const activity = hasCacheActivity(totals);\n\n this.CostKpis.push({\n Label: 'Cache Hit Rate',\n Value: (cacheHitRate(totals) * 100).toFixed(1) + '%',\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: false,\n Icon: 'fa-solid fa-bolt'\n });\n\n // Savings requires cache rates on AIModelCost. When cache engaged but no savings computed,\n // it means rates aren't configured yet — say so rather than implying $0 was saved.\n const savingsValue = savings > 0\n ? this.FormatCurrency(savings)\n : (activity ? 'Set rates' : '$0.00');\n this.CostKpis.push({\n Label: 'Saved via Cache',\n Value: savingsValue,\n Delta: null,\n DeltaDirection: 'stable',\n Highlighted: savings > 0,\n Icon: 'fa-solid fa-piggy-bank'\n });\n }\n\n private computeDailyBars(): void {\n const buckets = new Map<string, number>();\n for (const run of this.allRuns) {\n const date = new Date(run.RunAt);\n const key = date.toISOString().slice(0, 10);\n buckets.set(key, (buckets.get(key) ?? 0) + (run.Cost ?? run.TotalCost ?? 0));\n }\n\n const sortedKeys = Array.from(buckets.keys()).sort();\n const values = sortedKeys.map(k => buckets.get(k) ?? 0);\n const maxVal = Math.max(...values, 0.001);\n\n // Anomaly detection: > 2 standard deviations from mean\n const mean = values.length > 0 ? values.reduce((s, v) => s + v, 0) / values.length : 0;\n const variance = values.length > 1\n ? values.reduce((s, v) => s + Math.pow(v - mean, 2), 0) / values.length\n : 0;\n const stdDev = Math.sqrt(variance);\n const anomalyThreshold = mean + 2 * stdDev;\n\n this.DailyBars = sortedKeys.map((key, i) => ({\n Date: key,\n Label: this.formatBarLabel(key),\n Cost: values[i],\n HeightPercent: maxVal > 0 ? (values[i] / maxVal) * 100 : 0,\n IsAnomaly: stdDev > 0 && values[i] > anomalyThreshold\n }));\n\n this.AvgLinePercent = maxVal > 0 ? (mean / maxVal) * 100 : 0;\n }\n\n private computeTreemap(): void {\n const vendorCosts = new Map<string, number>();\n for (const run of this.allRuns) {\n const vendor = run.Vendor ?? 'Other';\n vendorCosts.set(vendor, (vendorCosts.get(vendor) ?? 0) + (run.Cost ?? run.TotalCost ?? 0));\n }\n\n const total = Array.from(vendorCosts.values()).reduce((s, v) => s + v, 0);\n const sorted = Array.from(vendorCosts.entries()).sort((a, b) => b[1] - a[1]);\n\n this.TreemapCells = sorted.map(([vendor, cost], i) => ({\n Label: vendor,\n Cost: cost,\n Percent: total > 0 ? (cost / total) * 100 : 0,\n Color: TREEMAP_COLORS[i % TREEMAP_COLORS.length],\n GridArea: ''\n }));\n }\n\n private computeCostByModel(): void {\n const groups = new Map<string, PromptRunRecord[]>();\n for (const run of this.allRuns) {\n const key = run.ModelID ?? 'unknown';\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(run);\n }\n\n const totalCost = this.allRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n const rows: CostByModelRow[] = [];\n for (const [, modelRuns] of groups) {\n const inputTokens = modelRuns.reduce((s, r) => s + (r.TokensPrompt ?? 0), 0);\n const outputTokens = modelRuns.reduce((s, r) => s + (r.TokensCompletion ?? 0), 0);\n const cacheReadTokens = modelRuns.reduce((s, r) => s + (r.TokensCacheRead ?? 0), 0);\n const cacheWriteTokens = modelRuns.reduce((s, r) => s + (r.TokensCacheWrite ?? 0), 0);\n const cost = modelRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n\n // Approximate input/output cost split based on token ratio\n const totalTk = inputTokens + outputTokens;\n const inputCost = totalTk > 0 ? cost * (inputTokens / totalTk) : 0;\n const outputCost = totalTk > 0 ? cost * (outputTokens / totalTk) : 0;\n\n rows.push({\n Model: modelRuns[0].Model ?? 'Unknown',\n Vendor: modelRuns[0].Vendor ?? 'Unknown',\n Runs: modelRuns.length,\n InputTokens: inputTokens,\n OutputTokens: outputTokens,\n CacheReadTokens: cacheReadTokens,\n CacheWriteTokens: cacheWriteTokens,\n CacheHitRate: cacheHitRate({ uncachedInputTokens: inputTokens, cacheReadTokens, cacheWriteTokens }),\n CacheSavings: this.sumCacheSavings(modelRuns),\n InputCost: inputCost,\n OutputCost: outputCost,\n TotalCost: cost,\n PercentOfTotal: totalCost > 0 ? (cost / totalCost) * 100 : 0\n });\n }\n\n this.CostByModelRows = rows.sort((a, b) => b.TotalCost - a.TotalCost);\n }\n\n // ── Helpers ──\n\n private sumCostInRange(runs: PromptRunRecord[], start: Date, end: Date): number {\n return runs\n .filter(r => {\n const d = new Date(r.RunAt);\n return d >= start && d <= end;\n })\n .reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);\n }\n\n private getDateBounds(): { currentStart: Date; previousStart: Date } {\n const now = new Date();\n const msMap: Record<string, number> = {\n 'Today': 86400000,\n '7d': 604800000,\n '30d': 2592000000,\n 'MTD': now.getDate() * 86400000\n };\n const ms = msMap[this.TimeRange] ?? 604800000;\n const currentStart = new Date(now.getTime() - ms);\n const previousStart = new Date(currentStart.getTime() - ms);\n return { currentStart, previousStart };\n }\n\n private buildModelFilter(): string {\n if (this.Filters.Models.length === 0) return '';\n const ids = this.Filters.Models.map(id => `'${id}'`).join(',');\n return `ModelID IN (${ids})`;\n }\n\n private combineDateAndModelFilter(start: Date, end: Date, modelFilter: string): string {\n const parts = [\n `RunAt >= '${start.toISOString()}'`,\n `RunAt <= '${end.toISOString()}'`\n ];\n if (modelFilter) parts.push(modelFilter);\n return parts.join(' AND ');\n }\n\n private formatBarLabel(dateStr: string): string {\n const d = new Date(dateStr + 'T00:00:00');\n const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n return months[d.getMonth()] + ' ' + d.getDate();\n }\n\n private downloadCSV(csv: string, filename: string): void {\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.click();\n URL.revokeObjectURL(url);\n }\n}\n\nexport function LoadAnalyticsCostBudget() { /* tree-shaking prevention */ }\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"executive-summary.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/executive-summary/executive-summary.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACqB,YAAY,EAAE,MAAM,EAAE,SAAS,EAE1D,MAAM,eAAe,CAAC;AAGvB,OAAO,EAGL,SAAS,EAEV,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qDAAqD,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAIrE,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,qBAuaa,kCAAmC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAGvG,OAAO,CAAC,UAAU,CAAS;IAC3B,IACI,SAAS,CAAC,KAAK,EAAE,MAAM,EAO1B;IACD,IAAI,SAAS,IAAI,MAAM,CAA4B;IAE1C,OAAO,EAAE,iBAAiB,CAAyD;IAElF,eAAe,uBAA8B;IAC7C,aAAa,kCAAyC;IACtD,eAAe,uBAA8B;IAIvD,OAAO,CAAC,sBAAsB,CAAoC;IAClE,OAAO,CAAC,GAAG,CAA6B;IAIxC,QAAQ,EAAE,cAAc,EAAE,CAAM;IAChC,UAAU,EAAE,SAAS,EAAE,CAAM;IAC7B,YAAY,EAAE,WAAW,EAAE,CAAM;IACjC,aAAa,EAAE,YAAY,EAAE,CAAM;IACnC,SAAS,UAAS;IAClB,iBAAiB,UAAS;IAC1B,WAAW,SAAY;IAEvB,gBAAgB,EAAE,gBAAgB,CAKhC;IAIF,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAA8B;IAIlD,QAAQ,IAAI,IAAI;IAOhB,WAAW,IAAI,IAAI;IAOnB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKtC,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAKjD,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAUvC,SAAS,IAAI,IAAI;IAOjB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAMxC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAYhC,OAAO,CAAC,UAAU,CAA8B;IAEhD,OAAO,CAAC,kBAAkB;IAkC1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,cAAc;YAaR,kBAAkB;IAwBhC,OAAO,CAAC,eAAe;IA+CvB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IAoCzB,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;yCAjZV,kCAAkC;2CAAlC,kCAAkC;CAsZ9C;AAED,wBAAgB,6BAA6B,SAE5C"}
1
+ {"version":3,"file":"executive-summary.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/executive-summary/executive-summary.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACqB,YAAY,EAAE,MAAM,EAAE,SAAS,EAE1D,MAAM,eAAe,CAAC;AAGvB,OAAO,EAGL,SAAS,EAEV,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qDAAqD,CAAC;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAIrE,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,IAAI,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,qBAuaa,kCAAmC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IAGvG,OAAO,CAAC,UAAU,CAAS;IAC3B,IACI,SAAS,CAAC,KAAK,EAAE,MAAM,EAO1B;IACD,IAAI,SAAS,IAAI,MAAM,CAA4B;IAE1C,OAAO,EAAE,iBAAiB,CAAyD;IAElF,eAAe,uBAA8B;IAC7C,aAAa,kCAAyC;IACtD,eAAe,uBAA8B;IAIvD,OAAO,CAAC,sBAAsB,CAAoC;IAClE,OAAO,CAAC,GAAG,CAA6B;IAIxC,QAAQ,EAAE,cAAc,EAAE,CAAM;IAChC,UAAU,EAAE,SAAS,EAAE,CAAM;IAC7B,YAAY,EAAE,WAAW,EAAE,CAAM;IACjC,aAAa,EAAE,YAAY,EAAE,CAAM;IACnC,SAAS,UAAS;IAClB,iBAAiB,UAAS;IAC1B,WAAW,SAAY;IAEvB,gBAAgB,EAAE,gBAAgB,CAKhC;IAIF,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAA8B;IAIlD,QAAQ,IAAI,IAAI;IAOhB,WAAW,IAAI,IAAI;IAOnB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKtC,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAKjD,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAUvC,SAAS,IAAI,IAAI;IAOjB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAMxC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAYhC,OAAO,CAAC,UAAU,CAA8B;IAEhD,OAAO,CAAC,kBAAkB;IAkC1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,cAAc;YAaR,kBAAkB;IAwBhC,OAAO,CAAC,eAAe;IAqDvB,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,iBAAiB;IAoCzB,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,aAAa;yCAvZV,kCAAkC;2CAAlC,kCAAkC;CA4Z9C;AAED,wBAAgB,6BAA6B,SAE5C"}
@@ -339,7 +339,8 @@ export class AnalyticsExecutiveSummaryComponent extends BaseAngularComponent {
339
339
  this.buildKpiCard('Success Rate', (kpis.successRate * 100).toFixed(1) + '%', this.extractSparkline(trends, 'executions'), kpis.successRate, this.previousKpis?.successRate ?? null, 'up-is-good', 'var(--mj-status-success)'),
340
340
  this.buildKpiCard('Avg Latency', this.formatLatency(kpis.avgExecutionTime), this.extractSparkline(trends, 'avgTime'), kpis.avgExecutionTime, this.previousKpis?.avgExecutionTime ?? null, 'down-is-good', 'var(--mj-status-info)'),
341
341
  this.buildKpiCard('Token Usage', this.formatNumber(kpis.totalTokens), this.extractSparkline(trends, 'tokens'), kpis.totalTokens, this.previousKpis?.totalTokens ?? null, 'up-is-neutral', 'var(--mj-brand-accent, var(--mj-brand-primary))'),
342
- this.buildKpiCard('Errors', this.formatNumber(Math.round(kpis.errorRate * kpis.totalExecutions)), this.extractSparkline(trends, 'errors'), kpis.errorRate, this.previousKpis?.errorRate ?? null, 'down-is-good', 'var(--mj-status-error)')
342
+ this.buildKpiCard('Errors', this.formatNumber(Math.round(kpis.errorRate * kpis.totalExecutions)), this.extractSparkline(trends, 'errors'), kpis.errorRate, this.previousKpis?.errorRate ?? null, 'down-is-good', 'var(--mj-status-error)'),
343
+ this.buildKpiCard('Cache Hit Rate', (kpis.cacheHitRate * 100).toFixed(1) + '%', this.extractSparkline(trends, 'tokens'), kpis.cacheHitRate, this.previousKpis?.cacheHitRate ?? null, 'up-is-good', 'var(--mj-status-info)')
343
344
  ];
344
345
  }
345
346
  buildKpiCard(label, value, sparkline, current, previous, goodDirection, borderColor) {
@@ -1 +1 @@
1
- {"version":3,"file":"executive-summary.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/executive-summary/executive-summary.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter, OnInit, OnDestroy,\n ChangeDetectorRef, inject\n} from '@angular/core';\nimport { Subject, Subscription } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport {\n AIInstrumentationService,\n DashboardKPIs,\n TrendData,\n ChartData\n} from '../../../services/ai-instrumentation.service';\nimport { GlobalFilterState } from '../../../interfaces/analytics-preferences.interface';\nimport { TimeSeriesConfig } from '../../charts/time-series-chart.component';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n// ─── Local Interfaces ──────────────────────────────────────────────\n\ninterface KpiDisplayCard {\n Label: string;\n Value: string;\n SparklineData: number[];\n DeltaPercent: number;\n DeltaDirection: 'up' | 'down' | 'stable';\n IsImprovement: boolean;\n BorderColor: string;\n}\n\ninterface TopConsumer {\n Rank: number;\n Type: 'agent' | 'prompt';\n Name: string;\n Cost: number;\n Proportion: number;\n}\n\ninterface ErrorHotspot {\n Source: string;\n ErrorMessage: string;\n Count: number;\n}\n\n// ─── Component ─────────────────────────────────────────────────────\n\n@Component({\n standalone: false,\n selector: 'app-analytics-executive-summary',\n template: `\n @if (IsLoading && KpiCards.length === 0) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading executive summary...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- KPI Row -->\n <div class=\"kpi-row\">\n @for (card of KpiCards; track card.Label) {\n <div class=\"kpi-card\" [style.border-left-color]=\"card.BorderColor\">\n <div class=\"kpi-label\">{{ card.Label }}</div>\n <div class=\"kpi-value\">{{ card.Value }}</div>\n <div class=\"kpi-sparkline\">\n @for (bar of card.SparklineData; track $index) {\n <div\n class=\"spark-bar\"\n [style.height.%]=\"bar\"\n [style.background]=\"card.BorderColor\"\n ></div>\n }\n </div>\n @if (ComparisonEnabled && card.DeltaDirection !== 'stable') {\n <div class=\"kpi-delta\" [class.kpi-delta--good]=\"card.IsImprovement\" [class.kpi-delta--bad]=\"!card.IsImprovement\">\n <i [class]=\"card.DeltaDirection === 'up' ? 'fa-solid fa-arrow-up' : 'fa-solid fa-arrow-down'\"></i>\n {{ card.DeltaPercent | number:'1.1-1' }}%\n <span class=\"kpi-delta__period\">vs prev {{ PeriodLabel }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Execution Trends Chart -->\n <div class=\"trends-panel\">\n <app-time-series-chart\n [data]=\"TrendsData\"\n title=\"Execution Trends\"\n [config]=\"TimeSeriesConfig\"\n ></app-time-series-chart>\n </div>\n\n <!-- Two-Column Panels -->\n <div class=\"panels-grid\">\n <!-- Top Consumers -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-ranking-star panel-header__icon\"></i>\n Top Consumers\n </div>\n <span class=\"panel-header__subtitle\">by cost</span>\n </div>\n <div class=\"panel-body\">\n @if (TopConsumers.length === 0) {\n <div class=\"panel-empty\">No data for selected period</div>\n }\n @for (item of TopConsumers; track item.Name) {\n <div\n class=\"consumer-item\"\n (click)=\"OnConsumerClick(item)\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"OnConsumerClick(item)\"\n >\n <div\n class=\"consumer-rank\"\n [class.consumer-rank--top]=\"item.Rank <= 3\"\n >{{ item.Rank }}</div>\n <div\n class=\"consumer-type-pill\"\n [class.consumer-type-pill--agent]=\"item.Type === 'agent'\"\n >{{ item.Type }}</div>\n <div class=\"consumer-name\" [title]=\"item.Name\">{{ item.Name }}</div>\n <div class=\"consumer-cost\">\\${{ FormatCost(item.Cost) }}</div>\n <div class=\"consumer-bar-container\">\n <div\n class=\"consumer-bar\"\n [style.width.%]=\"item.Proportion * 100\"\n ></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Error Hotspots -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-triangle-exclamation panel-header__icon panel-header__icon--error\"></i>\n Error Hotspots\n </div>\n <span class=\"panel-header__subtitle\">\n {{ ErrorHotspots.length }} source{{ ErrorHotspots.length !== 1 ? 's' : '' }}\n </span>\n </div>\n <div class=\"panel-body\">\n @if (ErrorHotspots.length === 0) {\n <div class=\"panel-empty\">No errors in selected period</div>\n }\n @for (item of ErrorHotspots; track item.Source) {\n <div class=\"error-item\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <div class=\"error-info\">\n <div class=\"error-source\">{{ item.Source }}</div>\n <div class=\"error-message\" [title]=\"item.ErrorMessage\">{{ item.ErrorMessage }}</div>\n </div>\n <div class=\"error-count\">{{ item.Count }}</div>\n </div>\n }\n @if (ErrorHotspots.length > 0) {\n <button class=\"view-all-link\" (click)=\"SectionNavigate.emit('error-analysis')\">\n View All Errors <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n `,\n styles: [`\n /* ─── Host ────────────────────────────────────────────────── */\n :host {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 4px;\n }\n\n /* ─── Loading ─────────────────────────────────────────────── */\n .loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n }\n\n /* ─── KPI Row ─────────────────────────────────────────────── */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n }\n .kpi-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-left: 4px solid var(--mj-brand-primary);\n border-radius: 12px;\n padding: 16px 18px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n transition: all 0.25s ease;\n }\n .kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n .kpi-label {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n color: var(--mj-text-muted);\n }\n .kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.1;\n letter-spacing: -0.02em;\n }\n\n /* ─── Sparkline ───────────────────────────────────────────── */\n .kpi-sparkline {\n display: flex;\n align-items: flex-end;\n gap: 2px;\n height: 24px;\n margin-top: 4px;\n }\n .spark-bar {\n flex: 1;\n min-width: 4px;\n max-width: 8px;\n border-radius: 1px;\n opacity: 0.35;\n transition: opacity 0.15s ease;\n }\n .kpi-card:hover .spark-bar {\n opacity: 0.55;\n }\n\n /* ─── Delta Badge ─────────────────────────────────────────── */\n .kpi-delta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n margin-top: 2px;\n }\n .kpi-delta--good {\n color: var(--mj-status-success);\n }\n .kpi-delta--bad {\n color: var(--mj-status-error);\n }\n .kpi-delta__period {\n font-weight: 400;\n color: var(--mj-text-disabled);\n }\n\n /* ─── Trends Panel ────────────────────────────────────────── */\n .trends-panel {\n height: 320px;\n border-radius: 12px;\n overflow: hidden;\n }\n\n /* ─── Panels Grid ─────────────────────────────────────────── */\n .panels-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n }\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n }\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n .panel-header__title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .panel-header__icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n }\n .panel-header__icon--error {\n color: var(--mj-status-warning);\n }\n .panel-header__subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n .panel-body {\n padding: 8px 0;\n }\n .panel-empty {\n padding: 24px 18px;\n text-align: center;\n font-size: 13px;\n color: var(--mj-text-disabled);\n }\n\n /* ─── Consumer Item ───────────────────────────────────────── */\n .consumer-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 18px;\n cursor: pointer;\n transition: background 0.15s ease;\n }\n .consumer-item:hover {\n background: var(--mj-bg-surface-hover);\n }\n .consumer-rank {\n width: 22px;\n height: 22px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n flex-shrink: 0;\n }\n .consumer-rank--top {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n .consumer-type-pill {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n padding: 2px 8px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n flex-shrink: 0;\n }\n .consumer-type-pill--agent {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n .consumer-name {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .consumer-cost {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n }\n .consumer-bar-container {\n width: 60px;\n height: 6px;\n border-radius: 3px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n flex-shrink: 0;\n }\n .consumer-bar {\n height: 100%;\n border-radius: 3px;\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n /* ─── Error Item ──────────────────────────────────────────── */\n .error-item {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 18px;\n }\n .error-icon {\n color: var(--mj-status-error);\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n }\n .error-info {\n flex: 1;\n min-width: 0;\n }\n .error-source {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 2px;\n }\n .error-message {\n font-size: 12px;\n color: var(--mj-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .error-count {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-status-error);\n flex-shrink: 0;\n min-width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n }\n .view-all-link {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 8px 18px 10px;\n padding: 0;\n border: none;\n background: none;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: color 0.15s ease;\n }\n .view-all-link:hover {\n color: var(--mj-brand-primary-hover);\n }\n\n /* ─── Responsive ──────────────────────────────────────────── */\n @media (max-width: 1200px) {\n .panels-grid {\n grid-template-columns: 1fr;\n }\n }\n @media (max-width: 768px) {\n .kpi-row {\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n }\n .trends-panel {\n height: 260px;\n }\n }\n `]\n})\nexport class AnalyticsExecutiveSummaryComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n // ─── Inputs / Outputs ────────────────────────────────────────────\n\n private _timeRange = '24h';\n @Input()\n set TimeRange(value: string) {\n if (value !== this._timeRange) {\n this._timeRange = value;\n if (this.isInitialized) {\n this.applyDateRange();\n }\n }\n }\n get TimeRange(): string { return this._timeRange; }\n\n @Input() Filters: GlobalFilterState = { Models: [], Agents: [], Prompts: [], Statuses: [] };\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<GlobalFilterState>();\n @Output() SectionNavigate = new EventEmitter<string>();\n\n // ─── DI ──────────────────────────────────────────────────────────\n\n private instrumentationService = inject(AIInstrumentationService);\n private cdr = inject(ChangeDetectorRef);\n\n // ─── Public State ────────────────────────────────────────────────\n\n KpiCards: KpiDisplayCard[] = [];\n TrendsData: TrendData[] = [];\n TopConsumers: TopConsumer[] = [];\n ErrorHotspots: ErrorHotspot[] = [];\n IsLoading = false;\n ComparisonEnabled = false;\n PeriodLabel = 'period';\n\n TimeSeriesConfig: TimeSeriesConfig = {\n showGrid: true,\n showTooltip: true,\n animationDuration: 300,\n useDualAxis: true\n };\n\n // ─── Private State ───────────────────────────────────────────────\n\n private destroy$ = new Subject<void>();\n private isInitialized = false;\n private previousKpis: DashboardKPIs | null = null;\n\n // ─── Lifecycle ───────────────────────────────────────────────────\n\n ngOnInit(): void {\n this.instrumentationService.Provider = this.ProviderToUse;\n this.subscribeToStreams();\n this.applyDateRange();\n this.isInitialized = true;\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ─── Event Handlers ──────────────────────────────────────────────\n\n OnTimeRangeChange(range: string): void {\n this.TimeRange = range;\n this.TimeRangeChange.emit(range);\n }\n\n OnFiltersChange(filters: GlobalFilterState): void {\n this.Filters = filters;\n this.FiltersChange.emit(filters);\n }\n\n OnCompareToggled(active: boolean): void {\n this.ComparisonEnabled = active;\n if (this.ComparisonEnabled) {\n this.loadComparisonData();\n } else {\n this.previousKpis = null;\n this.rebuildKpiCards(this.latestKpis);\n }\n }\n\n OnRefresh(): void {\n this.instrumentationService.refresh();\n if (this.ComparisonEnabled) {\n this.loadComparisonData();\n }\n }\n\n OnConsumerClick(item: TopConsumer): void {\n this.SectionNavigate.emit(item.Type === 'agent' ? 'agent-runs' : 'prompt-runs');\n }\n\n // ─── Formatting Helpers ──────────────────────────────────────────\n\n FormatCost(cost: number): string {\n if (cost >= 1000) {\n return (cost / 1000).toFixed(1) + 'K';\n }\n if (cost >= 1) {\n return cost.toFixed(2);\n }\n return cost.toFixed(4);\n }\n\n // ─── Private: Subscriptions ──────────────────────────────────────\n\n private latestKpis: DashboardKPIs | null = null;\n\n private subscribeToStreams(): void {\n this.instrumentationService.isLoading$\n .pipe(takeUntil(this.destroy$))\n .subscribe(loading => {\n this.IsLoading = loading;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.kpis$\n .pipe(takeUntil(this.destroy$))\n .subscribe(kpis => {\n this.latestKpis = kpis;\n this.rebuildKpiCards(kpis);\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.trends$\n .pipe(takeUntil(this.destroy$))\n .subscribe(trends => {\n this.TrendsData = trends;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.chartData$\n .pipe(takeUntil(this.destroy$))\n .subscribe(chartData => {\n this.TopConsumers = this.buildTopConsumers(chartData);\n this.ErrorHotspots = this.buildErrorHotspots(chartData);\n this.cdr.markForCheck();\n });\n }\n\n // ─── Private: Date Range ─────────────────────────────────────────\n\n private applyDateRange(): void {\n const { start, end } = this.computeDateRange(this.TimeRange);\n this.PeriodLabel = this.getPeriodLabel(this.TimeRange);\n this.instrumentationService.setDateRange(start, end);\n // Explicitly refresh to ensure data loads on first visit\n this.instrumentationService.refresh();\n }\n\n private computeDateRange(range: string): { start: Date; end: Date } {\n const end = new Date();\n const start = new Date();\n switch (range) {\n case '1h':\n start.setHours(start.getHours() - 1);\n break;\n case '24h':\n start.setDate(start.getDate() - 1);\n break;\n case '7d':\n start.setDate(start.getDate() - 7);\n break;\n case '30d':\n start.setDate(start.getDate() - 30);\n break;\n case '90d':\n start.setDate(start.getDate() - 90);\n break;\n default:\n start.setDate(start.getDate() - 1);\n }\n return { start, end };\n }\n\n private getPeriodLabel(range: string): string {\n switch (range) {\n case '1h': return 'hour';\n case '24h': return 'day';\n case '7d': return 'week';\n case '30d': return 'month';\n case '90d': return 'quarter';\n default: return 'period';\n }\n }\n\n // ─── Private: Comparison Data ────────────────────────────────────\n\n private async loadComparisonData(): Promise<void> {\n const { start: currentStart, end: currentEnd } = this.computeDateRange(this.TimeRange);\n const durationMs = currentEnd.getTime() - currentStart.getTime();\n const prevEnd = new Date(currentStart.getTime());\n const prevStart = new Date(prevEnd.getTime() - durationMs);\n\n // Temporarily set date range to previous period, capture KPIs, then restore\n const previousService = new AIInstrumentationService();\n previousService.Provider = this.ProviderToUse;\n previousService.setDateRange(prevStart, prevEnd);\n\n // We subscribe to the previousService's kpis$ once\n const sub: Subscription = previousService.kpis$\n .pipe(takeUntil(this.destroy$))\n .subscribe(kpis => {\n this.previousKpis = kpis;\n this.rebuildKpiCards(this.latestKpis);\n this.cdr.markForCheck();\n sub.unsubscribe();\n });\n }\n\n // ─── Private: KPI Card Builder ───────────────────────────────────\n\n private rebuildKpiCards(kpis: DashboardKPIs | null): void {\n if (!kpis) {\n this.KpiCards = [];\n return;\n }\n\n const trends = this.TrendsData;\n this.KpiCards = [\n this.buildKpiCard(\n 'Total Executions', this.formatNumber(kpis.totalExecutions),\n this.extractSparkline(trends, 'executions'),\n kpis.totalExecutions, this.previousKpis?.totalExecutions ?? null,\n 'up-is-neutral', 'var(--mj-brand-primary)'\n ),\n this.buildKpiCard(\n 'Total Cost', '$' + this.FormatCost(kpis.totalCost),\n this.extractSparkline(trends, 'cost'),\n kpis.totalCost, this.previousKpis?.totalCost ?? null,\n 'down-is-good', 'var(--mj-status-warning)'\n ),\n this.buildKpiCard(\n 'Success Rate', (kpis.successRate * 100).toFixed(1) + '%',\n this.extractSparkline(trends, 'executions'),\n kpis.successRate, this.previousKpis?.successRate ?? null,\n 'up-is-good', 'var(--mj-status-success)'\n ),\n this.buildKpiCard(\n 'Avg Latency', this.formatLatency(kpis.avgExecutionTime),\n this.extractSparkline(trends, 'avgTime'),\n kpis.avgExecutionTime, this.previousKpis?.avgExecutionTime ?? null,\n 'down-is-good', 'var(--mj-status-info)'\n ),\n this.buildKpiCard(\n 'Token Usage', this.formatNumber(kpis.totalTokens),\n this.extractSparkline(trends, 'tokens'),\n kpis.totalTokens, this.previousKpis?.totalTokens ?? null,\n 'up-is-neutral', 'var(--mj-brand-accent, var(--mj-brand-primary))'\n ),\n this.buildKpiCard(\n 'Errors', this.formatNumber(Math.round(kpis.errorRate * kpis.totalExecutions)),\n this.extractSparkline(trends, 'errors'),\n kpis.errorRate, this.previousKpis?.errorRate ?? null,\n 'down-is-good', 'var(--mj-status-error)'\n )\n ];\n }\n\n private buildKpiCard(\n label: string,\n value: string,\n sparkline: number[],\n current: number,\n previous: number | null,\n goodDirection: 'up-is-good' | 'down-is-good' | 'up-is-neutral',\n borderColor: string\n ): KpiDisplayCard {\n const { percent, direction } = this.computeDelta(current, previous);\n const isImprovement = this.isDirectionGood(direction, goodDirection);\n\n return {\n Label: label,\n Value: value,\n SparklineData: sparkline,\n DeltaPercent: percent,\n DeltaDirection: direction,\n IsImprovement: isImprovement,\n BorderColor: borderColor\n };\n }\n\n private computeDelta(current: number, previous: number | null): { percent: number; direction: 'up' | 'down' | 'stable' } {\n if (previous == null || previous === 0) {\n return { percent: 0, direction: 'stable' };\n }\n const change = ((current - previous) / previous) * 100;\n if (Math.abs(change) < 0.5) {\n return { percent: 0, direction: 'stable' };\n }\n return {\n percent: Math.abs(change),\n direction: change > 0 ? 'up' : 'down'\n };\n }\n\n private isDirectionGood(direction: 'up' | 'down' | 'stable', rule: 'up-is-good' | 'down-is-good' | 'up-is-neutral'): boolean {\n if (direction === 'stable') return true;\n if (rule === 'up-is-good') return direction === 'up';\n if (rule === 'down-is-good') return direction === 'down';\n return true; // neutral\n }\n\n // ─── Private: Sparkline ──────────────────────────────────────────\n\n private extractSparkline(trends: TrendData[], metric: 'executions' | 'cost' | 'tokens' | 'avgTime' | 'errors'): number[] {\n if (!trends || trends.length === 0) {\n return [20, 40, 30, 60, 50, 70, 45]; // placeholder\n }\n\n // Sample up to 7 evenly-spaced points\n const step = Math.max(1, Math.floor(trends.length / 7));\n const sampled: number[] = [];\n for (let i = 0; i < trends.length && sampled.length < 7; i += step) {\n sampled.push(this.getMetricFromTrend(trends[i], metric));\n }\n\n // Normalize to 0-100 percentage\n const maxVal = Math.max(...sampled, 1);\n return sampled.map(v => Math.max(5, (v / maxVal) * 100));\n }\n\n private getMetricFromTrend(trend: TrendData, metric: 'executions' | 'cost' | 'tokens' | 'avgTime' | 'errors'): number {\n switch (metric) {\n case 'executions': return trend.executions;\n case 'cost': return trend.cost;\n case 'tokens': return trend.tokens;\n case 'avgTime': return trend.avgTime;\n case 'errors': return trend.errors;\n }\n }\n\n // ─── Private: Top Consumers ──────────────────────────────────────\n\n private buildTopConsumers(chartData: ChartData): TopConsumer[] {\n const consumers: TopConsumer[] = [];\n const maxCost = Math.max(\n ...chartData.costByModel.map(m => m.cost),\n ...chartData.performanceMatrix.map(p => 1), // agents don't have cost here directly\n 1\n );\n\n // Add model-based consumers (from prompt runs)\n for (const model of chartData.costByModel.slice(0, 5)) {\n consumers.push({\n Rank: 0,\n Type: 'prompt',\n Name: model.model,\n Cost: model.cost,\n Proportion: 0\n });\n }\n\n // Sort by cost descending, assign ranks\n consumers.sort((a, b) => b.Cost - a.Cost);\n const topCost = consumers.length > 0 ? consumers[0].Cost : 1;\n return consumers.slice(0, 5).map((c, i) => ({\n ...c,\n Rank: i + 1,\n Proportion: topCost > 0 ? c.Cost / topCost : 0\n }));\n }\n\n // ─── Private: Error Hotspots ─────────────────────────────────────\n // Error hotspots are computed reactively when KPIs change.\n // Since rawData$ is private on the service, we compute from the\n // kpis errorRate + totalExecutions, and rely on chartData for names.\n // For a richer implementation, the service could expose an errors$ stream.\n // For now, we derive from chartData.performanceMatrix entries with low successRate.\n\n private buildErrorHotspots(chartData: ChartData): ErrorHotspot[] {\n const hotspots: ErrorHotspot[] = [];\n\n for (const entry of chartData.performanceMatrix) {\n if (entry.successRate < 1.0) {\n const errorCount = Math.round((1 - entry.successRate) * 10); // approximate\n hotspots.push({\n Source: `${entry.agent} / ${entry.model}`,\n ErrorMessage: `${((1 - entry.successRate) * 100).toFixed(0)}% failure rate (avg ${(entry.avgTime / 1000).toFixed(1)}s)`,\n Count: errorCount\n });\n }\n }\n\n return hotspots\n .sort((a, b) => b.Count - a.Count)\n .slice(0, 4);\n }\n\n // ─── Private: Formatting ─────────────────────────────────────────\n\n private formatNumber(value: number): string {\n if (value >= 1_000_000) return (value / 1_000_000).toFixed(1) + 'M';\n if (value >= 1_000) return (value / 1_000).toFixed(1) + 'K';\n return value.toLocaleString();\n }\n\n private formatLatency(ms: number): string {\n if (ms >= 60_000) return (ms / 60_000).toFixed(1) + 'm';\n if (ms >= 1_000) return (ms / 1_000).toFixed(1) + 's';\n return Math.round(ms) + 'ms';\n }\n}\n\nexport function LoadAnalyticsExecutiveSummary() {\n // Prevents tree-shaking\n}\n"]}
1
+ {"version":3,"file":"executive-summary.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/executive-summary/executive-summary.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter, OnInit, OnDestroy,\n ChangeDetectorRef, inject\n} from '@angular/core';\nimport { Subject, Subscription } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport {\n AIInstrumentationService,\n DashboardKPIs,\n TrendData,\n ChartData\n} from '../../../services/ai-instrumentation.service';\nimport { GlobalFilterState } from '../../../interfaces/analytics-preferences.interface';\nimport { TimeSeriesConfig } from '../../charts/time-series-chart.component';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n// ─── Local Interfaces ──────────────────────────────────────────────\n\ninterface KpiDisplayCard {\n Label: string;\n Value: string;\n SparklineData: number[];\n DeltaPercent: number;\n DeltaDirection: 'up' | 'down' | 'stable';\n IsImprovement: boolean;\n BorderColor: string;\n}\n\ninterface TopConsumer {\n Rank: number;\n Type: 'agent' | 'prompt';\n Name: string;\n Cost: number;\n Proportion: number;\n}\n\ninterface ErrorHotspot {\n Source: string;\n ErrorMessage: string;\n Count: number;\n}\n\n// ─── Component ─────────────────────────────────────────────────────\n\n@Component({\n standalone: false,\n selector: 'app-analytics-executive-summary',\n template: `\n @if (IsLoading && KpiCards.length === 0) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading executive summary...\" size=\"medium\"></mj-loading>\n </div>\n }\n\n <!-- KPI Row -->\n <div class=\"kpi-row\">\n @for (card of KpiCards; track card.Label) {\n <div class=\"kpi-card\" [style.border-left-color]=\"card.BorderColor\">\n <div class=\"kpi-label\">{{ card.Label }}</div>\n <div class=\"kpi-value\">{{ card.Value }}</div>\n <div class=\"kpi-sparkline\">\n @for (bar of card.SparklineData; track $index) {\n <div\n class=\"spark-bar\"\n [style.height.%]=\"bar\"\n [style.background]=\"card.BorderColor\"\n ></div>\n }\n </div>\n @if (ComparisonEnabled && card.DeltaDirection !== 'stable') {\n <div class=\"kpi-delta\" [class.kpi-delta--good]=\"card.IsImprovement\" [class.kpi-delta--bad]=\"!card.IsImprovement\">\n <i [class]=\"card.DeltaDirection === 'up' ? 'fa-solid fa-arrow-up' : 'fa-solid fa-arrow-down'\"></i>\n {{ card.DeltaPercent | number:'1.1-1' }}%\n <span class=\"kpi-delta__period\">vs prev {{ PeriodLabel }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n <!-- Execution Trends Chart -->\n <div class=\"trends-panel\">\n <app-time-series-chart\n [data]=\"TrendsData\"\n title=\"Execution Trends\"\n [config]=\"TimeSeriesConfig\"\n ></app-time-series-chart>\n </div>\n\n <!-- Two-Column Panels -->\n <div class=\"panels-grid\">\n <!-- Top Consumers -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-ranking-star panel-header__icon\"></i>\n Top Consumers\n </div>\n <span class=\"panel-header__subtitle\">by cost</span>\n </div>\n <div class=\"panel-body\">\n @if (TopConsumers.length === 0) {\n <div class=\"panel-empty\">No data for selected period</div>\n }\n @for (item of TopConsumers; track item.Name) {\n <div\n class=\"consumer-item\"\n (click)=\"OnConsumerClick(item)\"\n role=\"button\"\n tabindex=\"0\"\n (keydown.enter)=\"OnConsumerClick(item)\"\n >\n <div\n class=\"consumer-rank\"\n [class.consumer-rank--top]=\"item.Rank <= 3\"\n >{{ item.Rank }}</div>\n <div\n class=\"consumer-type-pill\"\n [class.consumer-type-pill--agent]=\"item.Type === 'agent'\"\n >{{ item.Type }}</div>\n <div class=\"consumer-name\" [title]=\"item.Name\">{{ item.Name }}</div>\n <div class=\"consumer-cost\">\\${{ FormatCost(item.Cost) }}</div>\n <div class=\"consumer-bar-container\">\n <div\n class=\"consumer-bar\"\n [style.width.%]=\"item.Proportion * 100\"\n ></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Error Hotspots -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-triangle-exclamation panel-header__icon panel-header__icon--error\"></i>\n Error Hotspots\n </div>\n <span class=\"panel-header__subtitle\">\n {{ ErrorHotspots.length }} source{{ ErrorHotspots.length !== 1 ? 's' : '' }}\n </span>\n </div>\n <div class=\"panel-body\">\n @if (ErrorHotspots.length === 0) {\n <div class=\"panel-empty\">No errors in selected period</div>\n }\n @for (item of ErrorHotspots; track item.Source) {\n <div class=\"error-item\">\n <div class=\"error-icon\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n </div>\n <div class=\"error-info\">\n <div class=\"error-source\">{{ item.Source }}</div>\n <div class=\"error-message\" [title]=\"item.ErrorMessage\">{{ item.ErrorMessage }}</div>\n </div>\n <div class=\"error-count\">{{ item.Count }}</div>\n </div>\n }\n @if (ErrorHotspots.length > 0) {\n <button class=\"view-all-link\" (click)=\"SectionNavigate.emit('error-analysis')\">\n View All Errors <i class=\"fa-solid fa-arrow-right\"></i>\n </button>\n }\n </div>\n </div>\n </div>\n `,\n styles: [`\n /* ─── Host ────────────────────────────────────────────────── */\n :host {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 4px;\n }\n\n /* ─── Loading ─────────────────────────────────────────────── */\n .loading-container {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 60px 20px;\n }\n\n /* ─── KPI Row ─────────────────────────────────────────────── */\n .kpi-row {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));\n gap: 14px;\n }\n .kpi-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-left: 4px solid var(--mj-brand-primary);\n border-radius: 12px;\n padding: 16px 18px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n transition: all 0.25s ease;\n }\n .kpi-card:hover {\n transform: translateY(-2px);\n box-shadow: 0 6px 20px color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n }\n .kpi-label {\n font-size: 10px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n color: var(--mj-text-muted);\n }\n .kpi-value {\n font-size: 24px;\n font-weight: 700;\n color: var(--mj-text-primary);\n line-height: 1.1;\n letter-spacing: -0.02em;\n }\n\n /* ─── Sparkline ───────────────────────────────────────────── */\n .kpi-sparkline {\n display: flex;\n align-items: flex-end;\n gap: 2px;\n height: 24px;\n margin-top: 4px;\n }\n .spark-bar {\n flex: 1;\n min-width: 4px;\n max-width: 8px;\n border-radius: 1px;\n opacity: 0.35;\n transition: opacity 0.15s ease;\n }\n .kpi-card:hover .spark-bar {\n opacity: 0.55;\n }\n\n /* ─── Delta Badge ─────────────────────────────────────────── */\n .kpi-delta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n margin-top: 2px;\n }\n .kpi-delta--good {\n color: var(--mj-status-success);\n }\n .kpi-delta--bad {\n color: var(--mj-status-error);\n }\n .kpi-delta__period {\n font-weight: 400;\n color: var(--mj-text-disabled);\n }\n\n /* ─── Trends Panel ────────────────────────────────────────── */\n .trends-panel {\n height: 320px;\n border-radius: 12px;\n overflow: hidden;\n }\n\n /* ─── Panels Grid ─────────────────────────────────────────── */\n .panels-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 16px;\n }\n .panel {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 12px;\n overflow: hidden;\n }\n .panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 18px;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n .panel-header__title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n .panel-header__icon {\n color: var(--mj-brand-primary);\n font-size: 14px;\n }\n .panel-header__icon--error {\n color: var(--mj-status-warning);\n }\n .panel-header__subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n .panel-body {\n padding: 8px 0;\n }\n .panel-empty {\n padding: 24px 18px;\n text-align: center;\n font-size: 13px;\n color: var(--mj-text-disabled);\n }\n\n /* ─── Consumer Item ───────────────────────────────────────── */\n .consumer-item {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 18px;\n cursor: pointer;\n transition: background 0.15s ease;\n }\n .consumer-item:hover {\n background: var(--mj-bg-surface-hover);\n }\n .consumer-rank {\n width: 22px;\n height: 22px;\n border-radius: 6px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 700;\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-muted);\n flex-shrink: 0;\n }\n .consumer-rank--top {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n .consumer-type-pill {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n padding: 2px 8px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n flex-shrink: 0;\n }\n .consumer-type-pill--agent {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n .consumer-name {\n flex: 1;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .consumer-cost {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n flex-shrink: 0;\n }\n .consumer-bar-container {\n width: 60px;\n height: 6px;\n border-radius: 3px;\n background: var(--mj-bg-surface-sunken);\n overflow: hidden;\n flex-shrink: 0;\n }\n .consumer-bar {\n height: 100%;\n border-radius: 3px;\n background: var(--mj-brand-primary);\n transition: width 0.3s ease;\n }\n\n /* ─── Error Item ──────────────────────────────────────────── */\n .error-item {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 10px 18px;\n }\n .error-icon {\n color: var(--mj-status-error);\n font-size: 14px;\n margin-top: 2px;\n flex-shrink: 0;\n }\n .error-info {\n flex: 1;\n min-width: 0;\n }\n .error-source {\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 2px;\n }\n .error-message {\n font-size: 12px;\n color: var(--mj-text-muted);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .error-count {\n font-size: 13px;\n font-weight: 700;\n color: var(--mj-status-error);\n flex-shrink: 0;\n min-width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n }\n .view-all-link {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 8px 18px 10px;\n padding: 0;\n border: none;\n background: none;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n cursor: pointer;\n transition: color 0.15s ease;\n }\n .view-all-link:hover {\n color: var(--mj-brand-primary-hover);\n }\n\n /* ─── Responsive ──────────────────────────────────────────── */\n @media (max-width: 1200px) {\n .panels-grid {\n grid-template-columns: 1fr;\n }\n }\n @media (max-width: 768px) {\n .kpi-row {\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n }\n .trends-panel {\n height: 260px;\n }\n }\n `]\n})\nexport class AnalyticsExecutiveSummaryComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n // ─── Inputs / Outputs ────────────────────────────────────────────\n\n private _timeRange = '24h';\n @Input()\n set TimeRange(value: string) {\n if (value !== this._timeRange) {\n this._timeRange = value;\n if (this.isInitialized) {\n this.applyDateRange();\n }\n }\n }\n get TimeRange(): string { return this._timeRange; }\n\n @Input() Filters: GlobalFilterState = { Models: [], Agents: [], Prompts: [], Statuses: [] };\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<GlobalFilterState>();\n @Output() SectionNavigate = new EventEmitter<string>();\n\n // ─── DI ──────────────────────────────────────────────────────────\n\n private instrumentationService = inject(AIInstrumentationService);\n private cdr = inject(ChangeDetectorRef);\n\n // ─── Public State ────────────────────────────────────────────────\n\n KpiCards: KpiDisplayCard[] = [];\n TrendsData: TrendData[] = [];\n TopConsumers: TopConsumer[] = [];\n ErrorHotspots: ErrorHotspot[] = [];\n IsLoading = false;\n ComparisonEnabled = false;\n PeriodLabel = 'period';\n\n TimeSeriesConfig: TimeSeriesConfig = {\n showGrid: true,\n showTooltip: true,\n animationDuration: 300,\n useDualAxis: true\n };\n\n // ─── Private State ───────────────────────────────────────────────\n\n private destroy$ = new Subject<void>();\n private isInitialized = false;\n private previousKpis: DashboardKPIs | null = null;\n\n // ─── Lifecycle ───────────────────────────────────────────────────\n\n ngOnInit(): void {\n this.instrumentationService.Provider = this.ProviderToUse;\n this.subscribeToStreams();\n this.applyDateRange();\n this.isInitialized = true;\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n // ─── Event Handlers ──────────────────────────────────────────────\n\n OnTimeRangeChange(range: string): void {\n this.TimeRange = range;\n this.TimeRangeChange.emit(range);\n }\n\n OnFiltersChange(filters: GlobalFilterState): void {\n this.Filters = filters;\n this.FiltersChange.emit(filters);\n }\n\n OnCompareToggled(active: boolean): void {\n this.ComparisonEnabled = active;\n if (this.ComparisonEnabled) {\n this.loadComparisonData();\n } else {\n this.previousKpis = null;\n this.rebuildKpiCards(this.latestKpis);\n }\n }\n\n OnRefresh(): void {\n this.instrumentationService.refresh();\n if (this.ComparisonEnabled) {\n this.loadComparisonData();\n }\n }\n\n OnConsumerClick(item: TopConsumer): void {\n this.SectionNavigate.emit(item.Type === 'agent' ? 'agent-runs' : 'prompt-runs');\n }\n\n // ─── Formatting Helpers ──────────────────────────────────────────\n\n FormatCost(cost: number): string {\n if (cost >= 1000) {\n return (cost / 1000).toFixed(1) + 'K';\n }\n if (cost >= 1) {\n return cost.toFixed(2);\n }\n return cost.toFixed(4);\n }\n\n // ─── Private: Subscriptions ──────────────────────────────────────\n\n private latestKpis: DashboardKPIs | null = null;\n\n private subscribeToStreams(): void {\n this.instrumentationService.isLoading$\n .pipe(takeUntil(this.destroy$))\n .subscribe(loading => {\n this.IsLoading = loading;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.kpis$\n .pipe(takeUntil(this.destroy$))\n .subscribe(kpis => {\n this.latestKpis = kpis;\n this.rebuildKpiCards(kpis);\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.trends$\n .pipe(takeUntil(this.destroy$))\n .subscribe(trends => {\n this.TrendsData = trends;\n this.cdr.markForCheck();\n });\n\n this.instrumentationService.chartData$\n .pipe(takeUntil(this.destroy$))\n .subscribe(chartData => {\n this.TopConsumers = this.buildTopConsumers(chartData);\n this.ErrorHotspots = this.buildErrorHotspots(chartData);\n this.cdr.markForCheck();\n });\n }\n\n // ─── Private: Date Range ─────────────────────────────────────────\n\n private applyDateRange(): void {\n const { start, end } = this.computeDateRange(this.TimeRange);\n this.PeriodLabel = this.getPeriodLabel(this.TimeRange);\n this.instrumentationService.setDateRange(start, end);\n // Explicitly refresh to ensure data loads on first visit\n this.instrumentationService.refresh();\n }\n\n private computeDateRange(range: string): { start: Date; end: Date } {\n const end = new Date();\n const start = new Date();\n switch (range) {\n case '1h':\n start.setHours(start.getHours() - 1);\n break;\n case '24h':\n start.setDate(start.getDate() - 1);\n break;\n case '7d':\n start.setDate(start.getDate() - 7);\n break;\n case '30d':\n start.setDate(start.getDate() - 30);\n break;\n case '90d':\n start.setDate(start.getDate() - 90);\n break;\n default:\n start.setDate(start.getDate() - 1);\n }\n return { start, end };\n }\n\n private getPeriodLabel(range: string): string {\n switch (range) {\n case '1h': return 'hour';\n case '24h': return 'day';\n case '7d': return 'week';\n case '30d': return 'month';\n case '90d': return 'quarter';\n default: return 'period';\n }\n }\n\n // ─── Private: Comparison Data ────────────────────────────────────\n\n private async loadComparisonData(): Promise<void> {\n const { start: currentStart, end: currentEnd } = this.computeDateRange(this.TimeRange);\n const durationMs = currentEnd.getTime() - currentStart.getTime();\n const prevEnd = new Date(currentStart.getTime());\n const prevStart = new Date(prevEnd.getTime() - durationMs);\n\n // Temporarily set date range to previous period, capture KPIs, then restore\n const previousService = new AIInstrumentationService();\n previousService.Provider = this.ProviderToUse;\n previousService.setDateRange(prevStart, prevEnd);\n\n // We subscribe to the previousService's kpis$ once\n const sub: Subscription = previousService.kpis$\n .pipe(takeUntil(this.destroy$))\n .subscribe(kpis => {\n this.previousKpis = kpis;\n this.rebuildKpiCards(this.latestKpis);\n this.cdr.markForCheck();\n sub.unsubscribe();\n });\n }\n\n // ─── Private: KPI Card Builder ───────────────────────────────────\n\n private rebuildKpiCards(kpis: DashboardKPIs | null): void {\n if (!kpis) {\n this.KpiCards = [];\n return;\n }\n\n const trends = this.TrendsData;\n this.KpiCards = [\n this.buildKpiCard(\n 'Total Executions', this.formatNumber(kpis.totalExecutions),\n this.extractSparkline(trends, 'executions'),\n kpis.totalExecutions, this.previousKpis?.totalExecutions ?? null,\n 'up-is-neutral', 'var(--mj-brand-primary)'\n ),\n this.buildKpiCard(\n 'Total Cost', '$' + this.FormatCost(kpis.totalCost),\n this.extractSparkline(trends, 'cost'),\n kpis.totalCost, this.previousKpis?.totalCost ?? null,\n 'down-is-good', 'var(--mj-status-warning)'\n ),\n this.buildKpiCard(\n 'Success Rate', (kpis.successRate * 100).toFixed(1) + '%',\n this.extractSparkline(trends, 'executions'),\n kpis.successRate, this.previousKpis?.successRate ?? null,\n 'up-is-good', 'var(--mj-status-success)'\n ),\n this.buildKpiCard(\n 'Avg Latency', this.formatLatency(kpis.avgExecutionTime),\n this.extractSparkline(trends, 'avgTime'),\n kpis.avgExecutionTime, this.previousKpis?.avgExecutionTime ?? null,\n 'down-is-good', 'var(--mj-status-info)'\n ),\n this.buildKpiCard(\n 'Token Usage', this.formatNumber(kpis.totalTokens),\n this.extractSparkline(trends, 'tokens'),\n kpis.totalTokens, this.previousKpis?.totalTokens ?? null,\n 'up-is-neutral', 'var(--mj-brand-accent, var(--mj-brand-primary))'\n ),\n this.buildKpiCard(\n 'Errors', this.formatNumber(Math.round(kpis.errorRate * kpis.totalExecutions)),\n this.extractSparkline(trends, 'errors'),\n kpis.errorRate, this.previousKpis?.errorRate ?? null,\n 'down-is-good', 'var(--mj-status-error)'\n ),\n this.buildKpiCard(\n 'Cache Hit Rate', (kpis.cacheHitRate * 100).toFixed(1) + '%',\n this.extractSparkline(trends, 'tokens'),\n kpis.cacheHitRate, this.previousKpis?.cacheHitRate ?? null,\n 'up-is-good', 'var(--mj-status-info)'\n )\n ];\n }\n\n private buildKpiCard(\n label: string,\n value: string,\n sparkline: number[],\n current: number,\n previous: number | null,\n goodDirection: 'up-is-good' | 'down-is-good' | 'up-is-neutral',\n borderColor: string\n ): KpiDisplayCard {\n const { percent, direction } = this.computeDelta(current, previous);\n const isImprovement = this.isDirectionGood(direction, goodDirection);\n\n return {\n Label: label,\n Value: value,\n SparklineData: sparkline,\n DeltaPercent: percent,\n DeltaDirection: direction,\n IsImprovement: isImprovement,\n BorderColor: borderColor\n };\n }\n\n private computeDelta(current: number, previous: number | null): { percent: number; direction: 'up' | 'down' | 'stable' } {\n if (previous == null || previous === 0) {\n return { percent: 0, direction: 'stable' };\n }\n const change = ((current - previous) / previous) * 100;\n if (Math.abs(change) < 0.5) {\n return { percent: 0, direction: 'stable' };\n }\n return {\n percent: Math.abs(change),\n direction: change > 0 ? 'up' : 'down'\n };\n }\n\n private isDirectionGood(direction: 'up' | 'down' | 'stable', rule: 'up-is-good' | 'down-is-good' | 'up-is-neutral'): boolean {\n if (direction === 'stable') return true;\n if (rule === 'up-is-good') return direction === 'up';\n if (rule === 'down-is-good') return direction === 'down';\n return true; // neutral\n }\n\n // ─── Private: Sparkline ──────────────────────────────────────────\n\n private extractSparkline(trends: TrendData[], metric: 'executions' | 'cost' | 'tokens' | 'avgTime' | 'errors'): number[] {\n if (!trends || trends.length === 0) {\n return [20, 40, 30, 60, 50, 70, 45]; // placeholder\n }\n\n // Sample up to 7 evenly-spaced points\n const step = Math.max(1, Math.floor(trends.length / 7));\n const sampled: number[] = [];\n for (let i = 0; i < trends.length && sampled.length < 7; i += step) {\n sampled.push(this.getMetricFromTrend(trends[i], metric));\n }\n\n // Normalize to 0-100 percentage\n const maxVal = Math.max(...sampled, 1);\n return sampled.map(v => Math.max(5, (v / maxVal) * 100));\n }\n\n private getMetricFromTrend(trend: TrendData, metric: 'executions' | 'cost' | 'tokens' | 'avgTime' | 'errors'): number {\n switch (metric) {\n case 'executions': return trend.executions;\n case 'cost': return trend.cost;\n case 'tokens': return trend.tokens;\n case 'avgTime': return trend.avgTime;\n case 'errors': return trend.errors;\n }\n }\n\n // ─── Private: Top Consumers ──────────────────────────────────────\n\n private buildTopConsumers(chartData: ChartData): TopConsumer[] {\n const consumers: TopConsumer[] = [];\n const maxCost = Math.max(\n ...chartData.costByModel.map(m => m.cost),\n ...chartData.performanceMatrix.map(p => 1), // agents don't have cost here directly\n 1\n );\n\n // Add model-based consumers (from prompt runs)\n for (const model of chartData.costByModel.slice(0, 5)) {\n consumers.push({\n Rank: 0,\n Type: 'prompt',\n Name: model.model,\n Cost: model.cost,\n Proportion: 0\n });\n }\n\n // Sort by cost descending, assign ranks\n consumers.sort((a, b) => b.Cost - a.Cost);\n const topCost = consumers.length > 0 ? consumers[0].Cost : 1;\n return consumers.slice(0, 5).map((c, i) => ({\n ...c,\n Rank: i + 1,\n Proportion: topCost > 0 ? c.Cost / topCost : 0\n }));\n }\n\n // ─── Private: Error Hotspots ─────────────────────────────────────\n // Error hotspots are computed reactively when KPIs change.\n // Since rawData$ is private on the service, we compute from the\n // kpis errorRate + totalExecutions, and rely on chartData for names.\n // For a richer implementation, the service could expose an errors$ stream.\n // For now, we derive from chartData.performanceMatrix entries with low successRate.\n\n private buildErrorHotspots(chartData: ChartData): ErrorHotspot[] {\n const hotspots: ErrorHotspot[] = [];\n\n for (const entry of chartData.performanceMatrix) {\n if (entry.successRate < 1.0) {\n const errorCount = Math.round((1 - entry.successRate) * 10); // approximate\n hotspots.push({\n Source: `${entry.agent} / ${entry.model}`,\n ErrorMessage: `${((1 - entry.successRate) * 100).toFixed(0)}% failure rate (avg ${(entry.avgTime / 1000).toFixed(1)}s)`,\n Count: errorCount\n });\n }\n }\n\n return hotspots\n .sort((a, b) => b.Count - a.Count)\n .slice(0, 4);\n }\n\n // ─── Private: Formatting ─────────────────────────────────────────\n\n private formatNumber(value: number): string {\n if (value >= 1_000_000) return (value / 1_000_000).toFixed(1) + 'M';\n if (value >= 1_000) return (value / 1_000).toFixed(1) + 'K';\n return value.toLocaleString();\n }\n\n private formatLatency(ms: number): string {\n if (ms >= 60_000) return (ms / 60_000).toFixed(1) + 'm';\n if (ms >= 1_000) return (ms / 1_000).toFixed(1) + 's';\n return Math.round(ms) + 'ms';\n }\n}\n\nexport function LoadAnalyticsExecutiveSummary() {\n // Prevents tree-shaking\n}\n"]}
@@ -20,6 +20,7 @@ interface ModelLeaderboardRow {
20
20
  P95LatencyMs: number;
21
21
  SuccessRate: number;
22
22
  CostPer1KTokens: number;
23
+ CacheHitRate: number;
23
24
  TotalCost: number;
24
25
  }
25
26
  type SortByOption = 'cost-efficiency' | 'speed' | 'reliability' | 'usage-volume';
@@ -1 +1 @@
1
- {"version":3,"file":"model-performance.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/model-performance/model-performance.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEH,MAAM,EAAE,SAAS,EAEpB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAuBrE,UAAU,mBAAmB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,YAAY,GAAG,iBAAiB,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;AAQjF,qBA8Oa,kCAAmC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IACrG,OAAO,CAAC,UAAU,CAAQ;IAC1B,IACI,SAAS,CAAC,KAAK,EAAE,MAAM,EAI1B;IACD,IAAI,SAAS,IAAI,MAAM,CAA4B;IAEnD,OAAO,CAAC,OAAO,CAAmC;IAClD,IACI,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAOtC;IACD,IAAI,MAAM,IAAI,YAAY,CAAyB;IAEnD,OAAO,CAAC,eAAe,CAAM;IAC7B,IACI,cAAc,CAAC,KAAK,EAAE,MAAM,EAO/B;IACD,IAAI,cAAc,IAAI,MAAM,CAAiC;IAE7D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAS;IAErB,SAAS,UAAS;IAClB,IAAI,EAAE,mBAAmB,EAAE,CAAM;IAExC,OAAO,CAAC,OAAO,CAAyB;IAElC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,WAAW,IAAI,IAAI;IAKZ,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAKjC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM;YAQ5C,QAAQ;IA4BtB,OAAO,CAAC,SAAS;IAkCjB,OAAO,CAAC,mBAAmB;IAgD3B,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;yCA1Nd,kCAAkC;2CAAlC,kCAAkC;CAqO9C;AAED,wBAAgB,6BAA6B,SAAoC"}
1
+ {"version":3,"file":"model-performance.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/model-performance/model-performance.component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEH,MAAM,EAAE,SAAS,EAEpB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAyBrE,UAAU,mBAAmB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,YAAY,GAAG,iBAAiB,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;AAQjF,qBAgPa,kCAAmC,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IACrG,OAAO,CAAC,UAAU,CAAQ;IAC1B,IACI,SAAS,CAAC,KAAK,EAAE,MAAM,EAI1B;IACD,IAAI,SAAS,IAAI,MAAM,CAA4B;IAEnD,OAAO,CAAC,OAAO,CAAmC;IAClD,IACI,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAOtC;IACD,IAAI,MAAM,IAAI,YAAY,CAAyB;IAEnD,OAAO,CAAC,eAAe,CAAM;IAC7B,IACI,cAAc,CAAC,KAAK,EAAE,MAAM,EAO/B;IACD,IAAI,cAAc,IAAI,MAAM,CAAiC;IAE7D,OAAO,CAAC,GAAG,CAA6B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAS;IAErB,SAAS,UAAS;IAClB,IAAI,EAAE,mBAAmB,EAAE,CAAM;IAExC,OAAO,CAAC,OAAO,CAAyB;IAElC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,WAAW,IAAI,IAAI;IAKZ,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IAKjC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM;YAQ5C,QAAQ;IA4BtB,OAAO,CAAC,SAAS;IAkCjB,OAAO,CAAC,mBAAmB;IAyD3B,OAAO,CAAC,QAAQ;IAmBhB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;yCAnOd,kCAAkC;2CAAlC,kCAAkC;CA8O9C;AAED,wBAAgB,6BAA6B,SAAoC"}