@memberjunction/ng-dashboards 5.38.0 → 5.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -7
- package/dist/AI/components/agents/agent-configuration.component.js +199 -198
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/ai-analytics-resource.component.js +20 -17
- package/dist/AI/components/analytics/ai-analytics-resource.component.js.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts +15 -0
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js +166 -58
- package/dist/AI/components/analytics/cost-budget/cost-budget.component.js.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js +2 -1
- package/dist/AI/components/analytics/executive-summary/executive-summary.component.js.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts +1 -0
- package/dist/AI/components/analytics/model-performance/model-performance.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/model-performance/model-performance.component.js +55 -36
- package/dist/AI/components/analytics/model-performance/model-performance.component.js.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts +9 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js +158 -117
- package/dist/AI/components/analytics/prompt-runs/prompt-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts +1 -0
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js +22 -8
- package/dist/AI/components/analytics/usage-patterns/usage-patterns.component.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +89 -856
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +1353 -7841
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts +87 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js +475 -0
- package/dist/AI/components/autotagging/dialogs/dry-run-preview.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts +29 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js +208 -0
- package/dist/AI/components/autotagging/dialogs/item-detail.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts +21 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js +70 -0
- package/dist/AI/components/autotagging/dialogs/no-content-type-warning.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts +235 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1735 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts +61 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js +78 -0
- package/dist/AI/components/autotagging/shared/classify.dryrun.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts +43 -0
- package/dist/AI/components/autotagging/shared/classify.format.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.format.js +209 -0
- package/dist/AI/components/autotagging/shared/classify.format.js.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts +276 -0
- package/dist/AI/components/autotagging/shared/classify.types.d.ts.map +1 -0
- package/dist/AI/components/autotagging/shared/classify.types.js +6 -0
- package/dist/AI/components/autotagging/shared/classify.types.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts +103 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js +571 -0
- package/dist/AI/components/autotagging/tabs/health-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts +40 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js +402 -0
- package/dist/AI/components/autotagging/tabs/history-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts +107 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js +719 -0
- package/dist/AI/components/autotagging/tabs/inbox-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts +122 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js +752 -0
- package/dist/AI/components/autotagging/tabs/pipeline-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts +166 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1384 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts +70 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js +448 -0
- package/dist/AI/components/autotagging/tabs/tags-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts +397 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js +3490 -0
- package/dist/AI/components/autotagging/tabs/taxonomy-tab.component.js.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts +47 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.d.ts.map +1 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js +220 -0
- package/dist/AI/components/autotagging/tabs/types-tab.component.js.map +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +293 -289
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +209 -208
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +130 -128
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/requests/agent-requests-resource.component.js +61 -61
- package/dist/AI/components/requests/agent-requests-resource.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +17 -17
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +550 -532
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts +5 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +14 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/AI/services/cache-metrics.d.ts +50 -0
- package/dist/AI/services/cache-metrics.d.ts.map +1 -0
- package/dist/AI/services/cache-metrics.js +43 -0
- package/dist/AI/services/cache-metrics.js.map +1 -0
- package/dist/APIKeys/api-key-edit-panel.component.js +2 -2
- package/dist/APIKeys/api-keys-resource.component.js +132 -131
- package/dist/APIKeys/api-keys-resource.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +141 -141
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +15 -15
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.d.ts +0 -5
- package/dist/Actions/components/explorer/action-explorer.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-explorer.component.js +139 -212
- package/dist/Actions/components/explorer/action-explorer.component.js.map +1 -1
- package/dist/Admin/admin-data-schema.component.js +2 -2
- package/dist/Admin/admin-data-schema.component.js.map +1 -1
- package/dist/Admin/admin-dev-tools-resource.component.js +2 -2
- package/dist/Admin/admin-dev-tools-resource.component.js.map +1 -1
- package/dist/Admin/admin-identity-access.component.js +2 -2
- package/dist/Admin/admin-identity-access.component.js.map +1 -1
- package/dist/Admin/admin-monitoring.component.js +2 -2
- package/dist/Admin/admin-monitoring.component.js.map +1 -1
- package/dist/ApplicationRoles/application-roles-resource.component.js +54 -49
- package/dist/ApplicationRoles/application-roles-resource.component.js.map +1 -1
- package/dist/Communication/communication-logs-resource.component.d.ts +6 -0
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +72 -50
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +103 -102
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-providers-resource.component.js +52 -51
- package/dist/Communication/communication-providers-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +39 -38
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/Communication/communication-templates-resource.component.d.ts +6 -0
- package/dist/Communication/communication-templates-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-templates-resource.component.js +92 -89
- package/dist/Communication/communication-templates-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-audit-resource.component.js +136 -135
- package/dist/Credentials/components/credentials-audit-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-categories-resource.component.js +155 -152
- package/dist/Credentials/components/credentials-categories-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-list-resource.component.js +119 -118
- package/dist/Credentials/components/credentials-list-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-overview-resource.component.js +129 -128
- package/dist/Credentials/components/credentials-overview-resource.component.js.map +1 -1
- package/dist/Credentials/components/credentials-types-resource.component.js +107 -106
- package/dist/Credentials/components/credentials-types-resource.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +2 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DatabaseDesigner/components/database-designer-dashboard.component.js +1 -1
- package/dist/DatabaseDesigner/components/entity-list.component.js +115 -114
- package/dist/DatabaseDesigner/components/entity-list.component.js.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts +5 -6
- package/dist/DatabaseDesigner/database-designer-dashboards.module.d.ts.map +1 -1
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js +4 -5
- package/dist/DatabaseDesigner/database-designer-dashboards.module.js.map +1 -1
- package/dist/DevTools/app-state-inspector.component.js +18 -17
- package/dist/DevTools/app-state-inspector.component.js.map +1 -1
- package/dist/DevTools/class-registry.component.js +88 -85
- package/dist/DevTools/class-registry.component.js.map +1 -1
- package/dist/DevTools/event-monitor.component.js +155 -150
- package/dist/DevTools/event-monitor.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +245 -243
- package/dist/DevTools/graphql-console.component.js.map +1 -1
- package/dist/DevTools/layout-inspector.component.js +18 -17
- package/dist/DevTools/layout-inspector.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +20 -19
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/Home/home-dashboard.component.js +2 -2
- package/dist/Integration/components/activity/activity.component.d.ts.map +1 -1
- package/dist/Integration/components/activity/activity.component.js +236 -229
- package/dist/Integration/components/activity/activity.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +390 -389
- package/dist/Integration/components/connections/connections.component.js.map +1 -1
- package/dist/Integration/components/overview/overview.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js +2 -2
- package/dist/KnowledgeHub/components/analytics/analytics-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js +45 -44
- package/dist/KnowledgeHub/components/clusters/cluster-visualization-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js +293 -291
- package/dist/KnowledgeHub/components/config/knowledge-config-resource.component.js.map +1 -1
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js +62 -61
- package/dist/KnowledgeHub/components/scheduling/scheduling-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.d.ts +6 -2
- package/dist/Lists/components/lists-browse-resource.component.d.ts.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +525 -566
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-categories-resource.component.js +135 -134
- package/dist/Lists/components/lists-categories-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +199 -198
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +443 -438
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.d.ts.map +1 -1
- package/dist/Scheduling/components/scheduling-activity.component.js +146 -147
- package/dist/Scheduling/components/scheduling-activity.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-jobs.component.js +76 -75
- package/dist/Scheduling/components/scheduling-jobs.component.js.map +1 -1
- package/dist/Scheduling/components/scheduling-overview.component.js +97 -96
- package/dist/Scheduling/components/scheduling-overview.component.js.map +1 -1
- package/dist/Scheduling/scheduling-dashboard.component.js +24 -22
- package/dist/Scheduling/scheduling-dashboard.component.js.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts +2 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.d.ts.map +1 -1
- package/dist/Scheduling/services/scheduling-instrumentation.service.js +1 -0
- package/dist/Scheduling/services/scheduling-instrumentation.service.js.map +1 -1
- package/dist/Testing/components/testing-dashboard-tab-resource.component.js +1 -1
- package/dist/Testing/components/testing-explorer.component.d.ts +14 -4
- package/dist/Testing/components/testing-explorer.component.d.ts.map +1 -1
- package/dist/Testing/components/testing-explorer.component.js +436 -427
- package/dist/Testing/components/testing-explorer.component.js.map +1 -1
- package/dist/Testing/components/testing-runs-resource.component.js +1 -1
- package/dist/Testing/components/testing-runs.component.js +116 -115
- package/dist/Testing/components/testing-runs.component.js.map +1 -1
- package/dist/Testing/testing-dashboard.component.js +6 -7
- package/dist/Testing/testing-dashboard.component.js.map +1 -1
- package/dist/VersionHistory/components/labels-resource.component.js +173 -172
- package/dist/VersionHistory/components/labels-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.d.ts +6 -0
- package/dist/VersionHistory/components/restore-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/restore-resource.component.js +116 -92
- package/dist/VersionHistory/components/restore-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +47 -35
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +40 -1
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/communication-dashboards.module.d.ts +1 -1
- package/dist/communication-dashboards.module.d.ts.map +1 -1
- package/dist/communication-dashboards.module.js +7 -1
- package/dist/communication-dashboards.module.js.map +1 -1
- package/dist/testing-dashboards.module.d.ts +4 -5
- package/dist/testing-dashboards.module.d.ts.map +1 -1
- package/dist/testing-dashboards.module.js +7 -5
- package/dist/testing-dashboards.module.js.map +1 -1
- package/package.json +55 -54
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, inject } from '@angular/core';
|
|
8
8
|
import { Subject } from 'rxjs';
|
|
9
9
|
import { RunView } from '@memberjunction/core';
|
|
10
|
+
import { NormalizeUUID } from '@memberjunction/global';
|
|
11
|
+
import { cacheHitRate, hasCacheActivity, netCacheSavings } from '../../../services/cache-metrics';
|
|
10
12
|
import { BaseAngularComponent } from '@memberjunction/ng-base-types';
|
|
11
13
|
import * as i0 from "@angular/core";
|
|
12
14
|
import * as i1 from "@memberjunction/ng-shared-generic";
|
|
@@ -20,14 +22,14 @@ function AnalyticsCostBudgetComponent_Conditional_0_Template(rf, ctx) { if (rf &
|
|
|
20
22
|
i0.ɵɵelementEnd();
|
|
21
23
|
} }
|
|
22
24
|
function AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
23
|
-
i0.ɵɵelement(0, "i",
|
|
25
|
+
i0.ɵɵelement(0, "i", 32);
|
|
24
26
|
} }
|
|
25
27
|
function AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
26
|
-
i0.ɵɵelement(0, "i",
|
|
28
|
+
i0.ɵɵelement(0, "i", 33);
|
|
27
29
|
} }
|
|
28
30
|
function AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Template(rf, ctx) { if (rf & 1) {
|
|
29
|
-
i0.ɵɵelementStart(0, "div",
|
|
30
|
-
i0.ɵɵconditionalCreate(1, AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Conditional_1_Template, 1, 0, "i",
|
|
31
|
+
i0.ɵɵelementStart(0, "div", 31);
|
|
32
|
+
i0.ɵɵconditionalCreate(1, AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Conditional_1_Template, 1, 0, "i", 32)(2, AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Conditional_2_Template, 1, 0, "i", 33);
|
|
31
33
|
i0.ɵɵtext(3);
|
|
32
34
|
i0.ɵɵpipe(4, "number");
|
|
33
35
|
i0.ɵɵelementEnd();
|
|
@@ -40,16 +42,16 @@ function AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Template
|
|
|
40
42
|
i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind2(4, 6, kpi_r2.Delta, "1.1-1"), "% vs prev ");
|
|
41
43
|
} }
|
|
42
44
|
function AnalyticsCostBudgetComponent_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
43
|
-
i0.ɵɵelementStart(0, "div",
|
|
45
|
+
i0.ɵɵelementStart(0, "div", 25)(1, "div", 26);
|
|
44
46
|
i0.ɵɵelement(2, "i");
|
|
45
47
|
i0.ɵɵelementEnd();
|
|
46
|
-
i0.ɵɵelementStart(3, "div",
|
|
48
|
+
i0.ɵɵelementStart(3, "div", 27)(4, "div", 28);
|
|
47
49
|
i0.ɵɵtext(5);
|
|
48
50
|
i0.ɵɵelementEnd();
|
|
49
|
-
i0.ɵɵelementStart(6, "div",
|
|
51
|
+
i0.ɵɵelementStart(6, "div", 29);
|
|
50
52
|
i0.ɵɵtext(7);
|
|
51
53
|
i0.ɵɵelementEnd();
|
|
52
|
-
i0.ɵɵconditionalCreate(8, AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Template, 5, 9, "div",
|
|
54
|
+
i0.ɵɵconditionalCreate(8, AnalyticsCostBudgetComponent_Conditional_1_For_2_Conditional_8_Template, 5, 9, "div", 30);
|
|
53
55
|
i0.ɵɵelementEnd()();
|
|
54
56
|
} if (rf & 2) {
|
|
55
57
|
const kpi_r2 = ctx.$implicit;
|
|
@@ -69,7 +71,7 @@ function AnalyticsCostBudgetComponent_Conditional_1_Conditional_10_Template(rf,
|
|
|
69
71
|
i0.ɵɵelementEnd();
|
|
70
72
|
} }
|
|
71
73
|
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
72
|
-
i0.ɵɵelementStart(0, "div",
|
|
74
|
+
i0.ɵɵelementStart(0, "div", 37)(1, "span", 38);
|
|
73
75
|
i0.ɵɵtext(2, "avg");
|
|
74
76
|
i0.ɵɵelementEnd()();
|
|
75
77
|
} if (rf & 2) {
|
|
@@ -77,9 +79,9 @@ function AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_Conditional_2
|
|
|
77
79
|
i0.ɵɵstyleProp("bottom", ctx_r2.AvgLinePercent, "%");
|
|
78
80
|
} }
|
|
79
81
|
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
80
|
-
i0.ɵɵelementStart(0, "div",
|
|
81
|
-
i0.ɵɵelement(1, "div",
|
|
82
|
-
i0.ɵɵelementStart(2, "div",
|
|
82
|
+
i0.ɵɵelementStart(0, "div", 36);
|
|
83
|
+
i0.ɵɵelement(1, "div", 39);
|
|
84
|
+
i0.ɵɵelementStart(2, "div", 40);
|
|
83
85
|
i0.ɵɵtext(3);
|
|
84
86
|
i0.ɵɵelementEnd()();
|
|
85
87
|
} if (rf & 2) {
|
|
@@ -93,9 +95,9 @@ function AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_For_4_Templat
|
|
|
93
95
|
i0.ɵɵtextInterpolate(bar_r4.Label);
|
|
94
96
|
} }
|
|
95
97
|
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_Template(rf, ctx) { if (rf & 1) {
|
|
96
|
-
i0.ɵɵelementStart(0, "div", 11)(1, "div",
|
|
97
|
-
i0.ɵɵconditionalCreate(2, AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_Conditional_2_Template, 3, 2, "div",
|
|
98
|
-
i0.ɵɵrepeaterCreate(3, AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_For_4_Template, 4, 6, "div",
|
|
98
|
+
i0.ɵɵelementStart(0, "div", 11)(1, "div", 34);
|
|
99
|
+
i0.ɵɵconditionalCreate(2, AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_Conditional_2_Template, 3, 2, "div", 35);
|
|
100
|
+
i0.ɵɵrepeaterCreate(3, AnalyticsCostBudgetComponent_Conditional_1_Conditional_11_For_4_Template, 4, 6, "div", 36, _forTrack2);
|
|
99
101
|
i0.ɵɵelementEnd()();
|
|
100
102
|
} if (rf & 2) {
|
|
101
103
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
@@ -110,15 +112,15 @@ function AnalyticsCostBudgetComponent_Conditional_1_Conditional_18_Template(rf,
|
|
|
110
112
|
i0.ɵɵelementEnd();
|
|
111
113
|
} }
|
|
112
114
|
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_19_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
113
|
-
i0.ɵɵelementStart(0, "div",
|
|
115
|
+
i0.ɵɵelementStart(0, "div", 42);
|
|
114
116
|
i0.ɵɵpipe(1, "number");
|
|
115
|
-
i0.ɵɵelementStart(2, "span",
|
|
117
|
+
i0.ɵɵelementStart(2, "span", 43);
|
|
116
118
|
i0.ɵɵtext(3);
|
|
117
119
|
i0.ɵɵelementEnd();
|
|
118
|
-
i0.ɵɵelementStart(4, "span",
|
|
120
|
+
i0.ɵɵelementStart(4, "span", 44);
|
|
119
121
|
i0.ɵɵtext(5);
|
|
120
122
|
i0.ɵɵelementEnd();
|
|
121
|
-
i0.ɵɵelementStart(6, "span",
|
|
123
|
+
i0.ɵɵelementStart(6, "span", 45);
|
|
122
124
|
i0.ɵɵtext(7);
|
|
123
125
|
i0.ɵɵpipe(8, "number");
|
|
124
126
|
i0.ɵɵelementEnd()();
|
|
@@ -136,49 +138,56 @@ function AnalyticsCostBudgetComponent_Conditional_1_Conditional_19_For_2_Templat
|
|
|
136
138
|
} }
|
|
137
139
|
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_19_Template(rf, ctx) { if (rf & 1) {
|
|
138
140
|
i0.ɵɵelementStart(0, "div", 15);
|
|
139
|
-
i0.ɵɵrepeaterCreate(1, AnalyticsCostBudgetComponent_Conditional_1_Conditional_19_For_2_Template, 9, 14, "div",
|
|
141
|
+
i0.ɵɵrepeaterCreate(1, AnalyticsCostBudgetComponent_Conditional_1_Conditional_19_For_2_Template, 9, 14, "div", 41, _forTrack0);
|
|
140
142
|
i0.ɵɵelementEnd();
|
|
141
143
|
} if (rf & 2) {
|
|
142
144
|
const ctx_r2 = i0.ɵɵnextContext(2);
|
|
143
145
|
i0.ɵɵadvance();
|
|
144
146
|
i0.ɵɵrepeater(ctx_r2.TreemapCells);
|
|
145
147
|
} }
|
|
146
|
-
function
|
|
147
|
-
i0.ɵɵelementStart(0, "tr")(1, "td",
|
|
148
|
+
function AnalyticsCostBudgetComponent_Conditional_1_Conditional_55_Template(rf, ctx) { if (rf & 1) {
|
|
149
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 46);
|
|
148
150
|
i0.ɵɵtext(2, "No data available");
|
|
149
151
|
i0.ɵɵelementEnd()();
|
|
150
152
|
} }
|
|
151
|
-
function
|
|
152
|
-
i0.ɵɵelementStart(0, "tr")(1, "td",
|
|
153
|
+
function AnalyticsCostBudgetComponent_Conditional_1_For_57_Template(rf, ctx) { if (rf & 1) {
|
|
154
|
+
i0.ɵɵelementStart(0, "tr")(1, "td", 47);
|
|
153
155
|
i0.ɵɵtext(2);
|
|
154
156
|
i0.ɵɵelementEnd();
|
|
155
|
-
i0.ɵɵelementStart(3, "td",
|
|
157
|
+
i0.ɵɵelementStart(3, "td", 48);
|
|
156
158
|
i0.ɵɵtext(4);
|
|
157
159
|
i0.ɵɵelementEnd();
|
|
158
|
-
i0.ɵɵelementStart(5, "td",
|
|
160
|
+
i0.ɵɵelementStart(5, "td", 49);
|
|
159
161
|
i0.ɵɵtext(6);
|
|
160
162
|
i0.ɵɵpipe(7, "number");
|
|
161
163
|
i0.ɵɵelementEnd();
|
|
162
|
-
i0.ɵɵelementStart(8, "td",
|
|
164
|
+
i0.ɵɵelementStart(8, "td", 49);
|
|
163
165
|
i0.ɵɵtext(9);
|
|
164
166
|
i0.ɵɵpipe(10, "number");
|
|
165
167
|
i0.ɵɵelementEnd();
|
|
166
|
-
i0.ɵɵelementStart(11, "td",
|
|
168
|
+
i0.ɵɵelementStart(11, "td", 49);
|
|
167
169
|
i0.ɵɵtext(12);
|
|
168
170
|
i0.ɵɵpipe(13, "number");
|
|
169
171
|
i0.ɵɵelementEnd();
|
|
170
|
-
i0.ɵɵelementStart(14, "td",
|
|
172
|
+
i0.ɵɵelementStart(14, "td", 49);
|
|
171
173
|
i0.ɵɵtext(15);
|
|
174
|
+
i0.ɵɵpipe(16, "number");
|
|
172
175
|
i0.ɵɵelementEnd();
|
|
173
|
-
i0.ɵɵelementStart(
|
|
174
|
-
i0.ɵɵtext(
|
|
176
|
+
i0.ɵɵelementStart(17, "td", 49);
|
|
177
|
+
i0.ɵɵtext(18);
|
|
175
178
|
i0.ɵɵelementEnd();
|
|
176
|
-
i0.ɵɵelementStart(
|
|
177
|
-
i0.ɵɵtext(
|
|
179
|
+
i0.ɵɵelementStart(19, "td", 49);
|
|
180
|
+
i0.ɵɵtext(20);
|
|
178
181
|
i0.ɵɵelementEnd();
|
|
179
|
-
i0.ɵɵelementStart(
|
|
180
|
-
i0.ɵɵtext(
|
|
181
|
-
i0.ɵɵ
|
|
182
|
+
i0.ɵɵelementStart(21, "td", 50);
|
|
183
|
+
i0.ɵɵtext(22);
|
|
184
|
+
i0.ɵɵelementEnd();
|
|
185
|
+
i0.ɵɵelementStart(23, "td", 49);
|
|
186
|
+
i0.ɵɵtext(24);
|
|
187
|
+
i0.ɵɵelementEnd();
|
|
188
|
+
i0.ɵɵelementStart(25, "td", 49);
|
|
189
|
+
i0.ɵɵtext(26);
|
|
190
|
+
i0.ɵɵpipe(27, "number");
|
|
182
191
|
i0.ɵɵelementEnd()();
|
|
183
192
|
} if (rf & 2) {
|
|
184
193
|
const row_r6 = ctx.$implicit;
|
|
@@ -188,11 +197,13 @@ function AnalyticsCostBudgetComponent_Conditional_1_For_53_Template(rf, ctx) { i
|
|
|
188
197
|
i0.ɵɵadvance(2);
|
|
189
198
|
i0.ɵɵtextInterpolate(row_r6.Vendor);
|
|
190
199
|
i0.ɵɵadvance(2);
|
|
191
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7,
|
|
200
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(7, 11, row_r6.Runs));
|
|
192
201
|
i0.ɵɵadvance(3);
|
|
193
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(10,
|
|
202
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(10, 13, row_r6.InputTokens));
|
|
194
203
|
i0.ɵɵadvance(3);
|
|
195
|
-
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(13,
|
|
204
|
+
i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(13, 15, row_r6.OutputTokens));
|
|
205
|
+
i0.ɵɵadvance(3);
|
|
206
|
+
i0.ɵɵtextInterpolate(row_r6.CacheReadTokens + row_r6.CacheWriteTokens > 0 ? i0.ɵɵpipeBind2(16, 17, row_r6.CacheHitRate * 100, "1.0-0") + "%" : "\u2014");
|
|
196
207
|
i0.ɵɵadvance(3);
|
|
197
208
|
i0.ɵɵtextInterpolate(ctx_r2.FormatCurrency(row_r6.InputCost, 4));
|
|
198
209
|
i0.ɵɵadvance(2);
|
|
@@ -200,7 +211,9 @@ function AnalyticsCostBudgetComponent_Conditional_1_For_53_Template(rf, ctx) { i
|
|
|
200
211
|
i0.ɵɵadvance(2);
|
|
201
212
|
i0.ɵɵtextInterpolate(ctx_r2.FormatCurrency(row_r6.TotalCost));
|
|
202
213
|
i0.ɵɵadvance(2);
|
|
203
|
-
i0.ɵɵ
|
|
214
|
+
i0.ɵɵtextInterpolate(row_r6.CacheSavings > 0 ? ctx_r2.FormatCurrency(row_r6.CacheSavings, 4) : "\u2014");
|
|
215
|
+
i0.ɵɵadvance(2);
|
|
216
|
+
i0.ɵɵtextInterpolate1("", i0.ɵɵpipeBind2(27, 20, row_r6.PercentOfTotal, "1.1-1"), "%");
|
|
204
217
|
} }
|
|
205
218
|
function AnalyticsCostBudgetComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
206
219
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
@@ -245,21 +258,27 @@ function AnalyticsCostBudgetComponent_Conditional_1_Template(rf, ctx) { if (rf &
|
|
|
245
258
|
i0.ɵɵelementStart(40, "th", 22);
|
|
246
259
|
i0.ɵɵtext(41, "Output Tokens");
|
|
247
260
|
i0.ɵɵelementEnd();
|
|
248
|
-
i0.ɵɵelementStart(42, "th",
|
|
249
|
-
i0.ɵɵtext(43, "
|
|
261
|
+
i0.ɵɵelementStart(42, "th", 23);
|
|
262
|
+
i0.ɵɵtext(43, "Cache Hit");
|
|
250
263
|
i0.ɵɵelementEnd();
|
|
251
264
|
i0.ɵɵelementStart(44, "th", 22);
|
|
252
|
-
i0.ɵɵtext(45, "
|
|
265
|
+
i0.ɵɵtext(45, "Input Cost");
|
|
253
266
|
i0.ɵɵelementEnd();
|
|
254
267
|
i0.ɵɵelementStart(46, "th", 22);
|
|
255
|
-
i0.ɵɵtext(47, "
|
|
268
|
+
i0.ɵɵtext(47, "Output Cost");
|
|
256
269
|
i0.ɵɵelementEnd();
|
|
257
270
|
i0.ɵɵelementStart(48, "th", 22);
|
|
258
|
-
i0.ɵɵtext(49, "
|
|
271
|
+
i0.ɵɵtext(49, "Total Cost");
|
|
272
|
+
i0.ɵɵelementEnd();
|
|
273
|
+
i0.ɵɵelementStart(50, "th", 24);
|
|
274
|
+
i0.ɵɵtext(51, "Cache Saved");
|
|
275
|
+
i0.ɵɵelementEnd();
|
|
276
|
+
i0.ɵɵelementStart(52, "th", 22);
|
|
277
|
+
i0.ɵɵtext(53, "% of Total");
|
|
259
278
|
i0.ɵɵelementEnd()()();
|
|
260
|
-
i0.ɵɵelementStart(
|
|
261
|
-
i0.ɵɵconditionalCreate(
|
|
262
|
-
i0.ɵɵrepeaterCreate(
|
|
279
|
+
i0.ɵɵelementStart(54, "tbody");
|
|
280
|
+
i0.ɵɵconditionalCreate(55, AnalyticsCostBudgetComponent_Conditional_1_Conditional_55_Template, 3, 0, "tr");
|
|
281
|
+
i0.ɵɵrepeaterCreate(56, AnalyticsCostBudgetComponent_Conditional_1_For_57_Template, 28, 23, "tr", null, _forTrack1);
|
|
263
282
|
i0.ɵɵelementEnd()()()();
|
|
264
283
|
} if (rf & 2) {
|
|
265
284
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
@@ -269,15 +288,21 @@ function AnalyticsCostBudgetComponent_Conditional_1_Template(rf, ctx) { if (rf &
|
|
|
269
288
|
i0.ɵɵconditional(ctx_r2.DailyBars.length === 0 ? 10 : 11);
|
|
270
289
|
i0.ɵɵadvance(8);
|
|
271
290
|
i0.ɵɵconditional(ctx_r2.TreemapCells.length === 0 ? 18 : 19);
|
|
272
|
-
i0.ɵɵadvance(
|
|
273
|
-
i0.ɵɵconditional(ctx_r2.CostByModelRows.length === 0 ?
|
|
291
|
+
i0.ɵɵadvance(37);
|
|
292
|
+
i0.ɵɵconditional(ctx_r2.CostByModelRows.length === 0 ? 55 : -1);
|
|
274
293
|
i0.ɵɵadvance();
|
|
275
294
|
i0.ɵɵrepeater(ctx_r2.CostByModelRows);
|
|
276
295
|
} }
|
|
277
296
|
const FIELDS = [
|
|
278
297
|
'ID', 'RunAt', 'Cost', 'TotalCost', 'TokensPrompt', 'TokensCompletion',
|
|
279
|
-
'TokensUsed', 'ModelID', 'Model', 'VendorID', 'Vendor', 'Success'
|
|
298
|
+
'TokensUsed', 'TokensCacheRead', 'TokensCacheWrite', 'ModelID', 'Model', 'VendorID', 'Vendor', 'Success'
|
|
280
299
|
];
|
|
300
|
+
// AIModelCost UnitType name -> token divisor, matching the BasePriceUnitType driver classes.
|
|
301
|
+
const UNIT_DIVISORS = {
|
|
302
|
+
'Per Million Tokens': 1_000_000,
|
|
303
|
+
'Per Hundred Thousand Tokens': 100_000,
|
|
304
|
+
'Per Thousand Tokens': 1_000
|
|
305
|
+
};
|
|
281
306
|
const TIME_RANGE_OPTIONS = ['Today', '7d', '30d', 'MTD'];
|
|
282
307
|
const TREEMAP_COLORS = [
|
|
283
308
|
'var(--mj-brand-primary)',
|
|
@@ -323,6 +348,9 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
323
348
|
CostByModelRows = [];
|
|
324
349
|
allRuns = [];
|
|
325
350
|
previousPeriodRuns = [];
|
|
351
|
+
// Per model+vendor cache pricing (rates already normalized to currency-per-token). Empty until
|
|
352
|
+
// AIModelCost cache rates are configured — savings then stays 0 (surfaced as "Set rates").
|
|
353
|
+
cacheRates = new Map();
|
|
326
354
|
ngOnInit() {
|
|
327
355
|
this.initialized = true;
|
|
328
356
|
this.LoadData();
|
|
@@ -350,8 +378,8 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
350
378
|
return '$' + value.toFixed(decimals);
|
|
351
379
|
}
|
|
352
380
|
ExportCSV() {
|
|
353
|
-
const header = 'Model,Vendor,Runs,Input Tokens,Output Tokens,Input Cost,Output Cost,Total Cost,% of Total';
|
|
354
|
-
const rows = this.CostByModelRows.map(r => `"${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)}`);
|
|
381
|
+
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';
|
|
382
|
+
const rows = this.CostByModelRows.map(r => `"${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)}`);
|
|
355
383
|
const csv = [header, ...rows].join('\n');
|
|
356
384
|
this.downloadCSV(csv, 'cost-by-model.csv');
|
|
357
385
|
}
|
|
@@ -366,7 +394,7 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
366
394
|
const modelFilter = this.buildModelFilter();
|
|
367
395
|
const currentFilter = this.combineDateAndModelFilter(currentStart, now, modelFilter);
|
|
368
396
|
const prevFilter = this.combineDateAndModelFilter(previousStart, currentStart, modelFilter);
|
|
369
|
-
const [currentResult, prevResult] = await rv.RunViews([
|
|
397
|
+
const [currentResult, prevResult, rateResult] = await rv.RunViews([
|
|
370
398
|
{
|
|
371
399
|
EntityName: 'MJ: AI Prompt Runs',
|
|
372
400
|
ExtraFilter: currentFilter,
|
|
@@ -380,10 +408,17 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
380
408
|
Fields: FIELDS,
|
|
381
409
|
OrderBy: 'RunAt ASC',
|
|
382
410
|
ResultType: 'simple'
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
EntityName: 'MJ: AI Model Costs',
|
|
414
|
+
ExtraFilter: `Status='Active' AND ProcessingType='Realtime'`,
|
|
415
|
+
Fields: ['ModelID', 'VendorID', 'InputPricePerUnit', 'OutputPricePerUnit', 'CacheReadPricePerUnit', 'CacheWritePricePerUnit', 'UnitType'],
|
|
416
|
+
ResultType: 'simple'
|
|
383
417
|
}
|
|
384
418
|
]);
|
|
385
419
|
this.allRuns = (currentResult?.Results ?? []);
|
|
386
420
|
this.previousPeriodRuns = (prevResult?.Results ?? []);
|
|
421
|
+
this.buildCacheRateMap(rateResult?.Results ?? []);
|
|
387
422
|
this.computeKpis();
|
|
388
423
|
this.computeDailyBars();
|
|
389
424
|
this.computeTreemap();
|
|
@@ -397,6 +432,36 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
397
432
|
this.cdr.detectChanges();
|
|
398
433
|
}
|
|
399
434
|
}
|
|
435
|
+
// ── Cache pricing ──
|
|
436
|
+
/** Stable map key for a model+vendor pair (UUIDs normalized for case-insensitive matching). */
|
|
437
|
+
rateKey(modelID, vendorID) {
|
|
438
|
+
return `${NormalizeUUID(modelID ?? '')}|${NormalizeUUID(vendorID ?? '')}`;
|
|
439
|
+
}
|
|
440
|
+
/** The cache rate for a run's model+vendor, or undefined when no active cost row is configured. */
|
|
441
|
+
rateFor(run) {
|
|
442
|
+
return this.cacheRates.get(this.rateKey(run.ModelID, run.VendorID));
|
|
443
|
+
}
|
|
444
|
+
/** Build the per-model+vendor rate lookup, normalizing each per-unit price to currency-per-token. */
|
|
445
|
+
buildCacheRateMap(rows) {
|
|
446
|
+
this.cacheRates.clear();
|
|
447
|
+
for (const row of rows) {
|
|
448
|
+
const divisor = UNIT_DIVISORS[row.UnitType ?? ''] ?? 1_000_000;
|
|
449
|
+
const inputRate = (row.InputPricePerUnit ?? 0) / divisor;
|
|
450
|
+
// Cache read/write fall back to the input rate when no distinct rate is recorded — exactly
|
|
451
|
+
// as the server-side cost calculator does — which makes the corresponding savings term 0.
|
|
452
|
+
const cacheReadRate = (row.CacheReadPricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor;
|
|
453
|
+
const cacheWriteRate = (row.CacheWritePricePerUnit ?? row.InputPricePerUnit ?? 0) / divisor;
|
|
454
|
+
this.cacheRates.set(this.rateKey(row.ModelID, row.VendorID), { inputRate, cacheReadRate, cacheWriteRate });
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
/** Sum net cache savings across a set of runs using each run's model+vendor rate. */
|
|
458
|
+
sumCacheSavings(runs) {
|
|
459
|
+
return runs.reduce((total, run) => total + netCacheSavings({
|
|
460
|
+
uncachedInputTokens: 0,
|
|
461
|
+
cacheReadTokens: run.TokensCacheRead ?? 0,
|
|
462
|
+
cacheWriteTokens: run.TokensCacheWrite ?? 0
|
|
463
|
+
}, this.rateFor(run)), 0);
|
|
464
|
+
}
|
|
400
465
|
// ── Computations ──
|
|
401
466
|
computeKpis() {
|
|
402
467
|
const now = new Date();
|
|
@@ -446,6 +511,39 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
446
511
|
Icon: 'fa-solid fa-chart-line'
|
|
447
512
|
}
|
|
448
513
|
];
|
|
514
|
+
this.appendCacheKpis();
|
|
515
|
+
}
|
|
516
|
+
/** Append the cache hit-rate and cache-savings KPIs (computed from the current-period runs). */
|
|
517
|
+
appendCacheKpis() {
|
|
518
|
+
const totals = { uncachedInputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };
|
|
519
|
+
for (const r of this.allRuns) {
|
|
520
|
+
totals.uncachedInputTokens += r.TokensPrompt ?? 0;
|
|
521
|
+
totals.cacheReadTokens += r.TokensCacheRead ?? 0;
|
|
522
|
+
totals.cacheWriteTokens += r.TokensCacheWrite ?? 0;
|
|
523
|
+
}
|
|
524
|
+
const savings = this.sumCacheSavings(this.allRuns);
|
|
525
|
+
const activity = hasCacheActivity(totals);
|
|
526
|
+
this.CostKpis.push({
|
|
527
|
+
Label: 'Cache Hit Rate',
|
|
528
|
+
Value: (cacheHitRate(totals) * 100).toFixed(1) + '%',
|
|
529
|
+
Delta: null,
|
|
530
|
+
DeltaDirection: 'stable',
|
|
531
|
+
Highlighted: false,
|
|
532
|
+
Icon: 'fa-solid fa-bolt'
|
|
533
|
+
});
|
|
534
|
+
// Savings requires cache rates on AIModelCost. When cache engaged but no savings computed,
|
|
535
|
+
// it means rates aren't configured yet — say so rather than implying $0 was saved.
|
|
536
|
+
const savingsValue = savings > 0
|
|
537
|
+
? this.FormatCurrency(savings)
|
|
538
|
+
: (activity ? 'Set rates' : '$0.00');
|
|
539
|
+
this.CostKpis.push({
|
|
540
|
+
Label: 'Saved via Cache',
|
|
541
|
+
Value: savingsValue,
|
|
542
|
+
Delta: null,
|
|
543
|
+
DeltaDirection: 'stable',
|
|
544
|
+
Highlighted: savings > 0,
|
|
545
|
+
Icon: 'fa-solid fa-piggy-bank'
|
|
546
|
+
});
|
|
449
547
|
}
|
|
450
548
|
computeDailyBars() {
|
|
451
549
|
const buckets = new Map();
|
|
@@ -502,6 +600,8 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
502
600
|
for (const [, modelRuns] of groups) {
|
|
503
601
|
const inputTokens = modelRuns.reduce((s, r) => s + (r.TokensPrompt ?? 0), 0);
|
|
504
602
|
const outputTokens = modelRuns.reduce((s, r) => s + (r.TokensCompletion ?? 0), 0);
|
|
603
|
+
const cacheReadTokens = modelRuns.reduce((s, r) => s + (r.TokensCacheRead ?? 0), 0);
|
|
604
|
+
const cacheWriteTokens = modelRuns.reduce((s, r) => s + (r.TokensCacheWrite ?? 0), 0);
|
|
505
605
|
const cost = modelRuns.reduce((s, r) => s + (r.Cost ?? r.TotalCost ?? 0), 0);
|
|
506
606
|
// Approximate input/output cost split based on token ratio
|
|
507
607
|
const totalTk = inputTokens + outputTokens;
|
|
@@ -513,6 +613,10 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
513
613
|
Runs: modelRuns.length,
|
|
514
614
|
InputTokens: inputTokens,
|
|
515
615
|
OutputTokens: outputTokens,
|
|
616
|
+
CacheReadTokens: cacheReadTokens,
|
|
617
|
+
CacheWriteTokens: cacheWriteTokens,
|
|
618
|
+
CacheHitRate: cacheHitRate({ uncachedInputTokens: inputTokens, cacheReadTokens, cacheWriteTokens }),
|
|
619
|
+
CacheSavings: this.sumCacheSavings(modelRuns),
|
|
516
620
|
InputCost: inputCost,
|
|
517
621
|
OutputCost: outputCost,
|
|
518
622
|
TotalCost: cost,
|
|
@@ -573,8 +677,8 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
573
677
|
URL.revokeObjectURL(url);
|
|
574
678
|
}
|
|
575
679
|
static ɵfac = /*@__PURE__*/ (() => { let ɵAnalyticsCostBudgetComponent_BaseFactory; return function AnalyticsCostBudgetComponent_Factory(__ngFactoryType__) { return (ɵAnalyticsCostBudgetComponent_BaseFactory || (ɵAnalyticsCostBudgetComponent_BaseFactory = i0.ɵɵgetInheritedFactory(AnalyticsCostBudgetComponent)))(__ngFactoryType__ || AnalyticsCostBudgetComponent); }; })();
|
|
576
|
-
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsCostBudgetComponent, selectors: [["app-analytics-cost-budget"]], inputs: { TimeRange: "TimeRange", Filters: "Filters" }, outputs: { TimeRangeChange: "TimeRangeChange", FiltersChange: "FiltersChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], ["text", "Loading cost data..."], [1, "kpi-row"], [1, "kpi-card", 3, "kpi-card--highlighted"], [1, "two-col"], [1, "panel", "panel-chart"], [1, "panel-header"], [1, "panel-header__title"], [1, "fa-solid", "fa-chart-column", "panel-header__icon"], [1, "chart-body"], [1, "panel-empty"], [1, "bar-chart"], [1, "panel", "panel-treemap"], [1, "fa-solid", "fa-chart-pie", "panel-header__icon"], [1, "treemap-body"], [1, "treemap-grid"], [1, "panel"], [1, "fa-solid", "fa-table", "panel-header__icon"], [1, "export-btn", 3, "click"], [1, "fa-solid", "fa-download"], [1, "table-wrapper"], [1, "data-table"], [1, "col-numeric"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-label"], [1, "kpi-value"], [1, "kpi-delta", 3, "kpi-delta--up", "kpi-delta--down"], [1, "kpi-delta"], [1, "fa-solid", "fa-arrow-up"], [1, "fa-solid", "fa-arrow-down"], [1, "bar-chart-area"], [1, "avg-line", 3, "bottom"], [1, "bar-col", 3, "title"], [1, "avg-line"], [1, "avg-label"], [1, "bar"], [1, "bar-label"], [1, "treemap-cell", 3, "background", "flex-basis", "title"], [1, "treemap-cell", 3, "title"], [1, "treemap-label"], [1, "treemap-value"], [1, "treemap-pct"], ["colspan", "
|
|
577
|
-
i0.ɵɵconditionalCreate(0, AnalyticsCostBudgetComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsCostBudgetComponent_Conditional_1_Template,
|
|
680
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: AnalyticsCostBudgetComponent, selectors: [["app-analytics-cost-budget"]], inputs: { TimeRange: "TimeRange", Filters: "Filters" }, outputs: { TimeRangeChange: "TimeRangeChange", FiltersChange: "FiltersChange" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 2, vars: 1, consts: [[1, "loading-container"], ["text", "Loading cost data..."], [1, "kpi-row"], [1, "kpi-card", 3, "kpi-card--highlighted"], [1, "two-col"], [1, "panel", "panel-chart"], [1, "panel-header"], [1, "panel-header__title"], [1, "fa-solid", "fa-chart-column", "panel-header__icon"], [1, "chart-body"], [1, "panel-empty"], [1, "bar-chart"], [1, "panel", "panel-treemap"], [1, "fa-solid", "fa-chart-pie", "panel-header__icon"], [1, "treemap-body"], [1, "treemap-grid"], [1, "panel"], [1, "fa-solid", "fa-table", "panel-header__icon"], [1, "export-btn", 3, "click"], [1, "fa-solid", "fa-download"], [1, "table-wrapper"], [1, "data-table"], [1, "col-numeric"], ["title", "Share of input tokens served from the provider's prompt cache", 1, "col-numeric"], ["title", "Net dollars saved by caching vs. full input pricing (requires cache rates on AI Model Costs)", 1, "col-numeric"], [1, "kpi-card"], [1, "kpi-icon"], [1, "kpi-content"], [1, "kpi-label"], [1, "kpi-value"], [1, "kpi-delta", 3, "kpi-delta--up", "kpi-delta--down"], [1, "kpi-delta"], [1, "fa-solid", "fa-arrow-up"], [1, "fa-solid", "fa-arrow-down"], [1, "bar-chart-area"], [1, "avg-line", 3, "bottom"], [1, "bar-col", 3, "title"], [1, "avg-line"], [1, "avg-label"], [1, "bar"], [1, "bar-label"], [1, "treemap-cell", 3, "background", "flex-basis", "title"], [1, "treemap-cell", 3, "title"], [1, "treemap-label"], [1, "treemap-value"], [1, "treemap-pct"], ["colspan", "11", 1, "empty-row"], [1, "cell-model"], [1, "cell-vendor"], [1, "cell-numeric"], [1, "cell-numeric", "cell-cost"]], template: function AnalyticsCostBudgetComponent_Template(rf, ctx) { if (rf & 1) {
|
|
681
|
+
i0.ɵɵconditionalCreate(0, AnalyticsCostBudgetComponent_Conditional_0_Template, 2, 0, "div", 0)(1, AnalyticsCostBudgetComponent_Conditional_1_Template, 58, 3);
|
|
578
682
|
} if (rf & 2) {
|
|
579
683
|
i0.ɵɵconditional(ctx.IsLoading ? 0 : 1);
|
|
580
684
|
} }, dependencies: [i1.LoadingComponent, i2.DecimalPipe], styles: ["[_nghost-%COMP%] { display: block; }\n\n .loading-container[_ngcontent-%COMP%] {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 300px;\n }\n\n \n\n .kpi-row[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .kpi-icon[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 20%, var(--mj-bg-surface));\n }\n\n .kpi-label[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .kpi-delta--down[_ngcontent-%COMP%] {\n color: var(--mj-status-success);\n }\n\n \n\n .two-col[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: 3fr 2fr;\n gap: 16px;\n margin-bottom: 16px;\n }\n\n \n\n .panel[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n font-size: 13px;\n color: var(--mj-brand-primary);\n }\n\n .panel-empty[_ngcontent-%COMP%] {\n text-align: center;\n padding: 32px;\n color: var(--mj-text-disabled);\n font-size: 13px;\n }\n\n .export-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n }\n\n \n\n .chart-body[_ngcontent-%COMP%] {\n padding: 16px 18px;\n }\n\n .bar-chart[_ngcontent-%COMP%] {\n width: 100%;\n }\n\n .bar-chart-area[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n }\n\n .bar-label[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n white-space: nowrap;\n }\n\n .avg-line[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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 \n\n .treemap-body[_ngcontent-%COMP%] {\n padding: 16px 18px;\n }\n\n .treemap-grid[_ngcontent-%COMP%] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n min-height: 160px;\n }\n\n .treemap-cell[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover {\n opacity: 0.85;\n }\n\n .treemap-label[_ngcontent-%COMP%] {\n font-size: 12px;\n font-weight: 600;\n opacity: 0.95;\n }\n\n .treemap-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n margin-top: 2px;\n }\n\n .treemap-pct[_ngcontent-%COMP%] {\n font-size: 11px;\n opacity: 0.8;\n }\n\n \n\n .table-wrapper[_ngcontent-%COMP%] {\n overflow-x: auto;\n }\n\n .data-table[_ngcontent-%COMP%] {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n }\n\n .data-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%], \n .data-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] {\n padding: 10px 14px;\n text-align: left;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .data-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] { text-align: right; }\n\n .data-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%] {\n transition: background 0.15s;\n }\n\n .data-table[_ngcontent-%COMP%] tbody[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n }\n\n .cell-model[_ngcontent-%COMP%] {\n font-weight: 500;\n color: var(--mj-text-primary);\n }\n\n .cell-vendor[_ngcontent-%COMP%] {\n color: var(--mj-text-secondary);\n }\n\n .cell-numeric[_ngcontent-%COMP%] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n color: var(--mj-text-secondary);\n }\n\n .cell-cost[_ngcontent-%COMP%] {\n font-weight: 600;\n color: var(--mj-text-primary);\n }\n\n .empty-row[_ngcontent-%COMP%] {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n \n\n @media (max-width: 1200px) {\n .two-col[_ngcontent-%COMP%] {\n grid-template-columns: 1fr;\n }\n }\n\n @media (max-width: 768px) {\n .kpi-row[_ngcontent-%COMP%] {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .kpi-value[_ngcontent-%COMP%] {\n font-size: 18px;\n }\n }"] });
|
|
@@ -703,15 +807,17 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
703
807
|
<th class="col-numeric">Runs</th>
|
|
704
808
|
<th class="col-numeric">Input Tokens</th>
|
|
705
809
|
<th class="col-numeric">Output Tokens</th>
|
|
810
|
+
<th class="col-numeric" title="Share of input tokens served from the provider's prompt cache">Cache Hit</th>
|
|
706
811
|
<th class="col-numeric">Input Cost</th>
|
|
707
812
|
<th class="col-numeric">Output Cost</th>
|
|
708
813
|
<th class="col-numeric">Total Cost</th>
|
|
814
|
+
<th class="col-numeric" title="Net dollars saved by caching vs. full input pricing (requires cache rates on AI Model Costs)">Cache Saved</th>
|
|
709
815
|
<th class="col-numeric">% of Total</th>
|
|
710
816
|
</tr>
|
|
711
817
|
</thead>
|
|
712
818
|
<tbody>
|
|
713
819
|
@if (CostByModelRows.length === 0) {
|
|
714
|
-
<tr><td colspan="
|
|
820
|
+
<tr><td colspan="11" class="empty-row">No data available</td></tr>
|
|
715
821
|
}
|
|
716
822
|
@for (row of CostByModelRows; track row.Model) {
|
|
717
823
|
<tr>
|
|
@@ -720,9 +826,11 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
720
826
|
<td class="cell-numeric">{{ row.Runs | number }}</td>
|
|
721
827
|
<td class="cell-numeric">{{ row.InputTokens | number }}</td>
|
|
722
828
|
<td class="cell-numeric">{{ row.OutputTokens | number }}</td>
|
|
829
|
+
<td class="cell-numeric">{{ (row.CacheReadTokens + row.CacheWriteTokens) > 0 ? ((row.CacheHitRate * 100 | number:'1.0-0') + '%') : '—' }}</td>
|
|
723
830
|
<td class="cell-numeric">{{ FormatCurrency(row.InputCost, 4) }}</td>
|
|
724
831
|
<td class="cell-numeric">{{ FormatCurrency(row.OutputCost, 4) }}</td>
|
|
725
832
|
<td class="cell-numeric cell-cost">{{ FormatCurrency(row.TotalCost) }}</td>
|
|
833
|
+
<td class="cell-numeric">{{ row.CacheSavings > 0 ? FormatCurrency(row.CacheSavings, 4) : '—' }}</td>
|
|
726
834
|
<td class="cell-numeric">{{ row.PercentOfTotal | number:'1.1-1' }}%</td>
|
|
727
835
|
</tr>
|
|
728
836
|
}
|
|
@@ -741,6 +849,6 @@ export class AnalyticsCostBudgetComponent extends BaseAngularComponent {
|
|
|
741
849
|
}], FiltersChange: [{
|
|
742
850
|
type: Output
|
|
743
851
|
}] }); })();
|
|
744
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsCostBudgetComponent, { className: "AnalyticsCostBudgetComponent", filePath: "src/AI/components/analytics/cost-budget/cost-budget.component.ts", lineNumber:
|
|
852
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(AnalyticsCostBudgetComponent, { className: "AnalyticsCostBudgetComponent", filePath: "src/AI/components/analytics/cost-budget/cost-budget.component.ts", lineNumber: 618 }); })();
|
|
745
853
|
export function LoadAnalyticsCostBudget() { }
|
|
746
854
|
//# sourceMappingURL=cost-budget.component.js.map
|