@memberjunction/ng-dashboards 6.2.0-edge.6 → 6.2.0-edge.7
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 +23 -16
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js +2 -2
- package/dist/AI/components/analytics/agent-runs/agent-run-analysis.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.js +3 -1
- package/dist/AI/components/analytics/realtime/realtime-management.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-overview.component.d.ts +1 -1
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js +3 -3
- package/dist/AI/components/analytics/realtime/realtime-overview.component.js.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts +6 -4
- package/dist/AI/components/analytics/realtime/realtime-session-data.d.ts.map +1 -1
- package/dist/AI/components/analytics/realtime/realtime-session-data.js +8 -2
- package/dist/AI/components/analytics/realtime/realtime-session-data.js.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +6 -6
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js +1 -1
- package/dist/AI/components/autotagging/components/classify-item-grid.component.js.map +1 -1
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js +1 -0
- package/dist/AI/components/autotagging/components/classify-org-context-editor.component.js.map +1 -1
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js +1 -0
- package/dist/AI/components/autotagging/dialogs/source-type-form.dialog.component.js.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js +1 -0
- package/dist/AI/components/autotagging/tabs/sources-tab.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js +1 -0
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +2 -2
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +3 -2
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +12 -6
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -1
- package/dist/AI/services/ai-instrumentation.service.js +4 -2
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -1
- package/dist/Actions/action-result-code.d.ts +80 -0
- package/dist/Actions/action-result-code.d.ts.map +1 -0
- package/dist/Actions/action-result-code.js +163 -0
- package/dist/Actions/action-result-code.js.map +1 -0
- package/dist/Actions/components/actions-overview.component.d.ts +8 -0
- package/dist/Actions/components/actions-overview.component.d.ts.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +12 -9
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.d.ts +29 -9
- package/dist/Actions/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +65 -42
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.d.ts.map +1 -1
- package/dist/Actions/components/explorer/action-card.component.js +5 -4
- package/dist/Actions/components/explorer/action-card.component.js.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +92 -130
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +189 -274
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -1
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts +29 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js +666 -0
- package/dist/ChiefOfStaff/chief-of-staff-approvals.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts +56 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.js +515 -0
- package/dist/ChiefOfStaff/chief-of-staff-governance.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts +14 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js +39 -0
- package/dist/ChiefOfStaff/chief-of-staff-live-refresh.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts +17 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.js +485 -0
- package/dist/ChiefOfStaff/chief-of-staff-overview.component.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts +139 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.js +602 -0
- package/dist/ChiefOfStaff/chief-of-staff-page-base.js.map +1 -0
- package/dist/ChiefOfStaff/index.d.ts +4 -1
- package/dist/ChiefOfStaff/index.d.ts.map +1 -1
- package/dist/ChiefOfStaff/index.js +4 -1
- package/dist/ChiefOfStaff/index.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +3 -3
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +3 -3
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.d.ts.map +1 -1
- package/dist/ComponentStudio/component-studio-dashboard.component.js +1 -0
- package/dist/ComponentStudio/component-studio-dashboard.component.js.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.d.ts.map +1 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js +2 -1
- package/dist/ComponentStudio/components/artifact-selection-dialog.component.js.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.d.ts.map +1 -1
- package/dist/ComponentStudio/services/component-version.service.js +3 -0
- package/dist/ComponentStudio/services/component-version.service.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +21 -2
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +32 -5
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DevTools/graphql-console.component.js +2 -2
- package/dist/DevTools/lazy-module-status.component.js +2 -2
- package/dist/FormBuilder/form-builder-resource.component.d.ts.map +1 -1
- package/dist/FormBuilder/form-builder-resource.component.js +5 -0
- package/dist/FormBuilder/form-builder-resource.component.js.map +1 -1
- package/dist/Integration/components/connections/connections.component.js +2 -2
- package/dist/Integration/services/integration-data.service.d.ts +1 -1
- package/dist/Integration/services/integration-data.service.d.ts.map +1 -1
- package/dist/Integration/services/integration-data.service.js +4 -3
- package/dist/Integration/services/integration-data.service.js.map +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js +1 -1
- package/dist/Lists/components/lists-browse-resource.component.js.map +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js +1 -1
- package/dist/Lists/components/lists-my-lists-resource.component.js.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.js +1 -0
- package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +1 -0
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +2 -2
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +3 -0
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js +1 -0
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +1 -0
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.d.ts +26 -0
- package/dist/QueryBrowser/query-browser-resource.component.d.ts.map +1 -1
- package/dist/QueryBrowser/query-browser-resource.component.js +375 -252
- package/dist/QueryBrowser/query-browser-resource.component.js.map +1 -1
- package/dist/UserRoutines/user-routines-resource.component.d.ts +8 -1
- package/dist/UserRoutines/user-routines-resource.component.d.ts.map +1 -1
- package/dist/UserRoutines/user-routines-resource.component.js +22 -4
- package/dist/UserRoutines/user-routines-resource.component.js.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.d.ts.map +1 -1
- package/dist/VersionHistory/components/diff-resource.component.js +1 -0
- package/dist/VersionHistory/components/diff-resource.component.js.map +1 -1
- package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts +162 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.js +1105 -0
- package/dist/VideoStudio/components/vs-archetype-editor.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-audio-options.component.d.ts +27 -0
- package/dist/VideoStudio/components/vs-audio-options.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-audio-options.component.js +119 -0
- package/dist/VideoStudio/components/vs-audio-options.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts +105 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.js +560 -0
- package/dist/VideoStudio/components/vs-copilot-panel.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-production-brief.component.d.ts +163 -0
- package/dist/VideoStudio/components/vs-production-brief.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-production-brief.component.js +1054 -0
- package/dist/VideoStudio/components/vs-production-brief.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts +43 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.js +412 -0
- package/dist/VideoStudio/components/vs-setup-health-card.component.js.map +1 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts +73 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.d.ts.map +1 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.js +271 -0
- package/dist/VideoStudio/components/vs-studio-slide-in.component.js.map +1 -0
- package/dist/VideoStudio/index.d.ts +12 -0
- package/dist/VideoStudio/index.d.ts.map +1 -0
- package/dist/VideoStudio/index.js +12 -0
- package/dist/VideoStudio/index.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts +118 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js +964 -0
- package/dist/VideoStudio/resources/video-studio-archetypes-resource.component.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts +70 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js +600 -0
- package/dist/VideoStudio/resources/video-studio-brand-kits-resource.component.js.map +1 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts +182 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.d.ts.map +1 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.js +1481 -0
- package/dist/VideoStudio/resources/video-studio-productions-resource.component.js.map +1 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts +102 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.d.ts.map +1 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js +240 -0
- package/dist/VideoStudio/services/vs-studio-slide-in-state.service.js.map +1 -0
- package/dist/VideoStudio/video-studio-agent-context.d.ts +495 -0
- package/dist/VideoStudio/video-studio-agent-context.d.ts.map +1 -0
- package/dist/VideoStudio/video-studio-agent-context.js +992 -0
- package/dist/VideoStudio/video-studio-agent-context.js.map +1 -0
- package/dist/ai-dashboards.module.d.ts +25 -22
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +23 -7
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/module.d.ts +13 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +7 -0
- package/dist/module.js.map +1 -1
- package/dist/public-api.d.ts +7 -1
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +9 -2
- package/dist/public-api.js.map +1 -1
- package/dist/shared/action-scheduled-job.d.ts.map +1 -1
- package/dist/shared/action-scheduled-job.js +2 -0
- package/dist/shared/action-scheduled-job.js.map +1 -1
- package/dist/video-studio-dashboards.module.d.ts +40 -0
- package/dist/video-studio-dashboards.module.d.ts.map +1 -0
- package/dist/video-studio-dashboards.module.js +159 -0
- package/dist/video-studio-dashboards.module.js.map +1 -0
- package/package.json +77 -71
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +0 -195
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +0 -1
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +0 -2910
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js.map +0 -1
package/README.md
CHANGED
|
@@ -140,33 +140,40 @@ Architecture: the former 5,147-line monolith was decomposed into 6 tab component
|
|
|
140
140
|
|
|
141
141
|
The Predictive Studio app (`src/PredictiveStudio/`) is a multi-section, lazy-loaded surface for training, comparing, deploying, and monitoring ML models (see the [Predictive Studio Guide](../../../../guides/PREDICTIVE_STUDIO_GUIDE.md)). Its sections include Home, Algorithm Catalog, Pipeline Builder, Experiments, Model Registry, Compare Runs, and **Models in Production** (`PSProductionResourceComponent` — deployed models, what each writes, schedule, last run, and a generic prediction-distribution mini-viz, all driven by `MJ: ML Model Scoring Bindings` + `MJ: Process Runs`). The panels read live engine data via `PredictiveStudioEngine`; Promote/Validate/Archive and experiment Pause/Resume/Cancel are wired to Remote Operations behind a confirm modal, and Home's "Ask the agent" CTA opens a docked, seeded Model-Dev-Agent chat. See [`src/PredictiveStudio/`](src/PredictiveStudio/) and the guide's [Business-User Experience](../../../../guides/PREDICTIVE_STUDIO_GUIDE.md#16-the-business-user-experience) section.
|
|
142
142
|
|
|
143
|
-
### Chief of Staff
|
|
143
|
+
### Chief of Staff
|
|
144
144
|
|
|
145
|
-
The Chief of Staff
|
|
145
|
+
The **Chief of Staff** application (`metadata/applications/.chief-of-staff-application.json`) is the control surface for a user's personal Chief of Staff agent. Each page is its own nav item and its own `BaseResourceComponent` in `src/ChiefOfStaff/`, all extending `BaseChiefOfStaffPage` ([`chief-of-staff-page-base.ts`](src/ChiefOfStaff/chief-of-staff-page-base.ts)), which holds the shared data load, request and routine actions, briefing reader, live reload and agent context. The pages use core entities only.
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
| Nav item | Driver class | What it shows |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| **Overview** (default) | `ChiefOfStaffOverview` (also registered as `ChiefOfStaffDashboard` and `ChiefOfStaffResource`, so tabs saved before the split still open) | KPI cards (active wakes, pending approvals, governance posture), the top pending approvals with inline Approve / Reject, and the next wake routines. Cards and "Manage" buttons open the other pages through their nav items (`OpenPage`). |
|
|
150
|
+
| **Approvals & Wakes** | `ChiefOfStaffApprovals` | The pending `MJ: AI Agent Requests` queue with Approve / Reject / Details (`<mj-agent-request-dialog>`), "Recent Resolved Decisions", and the user's AgentWake `MJ: User Routines` with Wake Now / Pause-Resume / Read Briefing / open-record actions. A `<mj-page-search>` filters both lists; `search` round-trips through the query params. |
|
|
151
|
+
| **Governance** | `ChiefOfStaffGovernance` | The user's `MJ: AI Agent User Policies` row for the Chief of Staff agent as an editable draft: coordination mode, status, data-access mode, the four channel modes, inter-agent coordination, the approval guardrails, the auto-approve threshold, and display-name and standing-instructions overrides, with Save / Reset. |
|
|
152
152
|
|
|
153
|
-
Data (one `RunViews` batch in `
|
|
154
|
-
- `MJ: AI Agent User Policies` filtered to the Chief of Staff agent (`
|
|
153
|
+
Data (one `RunViews` batch in `LoadChiefOfStaffData`; every filter comes from `BuildChiefOfStaffScopeFilters` and is bound to the signed-in user — with no current user a page loads nothing and shows an error banner):
|
|
154
|
+
- `MJ: AI Agent User Policies` filtered to the Chief of Staff agent (resolved by name, `CHIEF_OF_STAFF_AGENT_NAME`) and the current user
|
|
155
155
|
- `MJ: User Routines` for the current user where `RoutineType = 'AgentWake'` or the target is the Chief of Staff agent
|
|
156
156
|
- `MJ: AI Agent Requests` for the Chief of Staff agent **and** `RequestForUserID = current user`, excluding `Information` requests (max 100); each queue row shows its `RequestType` as a badge
|
|
157
|
-
- `MJ_BizApps_Tasks: Tasks` — only when that OpenApp entity is present in metadata (`EntityByName`), and only for the signed-in user: `ResolvePersonTaskScope` first finds the `MJ_BizApps_Common: People` row whose `LinkedUserID` is the current user, then that person's `MJ_BizApps_Tasks: Task Assignments`, and filters tasks to those the person created (`CreatedByPersonID`) or is assigned to. With no linked person the tasks query is skipped and the Priorities tab shows a "No People Record Linked" empty state. Rows load as `simple` (max 250) and are grouped into priority-objective cards by `CalculateChiefOfStaffMetrics`. The task primary key is derived from entity metadata via `CompositeKey.FromURLSegment`, never assumed to be `ID`
|
|
158
157
|
|
|
159
|
-
|
|
158
|
+
Wake routines are listed in display order (`SortRoutinesForDisplay`: next wake first, unscheduled, then spent one-shots most recent first); a spent one-shot (`IsSpentOneShotRoutine`, Disabled after running with no next time) shows as `Fired` (`RoutineDisplayStatus`) and is hidden behind a "Show fired" toggle. "Wake Now" runs the `Run User Routine Now` action, which executes the routine without touching `NextRunAt`, so a one-shot keeps its scheduled time. An approval request that carries an outbound email (the email action stores To/CC/Subject/Body as JSON in `Comments`) gets a "View draft" toggle on its card: `ParseEmailApprovalPayload` reads the draft, the card shows headers and body inline, and "Copy" puts `FormatEmailDraftForClipboard` output (headers, blank line, body) on the clipboard for a mail client.
|
|
160
159
|
|
|
161
|
-
Mutations (all `BaseEntity.Save()` with `LatestResult.CompleteMessage` surfaced in a banner
|
|
160
|
+
Mutations (all `BaseEntity.Save()` with `LatestResult.CompleteMessage` surfaced in a banner): `QuickRespondToRequest` (sets `Status` to Approved/Rejected, `RespondedAt`, `ResponseSource = 'Dashboard'`, `ResponseByUserID`), `TriggerWakeNow` (runs the `Run User Routine Now` action), `ToggleRoutineStatus` (Active ↔ Paused) and `SaveGovernancePolicy` (creates the policy row if none exists).
|
|
162
161
|
|
|
163
|
-
|
|
162
|
+
Live reload: a save or remote invalidation of any entity in `CHIEF_OF_STAFF_LIVE_ENTITIES` (`IsChiefOfStaffEntityChange`) reloads an attached page once per burst; a detached page reloads when it is shown again.
|
|
164
163
|
|
|
165
|
-
|
|
164
|
+
**Adding pages from another app.** An Open App adds its own pages to the Chief of Staff application with `MJ: Application Settings` rows, not by extending these components. Each row is scoped to the Chief of Staff application (`ApplicationID`), named `NavItem.<unique key>` (for example `NavItem.bizapps-tasks.priorities`), and holds one nav item as JSON in `Value`:
|
|
166
165
|
|
|
167
|
-
|
|
166
|
+
```json
|
|
167
|
+
{ "Label": "Priorities", "Icon": "fa-solid fa-bullseye", "ResourceType": "Custom", "DriverClass": "BizAppsTasksPriorities", "Sequence": 15 }
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`BaseApplication.GetNavItems()` (`@memberjunction/ng-base-application`, `MergeNavItemExtensions`) adds these to every application's nav bar, so the mechanism is generic. The core pages sit at 10, 20 and 30, so `Sequence: 15` lands between Overview and Approvals & Wakes; an item without a `Sequence` goes last. An extension never becomes the default item, and one whose `Label` is already present is skipped. The `DriverClass` is a `BaseResourceComponent` registered by the app's client package; the page loads its own data, publishes its own agent context and reloads itself. The app's teardown deletes its rows. An extension cannot add cards to the Overview page.
|
|
171
|
+
|
|
172
|
+
The application is opt-in (`DefaultForNewUser: false`) and is not registered in the AI application. Its `DriverClass` values must be unique across all applications (integration check `app-wiring.AW4`); the Agent Requests and Routines screens already belong to the AI and Routines applications, and the Approvals & Wakes page links to those records directly.
|
|
173
|
+
|
|
174
|
+
Not yet implemented from the Phase 2 plan: `QuietHoursStart` / `QuietHoursEnd` and `MaxAutonomousActionsPerRun` do not exist on `MJ: AI Agent User Policies` and are not shown.
|
|
168
175
|
|
|
169
|
-
Agent context and client tools (
|
|
176
|
+
Agent context and client tools (open page / search / refresh only — no mutations) are built by the pure helpers in [`src/ChiefOfStaff/chief-of-staff-agent-context.ts`](src/ChiefOfStaff/chief-of-staff-agent-context.ts); see the package `CLAUDE.md` registry row for the boundary.
|
|
170
177
|
|
|
171
178
|
### Additional Dashboards
|
|
172
179
|
- **API Keys**: API key management with scopes, applications, and usage tracking
|
|
@@ -434,9 +434,9 @@ export class AnalyticsAgentRunsComponent extends BaseAngularComponent {
|
|
|
434
434
|
console.error(`Agent Run Analysis: run counts failed to load. ${totalResult.ErrorMessage ?? successResult.ErrorMessage}`);
|
|
435
435
|
}
|
|
436
436
|
this.agentRuns = agentResult.Success ? agentResult.Results ?? [] : [];
|
|
437
|
-
this.totalRunCount = totalResult.Success ? totalResult.TotalRowCount : this.agentRuns.length;
|
|
437
|
+
this.totalRunCount = totalResult.Success ? totalResult.TotalRowCount ?? 0 : this.agentRuns.length;
|
|
438
438
|
this.successRunCount = successResult.Success
|
|
439
|
-
? successResult.TotalRowCount
|
|
439
|
+
? successResult.TotalRowCount ?? 0
|
|
440
440
|
: this.agentRuns.filter(r => r.Success === true).length;
|
|
441
441
|
const agentIds = new Set(this.Filters.Agents.map(a => a.toLowerCase()));
|
|
442
442
|
const usage = usageRows;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-run-analysis.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/agent-runs/agent-run-analysis.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Run Analysis -- Cost Attribution Focus.\n *\n * Displays agent run stats, cost attribution horizontal stacked bars per agent,\n * and a sortable recent agent runs table. Agent runs are read via RunView from\n * \"MJ: AI Agent Runs\"; per-agent prompt volume and cost attribution come from the\n * AI usage aggregates (AIUsageHourly / AIUsageDaily), which already resolve each\n * prompt run to its agent and exclude parallel parents — no raw prompt-run pull.\n */\n\nimport {\n Component, ChangeDetectionStrategy, 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';\nimport { AIInstrumentationService } from '../../../services/ai-instrumentation.service';\nimport { ComputeTotalCost, ComputeCoveragePercent, ResolveCostCurrency } from '../../../services/ai-usage-analytics.compute';\nimport { AIUsageDailyRow, AIUsageHourlyRow } from '../../../services/ai-usage-analytics.types';\n\n// ── Interfaces ──\n\ninterface AgentRunFilters {\n Agents: string[];\n Statuses: string[];\n}\n\ninterface AgentRunRecord {\n ID: string;\n StartedAt: string;\n CompletedAt: string | null;\n Status: string;\n Success: boolean | null;\n TotalCost: number | null;\n TotalTokensUsed: number | null;\n AgentID: string;\n Agent: string | null;\n ErrorMessage: string | null;\n TotalPromptIterations: number | null;\n}\n\n/** An hourly or daily usage aggregate row — the fields this view reads are common to both. */\ntype UsageRow = AIUsageHourlyRow | AIUsageDailyRow;\n\ninterface AgentRunStats {\n TotalRuns: number;\n TotalCost: number | null;\n CoverageSubtitle?: string;\n PromptRuns: number;\n AvgCostPerRun: number | null;\n SuccessRate: number;\n AvgDurationSeconds: number;\n /** How many recent runs the duration average is taken over (the list is capped). */\n DurationSampleSize: number;\n}\n\ninterface CostAttributionRow {\n AgentName: string;\n AgentID: string;\n TotalCost: number | null;\n Segments: CostSegment[];\n}\n\ninterface CostSegment {\n Label: string;\n Value: number;\n Percent: number;\n Color: string;\n}\n\ninterface RecentRunRow {\n ID: string;\n Agent: string;\n Status: string;\n StatusClass: string;\n StepCount: number;\n Duration: string;\n Cost: string;\n Time: string;\n}\n\ntype SortField = 'Agent' | 'Status' | 'StepCount' | 'Duration' | 'Cost' | 'Time';\ntype SortDirection = 'asc' | 'desc';\n\nconst AGENT_RUN_FIELDS = [\n 'ID', 'StartedAt', 'CompletedAt', 'Status', 'Success',\n 'TotalCost', 'TotalTokensUsed', 'AgentID', 'Agent', 'ErrorMessage', 'TotalPromptIterations'\n];\n\n// Vendors are categories, so they take the categorical --mj-viz palette; brand/status tokens were\n// all blues and greys, and two vendors read as one. The palette is a hue ramp whose neighbours are\n// close (1-3 run blue to violet), so the steps are taken spread out.\nconst COST_COLORS = [\n 'var(--mj-viz-1)',\n 'var(--mj-viz-6)',\n 'var(--mj-viz-3)',\n 'var(--mj-viz-9)',\n 'var(--mj-viz-5)',\n 'var(--mj-viz-8)',\n 'var(--mj-viz-4)',\n 'var(--mj-viz-10)'\n];\n\n@Component({\n standalone: false,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'app-analytics-agent-runs',\n template: `\n\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading agent runs...\"></mj-loading>\n </div>\n } @else {\n <!-- Stats Bar -->\n <div class=\"stats-grid\">\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Runs</div>\n <div class=\"stat-value\">{{ Stats.TotalRuns | number }}</div>\n </div>\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Cost</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.TotalCost) }}</div>\n @if (Stats.CoverageSubtitle) {\n <div class=\"stat-subtitle\">{{ Stats.CoverageSubtitle }}</div>\n }\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Prompt Runs</div>\n <div class=\"stat-value\">{{ Stats.PromptRuns | number }}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Cost/Run</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.AvgCostPerRun, 4) }}</div>\n </div>\n <div class=\"stat-card accent-success\">\n <div class=\"stat-label\">Success Rate</div>\n <div class=\"stat-value\">{{ Stats.SuccessRate | number:'1.1-1' }}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Duration</div>\n <div class=\"stat-value\">{{ Stats.AvgDurationSeconds | number:'1.1-1' }}s</div>\n @if (Stats.DurationSampleSize > 0 && Stats.DurationSampleSize < Stats.TotalRuns) {\n <div class=\"stat-subtitle\">last {{ Stats.DurationSampleSize }} completed runs</div>\n }\n </div>\n </div>\n\n <!-- Cost Attribution Panel -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-bar panel-header__icon\"></i>\n Cost Attribution by Agent\n </div>\n </div>\n <div class=\"panel-body\">\n @if (CostAttributionRows.length === 0) {\n <mj-empty-state Size=\"compact\" Variant=\"empty\" Icon=\"fa-solid fa-chart-bar\"\n Title=\"No agent cost data for selected period\" />\n }\n @for (row of CostAttributionRows; track row.AgentID) {\n <div class=\"attribution-row\">\n <div class=\"attribution-name\" [title]=\"row.AgentName\">{{ row.AgentName }}</div>\n <div class=\"attribution-bar-container\">\n @for (seg of row.Segments; track seg.Label) {\n <div\n class=\"attribution-segment\"\n [style.width.%]=\"seg.Percent\"\n [style.background]=\"seg.Color\"\n [title]=\"seg.Label + ': ' + FormatCurrency(seg.Value, 4)\"\n ></div>\n }\n </div>\n <div class=\"attribution-total\">{{ FormatCurrency(row.TotalCost) }}</div>\n </div>\n }\n @if (CostAttributionRows.length > 0) {\n <div class=\"legend-row\">\n @for (item of LegendItems; track item.Label) {\n <div class=\"legend-item\">\n <span class=\"legend-swatch\" [style.background]=\"item.Color\"></span>\n {{ item.Label }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Recent Agent Runs Table -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-list panel-header__icon\"></i>\n Recent Agent Runs\n </div>\n <span class=\"panel-header__subtitle\">showing latest 100</span>\n </div>\n <div class=\"table-wrapper\">\n <table class=\"data-table\">\n <thead>\n <tr>\n @for (col of TableColumns; track col.field) {\n <th\n class=\"sortable-header\"\n [class.sorted]=\"SortField === col.field\"\n (click)=\"OnSort(col.field)\">\n {{ col.label }}\n @if (SortField === col.field) {\n <i [class]=\"SortDir === 'asc' ? 'fa-solid fa-caret-up' : 'fa-solid fa-caret-down'\"></i>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (RecentRuns.length === 0) {\n <tr><td [attr.colspan]=\"TableColumns.length\" class=\"empty-row\"><mj-empty-state Variant=\"no-results\" Size=\"compact\" Title=\"No runs found\" Message=\"No agent runs match this period and these filters.\"></mj-empty-state></td></tr>\n }\n @for (run of RecentRuns; track run.ID) {\n <tr>\n <td class=\"cell-agent\">{{ run.Agent }}</td>\n <td><span class=\"status-pill\" [class]=\"run.StatusClass\">{{ run.Status }}</span></td>\n <td class=\"cell-numeric\">{{ run.StepCount }}</td>\n <td class=\"cell-numeric\">{{ run.Duration }}</td>\n <td class=\"cell-numeric\">{{ run.Cost }}</td>\n <td class=\"cell-time\">{{ run.Time }}</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 /* ── Stats Grid ── */\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 12px;\n margin: 16px 0;\n }\n\n .stat-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 14px 16px;\n text-align: center;\n border-top: 3px solid var(--mj-border-subtle);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .stat-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 .stat-card.accent-brand { border-top-color: var(--mj-brand-primary); }\n .stat-card.accent-success { border-top-color: var(--mj-status-success); }\n .stat-card.accent-warning { border-top-color: var(--mj-status-warning); }\n\n .stat-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 margin-bottom: 4px;\n }\n\n .stat-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n letter-spacing: -0.02em;\n }\n\n .stat-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\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 margin-bottom: 16px;\n overflow: hidden;\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-header__subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .panel-body {\n padding: 16px 18px;\n }\n\n /* ── Cost Attribution ── */\n .attribution-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .attribution-row:last-of-type {\n border-bottom: none;\n }\n\n .attribution-name {\n width: 140px;\n min-width: 140px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .attribution-bar-container {\n flex: 1;\n display: flex;\n height: 24px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .attribution-segment {\n height: 100%;\n min-width: 2px;\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .attribution-total {\n width: 80px;\n min-width: 80px;\n text-align: right;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n }\n\n .legend-row {\n display: flex;\n gap: 16px;\n padding: 12px 0 4px;\n flex-wrap: wrap;\n }\n\n .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n }\n\n .legend-swatch {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n flex-shrink: 0;\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 }\n\n .sortable-header {\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: color 0.15s;\n }\n\n .sortable-header:hover {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header.sorted {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header i {\n margin-left: 4px;\n font-size: 10px;\n }\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-agent {\n font-weight: 500;\n color: var(--mj-text-primary);\n max-width: 200px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\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-time {\n white-space: nowrap;\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* ── Status Pills ── */\n .status-pill {\n display: inline-block;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.3px;\n }\n\n .status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n }\n\n .status-cancelled {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n }\n\n .status-paused, .status-awaitingfeedback {\n background: color-mix(in srgb, var(--mj-text-disabled) 12%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n }\n\n /* ── Responsive ── */\n @media (max-width: 1200px) {\n .stats-grid {\n grid-template-columns: repeat(3, 1fr);\n }\n }\n\n @media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .attribution-name {\n width: 100px;\n min-width: 100px;\n }\n\n .attribution-total {\n width: 60px;\n min-width: 60px;\n }\n\n .stat-value {\n font-size: 18px;\n }\n }\n `]\n})\nexport class AnalyticsAgentRunsComponent 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: AgentRunFilters = { Agents: [], Statuses: [] };\n @Input()\n set Filters(value: AgentRunFilters) {\n const next = value ?? { Agents: [], Statuses: [] };\n const changed = !this.shallowFiltersEqual(this._filters, next);\n this._filters = next;\n if (changed && this.initialized) this.loadData();\n }\n get Filters(): AgentRunFilters { return this._filters; }\n\n private shallowFiltersEqual(a: AgentRunFilters, b: AgentRunFilters): boolean {\n const sameArr = (x: string[], y: string[]) => x.length === y.length && x.every((v, i) => v === y[i]);\n return sameArr(a.Agents, b.Agents) && sameArr(a.Statuses, b.Statuses);\n }\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<AgentRunFilters>();\n\n private initialized = false;\n\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n\n public IsLoading = false;\n\n public Stats: AgentRunStats = {\n TotalRuns: 0,\n TotalCost: 0,\n PromptRuns: 0,\n AvgCostPerRun: 0,\n SuccessRate: 0,\n AvgDurationSeconds: 0,\n DurationSampleSize: 0\n };\n\n public CostAttributionRows: CostAttributionRow[] = [];\n public LegendItems: { Label: string; Color: string }[] = [];\n public RecentRuns: RecentRunRow[] = [];\n public SortField: SortField = 'Time';\n public SortDir: SortDirection = 'desc';\n\n public TableColumns: { field: SortField; label: string }[] = [\n { field: 'Agent', label: 'Agent' },\n { field: 'Status', label: 'Status' },\n { field: 'StepCount', label: 'Prompts' },\n { field: 'Duration', label: 'Duration' },\n { field: 'Cost', label: 'Cost' },\n { field: 'Time', label: 'Time' }\n ];\n\n /** Bridge the local filter shape to the global shape the filter bar expects */\n public get GlobalFilters(): GlobalFilterState {\n return {\n Models: [],\n Agents: this.Filters.Agents,\n Prompts: [],\n Statuses: this.Filters.Statuses\n };\n }\n\n /** @deprecated Use {@link GlobalFilters}. */\n public get globalFilters(): GlobalFilterState {\n return this.GlobalFilters;\n }\n\n private instrumentation = inject(AIInstrumentationService);\n\n private agentRuns: AgentRunRecord[] = [];\n\n private totalRunCount = 0;\n\n private successRunCount = 0;\n /** Usage aggregate rows for agent-driven prompt runs in the period (AgentID set, agent filter applied). */\n private agentUsageRows: UsageRow[] = [];\n private vendorNames = new Map<string, string>();\n private agentNames = new Map<string, string>();\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 Event 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 = { Agents: filters.Agents, Statuses: filters.Statuses };\n this.FiltersChange.emit(this.Filters);\n this.loadData();\n }\n\n public OnSort(field: SortField): void {\n if (this.SortField === field) {\n this.SortDir = this.SortDir === 'asc' ? 'desc' : 'asc';\n } else {\n this.SortField = field;\n this.SortDir = field === 'Time' ? 'desc' : 'asc';\n }\n this.sortRecentRuns();\n this.cdr.detectChanges();\n }\n\n public FormatCurrency(value: number | null | undefined, decimals = 2): string {\n if (value === null || value === undefined) return '—';\n if (value === 0) return '$0.00';\n if (value < 0.01 && decimals < 4) decimals = 4;\n return '$' + value.toFixed(decimals);\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 dateFilter = this.buildDateFilter('StartedAt');\n const agentFilter = this.buildAgentFilter();\n const statusFilter = this.buildStatusFilter();\n const extraFilter = [dateFilter, agentFilter, statusFilter, 'ParentRunID IS NULL'].filter(Boolean).join(' AND ');\n\n this.instrumentation.Provider = this.ProviderToUse;\n const rangeMs = this.timeRangeToMs(this.TimeRange);\n const now = new Date();\n const start = new Date(now.getTime() - rangeMs);\n\n // The run list is capped at the 100 most recent; the totals are exact counts, so the KPI\n // cards never report the cap as if it were the period's run count.\n const [agentResults, usageRows, lookups] = await Promise.all([\n rv.RunViews([\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: extraFilter,\n Fields: AGENT_RUN_FIELDS,\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n ResultType: 'simple'\n },\n { EntityName: 'MJ: AI Agent Runs', ExtraFilter: extraFilter, ResultType: 'count_only' },\n { EntityName: 'MJ: AI Agent Runs', ExtraFilter: `${extraFilter} AND Success = 1`, ResultType: 'count_only' }\n ]),\n // Hourly buckets for sub-day ranges so \"last hour\" is not a whole day's usage.\n rangeMs <= 86400000\n ? this.instrumentation.GetUsageHourly(start, now)\n : this.instrumentation.GetUsageDaily(start, now),\n this.instrumentation.GetModelAndVendorLookups()\n ]);\n\n const [agentResult, totalResult, successResult] = agentResults;\n if (!agentResult.Success) {\n console.error(`Agent Run Analysis: agent runs failed to load. ${agentResult.ErrorMessage}`);\n }\n if (!totalResult.Success || !successResult.Success) {\n console.error(`Agent Run Analysis: run counts failed to load. ${totalResult.ErrorMessage ?? successResult.ErrorMessage}`);\n }\n this.agentRuns = agentResult.Success ? (agentResult.Results as AgentRunRecord[]) ?? [] : [];\n this.totalRunCount = totalResult.Success ? totalResult.TotalRowCount : this.agentRuns.length;\n this.successRunCount = successResult.Success\n ? successResult.TotalRowCount\n : this.agentRuns.filter(r => r.Success === true).length;\n const agentIds = new Set(this.Filters.Agents.map(a => a.toLowerCase()));\n const usage: UsageRow[] = usageRows;\n this.agentUsageRows = usage.filter(r =>\n r.AgentID !== null && (agentIds.size === 0 || agentIds.has(r.AgentID.toLowerCase())));\n this.vendorNames = lookups.vendors;\n this.agentNames = lookups.agents;\n\n this.computeStats();\n this.computeCostAttribution();\n this.buildRecentRuns();\n this.sortRecentRuns();\n } catch (e) {\n console.error('Agent Run Analysis load error:', e);\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n // ── Computations ──\n\n private computeStats(): void {\n const runs = this.agentRuns;\n const total = this.totalRunCount;\n // Own cost at prompt-run grain, from the usage aggregates — never a sum of\n // AIAgentRun.TotalCost, which is subtree-inclusive (and defaults to 0, so it can\n // never express \"unpriced\").\n const totalCost = ComputeTotalCost(this.agentUsageRows);\n const completed = runs.filter(r => r.Status === 'Completed');\n\n const durations = completed\n .filter(r => r.CompletedAt)\n .map(r => {\n const start = new Date(r.StartedAt).getTime();\n const end = new Date(r.CompletedAt!).getTime();\n return (end - start) / 1000;\n })\n .filter(d => d > 0);\n\n const avgDuration = durations.length > 0\n ? durations.reduce((s, d) => s + d, 0) / durations.length\n : 0;\n\n const agentPromptRuns = this.agentUsageRows.reduce((sum, r) => sum + (r.Runs ?? 0), 0);\n\n const covPriced = this.agentUsageRows.reduce((sum, r) => sum + (r.PricedRuns ?? 0), 0);\n const covUnpriced = this.agentUsageRows.reduce((sum, r) => sum + (r.UnpricedRuns ?? 0), 0);\n const covPct = ComputeCoveragePercent({ PricedRuns: covPriced, UnpricedRuns: covUnpriced });\n const covSubtitle = covPriced + covUnpriced > 0 ? `covers ${Math.round(covPct)}% of prompt runs` : undefined;\n\n this.Stats = {\n TotalRuns: total,\n TotalCost: totalCost,\n CoverageSubtitle: covSubtitle,\n PromptRuns: agentPromptRuns,\n AvgCostPerRun: total > 0 && totalCost !== null ? totalCost / total : null,\n SuccessRate: total > 0 ? (this.successRunCount / total) * 100 : 0,\n AvgDurationSeconds: avgDuration,\n DurationSampleSize: durations.length\n };\n }\n\n /**\n * Cost per agent, split by vendor, from the usage aggregates. Each (agent, vendor) figure is a\n * ComputeTotalCost over its rows in the period's primary currency, so an unpriced slice stays\n * unpriced instead of reading as a zero-width free segment, and currencies are never summed.\n */\n private computeCostAttribution(): void {\n const currency = ResolveCostCurrency(this.agentUsageRows).Currency;\n const byAgent = new Map<string, Map<string, UsageRow[]>>();\n for (const r of this.agentUsageRows) {\n const agentKey = r.AgentID!.toLowerCase();\n const vendorName = (r.VendorID ? this.vendorNames.get(r.VendorID.toLowerCase()) : undefined) ?? 'Other';\n let vendors = byAgent.get(agentKey);\n if (!vendors) {\n vendors = new Map<string, UsageRow[]>();\n byAgent.set(agentKey, vendors);\n }\n const list = vendors.get(vendorName);\n if (list) {\n list.push(r);\n } else {\n vendors.set(vendorName, [r]);\n }\n }\n\n const agentCosts: Array<{ agentId: string; name: string; vendorCosts: Map<string, number>; totalCost: number | null }> = [];\n const allVendors = new Set<string>();\n for (const [agentId, vendors] of byAgent) {\n const vendorCosts = new Map<string, number>();\n for (const [vendor, rows] of vendors) {\n const cost = ComputeTotalCost(rows, currency);\n if (cost !== null && cost > 0) {\n vendorCosts.set(vendor, cost);\n allVendors.add(vendor);\n }\n }\n const allRows = Array.from(vendors.values()).flat();\n agentCosts.push({\n agentId,\n name: this.agentNames.get(agentId) ?? 'Unknown',\n vendorCosts,\n totalCost: ComputeTotalCost(allRows, currency)\n });\n }\n\n const vendorList = Array.from(allVendors);\n this.LegendItems = vendorList.map((v, i) => ({\n Label: v,\n Color: COST_COLORS[i % COST_COLORS.length]\n }));\n\n // Sort by total cost descending; fully unpriced agents last.\n agentCosts.sort((a, b) => (b.totalCost ?? -1) - (a.totalCost ?? -1));\n\n this.CostAttributionRows = agentCosts.map(entry => ({\n AgentName: entry.name,\n AgentID: entry.agentId,\n TotalCost: entry.totalCost,\n Segments: vendorList.map((vendor, i) => {\n const val = entry.vendorCosts.get(vendor) ?? 0;\n return {\n Label: vendor,\n Value: val,\n Percent: entry.totalCost !== null && entry.totalCost > 0 ? (val / entry.totalCost) * 100 : 0,\n Color: COST_COLORS[i % COST_COLORS.length]\n };\n }).filter(seg => seg.Value > 0)\n }));\n }\n\n private buildRecentRuns(): void {\n this.RecentRuns = this.agentRuns.slice(0, 100).map(r => ({\n ID: r.ID,\n Agent: r.Agent ?? 'Unknown',\n Status: r.Status,\n StatusClass: this.getStatusClass(r.Status),\n // The run's own prompt-iteration count, recorded by the agent framework.\n StepCount: r.TotalPromptIterations ?? 0,\n Duration: this.formatDuration(r.StartedAt, r.CompletedAt),\n Cost: this.FormatCurrency(r.TotalCost),\n Time: this.formatRelativeTime(r.StartedAt)\n }));\n }\n\n private sortRecentRuns(): void {\n const dir = this.SortDir === 'asc' ? 1 : -1;\n this.RecentRuns.sort((a, b) => {\n switch (this.SortField) {\n case 'Agent': return dir * a.Agent.localeCompare(b.Agent);\n case 'Status': return dir * a.Status.localeCompare(b.Status);\n case 'StepCount': return dir * (a.StepCount - b.StepCount);\n case 'Duration': return dir * a.Duration.localeCompare(b.Duration);\n case 'Cost': return dir * a.Cost.localeCompare(b.Cost);\n case 'Time': return dir * a.Time.localeCompare(b.Time);\n default: return 0;\n }\n });\n }\n\n // ── Helpers ──\n\n private buildDateFilter(field: string): string {\n const now = new Date();\n const ms = this.timeRangeToMs(this.TimeRange);\n const start = new Date(now.getTime() - ms);\n return `${field} >= '${start.toISOString()}'`;\n }\n\n private buildAgentFilter(): string {\n if (this.Filters.Agents.length === 0) return '';\n const ids = this.Filters.Agents.map(id => `'${id}'`).join(',');\n return `AgentID IN (${ids})`;\n }\n\n private buildStatusFilter(): string {\n if (this.Filters.Statuses.length === 0) return '';\n const values = this.Filters.Statuses.map(s => `'${s}'`).join(',');\n return `Status IN (${values})`;\n }\n\n private timeRangeToMs(range: string): number {\n const map: Record<string, number> = {\n '1h': 3600000,\n '6h': 21600000,\n '24h': 86400000,\n '7d': 604800000,\n '30d': 2592000000\n };\n return map[range] ?? 604800000;\n }\n\n private getStatusClass(status: string): string {\n return 'status-pill status-' + status.toLowerCase().replace(/\\s+/g, '');\n }\n\n private formatDuration(startStr: string, endStr: string | null): string {\n if (!endStr) return '--';\n const ms = new Date(endStr).getTime() - new Date(startStr).getTime();\n if (ms < 1000) return ms + 'ms';\n if (ms < 60000) return (ms / 1000).toFixed(1) + 's';\n return (ms / 60000).toFixed(1) + 'm';\n }\n\n private formatRelativeTime(dateStr: string): string {\n const now = Date.now();\n const then = new Date(dateStr).getTime();\n const diffMs = now - then;\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return diffMin + 'm ago';\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return diffHr + 'h ago';\n const diffDay = Math.floor(diffHr / 24);\n return diffDay + 'd ago';\n }\n}\n\nexport function LoadAnalyticsAgentRuns() { /* tree-shaking prevention */ }\n"]}
|
|
1
|
+
{"version":3,"file":"agent-run-analysis.component.js","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/agent-runs/agent-run-analysis.component.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Agent Run Analysis -- Cost Attribution Focus.\n *\n * Displays agent run stats, cost attribution horizontal stacked bars per agent,\n * and a sortable recent agent runs table. Agent runs are read via RunView from\n * \"MJ: AI Agent Runs\"; per-agent prompt volume and cost attribution come from the\n * AI usage aggregates (AIUsageHourly / AIUsageDaily), which already resolve each\n * prompt run to its agent and exclude parallel parents — no raw prompt-run pull.\n */\n\nimport {\n Component, ChangeDetectionStrategy, 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';\nimport { AIInstrumentationService } from '../../../services/ai-instrumentation.service';\nimport { ComputeTotalCost, ComputeCoveragePercent, ResolveCostCurrency } from '../../../services/ai-usage-analytics.compute';\nimport { AIUsageDailyRow, AIUsageHourlyRow } from '../../../services/ai-usage-analytics.types';\n\n// ── Interfaces ──\n\ninterface AgentRunFilters {\n Agents: string[];\n Statuses: string[];\n}\n\ninterface AgentRunRecord {\n ID: string;\n StartedAt: string;\n CompletedAt: string | null;\n Status: string;\n Success: boolean | null;\n TotalCost: number | null;\n TotalTokensUsed: number | null;\n AgentID: string;\n Agent: string | null;\n ErrorMessage: string | null;\n TotalPromptIterations: number | null;\n}\n\n/** An hourly or daily usage aggregate row — the fields this view reads are common to both. */\ntype UsageRow = AIUsageHourlyRow | AIUsageDailyRow;\n\ninterface AgentRunStats {\n TotalRuns: number;\n TotalCost: number | null;\n CoverageSubtitle?: string;\n PromptRuns: number;\n AvgCostPerRun: number | null;\n SuccessRate: number;\n AvgDurationSeconds: number;\n /** How many recent runs the duration average is taken over (the list is capped). */\n DurationSampleSize: number;\n}\n\ninterface CostAttributionRow {\n AgentName: string;\n AgentID: string;\n TotalCost: number | null;\n Segments: CostSegment[];\n}\n\ninterface CostSegment {\n Label: string;\n Value: number;\n Percent: number;\n Color: string;\n}\n\ninterface RecentRunRow {\n ID: string;\n Agent: string;\n Status: string;\n StatusClass: string;\n StepCount: number;\n Duration: string;\n Cost: string;\n Time: string;\n}\n\ntype SortField = 'Agent' | 'Status' | 'StepCount' | 'Duration' | 'Cost' | 'Time';\ntype SortDirection = 'asc' | 'desc';\n\nconst AGENT_RUN_FIELDS = [\n 'ID', 'StartedAt', 'CompletedAt', 'Status', 'Success',\n 'TotalCost', 'TotalTokensUsed', 'AgentID', 'Agent', 'ErrorMessage', 'TotalPromptIterations'\n];\n\n// Vendors are categories, so they take the categorical --mj-viz palette; brand/status tokens were\n// all blues and greys, and two vendors read as one. The palette is a hue ramp whose neighbours are\n// close (1-3 run blue to violet), so the steps are taken spread out.\nconst COST_COLORS = [\n 'var(--mj-viz-1)',\n 'var(--mj-viz-6)',\n 'var(--mj-viz-3)',\n 'var(--mj-viz-9)',\n 'var(--mj-viz-5)',\n 'var(--mj-viz-8)',\n 'var(--mj-viz-4)',\n 'var(--mj-viz-10)'\n];\n\n@Component({\n standalone: false,\n changeDetection: ChangeDetectionStrategy.OnPush,\n selector: 'app-analytics-agent-runs',\n template: `\n\n @if (IsLoading) {\n <div class=\"loading-container\">\n <mj-loading text=\"Loading agent runs...\"></mj-loading>\n </div>\n } @else {\n <!-- Stats Bar -->\n <div class=\"stats-grid\">\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Runs</div>\n <div class=\"stat-value\">{{ Stats.TotalRuns | number }}</div>\n </div>\n <div class=\"stat-card accent-brand\">\n <div class=\"stat-label\">Total Cost</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.TotalCost) }}</div>\n @if (Stats.CoverageSubtitle) {\n <div class=\"stat-subtitle\">{{ Stats.CoverageSubtitle }}</div>\n }\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Prompt Runs</div>\n <div class=\"stat-value\">{{ Stats.PromptRuns | number }}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Cost/Run</div>\n <div class=\"stat-value\">{{ FormatCurrency(Stats.AvgCostPerRun, 4) }}</div>\n </div>\n <div class=\"stat-card accent-success\">\n <div class=\"stat-label\">Success Rate</div>\n <div class=\"stat-value\">{{ Stats.SuccessRate | number:'1.1-1' }}%</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">Avg Duration</div>\n <div class=\"stat-value\">{{ Stats.AvgDurationSeconds | number:'1.1-1' }}s</div>\n @if (Stats.DurationSampleSize > 0 && Stats.DurationSampleSize < Stats.TotalRuns) {\n <div class=\"stat-subtitle\">last {{ Stats.DurationSampleSize }} completed runs</div>\n }\n </div>\n </div>\n\n <!-- Cost Attribution Panel -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-chart-bar panel-header__icon\"></i>\n Cost Attribution by Agent\n </div>\n </div>\n <div class=\"panel-body\">\n @if (CostAttributionRows.length === 0) {\n <mj-empty-state Size=\"compact\" Variant=\"empty\" Icon=\"fa-solid fa-chart-bar\"\n Title=\"No agent cost data for selected period\" />\n }\n @for (row of CostAttributionRows; track row.AgentID) {\n <div class=\"attribution-row\">\n <div class=\"attribution-name\" [title]=\"row.AgentName\">{{ row.AgentName }}</div>\n <div class=\"attribution-bar-container\">\n @for (seg of row.Segments; track seg.Label) {\n <div\n class=\"attribution-segment\"\n [style.width.%]=\"seg.Percent\"\n [style.background]=\"seg.Color\"\n [title]=\"seg.Label + ': ' + FormatCurrency(seg.Value, 4)\"\n ></div>\n }\n </div>\n <div class=\"attribution-total\">{{ FormatCurrency(row.TotalCost) }}</div>\n </div>\n }\n @if (CostAttributionRows.length > 0) {\n <div class=\"legend-row\">\n @for (item of LegendItems; track item.Label) {\n <div class=\"legend-item\">\n <span class=\"legend-swatch\" [style.background]=\"item.Color\"></span>\n {{ item.Label }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Recent Agent Runs Table -->\n <div class=\"panel\">\n <div class=\"panel-header\">\n <div class=\"panel-header__title\">\n <i class=\"fa-solid fa-list panel-header__icon\"></i>\n Recent Agent Runs\n </div>\n <span class=\"panel-header__subtitle\">showing latest 100</span>\n </div>\n <div class=\"table-wrapper\">\n <table class=\"data-table\">\n <thead>\n <tr>\n @for (col of TableColumns; track col.field) {\n <th\n class=\"sortable-header\"\n [class.sorted]=\"SortField === col.field\"\n (click)=\"OnSort(col.field)\">\n {{ col.label }}\n @if (SortField === col.field) {\n <i [class]=\"SortDir === 'asc' ? 'fa-solid fa-caret-up' : 'fa-solid fa-caret-down'\"></i>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (RecentRuns.length === 0) {\n <tr><td [attr.colspan]=\"TableColumns.length\" class=\"empty-row\"><mj-empty-state Variant=\"no-results\" Size=\"compact\" Title=\"No runs found\" Message=\"No agent runs match this period and these filters.\"></mj-empty-state></td></tr>\n }\n @for (run of RecentRuns; track run.ID) {\n <tr>\n <td class=\"cell-agent\">{{ run.Agent }}</td>\n <td><span class=\"status-pill\" [class]=\"run.StatusClass\">{{ run.Status }}</span></td>\n <td class=\"cell-numeric\">{{ run.StepCount }}</td>\n <td class=\"cell-numeric\">{{ run.Duration }}</td>\n <td class=\"cell-numeric\">{{ run.Cost }}</td>\n <td class=\"cell-time\">{{ run.Time }}</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 /* ── Stats Grid ── */\n .stats-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));\n gap: 12px;\n margin: 16px 0;\n }\n\n .stat-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n padding: 14px 16px;\n text-align: center;\n border-top: 3px solid var(--mj-border-subtle);\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .stat-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 .stat-card.accent-brand { border-top-color: var(--mj-brand-primary); }\n .stat-card.accent-success { border-top-color: var(--mj-status-success); }\n .stat-card.accent-warning { border-top-color: var(--mj-status-warning); }\n\n .stat-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 margin-bottom: 4px;\n }\n\n .stat-value {\n font-size: 22px;\n font-weight: 700;\n color: var(--mj-text-primary);\n letter-spacing: -0.02em;\n }\n\n .stat-subtitle {\n font-size: 11px;\n color: var(--mj-text-muted);\n margin-top: 2px;\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 margin-bottom: 16px;\n overflow: hidden;\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-header__subtitle {\n font-size: 12px;\n color: var(--mj-text-muted);\n }\n\n .panel-body {\n padding: 16px 18px;\n }\n\n /* ── Cost Attribution ── */\n .attribution-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 8px 0;\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .attribution-row:last-of-type {\n border-bottom: none;\n }\n\n .attribution-name {\n width: 140px;\n min-width: 140px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .attribution-bar-container {\n flex: 1;\n display: flex;\n height: 24px;\n border-radius: 6px;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n }\n\n .attribution-segment {\n height: 100%;\n min-width: 2px;\n transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .attribution-total {\n width: 80px;\n min-width: 80px;\n text-align: right;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n }\n\n .legend-row {\n display: flex;\n gap: 16px;\n padding: 12px 0 4px;\n flex-wrap: wrap;\n }\n\n .legend-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--mj-text-muted);\n }\n\n .legend-swatch {\n width: 12px;\n height: 12px;\n border-radius: 3px;\n flex-shrink: 0;\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 }\n\n .sortable-header {\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: color 0.15s;\n }\n\n .sortable-header:hover {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header.sorted {\n color: var(--mj-brand-primary);\n }\n\n .sortable-header i {\n margin-left: 4px;\n font-size: 10px;\n }\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-agent {\n font-weight: 500;\n color: var(--mj-text-primary);\n max-width: 200px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\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-time {\n white-space: nowrap;\n color: var(--mj-text-muted);\n font-size: 12px;\n }\n\n .empty-row {\n text-align: center;\n color: var(--mj-text-disabled);\n padding: 24px;\n }\n\n /* ── Status Pills ── */\n .status-pill {\n display: inline-block;\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.3px;\n }\n\n .status-completed {\n background: color-mix(in srgb, var(--mj-status-success) 12%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n }\n\n .status-running {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n }\n\n .status-failed {\n background: color-mix(in srgb, var(--mj-status-error) 12%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n }\n\n .status-cancelled {\n background: color-mix(in srgb, var(--mj-status-warning) 12%, var(--mj-bg-surface));\n color: var(--mj-status-warning);\n }\n\n .status-paused, .status-awaitingfeedback {\n background: color-mix(in srgb, var(--mj-text-disabled) 12%, var(--mj-bg-surface));\n color: var(--mj-text-muted);\n }\n\n /* ── Responsive ── */\n @media (max-width: 1200px) {\n .stats-grid {\n grid-template-columns: repeat(3, 1fr);\n }\n }\n\n @media (max-width: 768px) {\n .stats-grid {\n grid-template-columns: repeat(2, 1fr);\n }\n\n .attribution-name {\n width: 100px;\n min-width: 100px;\n }\n\n .attribution-total {\n width: 60px;\n min-width: 60px;\n }\n\n .stat-value {\n font-size: 18px;\n }\n }\n `]\n})\nexport class AnalyticsAgentRunsComponent 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: AgentRunFilters = { Agents: [], Statuses: [] };\n @Input()\n set Filters(value: AgentRunFilters) {\n const next = value ?? { Agents: [], Statuses: [] };\n const changed = !this.shallowFiltersEqual(this._filters, next);\n this._filters = next;\n if (changed && this.initialized) this.loadData();\n }\n get Filters(): AgentRunFilters { return this._filters; }\n\n private shallowFiltersEqual(a: AgentRunFilters, b: AgentRunFilters): boolean {\n const sameArr = (x: string[], y: string[]) => x.length === y.length && x.every((v, i) => v === y[i]);\n return sameArr(a.Agents, b.Agents) && sameArr(a.Statuses, b.Statuses);\n }\n\n @Output() TimeRangeChange = new EventEmitter<string>();\n @Output() FiltersChange = new EventEmitter<AgentRunFilters>();\n\n private initialized = false;\n\n private cdr = inject(ChangeDetectorRef);\n private destroy$ = new Subject<void>();\n\n public IsLoading = false;\n\n public Stats: AgentRunStats = {\n TotalRuns: 0,\n TotalCost: 0,\n PromptRuns: 0,\n AvgCostPerRun: 0,\n SuccessRate: 0,\n AvgDurationSeconds: 0,\n DurationSampleSize: 0\n };\n\n public CostAttributionRows: CostAttributionRow[] = [];\n public LegendItems: { Label: string; Color: string }[] = [];\n public RecentRuns: RecentRunRow[] = [];\n public SortField: SortField = 'Time';\n public SortDir: SortDirection = 'desc';\n\n public TableColumns: { field: SortField; label: string }[] = [\n { field: 'Agent', label: 'Agent' },\n { field: 'Status', label: 'Status' },\n { field: 'StepCount', label: 'Prompts' },\n { field: 'Duration', label: 'Duration' },\n { field: 'Cost', label: 'Cost' },\n { field: 'Time', label: 'Time' }\n ];\n\n /** Bridge the local filter shape to the global shape the filter bar expects */\n public get GlobalFilters(): GlobalFilterState {\n return {\n Models: [],\n Agents: this.Filters.Agents,\n Prompts: [],\n Statuses: this.Filters.Statuses\n };\n }\n\n /** @deprecated Use {@link GlobalFilters}. */\n public get globalFilters(): GlobalFilterState {\n return this.GlobalFilters;\n }\n\n private instrumentation = inject(AIInstrumentationService);\n\n private agentRuns: AgentRunRecord[] = [];\n\n private totalRunCount = 0;\n\n private successRunCount = 0;\n /** Usage aggregate rows for agent-driven prompt runs in the period (AgentID set, agent filter applied). */\n private agentUsageRows: UsageRow[] = [];\n private vendorNames = new Map<string, string>();\n private agentNames = new Map<string, string>();\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 Event 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 = { Agents: filters.Agents, Statuses: filters.Statuses };\n this.FiltersChange.emit(this.Filters);\n this.loadData();\n }\n\n public OnSort(field: SortField): void {\n if (this.SortField === field) {\n this.SortDir = this.SortDir === 'asc' ? 'desc' : 'asc';\n } else {\n this.SortField = field;\n this.SortDir = field === 'Time' ? 'desc' : 'asc';\n }\n this.sortRecentRuns();\n this.cdr.detectChanges();\n }\n\n public FormatCurrency(value: number | null | undefined, decimals = 2): string {\n if (value === null || value === undefined) return '—';\n if (value === 0) return '$0.00';\n if (value < 0.01 && decimals < 4) decimals = 4;\n return '$' + value.toFixed(decimals);\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 dateFilter = this.buildDateFilter('StartedAt');\n const agentFilter = this.buildAgentFilter();\n const statusFilter = this.buildStatusFilter();\n const extraFilter = [dateFilter, agentFilter, statusFilter, 'ParentRunID IS NULL'].filter(Boolean).join(' AND ');\n\n this.instrumentation.Provider = this.ProviderToUse;\n const rangeMs = this.timeRangeToMs(this.TimeRange);\n const now = new Date();\n const start = new Date(now.getTime() - rangeMs);\n\n // The run list is capped at the 100 most recent; the totals are exact counts, so the KPI\n // cards never report the cap as if it were the period's run count.\n const [agentResults, usageRows, lookups] = await Promise.all([\n rv.RunViews([\n {\n EntityName: 'MJ: AI Agent Runs',\n ExtraFilter: extraFilter,\n Fields: AGENT_RUN_FIELDS,\n OrderBy: 'StartedAt DESC',\n MaxRows: 100,\n ResultType: 'simple'\n },\n { EntityName: 'MJ: AI Agent Runs', ExtraFilter: extraFilter, ResultType: 'count_only' },\n { EntityName: 'MJ: AI Agent Runs', ExtraFilter: `${extraFilter} AND Success = 1`, ResultType: 'count_only' }\n ]),\n // Hourly buckets for sub-day ranges so \"last hour\" is not a whole day's usage.\n rangeMs <= 86400000\n ? this.instrumentation.GetUsageHourly(start, now)\n : this.instrumentation.GetUsageDaily(start, now),\n this.instrumentation.GetModelAndVendorLookups()\n ]);\n\n const [agentResult, totalResult, successResult] = agentResults;\n if (!agentResult.Success) {\n console.error(`Agent Run Analysis: agent runs failed to load. ${agentResult.ErrorMessage}`);\n }\n if (!totalResult.Success || !successResult.Success) {\n console.error(`Agent Run Analysis: run counts failed to load. ${totalResult.ErrorMessage ?? successResult.ErrorMessage}`);\n }\n this.agentRuns = agentResult.Success ? (agentResult.Results as AgentRunRecord[]) ?? [] : [];\n this.totalRunCount = totalResult.Success ? totalResult.TotalRowCount ?? 0 : this.agentRuns.length;\n this.successRunCount = successResult.Success\n ? successResult.TotalRowCount ?? 0\n : this.agentRuns.filter(r => r.Success === true).length;\n const agentIds = new Set(this.Filters.Agents.map(a => a.toLowerCase()));\n const usage: UsageRow[] = usageRows;\n this.agentUsageRows = usage.filter(r =>\n r.AgentID !== null && (agentIds.size === 0 || agentIds.has(r.AgentID.toLowerCase())));\n this.vendorNames = lookups.vendors;\n this.agentNames = lookups.agents;\n\n this.computeStats();\n this.computeCostAttribution();\n this.buildRecentRuns();\n this.sortRecentRuns();\n } catch (e) {\n console.error('Agent Run Analysis load error:', e);\n } finally {\n this.IsLoading = false;\n this.cdr.detectChanges();\n }\n }\n\n // ── Computations ──\n\n private computeStats(): void {\n const runs = this.agentRuns;\n const total = this.totalRunCount;\n // Own cost at prompt-run grain, from the usage aggregates — never a sum of\n // AIAgentRun.TotalCost, which is subtree-inclusive (and defaults to 0, so it can\n // never express \"unpriced\").\n const totalCost = ComputeTotalCost(this.agentUsageRows);\n const completed = runs.filter(r => r.Status === 'Completed');\n\n const durations = completed\n .filter(r => r.CompletedAt)\n .map(r => {\n const start = new Date(r.StartedAt).getTime();\n const end = new Date(r.CompletedAt!).getTime();\n return (end - start) / 1000;\n })\n .filter(d => d > 0);\n\n const avgDuration = durations.length > 0\n ? durations.reduce((s, d) => s + d, 0) / durations.length\n : 0;\n\n const agentPromptRuns = this.agentUsageRows.reduce((sum, r) => sum + (r.Runs ?? 0), 0);\n\n const covPriced = this.agentUsageRows.reduce((sum, r) => sum + (r.PricedRuns ?? 0), 0);\n const covUnpriced = this.agentUsageRows.reduce((sum, r) => sum + (r.UnpricedRuns ?? 0), 0);\n const covPct = ComputeCoveragePercent({ PricedRuns: covPriced, UnpricedRuns: covUnpriced });\n const covSubtitle = covPriced + covUnpriced > 0 ? `covers ${Math.round(covPct)}% of prompt runs` : undefined;\n\n this.Stats = {\n TotalRuns: total,\n TotalCost: totalCost,\n CoverageSubtitle: covSubtitle,\n PromptRuns: agentPromptRuns,\n AvgCostPerRun: total > 0 && totalCost !== null ? totalCost / total : null,\n SuccessRate: total > 0 ? (this.successRunCount / total) * 100 : 0,\n AvgDurationSeconds: avgDuration,\n DurationSampleSize: durations.length\n };\n }\n\n /**\n * Cost per agent, split by vendor, from the usage aggregates. Each (agent, vendor) figure is a\n * ComputeTotalCost over its rows in the period's primary currency, so an unpriced slice stays\n * unpriced instead of reading as a zero-width free segment, and currencies are never summed.\n */\n private computeCostAttribution(): void {\n const currency = ResolveCostCurrency(this.agentUsageRows).Currency;\n const byAgent = new Map<string, Map<string, UsageRow[]>>();\n for (const r of this.agentUsageRows) {\n const agentKey = r.AgentID!.toLowerCase();\n const vendorName = (r.VendorID ? this.vendorNames.get(r.VendorID.toLowerCase()) : undefined) ?? 'Other';\n let vendors = byAgent.get(agentKey);\n if (!vendors) {\n vendors = new Map<string, UsageRow[]>();\n byAgent.set(agentKey, vendors);\n }\n const list = vendors.get(vendorName);\n if (list) {\n list.push(r);\n } else {\n vendors.set(vendorName, [r]);\n }\n }\n\n const agentCosts: Array<{ agentId: string; name: string; vendorCosts: Map<string, number>; totalCost: number | null }> = [];\n const allVendors = new Set<string>();\n for (const [agentId, vendors] of byAgent) {\n const vendorCosts = new Map<string, number>();\n for (const [vendor, rows] of vendors) {\n const cost = ComputeTotalCost(rows, currency);\n if (cost !== null && cost > 0) {\n vendorCosts.set(vendor, cost);\n allVendors.add(vendor);\n }\n }\n const allRows = Array.from(vendors.values()).flat();\n agentCosts.push({\n agentId,\n name: this.agentNames.get(agentId) ?? 'Unknown',\n vendorCosts,\n totalCost: ComputeTotalCost(allRows, currency)\n });\n }\n\n const vendorList = Array.from(allVendors);\n this.LegendItems = vendorList.map((v, i) => ({\n Label: v,\n Color: COST_COLORS[i % COST_COLORS.length]\n }));\n\n // Sort by total cost descending; fully unpriced agents last.\n agentCosts.sort((a, b) => (b.totalCost ?? -1) - (a.totalCost ?? -1));\n\n this.CostAttributionRows = agentCosts.map(entry => ({\n AgentName: entry.name,\n AgentID: entry.agentId,\n TotalCost: entry.totalCost,\n Segments: vendorList.map((vendor, i) => {\n const val = entry.vendorCosts.get(vendor) ?? 0;\n return {\n Label: vendor,\n Value: val,\n Percent: entry.totalCost !== null && entry.totalCost > 0 ? (val / entry.totalCost) * 100 : 0,\n Color: COST_COLORS[i % COST_COLORS.length]\n };\n }).filter(seg => seg.Value > 0)\n }));\n }\n\n private buildRecentRuns(): void {\n this.RecentRuns = this.agentRuns.slice(0, 100).map(r => ({\n ID: r.ID,\n Agent: r.Agent ?? 'Unknown',\n Status: r.Status,\n StatusClass: this.getStatusClass(r.Status),\n // The run's own prompt-iteration count, recorded by the agent framework.\n StepCount: r.TotalPromptIterations ?? 0,\n Duration: this.formatDuration(r.StartedAt, r.CompletedAt),\n Cost: this.FormatCurrency(r.TotalCost),\n Time: this.formatRelativeTime(r.StartedAt)\n }));\n }\n\n private sortRecentRuns(): void {\n const dir = this.SortDir === 'asc' ? 1 : -1;\n this.RecentRuns.sort((a, b) => {\n switch (this.SortField) {\n case 'Agent': return dir * a.Agent.localeCompare(b.Agent);\n case 'Status': return dir * a.Status.localeCompare(b.Status);\n case 'StepCount': return dir * (a.StepCount - b.StepCount);\n case 'Duration': return dir * a.Duration.localeCompare(b.Duration);\n case 'Cost': return dir * a.Cost.localeCompare(b.Cost);\n case 'Time': return dir * a.Time.localeCompare(b.Time);\n default: return 0;\n }\n });\n }\n\n // ── Helpers ──\n\n private buildDateFilter(field: string): string {\n const now = new Date();\n const ms = this.timeRangeToMs(this.TimeRange);\n const start = new Date(now.getTime() - ms);\n return `${field} >= '${start.toISOString()}'`;\n }\n\n private buildAgentFilter(): string {\n if (this.Filters.Agents.length === 0) return '';\n const ids = this.Filters.Agents.map(id => `'${id}'`).join(',');\n return `AgentID IN (${ids})`;\n }\n\n private buildStatusFilter(): string {\n if (this.Filters.Statuses.length === 0) return '';\n const values = this.Filters.Statuses.map(s => `'${s}'`).join(',');\n return `Status IN (${values})`;\n }\n\n private timeRangeToMs(range: string): number {\n const map: Record<string, number> = {\n '1h': 3600000,\n '6h': 21600000,\n '24h': 86400000,\n '7d': 604800000,\n '30d': 2592000000\n };\n return map[range] ?? 604800000;\n }\n\n private getStatusClass(status: string): string {\n return 'status-pill status-' + status.toLowerCase().replace(/\\s+/g, '');\n }\n\n private formatDuration(startStr: string, endStr: string | null): string {\n if (!endStr) return '--';\n const ms = new Date(endStr).getTime() - new Date(startStr).getTime();\n if (ms < 1000) return ms + 'ms';\n if (ms < 60000) return (ms / 1000).toFixed(1) + 's';\n return (ms / 60000).toFixed(1) + 'm';\n }\n\n private formatRelativeTime(dateStr: string): string {\n const now = Date.now();\n const then = new Date(dateStr).getTime();\n const diffMs = now - then;\n const diffMin = Math.floor(diffMs / 60000);\n if (diffMin < 1) return 'just now';\n if (diffMin < 60) return diffMin + 'm ago';\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return diffHr + 'h ago';\n const diffDay = Math.floor(diffHr / 24);\n return diffDay + 'd ago';\n }\n}\n\nexport function LoadAnalyticsAgentRuns() { /* tree-shaking prevention */ }\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-management.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/realtime/realtime-management.component.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"realtime-management.component.d.ts","sourceRoot":"","sources":["../../../../../src/AI/components/analytics/realtime/realtime-management.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -999,7 +999,9 @@ export class RealtimeManagementComponent extends BaseAngularComponent {
|
|
|
999
999
|
CloseReasonClass(reason) {
|
|
1000
1000
|
switch (reason) {
|
|
1001
1001
|
case 'Error': return 'reason-pill reason-error';
|
|
1002
|
-
case 'Janitor':
|
|
1002
|
+
case 'Janitor':
|
|
1003
|
+
case 'TimeLimit':
|
|
1004
|
+
case 'Idle': return 'reason-pill reason-janitor';
|
|
1003
1005
|
case 'HostEnded': return 'reason-pill reason-hostended';
|
|
1004
1006
|
case 'Shutdown': return 'reason-pill reason-shutdown';
|
|
1005
1007
|
case 'Explicit': return 'reason-pill reason-explicit';
|