@memberjunction/ng-dashboards 6.2.0-edge.5 → 6.2.0-edge.6
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 +28 -0
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.d.ts.map +1 -1
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js +15 -7
- package/dist/AI/components/autotagging/autotagging-pipeline-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.d.ts +7 -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 +209 -57
- package/dist/AI/components/duplicates/duplicate-detection-resource.component.js.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts +12 -11
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.d.ts.map +1 -1
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js +15 -15
- package/dist/AI/components/duplicates/duplicate-detection-run-scope.js.map +1 -1
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +28 -16
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts +1 -0
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.d.ts.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +30 -6
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts +1 -1
- package/dist/AI/components/tags/tags-resource.component.d.ts.map +1 -1
- package/dist/AI/components/tags/tags-resource.component.js +15 -7
- package/dist/AI/components/tags/tags-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/sensitive-fields.d.ts +9 -4
- package/dist/AI/components/vectors/sensitive-fields.d.ts.map +1 -1
- package/dist/AI/components/vectors/sensitive-fields.js +39 -14
- package/dist/AI/components/vectors/sensitive-fields.js.map +1 -1
- package/dist/AI/components/vectors/vector-document-rules.d.ts +13 -0
- package/dist/AI/components/vectors/vector-document-rules.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-document-rules.js +14 -0
- package/dist/AI/components/vectors/vector-document-rules.js.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts +34 -14
- package/dist/AI/components/vectors/vector-management-resource.component.d.ts.map +1 -1
- package/dist/AI/components/vectors/vector-management-resource.component.js +127 -50
- package/dist/AI/components/vectors/vector-management-resource.component.js.map +1 -1
- package/dist/AI/components/vectors/vector-store-selection.d.ts +32 -0
- package/dist/AI/components/vectors/vector-store-selection.d.ts.map +1 -0
- package/dist/AI/components/vectors/vector-store-selection.js +57 -0
- package/dist/AI/components/vectors/vector-store-selection.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts +236 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js +374 -0
- package/dist/ChiefOfStaff/chief-of-staff-agent-context.js.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts +195 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.d.ts.map +1 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js +2910 -0
- package/dist/ChiefOfStaff/chief-of-staff-dashboard.component.js.map +1 -0
- package/dist/ChiefOfStaff/index.d.ts +3 -0
- package/dist/ChiefOfStaff/index.d.ts.map +1 -0
- package/dist/ChiefOfStaff/index.js +3 -0
- package/dist/ChiefOfStaff/index.js.map +1 -0
- package/dist/Communication/communication-logs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-logs-resource.component.js +2 -1
- package/dist/Communication/communication-logs-resource.component.js.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-monitor-resource.component.js +23 -18
- package/dist/Communication/communication-monitor-resource.component.js.map +1 -1
- package/dist/Communication/communication-runs-resource.component.d.ts.map +1 -1
- package/dist/Communication/communication-runs-resource.component.js +11 -10
- package/dist/Communication/communication-runs-resource.component.js.map +1 -1
- package/dist/DashboardEditor/dashboard-editor.component.d.ts +17 -2
- package/dist/DashboardEditor/dashboard-editor.component.d.ts.map +1 -1
- package/dist/DashboardEditor/dashboard-editor.component.js +94 -43
- package/dist/DashboardEditor/dashboard-editor.component.js.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts +24 -0
- package/dist/DataExplorer/data-explorer-dashboard.component.d.ts.map +1 -1
- package/dist/DataExplorer/data-explorer-dashboard.component.js +146 -50
- package/dist/DataExplorer/data-explorer-dashboard.component.js.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.d.ts +2 -0
- package/dist/DataExplorer/models/explorer-state.interface.d.ts.map +1 -1
- package/dist/DataExplorer/models/explorer-state.interface.js.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.d.ts +10 -2
- package/dist/LoginStudio/login-studio-resource.component.d.ts.map +1 -1
- package/dist/LoginStudio/login-studio-resource.component.js +110 -77
- package/dist/LoginStudio/login-studio-resource.component.js.map +1 -1
- package/dist/MCP/mcp-dashboard.component.d.ts +24 -4
- package/dist/MCP/mcp-dashboard.component.d.ts.map +1 -1
- package/dist/MCP/mcp-dashboard.component.js +118 -65
- package/dist/MCP/mcp-dashboard.component.js.map +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.d.ts +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.d.ts.map +1 -1
- package/dist/PredictiveStudio/business-predictions.view-models.js +3 -3
- package/dist/PredictiveStudio/business-predictions.view-models.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts +6 -63
- package/dist/PredictiveStudio/components/ps-experiments.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-experiments.component.js +256 -521
- package/dist/PredictiveStudio/components/ps-experiments.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts +0 -18
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js +122 -249
- package/dist/PredictiveStudio/components/ps-pipeline-wizard.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts +5 -9
- package/dist/PredictiveStudio/components/ps-pipelines.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-pipelines.component.js +98 -130
- package/dist/PredictiveStudio/components/ps-pipelines.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts +53 -4
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js +335 -326
- package/dist/PredictiveStudio/components/ps-predictions-grid.component.js.map +1 -1
- package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts +19 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.d.ts.map +1 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.js +85 -0
- package/dist/PredictiveStudio/components/ps-row-drivers.component.js.map +1 -0
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts +19 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.d.ts.map +1 -1
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js +51 -2
- package/dist/PredictiveStudio/engine/predictive-studio.engine.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts +3 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.d.ts.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-agent-context.js +3 -0
- package/dist/PredictiveStudio/predictive-studio-agent-context.js.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts +27 -4
- package/dist/PredictiveStudio/predictive-studio-score-history.service.d.ts.map +1 -1
- package/dist/PredictiveStudio/predictive-studio-score-history.service.js +94 -61
- package/dist/PredictiveStudio/predictive-studio-score-history.service.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts +29 -5
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.d.ts.map +1 -1
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js +185 -103
- package/dist/PredictiveStudio/resources/ps-predictions-resource.component.js.map +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js +1 -1
- package/dist/PredictiveStudio/resources/ps-studio-resource.component.js.map +1 -1
- package/dist/ai-dashboards.module.d.ts +22 -21
- package/dist/ai-dashboards.module.d.ts.map +1 -1
- package/dist/ai-dashboards.module.js +8 -2
- package/dist/ai-dashboards.module.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +3 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +71 -71
- package/dist/PredictiveStudio/at-risk.view-models.d.ts +0 -120
- package/dist/PredictiveStudio/at-risk.view-models.d.ts.map +0 -1
- package/dist/PredictiveStudio/at-risk.view-models.js +0 -261
- package/dist/PredictiveStudio/at-risk.view-models.js.map +0 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts +0 -109
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.d.ts.map +0 -1
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js +0 -323
- package/dist/PredictiveStudio/components/ps-confirm-modal.component.js.map +0 -1
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts +0 -137
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.d.ts.map +0 -1
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js +0 -826
- package/dist/PredictiveStudio/components/ps-run-experiment-modal.component.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RowDriver } from '@memberjunction/predictive-studio-core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/** The badge a person sees for a driver. */
|
|
4
|
+
export type DriverBadge = 'Increases Risk' | 'Lowers Risk';
|
|
5
|
+
/**
|
|
6
|
+
* L1 widget: one scored row's signed drivers with their risk badge. Each driver's `Up` is
|
|
7
|
+
* `AtRiskRules.DriverRaisesRisk`, the one rule for whether a driver raises risk; this widget owns only the copy.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PSRowDriversComponent {
|
|
10
|
+
/** The row's drivers, already signed relative to the displayed risk (`AtRiskRules.ParseRowDrivers(raw, invertedRisk)`). */
|
|
11
|
+
Drivers: readonly RowDriver[] | null | undefined;
|
|
12
|
+
/** Badge text for one driver. */
|
|
13
|
+
Badge(d: RowDriver): DriverBadge;
|
|
14
|
+
/** The one place the badge copy is decided. */
|
|
15
|
+
private static driverBadgeText;
|
|
16
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PSRowDriversComponent, never>;
|
|
17
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PSRowDriversComponent, "ps-row-drivers", never, { "Drivers": { "alias": "Drivers"; "required": false; }; }, {}, never, never, true, never>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ps-row-drivers.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ps-row-drivers.component.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-row-drivers.component.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;;AAExE,4CAA4C;AAC5C,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,aAAa,CAAC;AAE3D;;;GAGG;AACH,qBAwBa,qBAAqB;IAChC,2HAA2H;IAClH,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,GAAG,SAAS,CAAM;IAE/D,iCAAiC;IAC1B,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,WAAW;IAIvC,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAC,eAAe;yCAVnB,qBAAqB;2CAArB,qBAAqB;CAajC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
const _forTrack0 = ($index, $item) => $item.Label;
|
|
4
|
+
function PSRowDriversComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
i0.ɵɵdomElementStart(0, "div", 0);
|
|
6
|
+
i0.ɵɵtext(1, "No per-row breakdown was recorded for this row.");
|
|
7
|
+
i0.ɵɵdomElementEnd();
|
|
8
|
+
} }
|
|
9
|
+
function PSRowDriversComponent_Conditional_1_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
10
|
+
i0.ɵɵdomElementStart(0, "div", 2)(1, "div", 3);
|
|
11
|
+
i0.ɵɵdomElement(2, "i", 4);
|
|
12
|
+
i0.ɵɵtext(3);
|
|
13
|
+
i0.ɵɵdomElementEnd();
|
|
14
|
+
i0.ɵɵdomElementStart(4, "span", 5);
|
|
15
|
+
i0.ɵɵtext(5);
|
|
16
|
+
i0.ɵɵdomElementEnd()();
|
|
17
|
+
} if (rf & 2) {
|
|
18
|
+
const d_r1 = ctx.$implicit;
|
|
19
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
20
|
+
i0.ɵɵadvance(2);
|
|
21
|
+
i0.ɵɵstyleProp("color", d_r1.Up ? "var(--mj-status-error)" : "var(--mj-status-success)");
|
|
22
|
+
i0.ɵɵclassProp("fa-arrow-up", d_r1.Up)("fa-arrow-down", !d_r1.Up);
|
|
23
|
+
i0.ɵɵadvance();
|
|
24
|
+
i0.ɵɵtextInterpolate1(" ", d_r1.Label, " ");
|
|
25
|
+
i0.ɵɵadvance();
|
|
26
|
+
i0.ɵɵclassProp("red", d_r1.Up)("green", !d_r1.Up);
|
|
27
|
+
i0.ɵɵadvance();
|
|
28
|
+
i0.ɵɵtextInterpolate(ctx_r1.Badge(d_r1));
|
|
29
|
+
} }
|
|
30
|
+
function PSRowDriversComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
31
|
+
i0.ɵɵdomElementStart(0, "div", 1);
|
|
32
|
+
i0.ɵɵrepeaterCreate(1, PSRowDriversComponent_Conditional_1_For_2_Template, 6, 12, "div", 2, _forTrack0);
|
|
33
|
+
i0.ɵɵdomElementEnd();
|
|
34
|
+
} if (rf & 2) {
|
|
35
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
36
|
+
i0.ɵɵadvance();
|
|
37
|
+
i0.ɵɵrepeater(ctx_r1.Drivers);
|
|
38
|
+
} }
|
|
39
|
+
/**
|
|
40
|
+
* L1 widget: one scored row's signed drivers with their risk badge. Each driver's `Up` is
|
|
41
|
+
* `AtRiskRules.DriverRaisesRisk`, the one rule for whether a driver raises risk; this widget owns only the copy.
|
|
42
|
+
*/
|
|
43
|
+
export class PSRowDriversComponent {
|
|
44
|
+
/** The row's drivers, already signed relative to the displayed risk (`AtRiskRules.ParseRowDrivers(raw, invertedRisk)`). */
|
|
45
|
+
Drivers = [];
|
|
46
|
+
/** Badge text for one driver. */
|
|
47
|
+
Badge(d) {
|
|
48
|
+
return PSRowDriversComponent.driverBadgeText(d.Up);
|
|
49
|
+
}
|
|
50
|
+
/** The one place the badge copy is decided. */
|
|
51
|
+
static driverBadgeText(raisesRisk) {
|
|
52
|
+
return raisesRisk ? 'Increases Risk' : 'Lowers Risk';
|
|
53
|
+
}
|
|
54
|
+
static ɵfac = function PSRowDriversComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || PSRowDriversComponent)(); };
|
|
55
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PSRowDriversComponent, selectors: [["ps-row-drivers"]], inputs: { Drivers: "Drivers" }, decls: 2, vars: 1, consts: [["data-testid", "ps-row-drivers-empty", 1, "ps-small", "ps-muted"], ["data-testid", "ps-row-drivers", 1, "pg-detail-drivers-list"], [1, "pg-detail-driver-item"], ["data-testid", "ps-row-driver-label", 1, "pg-detail-driver-label"], [1, "fa-solid"], ["data-testid", "ps-row-driver-badge", 1, "ps-badge"]], template: function PSRowDriversComponent_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵconditionalCreate(0, PSRowDriversComponent_Conditional_0_Template, 2, 0, "div", 0)(1, PSRowDriversComponent_Conditional_1_Template, 3, 0, "div", 1);
|
|
57
|
+
} if (rf & 2) {
|
|
58
|
+
i0.ɵɵconditional(!ctx.Drivers || ctx.Drivers.length === 0 ? 0 : 1);
|
|
59
|
+
} }, styles: ["\n\n\n\n\n\n\n\n\n\n\n\n\n.ps-panel[_ngcontent-%COMP%] {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n \n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel[_ngcontent-%COMP%] {\n display: block;\n height: 100%;\n}\n\n\n.ps-row[_ngcontent-%COMP%] { display: flex; gap: 16px; }\n.ps-col[_ngcontent-%COMP%] { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap[_ngcontent-%COMP%] { flex-wrap: wrap; }\n.ps-spacer[_ngcontent-%COMP%] { flex: 1; }\n.ps-muted[_ngcontent-%COMP%] { color: var(--mj-text-muted); }\n.ps-small[_ngcontent-%COMP%] { font-size: 12.5px; }\n.ps-mono[_ngcontent-%COMP%] { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title[_ngcontent-%COMP%] {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n\n.ps-card[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-card-head[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body[_ngcontent-%COMP%] { padding: 16px; }\n\n\n.ps-kpi[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 8px; padding: 16px 18px;\n}\n.ps-kpi[_ngcontent-%COMP%] .label[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi[_ngcontent-%COMP%] .val[_ngcontent-%COMP%] { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n\n.ps-badge[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue[_ngcontent-%COMP%] { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green[_ngcontent-%COMP%] { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber[_ngcontent-%COMP%] { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red[_ngcontent-%COMP%] { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot[_ngcontent-%COMP%] { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n\n.ps-lvl[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n.ps-lvl-Strong[_ngcontent-%COMP%] { background: var(--mj-status-info); }\n.ps-lvl-Viable[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n.ps-lvl-Weak[_ngcontent-%COMP%] { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended[_ngcontent-%COMP%] { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n\n.ps-tag[_ngcontent-%COMP%] {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted[_ngcontent-%COMP%] { opacity: .6; }\n.ps-divider[_ngcontent-%COMP%] { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n\n.ps-table[_ngcontent-%COMP%] { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table[_ngcontent-%COMP%] th[_ngcontent-%COMP%] {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table[_ngcontent-%COMP%] td[_ngcontent-%COMP%] { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table[_ngcontent-%COMP%] tr[_ngcontent-%COMP%]:hover td[_ngcontent-%COMP%] { background: var(--mj-bg-surface-hover); }\n.ps-table[_ngcontent-%COMP%] .num[_ngcontent-%COMP%] { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank[_ngcontent-%COMP%] {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold[_ngcontent-%COMP%] { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n\n.ps-bar[_ngcontent-%COMP%] { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n.ps-bar.run[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] { background: var(--mj-brand-primary); }\n\n.ps-fbar[_ngcontent-%COMP%] { display: grid; grid-template-columns: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar[_ngcontent-%COMP%] + .ps-fbar[_ngcontent-%COMP%] { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] > span[_ngcontent-%COMP%] { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar[_ngcontent-%COMP%] .track[_ngcontent-%COMP%] > span.warn[_ngcontent-%COMP%] { background: var(--mj-status-warning); }\n.ps-fbar[_ngcontent-%COMP%] .name[_ngcontent-%COMP%] { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar[_ngcontent-%COMP%] > .ps-mono[_ngcontent-%COMP%] { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n\n.ps-gauge[_ngcontent-%COMP%] {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge[_ngcontent-%COMP%]::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge[_ngcontent-%COMP%] .g-val[_ngcontent-%COMP%] { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n\n.ps-callout[_ngcontent-%COMP%] { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn[_ngcontent-%COMP%] { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info[_ngcontent-%COMP%] { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success[_ngcontent-%COMP%] { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 16px; margin-top: 1px; }\n\n\n.ps-stepper[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done[_ngcontent-%COMP%] { color: var(--mj-status-success-text); }\n.ps-step.done[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr[_ngcontent-%COMP%] { color: var(--mj-brand-primary); }\n.ps-step.curr[_ngcontent-%COMP%] .pip[_ngcontent-%COMP%] { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step[_ngcontent-%COMP%] .ln[_ngcontent-%COMP%] { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n\n.ps-flow[_ngcontent-%COMP%] {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node[_ngcontent-%COMP%] {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 8px;\n cursor: pointer;\n}\n.ps-node[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] .ps-tag[_ngcontent-%COMP%] { margin-left: auto; }\n.ps-node[_ngcontent-%COMP%] .nb[_ngcontent-%COMP%] { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node[_ngcontent-%COMP%] .nb-row[_ngcontent-%COMP%] { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node[_ngcontent-%COMP%] .nb-row[_ngcontent-%COMP%] .k[_ngcontent-%COMP%] { color: var(--mj-text-muted); }\n.ps-node.src[_ngcontent-%COMP%] { border-left-color: var(--ps-node-source); }\n.ps-node.src[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--ps-node-source); }\n.ps-node.feat[_ngcontent-%COMP%] { border-left-color: var(--ps-node-feature); }\n.ps-node.feat[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--ps-node-feature); }\n.ps-node.emb[_ngcontent-%COMP%] { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--ps-node-embedding); }\n.ps-node.target[_ngcontent-%COMP%] { border-left-color: var(--ps-node-target); }\n.ps-node.target[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--ps-node-target); }\n.ps-node.algo[_ngcontent-%COMP%] { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--ps-node-algorithm); }\n.ps-node.output[_ngcontent-%COMP%] { border-left-color: var(--mj-status-success); }\n.ps-node.output[_ngcontent-%COMP%] .nh[_ngcontent-%COMP%] i.tile[_ngcontent-%COMP%] { background: var(--mj-status-success); }\n.ps-node.selected[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node[_ngcontent-%COMP%] .port[_ngcontent-%COMP%] {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node[_ngcontent-%COMP%] .port.in[_ngcontent-%COMP%] { left: -6px; }\n.ps-node[_ngcontent-%COMP%] .port.out[_ngcontent-%COMP%] { right: -6px; }\nsvg.ps-edges[_ngcontent-%COMP%] { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges[_ngcontent-%COMP%] path[_ngcontent-%COMP%] { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n\n.ps-pchip[_ngcontent-%COMP%] {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { background: var(--ps-node-source); }\n.ps-pchip.f[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { background: var(--ps-node-feature); }\n.ps-pchip.e[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { background: var(--ps-node-embedding); }\n.ps-pchip.t[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { background: var(--ps-node-target); }\n.ps-pchip.a[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { background: var(--ps-node-algorithm); }\n\n\n.ps-seg[_ngcontent-%COMP%] { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:last-child { border-right: none; }\n.ps-seg[_ngcontent-%COMP%] button.on[_ngcontent-%COMP%] { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n\n.ps-field[_ngcontent-%COMP%] { margin-bottom: 14px; }\n.ps-field[_ngcontent-%COMP%] > label[_ngcontent-%COMP%] {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input[_ngcontent-%COMP%] {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input[_ngcontent-%COMP%]:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n\n.ps-loading[_ngcontent-%COMP%] { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n\n.ps-empty[_ngcontent-%COMP%] {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty[_ngcontent-%COMP%] .ps-empty-ico[_ngcontent-%COMP%] {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty[_ngcontent-%COMP%] p[_ngcontent-%COMP%] { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n\n.ps-modal-backdrop[_ngcontent-%COMP%] {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal[_ngcontent-%COMP%] {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger[_ngcontent-%COMP%] .ico[_ngcontent-%COMP%] { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body[_ngcontent-%COMP%] { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body[_ngcontent-%COMP%] .ps-field[_ngcontent-%COMP%] { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot[_ngcontent-%COMP%] {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot[_ngcontent-%COMP%] .ps-spacer[_ngcontent-%COMP%] { flex: 1; }", ".pg-detail-drivers-list[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.pg-detail-driver-item[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-sm);\n}\n\n.pg-detail-driver-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}"], changeDetection: 0 });
|
|
60
|
+
}
|
|
61
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PSRowDriversComponent, [{
|
|
62
|
+
type: Component,
|
|
63
|
+
args: [{ standalone: true, selector: 'ps-row-drivers', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
64
|
+
@if (!Drivers || Drivers.length === 0) {
|
|
65
|
+
<div class="ps-small ps-muted" data-testid="ps-row-drivers-empty">No per-row breakdown was recorded for this row.</div>
|
|
66
|
+
} @else {
|
|
67
|
+
<div class="pg-detail-drivers-list" data-testid="ps-row-drivers">
|
|
68
|
+
@for (d of Drivers; track d.Label) {
|
|
69
|
+
<div class="pg-detail-driver-item">
|
|
70
|
+
<div class="pg-detail-driver-label" data-testid="ps-row-driver-label">
|
|
71
|
+
<i class="fa-solid" [class.fa-arrow-up]="d.Up" [class.fa-arrow-down]="!d.Up"
|
|
72
|
+
[style.color]="d.Up ? 'var(--mj-status-error)' : 'var(--mj-status-success)'"></i>
|
|
73
|
+
{{ d.Label }}
|
|
74
|
+
</div>
|
|
75
|
+
<span class="ps-badge" [class.red]="d.Up" [class.green]="!d.Up" data-testid="ps-row-driver-badge">{{ Badge(d) }}</span>
|
|
76
|
+
</div>
|
|
77
|
+
}
|
|
78
|
+
</div>
|
|
79
|
+
}
|
|
80
|
+
`, styles: ["/* ============================================================================\n Predictive Studio \u2014 shared panel styles (design-token compliant)\n Maps the mockup design system onto MemberJunction semantic --mj-* tokens.\n Loaded by every PS panel component (styleUrls) under ViewEncapsulation.None,\n so the class names are global within the PS dashboard subtree.\n No hardcoded colors except the intentional categorical node/algorithm palette\n (declared once as --ps-* custom props below) which must stay distinct across\n light/dark to remain readable as diagram accents.\n ============================================================================ */\n\n/* Categorical accents for DAG node types + algorithm chips. These are\n data-visualization colors that must remain distinct regardless of theme\n (allowed exception #3 in the design-token rules). */\n.ps-panel {\n --ps-node-source: #6b7280;\n --ps-node-feature: #2050c8;\n --ps-node-embedding: #7b3ff0;\n --ps-node-target: #1f9d57;\n --ps-node-algorithm: #d98213;\n /* budget-gauge categorical accents (reuse the node palette so light/dark stay distinct) */\n --ps-gauge-cost: var(--ps-node-algorithm);\n --ps-gauge-iterations: var(--ps-node-feature);\n}\n\n.ps-panel {\n display: block;\n height: 100%;\n}\n\n/* ---- generic layout helpers ---- */\n.ps-row { display: flex; gap: 16px; }\n.ps-col { display: flex; flex-direction: column; gap: 16px; }\n.ps-wrap { flex-wrap: wrap; }\n.ps-spacer { flex: 1; }\n.ps-muted { color: var(--mj-text-muted); }\n.ps-small { font-size: 12.5px; }\n.ps-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12.5px; }\n.ps-section-title {\n font-size: 12px; text-transform: uppercase; letter-spacing: .06em;\n color: var(--mj-text-muted); margin: 4px 0 2px; font-weight: 700;\n}\n\n/* ---- cards ---- */\n.ps-card {\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n.ps-card-head {\n display: flex; align-items: center; gap: 10px;\n padding: 14px 16px; border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-card-head h3 { font-size: 14.5px; margin: 0; font-weight: 650; color: var(--mj-text-primary); }\n.ps-card-body { padding: 16px; }\n\n/* ---- KPI tiles ---- */\n.ps-kpi {\n background: var(--mj-bg-surface); border: 1px solid var(--mj-border-default);\n border-radius: 8px; padding: 16px 18px;\n}\n.ps-kpi .label { font-size: 12px; color: var(--mj-text-muted); font-weight: 600; }\n.ps-kpi .val { font-size: 26px; font-weight: 720; letter-spacing: -.02em; margin-top: 2px; color: var(--mj-text-primary); }\n\n/* ---- badges ---- */\n.ps-badge {\n display: inline-flex; align-items: center; gap: 5px;\n padding: 2px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 650; line-height: 1.7;\n}\n.ps-badge.gray { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.ps-badge.blue { background: var(--mj-status-info-bg); color: var(--mj-status-info-text); }\n.ps-badge.green { background: var(--mj-status-success-bg); color: var(--mj-status-success-text); }\n.ps-badge.amber { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-badge.red { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }\n\n/* recommendation-level chips (the ranking matrix payoff) */\n.ps-lvl {\n display: inline-flex; align-items: center; justify-content: center;\n min-width: 92px; padding: 4px 10px; border-radius: 7px;\n font-weight: 650; font-size: 11.5px; color: var(--mj-text-inverse);\n}\n.ps-lvl-Primary { background: var(--mj-status-success); }\n.ps-lvl-Strong { background: var(--mj-status-info); }\n.ps-lvl-Viable { background: var(--mj-status-warning); }\n.ps-lvl-Weak { background: var(--mj-text-disabled); }\n.ps-lvl-NotRecommended { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n/* ---- tags ---- */\n.ps-tag {\n display: inline-block; padding: 2px 8px; border-radius: 6px;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary);\n font-size: 11.5px; font-weight: 600;\n}\n.ps-tag.muted { opacity: .6; }\n.ps-divider { height: 1px; background: var(--mj-border-subtle); margin: 8px 0; }\n\n/* ---- tables ---- */\n.ps-table { width: 100%; border-collapse: collapse; font-size: 13px; }\n.ps-table th {\n text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; padding: 9px 12px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n.ps-table td { padding: 11px 12px; border-bottom: 1px solid var(--mj-border-subtle); color: var(--mj-text-primary); }\n.ps-table tr:hover td { background: var(--mj-bg-surface-hover); }\n.ps-table .num { text-align: right; font-variant-numeric: tabular-nums; }\n\n.ps-rank {\n width: 22px; height: 22px; border-radius: 6px; background: var(--mj-bg-surface-sunken);\n display: inline-grid; place-items: center; font-weight: 700; font-size: 11.5px; color: var(--mj-text-secondary);\n}\n.ps-rank.gold { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n\n/* ---- progress bars ---- */\n.ps-bar { height: 8px; border-radius: 999px; background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-bar > span { display: block; height: 100%; border-radius: 999px; background: var(--mj-brand-primary); }\n.ps-bar.warn > span { background: var(--mj-status-warning); }\n.ps-bar.run > span { background: var(--mj-brand-primary); }\n\n.ps-fbar { display: grid; grid-template-columns: minmax(150px, 1.3fr) 2fr 56px; align-items: center; gap: 14px; padding: 8px 0; }\n.ps-fbar + .ps-fbar { border-top: 1px solid var(--mj-border-subtle); }\n.ps-fbar .track { height: 10px; border-radius: var(--mj-radius-full); background: var(--mj-bg-surface-sunken); overflow: hidden; }\n.ps-fbar .track > span { display: block; height: 100%; border-radius: var(--mj-radius-full); background: var(--mj-brand-primary); }\n.ps-fbar .track > span.warn { background: var(--mj-status-warning); }\n.ps-fbar .name { color: var(--mj-text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ps-fbar > .ps-mono { text-align: right; color: var(--mj-text-secondary); font-variant-numeric: tabular-nums; }\n\n/* gauge */\n.ps-gauge {\n position: relative; width: 64px; height: 64px; border-radius: 50%; flex: 0 0 auto;\n background: conic-gradient(var(--ps-gauge-color, var(--mj-brand-primary)) calc(var(--ps-p, 40) * 1%), var(--mj-bg-surface-sunken) 0);\n display: grid; place-items: center;\n}\n.ps-gauge::after { content: ''; position: absolute; inset: 9px; background: var(--mj-bg-surface); border-radius: 50%; }\n.ps-gauge .g-val { position: relative; font-weight: 720; font-size: 14px; color: var(--mj-text-primary); }\n\n/* warning / info callouts */\n.ps-callout { display: flex; gap: 11px; padding: 12px 14px; border-radius: 10px; border: 1px solid; }\n.ps-callout.warn { background: var(--mj-status-warning-bg); border-color: var(--mj-status-warning-border); color: var(--mj-status-warning-text); }\n.ps-callout.info { background: var(--mj-status-info-bg); border-color: var(--mj-status-info-border); color: var(--mj-status-info-text); }\n.ps-callout.success { background: var(--mj-status-success-bg); border-color: var(--mj-status-success-border); color: var(--mj-status-success-text); }\n.ps-callout i { font-size: 16px; margin-top: 1px; }\n\n/* lifecycle stepper */\n.ps-stepper { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }\n.ps-step { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--mj-text-muted); }\n.ps-step .pip {\n width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--mj-border-strong);\n display: grid; place-items: center; font-size: 11px;\n}\n.ps-step.done { color: var(--mj-status-success-text); }\n.ps-step.done .pip { background: var(--mj-status-success); border-color: var(--mj-status-success); color: var(--mj-text-inverse); }\n.ps-step.curr { color: var(--mj-brand-primary); }\n.ps-step.curr .pip { border-color: var(--mj-brand-primary); color: var(--mj-brand-primary); }\n.ps-step .ln { width: 26px; height: 2px; background: var(--mj-border-strong); }\n\n/* ---- DAG flow canvas ---- */\n.ps-flow {\n position: relative;\n background:\n linear-gradient(var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n linear-gradient(90deg, var(--mj-border-subtle) 1px, transparent 1px) 0 0 / 22px 22px,\n var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default); border-radius: 10px;\n min-height: 620px; overflow: hidden;\n}\n.ps-node {\n position: absolute; width: 190px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-strong); border-left-width: 3px; border-radius: 8px;\n cursor: pointer;\n}\n.ps-node .nh {\n display: flex; align-items: center; gap: 8px; padding: 9px 11px;\n border-bottom: 1px solid var(--mj-border-subtle); font-weight: 650; font-size: 12.5px; color: var(--mj-text-primary);\n}\n.ps-node .nh i.tile {\n width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center;\n color: var(--mj-text-inverse); font-size: 12px; flex: 0 0 auto;\n}\n.ps-node .nh .ps-tag { margin-left: auto; }\n.ps-node .nb { padding: 9px 11px; font-size: 12px; color: var(--mj-text-secondary); }\n.ps-node .nb-row { display: flex; justify-content: space-between; gap: 8px; padding: 2px 0; }\n.ps-node .nb-row .k { color: var(--mj-text-muted); }\n.ps-node.src { border-left-color: var(--ps-node-source); }\n.ps-node.src .nh i.tile { background: var(--ps-node-source); }\n.ps-node.feat { border-left-color: var(--ps-node-feature); }\n.ps-node.feat .nh i.tile { background: var(--ps-node-feature); }\n.ps-node.emb { border-left-color: var(--ps-node-embedding); }\n.ps-node.emb .nh i.tile { background: var(--ps-node-embedding); }\n.ps-node.target { border-left-color: var(--ps-node-target); }\n.ps-node.target .nh i.tile { background: var(--ps-node-target); }\n.ps-node.algo { border-left-color: var(--ps-node-algorithm); }\n.ps-node.algo .nh i.tile { background: var(--ps-node-algorithm); }\n.ps-node.output { border-left-color: var(--mj-status-success); }\n.ps-node.output .nh i.tile { background: var(--mj-status-success); }\n.ps-node.selected {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n}\n.ps-node .port {\n position: absolute; width: 11px; height: 11px; border-radius: 50%;\n background: var(--mj-bg-surface); border: 2px solid var(--mj-brand-primary);\n top: 50%; transform: translateY(-50%);\n}\n.ps-node .port.in { left: -6px; }\n.ps-node .port.out { right: -6px; }\nsvg.ps-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }\nsvg.ps-edges path { stroke: color-mix(in srgb, var(--mj-brand-primary) 45%, transparent); stroke-width: 2; fill: none; }\n\n/* palette chips */\n.ps-pchip {\n display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border-radius: 8px;\n border: 1px dashed var(--mj-border-strong); background: var(--mj-bg-surface);\n font-size: 12.5px; font-weight: 600; color: var(--mj-text-secondary); cursor: grab;\n}\n.ps-pchip i { font-size: 12px; color: var(--mj-text-inverse); width: 20px; height: 20px; border-radius: 5px; display: grid; place-items: center; }\n.ps-pchip.s i { background: var(--ps-node-source); }\n.ps-pchip.f i { background: var(--ps-node-feature); }\n.ps-pchip.e i { background: var(--ps-node-embedding); }\n.ps-pchip.t i { background: var(--ps-node-target); }\n.ps-pchip.a i { background: var(--ps-node-algorithm); }\n\n/* segmented control */\n.ps-seg { display: inline-flex; border: 1px solid var(--mj-border-default); border-radius: 8px; overflow: hidden; }\n.ps-seg button {\n border: none; background: var(--mj-bg-surface); color: var(--mj-text-secondary);\n padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;\n border-right: 1px solid var(--mj-border-default);\n}\n.ps-seg button:last-child { border-right: none; }\n.ps-seg button.on { background: var(--mj-brand-primary); color: var(--mj-text-inverse); }\n\n/* field control */\n.ps-field { margin-bottom: 14px; }\n.ps-field > label {\n display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;\n color: var(--mj-text-muted); font-weight: 700; margin-bottom: 6px;\n}\n.ps-input {\n width: 100%; padding: 8px 10px; border: 1px solid var(--mj-border-default);\n border-radius: 6px; font-size: 13px; background: var(--mj-bg-surface); color: var(--mj-text-primary);\n box-sizing: border-box;\n}\n.ps-input:focus { outline: none; border-color: var(--mj-brand-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 12%, transparent); }\n\n/* loading container */\n.ps-loading { display: flex; align-items: center; justify-content: center; padding: 60px 0; }\n\n/* ---- empty / prompt states ---- */\n.ps-empty {\n display: flex; flex-direction: column; align-items: center; justify-content: center;\n text-align: center; gap: 10px; padding: 56px 24px; color: var(--mj-text-muted);\n}\n.ps-empty .ps-empty-ico {\n width: 60px; height: 60px; border-radius: 16px; display: grid; place-items: center;\n background: var(--mj-bg-surface-sunken); color: var(--mj-text-disabled); font-size: 24px;\n}\n.ps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 650; color: var(--mj-text-secondary); }\n.ps-empty p { margin: 0; max-width: 420px; font-size: 13px; line-height: 1.5; }\n\n/* ---- confirm modal ---- */\n.ps-modal-backdrop {\n position: fixed; inset: 0; z-index: 1000;\n background: var(--mj-bg-overlay);\n display: flex; align-items: center; justify-content: center; padding: 24px;\n}\n.ps-modal {\n width: 100%; max-width: 480px; background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default); border-radius: 14px;\n box-shadow: var(--mj-shadow-lg, var(--mj-shadow-sm)); overflow: hidden;\n}\n.ps-modal-head {\n display: flex; align-items: center; gap: 12px; padding: 18px 20px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n.ps-modal-head .ico {\n width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center;\n font-size: 16px; flex: 0 0 auto;\n background: var(--mj-status-info-bg); color: var(--mj-status-info-text);\n}\n.ps-modal-head.warn .ico { background: var(--mj-status-warning-bg); color: var(--mj-status-warning-text); }\n.ps-modal-head.danger .ico { background: var(--mj-status-error-bg); color: var(--mj-status-error-text); }\n.ps-modal-head h3 { margin: 0; font-size: 15.5px; font-weight: 650; color: var(--mj-text-primary); }\n.ps-modal-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.55; color: var(--mj-text-secondary); }\n.ps-modal-body .ps-field { margin-top: 14px; margin-bottom: 0; }\n.ps-modal-foot {\n display: flex; align-items: center; gap: 10px; padding: 14px 20px;\n border-top: 1px solid var(--mj-border-subtle); background: var(--mj-bg-surface-card);\n}\n.ps-modal-foot .ps-spacer { flex: 1; }\n", ".pg-detail-drivers-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.pg-detail-driver-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-subtle);\n border-radius: var(--mj-radius-sm);\n}\n\n.pg-detail-driver-label {\n font-size: var(--mj-text-xs);\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 6px;\n}\n"] }]
|
|
81
|
+
}], null, { Drivers: [{
|
|
82
|
+
type: Input
|
|
83
|
+
}] }); })();
|
|
84
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(PSRowDriversComponent, { className: "PSRowDriversComponent", filePath: "src/PredictiveStudio/components/ps-row-drivers.component.ts", lineNumber: 35 }); })();
|
|
85
|
+
//# sourceMappingURL=ps-row-drivers.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ps-row-drivers.component.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/components/ps-row-drivers.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;;;IAiBpE,iCAAkE;IAAA,+DAA+C;IAAA,oBAAM;;;IAKjH,AADF,iCAAmC,aACqC;IACpE,0BACoF;IACpF,YACF;IAAA,oBAAM;IACN,kCAAkG;IAAA,YAAc;IAClH,AADkH,oBAAO,EACnH;;;;IAJC,eAA4E;IAA5E,wFAA4E;IADhC,AAA3B,sCAA0B,2BAA8B;IAE5E,cACF;IADE,2CACF;IACuB,cAAkB;IAAC,AAAnB,8BAAkB,mBAAsB;IAAmC,cAAc;IAAd,wCAAc;;;IARtH,iCAAiE;IAC/D,uGASC;IACH,oBAAM;;;IAVJ,cASC;IATD,6BASC;;AAvBT;;;GAGG;AAyBH,MAAM,OAAO,qBAAqB;IAChC,2HAA2H;IAClH,OAAO,GAA4C,EAAE,CAAC;IAE/D,iCAAiC;IAC1B,KAAK,CAAC,CAAY;QACvB,OAAO,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,+CAA+C;IACvC,MAAM,CAAC,eAAe,CAAC,UAAmB;QAChD,OAAO,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC;IACvD,CAAC;+GAZU,qBAAqB;6DAArB,qBAAqB;YAhB5B,AAFF,uFAAwC,iEAE/B;;YAFT,kEAeC;;;iFAGQ,qBAAqB;cAxBjC,SAAS;6BACI,IAAI,YACN,gBAAgB,mBACT,uBAAuB,CAAC,MAAM,YAErC;;;;;;;;;;;;;;;;;GAiBT;;kBAIA,KAAK;;kFAFK,qBAAqB","sourcesContent":["import { ChangeDetectionStrategy, Component, Input } from '@angular/core';\nimport type { RowDriver } from '@memberjunction/predictive-studio-core';\n\n/** The badge a person sees for a driver. */\nexport type DriverBadge = 'Increases Risk' | 'Lowers Risk';\n\n/**\n * L1 widget: one scored row's signed drivers with their risk badge. Each driver's `Up` is\n * `AtRiskRules.DriverRaisesRisk`, the one rule for whether a driver raises risk; this widget owns only the copy.\n */\n@Component({\n standalone: true,\n selector: 'ps-row-drivers',\n changeDetection: ChangeDetectionStrategy.OnPush,\n styleUrls: ['../predictive-studio.shared.css', './ps-row-drivers.component.css'],\n template: `\n @if (!Drivers || Drivers.length === 0) {\n <div class=\"ps-small ps-muted\" data-testid=\"ps-row-drivers-empty\">No per-row breakdown was recorded for this row.</div>\n } @else {\n <div class=\"pg-detail-drivers-list\" data-testid=\"ps-row-drivers\">\n @for (d of Drivers; track d.Label) {\n <div class=\"pg-detail-driver-item\">\n <div class=\"pg-detail-driver-label\" data-testid=\"ps-row-driver-label\">\n <i class=\"fa-solid\" [class.fa-arrow-up]=\"d.Up\" [class.fa-arrow-down]=\"!d.Up\"\n [style.color]=\"d.Up ? 'var(--mj-status-error)' : 'var(--mj-status-success)'\"></i>\n {{ d.Label }}\n </div>\n <span class=\"ps-badge\" [class.red]=\"d.Up\" [class.green]=\"!d.Up\" data-testid=\"ps-row-driver-badge\">{{ Badge(d) }}</span>\n </div>\n }\n </div>\n }\n `,\n})\nexport class PSRowDriversComponent {\n /** The row's drivers, already signed relative to the displayed risk (`AtRiskRules.ParseRowDrivers(raw, invertedRisk)`). */\n @Input() Drivers: readonly RowDriver[] | null | undefined = [];\n\n /** Badge text for one driver. */\n public Badge(d: RowDriver): DriverBadge {\n return PSRowDriversComponent.driverBadgeText(d.Up);\n }\n\n /** The one place the badge copy is decided. */\n private static driverBadgeText(raisesRisk: boolean): DriverBadge {\n return raisesRisk ? 'Increases Risk' : 'Lowers Risk';\n }\n}\n"]}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { BaseEngine, IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
2
|
-
import { MJMLAlgorithmEntity, MJMLAlgorithmUseCaseEntity, MJMLAlgorithmUseCaseRankingEntity, MJMLModelEntity, MJMLModelScoringBindingEntity, MJMLTrainingPipelineEntity, MJMLTrainingRunEntity, MJExperimentEntity, MJExperimentSessionEntity, MJExperimentSessionIterationEntity, MJRecordProcessEntity } from '@memberjunction/core-entities';
|
|
2
|
+
import { MJMLAlgorithmEntity, MJMLAlgorithmUseCaseEntity, MJMLAlgorithmUseCaseRankingEntity, MJMLModelEntity, MJMLModelScoringBindingEntity, MJMLTrainingPipelineEntity, MJMLTrainingRunEntity, MJExperimentEntity, MJExperimentSessionEntity, MJExperimentSessionIterationEntity, MJProcessRunDetailEntity, MJRecordProcessEntity } from '@memberjunction/core-entities';
|
|
3
3
|
import { PSIterationRow, PSProcessRunRow } from '../predictive-studio.view-models';
|
|
4
|
+
/** The columns of a scored Process Run Detail the Predictive Studio surfaces read; `ID` is the keyset paging cursor. */
|
|
5
|
+
export type PSRunDetailRow = Pick<MJProcessRunDetailEntity, 'ID' | 'RecordID' | 'ResultPayload' | 'Status' | 'CompletedAt' | '__mj_CreatedAt'>;
|
|
6
|
+
/** A run's details as read by {@link PredictiveStudioEngine.LoadRunDetails}; `Capped` is true when the run has more. */
|
|
7
|
+
export interface PSRunDetails {
|
|
8
|
+
Rows: PSRunDetailRow[];
|
|
9
|
+
Capped: boolean;
|
|
10
|
+
}
|
|
4
11
|
/**
|
|
5
12
|
* Recommendation levels used by the Algorithm Use Case Rankings matrix, ordered weakest → strongest.
|
|
6
13
|
* Used to rank algorithms within a chosen scenario in the catalog "Guide me" picker.
|
|
@@ -138,6 +145,17 @@ export declare class PredictiveStudioEngine extends BaseEngine<PredictiveStudioE
|
|
|
138
145
|
sinceDays?: number;
|
|
139
146
|
maxRows?: number;
|
|
140
147
|
}): Promise<PSProcessRunRow[]>;
|
|
148
|
+
/** The most run details one read returns; a larger run is read up to this many and reported {@link PSRunDetails.Capped}. */
|
|
149
|
+
static readonly MaxRunDetailRows = 50000;
|
|
150
|
+
/** {@link MaxRunDetailRows} formatted for the notices that tell a user a run was capped ("50,000"). */
|
|
151
|
+
static readonly MaxRunDetailRowsLabel: string;
|
|
152
|
+
private static readonly runDetailPageSize;
|
|
153
|
+
/**
|
|
154
|
+
* Reads a run's process run details one keyset page at a time (read-only, only the columns the surfaces use), up to
|
|
155
|
+
* {@link PredictiveStudioEngine.MaxRunDetailRows}. Throws, with the provider's error message, when a page fails to load,
|
|
156
|
+
* so the caller shows the failure instead of an empty run.
|
|
157
|
+
*/
|
|
158
|
+
LoadRunDetails(runId: string, provider: IMetadataProvider, user: UserInfo | undefined): Promise<PSRunDetails>;
|
|
141
159
|
/** Shared run-loader: recent `MJ: Process Runs` for a set of Record-Process ids (capped, newest-first). */
|
|
142
160
|
private loadRunsForProcessIds;
|
|
143
161
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predictive-studio.engine.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/engine/predictive-studio.engine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,
|
|
1
|
+
{"version":3,"file":"predictive-studio.engine.d.ts","sourceRoot":"","sources":["../../../src/PredictiveStudio/engine/predictive-studio.engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BaseEngine, Metadata, RunView, } from '@memberjunction/core';
|
|
2
|
-
import { UUIDsEqual } from '@memberjunction/global';
|
|
1
|
+
import { BaseEngine, CompositeKey, Metadata, RunView, } from '@memberjunction/core';
|
|
2
|
+
import { EscapeSQLString, UUIDsEqual } from '@memberjunction/global';
|
|
3
3
|
/** Numeric rank for each {@link RecommendationLevel} (higher = better fit). */
|
|
4
4
|
export const RECOMMENDATION_RANK = {
|
|
5
5
|
NotRecommended: 0,
|
|
@@ -246,6 +246,55 @@ export class PredictiveStudioEngine extends BaseEngine {
|
|
|
246
246
|
async LoadRecentRunsForModel(modelId, provider, user, options) {
|
|
247
247
|
return this.loadRunsForProcessIds(this.RecordProcessIDsForModel(modelId), provider, user, options);
|
|
248
248
|
}
|
|
249
|
+
/** The most run details one read returns; a larger run is read up to this many and reported {@link PSRunDetails.Capped}. */
|
|
250
|
+
static MaxRunDetailRows = 50_000;
|
|
251
|
+
/** {@link MaxRunDetailRows} formatted for the notices that tell a user a run was capped ("50,000"). */
|
|
252
|
+
static MaxRunDetailRowsLabel = PredictiveStudioEngine.MaxRunDetailRows.toLocaleString('en-US');
|
|
253
|
+
static runDetailPageSize = 1000;
|
|
254
|
+
/**
|
|
255
|
+
* Reads a run's process run details one keyset page at a time (read-only, only the columns the surfaces use), up to
|
|
256
|
+
* {@link PredictiveStudioEngine.MaxRunDetailRows}. Throws, with the provider's error message, when a page fails to load,
|
|
257
|
+
* so the caller shows the failure instead of an empty run.
|
|
258
|
+
*/
|
|
259
|
+
async LoadRunDetails(runId, provider, user) {
|
|
260
|
+
const entityInfo = provider.EntityByName('MJ: Process Run Details');
|
|
261
|
+
if (!entityInfo) {
|
|
262
|
+
throw new Error("The 'MJ: Process Run Details' entity is not in this provider's metadata.");
|
|
263
|
+
}
|
|
264
|
+
const rv = RunView.FromMetadataProvider(provider);
|
|
265
|
+
const rows = [];
|
|
266
|
+
let lastKey;
|
|
267
|
+
while (true) {
|
|
268
|
+
const page = await rv.RunView({
|
|
269
|
+
EntityName: 'MJ: Process Run Details',
|
|
270
|
+
ExtraFilter: `ProcessRunID = '${EscapeSQLString(runId)}'`,
|
|
271
|
+
Fields: ['ID', 'RecordID', 'ResultPayload', 'Status', 'CompletedAt', '__mj_CreatedAt'],
|
|
272
|
+
MaxRows: PredictiveStudioEngine.runDetailPageSize,
|
|
273
|
+
AfterKey: lastKey,
|
|
274
|
+
ResultType: 'simple',
|
|
275
|
+
}, user);
|
|
276
|
+
if (!page.Success || !page.Results) {
|
|
277
|
+
throw new Error(`Could not read the predictions of run ${runId}: ${page.ErrorMessage || 'the request failed'}`);
|
|
278
|
+
}
|
|
279
|
+
rows.push(...page.Results);
|
|
280
|
+
if (page.Results.length < PredictiveStudioEngine.runDetailPageSize) {
|
|
281
|
+
return { Rows: rows, Capped: false };
|
|
282
|
+
}
|
|
283
|
+
if (rows.length >= PredictiveStudioEngine.MaxRunDetailRows) {
|
|
284
|
+
// Capped only when the run really has more: a run of exactly the cap is complete.
|
|
285
|
+
const probe = await rv.RunView({
|
|
286
|
+
EntityName: 'MJ: Process Run Details',
|
|
287
|
+
ExtraFilter: `ProcessRunID = '${EscapeSQLString(runId)}'`,
|
|
288
|
+
Fields: ['ID'],
|
|
289
|
+
MaxRows: 1,
|
|
290
|
+
AfterKey: CompositeKey.FromEntityRecord(entityInfo, page.Results[page.Results.length - 1]),
|
|
291
|
+
ResultType: 'simple',
|
|
292
|
+
}, user);
|
|
293
|
+
return { Rows: rows, Capped: probe.Success && probe.Results.length > 0 };
|
|
294
|
+
}
|
|
295
|
+
lastKey = CompositeKey.FromEntityRecord(entityInfo, page.Results[page.Results.length - 1]);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
249
298
|
/** Shared run-loader: recent `MJ: Process Runs` for a set of Record-Process ids (capped, newest-first). */
|
|
250
299
|
async loadRunsForProcessIds(processIds, provider, user, options) {
|
|
251
300
|
if (processIds.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predictive-studio.engine.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/engine/predictive-studio.engine.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BaseEngine,\n BaseEnginePropertyConfig,\n IMetadataProvider,\n Metadata,\n RunView,\n UserInfo,\n} from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport {\n MJMLAlgorithmEntity,\n MJMLAlgorithmUseCaseEntity,\n MJMLAlgorithmUseCaseRankingEntity,\n MJMLModelEntity,\n MJMLModelScoringBindingEntity,\n MJMLTrainingPipelineEntity,\n MJMLTrainingRunEntity,\n MJExperimentEntity,\n MJExperimentSessionEntity,\n MJExperimentSessionIterationEntity,\n MJProcessRunEntity,\n MJRecordProcessEntity,\n} from '@memberjunction/core-entities';\nimport { PSIterationRow, PSProcessRunRow } from '../predictive-studio.view-models';\n\n/**\n * Recommendation levels used by the Algorithm Use Case Rankings matrix, ordered weakest → strongest.\n * Used to rank algorithms within a chosen scenario in the catalog \"Guide me\" picker.\n */\nexport type RecommendationLevel = 'NotRecommended' | 'Weak' | 'Viable' | 'Strong' | 'Primary';\n\n/** Numeric rank for each {@link RecommendationLevel} (higher = better fit). */\nexport const RECOMMENDATION_RANK: Record<RecommendationLevel, number> = {\n NotRecommended: 0,\n Weak: 1,\n Viable: 2,\n Strong: 3,\n Primary: 4,\n};\n\n/** Minimal shape of a ranking row consumed by {@link computeBestLevels} (decoupled from the entity). */\nexport interface RankingRow {\n MLAlgorithmID: string;\n MLAlgorithmUseCaseID: string;\n RecommendationLevel: RecommendationLevel;\n}\n\n/**\n * Pure ranking-matrix reducer: given ranking rows and a set of selected use-case IDs, returns each\n * algorithm's BEST recommendation level (max by rank) across those scenarios. Extracted from the\n * engine so it is unit-testable without a metadata provider / DB.\n */\nexport function ComputeBestLevels(rankings: RankingRow[], useCaseIds: string[]): Map<string, RecommendationLevel> {\n const out = new Map<string, RecommendationLevel>();\n if (useCaseIds.length === 0) return out;\n for (const ranking of rankings) {\n if (!useCaseIds.some((id) => UUIDsEqual(id, ranking.MLAlgorithmUseCaseID))) continue;\n const current = out.get(ranking.MLAlgorithmID);\n if (!current || RECOMMENDATION_RANK[ranking.RecommendationLevel] > RECOMMENDATION_RANK[current]) {\n out.set(ranking.MLAlgorithmID, ranking.RecommendationLevel);\n }\n }\n return out;\n}\n\n/** @deprecated Use {@link ComputeBestLevels}. */\nexport function computeBestLevels(rankings: RankingRow[], useCaseIds: string[]): Map<string, RecommendationLevel> {\n return ComputeBestLevels(rankings, useCaseIds);\n}\n\n/**\n * PredictiveStudioEngine — the single, process-wide cache + domain-logic layer for the Predictive\n * Studio dashboard. Follows the canonical MJ BaseEngine pattern (Config() declaring\n * BaseEnginePropertyConfig[], lazy-loaded, ObserveProperty reactivity for free).\n *\n * It caches the SMALL Predictive Studio reference entities (algorithms, use cases, the rankings\n * matrix, models, pipelines, training runs, experiments + sessions + iterations) via RunView so\n * the panels bind to in-memory arrays and stay reactive to saves/deletes. Large columns\n * (serialized model artifacts, feature schemas) live on the entities themselves but these tables\n * are small enough to fully cache.\n */\nexport class PredictiveStudioEngine extends BaseEngine<PredictiveStudioEngine> {\n /** Singleton accessor — never `new` this class directly. */\n public static get Instance(): PredictiveStudioEngine {\n return super.getInstance<PredictiveStudioEngine>();\n }\n\n private _algorithms: MJMLAlgorithmEntity[] = [];\n private _useCases: MJMLAlgorithmUseCaseEntity[] = [];\n private _rankings: MJMLAlgorithmUseCaseRankingEntity[] = [];\n private _models: MJMLModelEntity[] = [];\n private _scoringBindings: MJMLModelScoringBindingEntity[] = [];\n private _recordProcesses: MJRecordProcessEntity[] = [];\n private _pipelines: MJMLTrainingPipelineEntity[] = [];\n private _trainingRuns: MJMLTrainingRunEntity[] = [];\n private _experiments: MJExperimentEntity[] = [];\n private _sessions: MJExperimentSessionEntity[] = [];\n private _iterations: MJExperimentSessionIterationEntity[] = [];\n\n public async Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void> {\n const c: Partial<BaseEnginePropertyConfig>[] = [\n { Type: 'entity', EntityName: 'MJ: ML Algorithms', PropertyName: '_algorithms', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Algorithm Use Cases', PropertyName: '_useCases', OrderBy: 'DisplayOrder' },\n { Type: 'entity', EntityName: 'MJ: ML Algorithm Use Case Rankings', PropertyName: '_rankings' },\n { Type: 'entity', EntityName: 'MJ: ML Models', PropertyName: '_models', OrderBy: '__mj_UpdatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: ML Model Scoring Bindings', PropertyName: '_scoringBindings', OrderBy: '__mj_UpdatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Record Processes', PropertyName: '_recordProcesses', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Training Pipelines', PropertyName: '_pipelines', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Training Runs', PropertyName: '_trainingRuns', OrderBy: '__mj_CreatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Experiments', PropertyName: '_experiments', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: Experiment Sessions', PropertyName: '_sessions', OrderBy: '__mj_CreatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Experiment Session Iterations', PropertyName: '_iterations', OrderBy: 'Sequence' },\n ];\n await super.Load(c, provider ?? Metadata.Provider, forceRefresh, contextUser);\n }\n\n // ---- Cached arrays (sync getters; observe via ObserveProperty for reactive UI) ----\n\n public get Algorithms(): MJMLAlgorithmEntity[] {\n return this._algorithms ?? [];\n }\n public get UseCases(): MJMLAlgorithmUseCaseEntity[] {\n return this._useCases ?? [];\n }\n public get Rankings(): MJMLAlgorithmUseCaseRankingEntity[] {\n return this._rankings ?? [];\n }\n public get Models(): MJMLModelEntity[] {\n return this._models ?? [];\n }\n /** Scoring bindings — a model → (target entity + column, optional Record Process) deployment link. */\n public get ScoringBindings(): MJMLModelScoringBindingEntity[] {\n return this._scoringBindings ?? [];\n }\n /** Record Processes — used to resolve the schedule (cron) + status of a binding's bound process. */\n public get RecordProcesses(): MJRecordProcessEntity[] {\n return this._recordProcesses ?? [];\n }\n public get Pipelines(): MJMLTrainingPipelineEntity[] {\n return this._pipelines ?? [];\n }\n public get TrainingRuns(): MJMLTrainingRunEntity[] {\n return this._trainingRuns ?? [];\n }\n public get Experiments(): MJExperimentEntity[] {\n return this._experiments ?? [];\n }\n public get Sessions(): MJExperimentSessionEntity[] {\n return this._sessions ?? [];\n }\n public get Iterations(): MJExperimentSessionIterationEntity[] {\n return this._iterations ?? [];\n }\n\n // ---- Domain helpers ----\n\n /** Look up an ML Model by ID (for joining a scoring binding to its model). */\n public ModelByID(modelId: string | null | undefined): MJMLModelEntity | undefined {\n if (!modelId) return undefined;\n return this.Models.find((m) => UUIDsEqual(m.ID, modelId));\n }\n\n /** Look up a Record Process by ID (for resolving a binding's schedule/status). */\n public RecordProcessByID(processId: string | null | undefined): MJRecordProcessEntity | undefined {\n if (!processId) return undefined;\n return this.RecordProcesses.find((p) => UUIDsEqual(p.ID, processId));\n }\n\n /** Look up an algorithm name by ID (for joining iterations/runs/models to a display name). */\n public AlgorithmName(algorithmId: string | null | undefined): string {\n if (!algorithmId) return 'Unknown';\n return this.Algorithms.find((a) => UUIDsEqual(a.ID, algorithmId))?.Name ?? 'Unknown';\n }\n\n /** All ranking rows for a given use case, joined to their algorithm and ranked best-first. */\n public RankingsForUseCase(useCaseId: string): MJMLAlgorithmUseCaseRankingEntity[] {\n return this.Rankings.filter((r) => UUIDsEqual(r.MLAlgorithmUseCaseID, useCaseId)).sort(\n (a, b) => RECOMMENDATION_RANK[b.RecommendationLevel] - RECOMMENDATION_RANK[a.RecommendationLevel],\n );\n }\n\n /**\n * Given a set of selected use-case IDs, compute each algorithm's BEST recommendation level\n * across those scenarios (max by rank) — the core of the catalog \"Guide me\" picker.\n * Returns a map of algorithmId → best level, omitting algorithms with no ranking row.\n */\n public BestLevelsForScenarios(useCaseIds: string[]): Map<string, RecommendationLevel> {\n return ComputeBestLevels(this.Rankings, useCaseIds);\n }\n\n /** Iterations belonging to a session, in sequence order. */\n public IterationsForSession(sessionId: string): MJExperimentSessionIterationEntity[] {\n return this.Iterations.filter((i) => UUIDsEqual(i.ExperimentSessionID, sessionId)).sort(\n (a, b) => a.Sequence - b.Sequence,\n );\n }\n\n /** Published models only — the production-quality set used for headline KPIs. */\n public get PublishedModels(): MJMLModelEntity[] {\n return this.Models.filter((m) => m.Status === 'Published');\n }\n\n /** Sessions whose status is `Running` — the active experiment count. */\n public get RunningSessions(): MJExperimentSessionEntity[] {\n return this.Sessions.filter((s) => s.Status === 'Running');\n }\n\n /**\n * Resolve a model's human-readable display name generically: the producing pipeline's name when\n * available (the most meaningful label — what the model predicts), else the model's denormalized\n * `Pipeline` view field, else a version-stamped fallback. Entity-agnostic — never hardcodes any\n * business entity.\n */\n public ModelDisplayName(model: MJMLModelEntity): string {\n const pipeline = this.Pipelines.find((p) => UUIDsEqual(p.ID, model.PipelineID));\n return pipeline?.Name ?? model.Pipeline ?? `Model v${model.Version}`;\n }\n\n /**\n * Map the engine's cached iterations for a session into the pure {@link PSIterationRow} shape the\n * view-model derivations consume — joining each iteration to its algorithm name via the resulting\n * training run (iteration → run → algorithm), since iterations don't carry the algorithm directly.\n */\n public IterationRowsForSession(sessionId: string): PSIterationRow[] {\n return this.IterationsForSession(sessionId).map((it) => ({\n ID: it.ID,\n ExperimentSessionID: it.ExperimentSessionID,\n Sequence: it.Sequence,\n Label: it.Label,\n Status: it.Status,\n Score: it.Score,\n ComputeCost: it.ComputeCost,\n TokensUsed: it.TokensUsed,\n Rationale: it.Rationale,\n AlgorithmName: this.AlgorithmForIteration(it.ID),\n }));\n }\n\n /** Resolve an iteration's algorithm display name via its training run (or 'Unknown'). */\n public AlgorithmForIteration(iterationId: string): string {\n const run = this.TrainingRuns.find((r) => UUIDsEqual(r.ExperimentSessionIterationID, iterationId));\n return run ? this.AlgorithmName(run.AlgorithmID) : 'Unknown';\n }\n\n /**\n * The `MJ: Record Processes` IDs that ML scoring write-backs run through — every scoring binding's\n * bound Record Process. Used to scope the Home activity feed to ML-scoring runs without depending\n * on a typed `WorkType='ML Model'` enum value (which is registered at runtime, not in the type).\n */\n public get ScoringRecordProcessIDs(): string[] {\n const ids = this.ScoringBindings.map((b) => b.RecordProcessID).filter((id): id is string => !!id);\n return [...new Set(ids)];\n }\n\n /**\n * Load recent ML-scoring process runs on demand (NOT bulk-cached — `MJ: Process Runs` grows\n * unbounded). Scopes to runs whose `RecordProcessID` is one of the ML scoring bindings'\n * processes, optionally to the last `sinceDays`, capped at `maxRows`, newest first. Returns the\n * pure {@link PSProcessRunRow} shape for the Home derivations. Returns `[]` (never throws) on any\n * failure or when there are no scoring bindings to scope to.\n *\n * @param provider The provider to run against (multi-provider correctness).\n * @param user The acting user (server-side audit/security).\n * @param options.sinceDays Only runs started within this many days (default 7).\n * @param options.maxRows Row cap (default 50).\n */\n public async LoadRecentScoringRuns(\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n return this.loadRunsForProcessIds(this.ScoringRecordProcessIDs, provider, user, options);\n }\n\n /**\n * Record Processes (`WorkType='ML Model'`) configured to score with `modelId` — the cached link from a\n * model to the processes that run it, idle/scheduled/bound alike (no DB hit). The `modelId` is read from\n * each Record Process's stored `Configuration` JSON.\n */\n public RecordProcessesForModel(modelId: string): MJRecordProcessEntity[] {\n return this.RecordProcesses.filter((rp) => {\n const id = this.recordProcessModelId(rp);\n return id != null && UUIDsEqual(id, modelId);\n });\n }\n\n /** The cached Record-Process ids scoring with `modelId`. */\n public RecordProcessIDsForModel(modelId: string): string[] {\n return this.RecordProcessesForModel(modelId).map((rp) => rp.ID);\n }\n\n /** Parse a Record Process's stored `modelId` (the `WorkType='ML Model'` config), or null. */\n private recordProcessModelId(rp: MJRecordProcessEntity): string | null {\n try {\n const cfg: unknown = JSON.parse(rp.Configuration ?? '{}');\n const id = (cfg as { modelId?: unknown })?.modelId;\n return typeof id === 'string' ? id : null;\n } catch {\n return null;\n }\n }\n\n /**\n * Load recent process runs for ONE model's Record Processes — same DB-light, on-demand contract as\n * {@link LoadRecentScoringRuns}, scoped to a single model. Powers the \"Models in Production\" per-model\n * run history (a model needs no scoring binding to have runs — any `WorkType='ML Model'` Record Process\n * run persists here).\n */\n public async LoadRecentRunsForModel(\n modelId: string,\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n return this.loadRunsForProcessIds(this.RecordProcessIDsForModel(modelId), provider, user, options);\n }\n\n /** Shared run-loader: recent `MJ: Process Runs` for a set of Record-Process ids (capped, newest-first). */\n private async loadRunsForProcessIds(\n processIds: string[],\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n if (processIds.length === 0) return [];\n const sinceDays = options?.sinceDays ?? 7;\n const maxRows = options?.maxRows ?? 50;\n const sinceIso = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString();\n const idList = processIds.map((id) => `'${id}'`).join(',');\n\n const rv = RunView.FromMetadataProvider(provider);\n const result = await rv.RunView<MJProcessRunEntity>(\n {\n EntityName: 'MJ: Process Runs',\n ExtraFilter: `RecordProcessID IN (${idList}) AND __mj_CreatedAt >= '${sinceIso}'`,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: maxRows,\n ResultType: 'entity_object',\n },\n user,\n );\n if (!result.Success) return [];\n return (result.Results ?? []).map((r) => ({\n ID: r.ID,\n Status: r.Status,\n StartTime: r.StartTime,\n CreatedAt: r.__mj_CreatedAt,\n SuccessCount: r.SuccessCount,\n TotalItemCount: r.TotalItemCount,\n ProcessName: r.RecordProcess,\n EntityName: r.Entity,\n DryRun: r.DryRun,\n }));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"predictive-studio.engine.js","sourceRoot":"","sources":["../../../src/PredictiveStudio/engine/predictive-studio.engine.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BaseEngine,\n BaseEnginePropertyConfig,\n CompositeKey,\n IMetadataProvider,\n Metadata,\n RunView,\n UserInfo,\n} from '@memberjunction/core';\nimport { EscapeSQLString, UUIDsEqual } from '@memberjunction/global';\nimport {\n MJMLAlgorithmEntity,\n MJMLAlgorithmUseCaseEntity,\n MJMLAlgorithmUseCaseRankingEntity,\n MJMLModelEntity,\n MJMLModelScoringBindingEntity,\n MJMLTrainingPipelineEntity,\n MJMLTrainingRunEntity,\n MJExperimentEntity,\n MJExperimentSessionEntity,\n MJExperimentSessionIterationEntity,\n MJProcessRunDetailEntity,\n MJProcessRunEntity,\n MJRecordProcessEntity,\n} from '@memberjunction/core-entities';\nimport { PSIterationRow, PSProcessRunRow } from '../predictive-studio.view-models';\n\n/** The columns of a scored Process Run Detail the Predictive Studio surfaces read; `ID` is the keyset paging cursor. */\nexport type PSRunDetailRow = Pick<MJProcessRunDetailEntity, 'ID' | 'RecordID' | 'ResultPayload' | 'Status' | 'CompletedAt' | '__mj_CreatedAt'>;\n\n/** A run's details as read by {@link PredictiveStudioEngine.LoadRunDetails}; `Capped` is true when the run has more. */\nexport interface PSRunDetails {\n Rows: PSRunDetailRow[];\n Capped: boolean;\n}\n\n/**\n * Recommendation levels used by the Algorithm Use Case Rankings matrix, ordered weakest → strongest.\n * Used to rank algorithms within a chosen scenario in the catalog \"Guide me\" picker.\n */\nexport type RecommendationLevel = 'NotRecommended' | 'Weak' | 'Viable' | 'Strong' | 'Primary';\n\n/** Numeric rank for each {@link RecommendationLevel} (higher = better fit). */\nexport const RECOMMENDATION_RANK: Record<RecommendationLevel, number> = {\n NotRecommended: 0,\n Weak: 1,\n Viable: 2,\n Strong: 3,\n Primary: 4,\n};\n\n/** Minimal shape of a ranking row consumed by {@link computeBestLevels} (decoupled from the entity). */\nexport interface RankingRow {\n MLAlgorithmID: string;\n MLAlgorithmUseCaseID: string;\n RecommendationLevel: RecommendationLevel;\n}\n\n/**\n * Pure ranking-matrix reducer: given ranking rows and a set of selected use-case IDs, returns each\n * algorithm's BEST recommendation level (max by rank) across those scenarios. Extracted from the\n * engine so it is unit-testable without a metadata provider / DB.\n */\nexport function ComputeBestLevels(rankings: RankingRow[], useCaseIds: string[]): Map<string, RecommendationLevel> {\n const out = new Map<string, RecommendationLevel>();\n if (useCaseIds.length === 0) return out;\n for (const ranking of rankings) {\n if (!useCaseIds.some((id) => UUIDsEqual(id, ranking.MLAlgorithmUseCaseID))) continue;\n const current = out.get(ranking.MLAlgorithmID);\n if (!current || RECOMMENDATION_RANK[ranking.RecommendationLevel] > RECOMMENDATION_RANK[current]) {\n out.set(ranking.MLAlgorithmID, ranking.RecommendationLevel);\n }\n }\n return out;\n}\n\n/** @deprecated Use {@link ComputeBestLevels}. */\nexport function computeBestLevels(rankings: RankingRow[], useCaseIds: string[]): Map<string, RecommendationLevel> {\n return ComputeBestLevels(rankings, useCaseIds);\n}\n\n/**\n * PredictiveStudioEngine — the single, process-wide cache + domain-logic layer for the Predictive\n * Studio dashboard. Follows the canonical MJ BaseEngine pattern (Config() declaring\n * BaseEnginePropertyConfig[], lazy-loaded, ObserveProperty reactivity for free).\n *\n * It caches the SMALL Predictive Studio reference entities (algorithms, use cases, the rankings\n * matrix, models, pipelines, training runs, experiments + sessions + iterations) via RunView so\n * the panels bind to in-memory arrays and stay reactive to saves/deletes. Large columns\n * (serialized model artifacts, feature schemas) live on the entities themselves but these tables\n * are small enough to fully cache.\n */\nexport class PredictiveStudioEngine extends BaseEngine<PredictiveStudioEngine> {\n /** Singleton accessor — never `new` this class directly. */\n public static get Instance(): PredictiveStudioEngine {\n return super.getInstance<PredictiveStudioEngine>();\n }\n\n private _algorithms: MJMLAlgorithmEntity[] = [];\n private _useCases: MJMLAlgorithmUseCaseEntity[] = [];\n private _rankings: MJMLAlgorithmUseCaseRankingEntity[] = [];\n private _models: MJMLModelEntity[] = [];\n private _scoringBindings: MJMLModelScoringBindingEntity[] = [];\n private _recordProcesses: MJRecordProcessEntity[] = [];\n private _pipelines: MJMLTrainingPipelineEntity[] = [];\n private _trainingRuns: MJMLTrainingRunEntity[] = [];\n private _experiments: MJExperimentEntity[] = [];\n private _sessions: MJExperimentSessionEntity[] = [];\n private _iterations: MJExperimentSessionIterationEntity[] = [];\n\n public async Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise<void> {\n const c: Partial<BaseEnginePropertyConfig>[] = [\n { Type: 'entity', EntityName: 'MJ: ML Algorithms', PropertyName: '_algorithms', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Algorithm Use Cases', PropertyName: '_useCases', OrderBy: 'DisplayOrder' },\n { Type: 'entity', EntityName: 'MJ: ML Algorithm Use Case Rankings', PropertyName: '_rankings' },\n { Type: 'entity', EntityName: 'MJ: ML Models', PropertyName: '_models', OrderBy: '__mj_UpdatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: ML Model Scoring Bindings', PropertyName: '_scoringBindings', OrderBy: '__mj_UpdatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Record Processes', PropertyName: '_recordProcesses', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Training Pipelines', PropertyName: '_pipelines', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: ML Training Runs', PropertyName: '_trainingRuns', OrderBy: '__mj_CreatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Experiments', PropertyName: '_experiments', OrderBy: 'Name' },\n { Type: 'entity', EntityName: 'MJ: Experiment Sessions', PropertyName: '_sessions', OrderBy: '__mj_CreatedAt DESC' },\n { Type: 'entity', EntityName: 'MJ: Experiment Session Iterations', PropertyName: '_iterations', OrderBy: 'Sequence' },\n ];\n await super.Load(c, provider ?? Metadata.Provider, forceRefresh, contextUser);\n }\n\n // ---- Cached arrays (sync getters; observe via ObserveProperty for reactive UI) ----\n\n public get Algorithms(): MJMLAlgorithmEntity[] {\n return this._algorithms ?? [];\n }\n public get UseCases(): MJMLAlgorithmUseCaseEntity[] {\n return this._useCases ?? [];\n }\n public get Rankings(): MJMLAlgorithmUseCaseRankingEntity[] {\n return this._rankings ?? [];\n }\n public get Models(): MJMLModelEntity[] {\n return this._models ?? [];\n }\n /** Scoring bindings — a model → (target entity + column, optional Record Process) deployment link. */\n public get ScoringBindings(): MJMLModelScoringBindingEntity[] {\n return this._scoringBindings ?? [];\n }\n /** Record Processes — used to resolve the schedule (cron) + status of a binding's bound process. */\n public get RecordProcesses(): MJRecordProcessEntity[] {\n return this._recordProcesses ?? [];\n }\n public get Pipelines(): MJMLTrainingPipelineEntity[] {\n return this._pipelines ?? [];\n }\n public get TrainingRuns(): MJMLTrainingRunEntity[] {\n return this._trainingRuns ?? [];\n }\n public get Experiments(): MJExperimentEntity[] {\n return this._experiments ?? [];\n }\n public get Sessions(): MJExperimentSessionEntity[] {\n return this._sessions ?? [];\n }\n public get Iterations(): MJExperimentSessionIterationEntity[] {\n return this._iterations ?? [];\n }\n\n // ---- Domain helpers ----\n\n /** Look up an ML Model by ID (for joining a scoring binding to its model). */\n public ModelByID(modelId: string | null | undefined): MJMLModelEntity | undefined {\n if (!modelId) return undefined;\n return this.Models.find((m) => UUIDsEqual(m.ID, modelId));\n }\n\n /** Look up a Record Process by ID (for resolving a binding's schedule/status). */\n public RecordProcessByID(processId: string | null | undefined): MJRecordProcessEntity | undefined {\n if (!processId) return undefined;\n return this.RecordProcesses.find((p) => UUIDsEqual(p.ID, processId));\n }\n\n /** Look up an algorithm name by ID (for joining iterations/runs/models to a display name). */\n public AlgorithmName(algorithmId: string | null | undefined): string {\n if (!algorithmId) return 'Unknown';\n return this.Algorithms.find((a) => UUIDsEqual(a.ID, algorithmId))?.Name ?? 'Unknown';\n }\n\n /** All ranking rows for a given use case, joined to their algorithm and ranked best-first. */\n public RankingsForUseCase(useCaseId: string): MJMLAlgorithmUseCaseRankingEntity[] {\n return this.Rankings.filter((r) => UUIDsEqual(r.MLAlgorithmUseCaseID, useCaseId)).sort(\n (a, b) => RECOMMENDATION_RANK[b.RecommendationLevel] - RECOMMENDATION_RANK[a.RecommendationLevel],\n );\n }\n\n /**\n * Given a set of selected use-case IDs, compute each algorithm's BEST recommendation level\n * across those scenarios (max by rank) — the core of the catalog \"Guide me\" picker.\n * Returns a map of algorithmId → best level, omitting algorithms with no ranking row.\n */\n public BestLevelsForScenarios(useCaseIds: string[]): Map<string, RecommendationLevel> {\n return ComputeBestLevels(this.Rankings, useCaseIds);\n }\n\n /** Iterations belonging to a session, in sequence order. */\n public IterationsForSession(sessionId: string): MJExperimentSessionIterationEntity[] {\n return this.Iterations.filter((i) => UUIDsEqual(i.ExperimentSessionID, sessionId)).sort(\n (a, b) => a.Sequence - b.Sequence,\n );\n }\n\n /** Published models only — the production-quality set used for headline KPIs. */\n public get PublishedModels(): MJMLModelEntity[] {\n return this.Models.filter((m) => m.Status === 'Published');\n }\n\n /** Sessions whose status is `Running` — the active experiment count. */\n public get RunningSessions(): MJExperimentSessionEntity[] {\n return this.Sessions.filter((s) => s.Status === 'Running');\n }\n\n /**\n * Resolve a model's human-readable display name generically: the producing pipeline's name when\n * available (the most meaningful label — what the model predicts), else the model's denormalized\n * `Pipeline` view field, else a version-stamped fallback. Entity-agnostic — never hardcodes any\n * business entity.\n */\n public ModelDisplayName(model: MJMLModelEntity): string {\n const pipeline = this.Pipelines.find((p) => UUIDsEqual(p.ID, model.PipelineID));\n return pipeline?.Name ?? model.Pipeline ?? `Model v${model.Version}`;\n }\n\n /**\n * Map the engine's cached iterations for a session into the pure {@link PSIterationRow} shape the\n * view-model derivations consume — joining each iteration to its algorithm name via the resulting\n * training run (iteration → run → algorithm), since iterations don't carry the algorithm directly.\n */\n public IterationRowsForSession(sessionId: string): PSIterationRow[] {\n return this.IterationsForSession(sessionId).map((it) => ({\n ID: it.ID,\n ExperimentSessionID: it.ExperimentSessionID,\n Sequence: it.Sequence,\n Label: it.Label,\n Status: it.Status,\n Score: it.Score,\n ComputeCost: it.ComputeCost,\n TokensUsed: it.TokensUsed,\n Rationale: it.Rationale,\n AlgorithmName: this.AlgorithmForIteration(it.ID),\n }));\n }\n\n /** Resolve an iteration's algorithm display name via its training run (or 'Unknown'). */\n public AlgorithmForIteration(iterationId: string): string {\n const run = this.TrainingRuns.find((r) => UUIDsEqual(r.ExperimentSessionIterationID, iterationId));\n return run ? this.AlgorithmName(run.AlgorithmID) : 'Unknown';\n }\n\n /**\n * The `MJ: Record Processes` IDs that ML scoring write-backs run through — every scoring binding's\n * bound Record Process. Used to scope the Home activity feed to ML-scoring runs without depending\n * on a typed `WorkType='ML Model'` enum value (which is registered at runtime, not in the type).\n */\n public get ScoringRecordProcessIDs(): string[] {\n const ids = this.ScoringBindings.map((b) => b.RecordProcessID).filter((id): id is string => !!id);\n return [...new Set(ids)];\n }\n\n /**\n * Load recent ML-scoring process runs on demand (NOT bulk-cached — `MJ: Process Runs` grows\n * unbounded). Scopes to runs whose `RecordProcessID` is one of the ML scoring bindings'\n * processes, optionally to the last `sinceDays`, capped at `maxRows`, newest first. Returns the\n * pure {@link PSProcessRunRow} shape for the Home derivations. Returns `[]` (never throws) on any\n * failure or when there are no scoring bindings to scope to.\n *\n * @param provider The provider to run against (multi-provider correctness).\n * @param user The acting user (server-side audit/security).\n * @param options.sinceDays Only runs started within this many days (default 7).\n * @param options.maxRows Row cap (default 50).\n */\n public async LoadRecentScoringRuns(\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n return this.loadRunsForProcessIds(this.ScoringRecordProcessIDs, provider, user, options);\n }\n\n /**\n * Record Processes (`WorkType='ML Model'`) configured to score with `modelId` — the cached link from a\n * model to the processes that run it, idle/scheduled/bound alike (no DB hit). The `modelId` is read from\n * each Record Process's stored `Configuration` JSON.\n */\n public RecordProcessesForModel(modelId: string): MJRecordProcessEntity[] {\n return this.RecordProcesses.filter((rp) => {\n const id = this.recordProcessModelId(rp);\n return id != null && UUIDsEqual(id, modelId);\n });\n }\n\n /** The cached Record-Process ids scoring with `modelId`. */\n public RecordProcessIDsForModel(modelId: string): string[] {\n return this.RecordProcessesForModel(modelId).map((rp) => rp.ID);\n }\n\n /** Parse a Record Process's stored `modelId` (the `WorkType='ML Model'` config), or null. */\n private recordProcessModelId(rp: MJRecordProcessEntity): string | null {\n try {\n const cfg: unknown = JSON.parse(rp.Configuration ?? '{}');\n const id = (cfg as { modelId?: unknown })?.modelId;\n return typeof id === 'string' ? id : null;\n } catch {\n return null;\n }\n }\n\n /**\n * Load recent process runs for ONE model's Record Processes — same DB-light, on-demand contract as\n * {@link LoadRecentScoringRuns}, scoped to a single model. Powers the \"Models in Production\" per-model\n * run history (a model needs no scoring binding to have runs — any `WorkType='ML Model'` Record Process\n * run persists here).\n */\n public async LoadRecentRunsForModel(\n modelId: string,\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n return this.loadRunsForProcessIds(this.RecordProcessIDsForModel(modelId), provider, user, options);\n }\n\n /** The most run details one read returns; a larger run is read up to this many and reported {@link PSRunDetails.Capped}. */\n public static readonly MaxRunDetailRows = 50_000;\n /** {@link MaxRunDetailRows} formatted for the notices that tell a user a run was capped (\"50,000\"). */\n public static readonly MaxRunDetailRowsLabel = PredictiveStudioEngine.MaxRunDetailRows.toLocaleString('en-US');\n private static readonly runDetailPageSize = 1000;\n\n /**\n * Reads a run's process run details one keyset page at a time (read-only, only the columns the surfaces use), up to\n * {@link PredictiveStudioEngine.MaxRunDetailRows}. Throws, with the provider's error message, when a page fails to load,\n * so the caller shows the failure instead of an empty run.\n */\n public async LoadRunDetails(runId: string, provider: IMetadataProvider, user: UserInfo | undefined): Promise<PSRunDetails> {\n const entityInfo = provider.EntityByName('MJ: Process Run Details');\n if (!entityInfo) {\n throw new Error(\"The 'MJ: Process Run Details' entity is not in this provider's metadata.\");\n }\n const rv = RunView.FromMetadataProvider(provider);\n const rows: PSRunDetailRow[] = [];\n let lastKey: CompositeKey | undefined;\n while (true) {\n const page = await rv.RunView<PSRunDetailRow>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `ProcessRunID = '${EscapeSQLString(runId)}'`,\n Fields: ['ID', 'RecordID', 'ResultPayload', 'Status', 'CompletedAt', '__mj_CreatedAt'],\n MaxRows: PredictiveStudioEngine.runDetailPageSize,\n AfterKey: lastKey,\n ResultType: 'simple',\n },\n user,\n );\n if (!page.Success || !page.Results) {\n throw new Error(`Could not read the predictions of run ${runId}: ${page.ErrorMessage || 'the request failed'}`);\n }\n rows.push(...page.Results);\n if (page.Results.length < PredictiveStudioEngine.runDetailPageSize) {\n return { Rows: rows, Capped: false };\n }\n if (rows.length >= PredictiveStudioEngine.MaxRunDetailRows) {\n // Capped only when the run really has more: a run of exactly the cap is complete.\n const probe = await rv.RunView<Pick<PSRunDetailRow, 'ID'>>(\n {\n EntityName: 'MJ: Process Run Details',\n ExtraFilter: `ProcessRunID = '${EscapeSQLString(runId)}'`,\n Fields: ['ID'],\n MaxRows: 1,\n AfterKey: CompositeKey.FromEntityRecord(entityInfo, page.Results[page.Results.length - 1]),\n ResultType: 'simple',\n },\n user,\n );\n return { Rows: rows, Capped: probe.Success && probe.Results.length > 0 };\n }\n lastKey = CompositeKey.FromEntityRecord(entityInfo, page.Results[page.Results.length - 1]);\n }\n }\n\n /** Shared run-loader: recent `MJ: Process Runs` for a set of Record-Process ids (capped, newest-first). */\n private async loadRunsForProcessIds(\n processIds: string[],\n provider: IMetadataProvider,\n user: UserInfo | undefined,\n options?: { sinceDays?: number; maxRows?: number },\n ): Promise<PSProcessRunRow[]> {\n if (processIds.length === 0) return [];\n const sinceDays = options?.sinceDays ?? 7;\n const maxRows = options?.maxRows ?? 50;\n const sinceIso = new Date(Date.now() - sinceDays * 24 * 60 * 60 * 1000).toISOString();\n const idList = processIds.map((id) => `'${id}'`).join(',');\n\n const rv = RunView.FromMetadataProvider(provider);\n const result = await rv.RunView<MJProcessRunEntity>(\n {\n EntityName: 'MJ: Process Runs',\n ExtraFilter: `RecordProcessID IN (${idList}) AND __mj_CreatedAt >= '${sinceIso}'`,\n OrderBy: '__mj_CreatedAt DESC',\n MaxRows: maxRows,\n ResultType: 'entity_object',\n },\n user,\n );\n if (!result.Success) return [];\n return (result.Results ?? []).map((r) => ({\n ID: r.ID,\n Status: r.Status,\n StartTime: r.StartTime,\n CreatedAt: r.__mj_CreatedAt,\n SuccessCount: r.SuccessCount,\n TotalItemCount: r.TotalItemCount,\n ProcessName: r.RecordProcess,\n EntityName: r.Entity,\n DryRun: r.DryRun,\n }));\n }\n}\n"]}
|
|
@@ -74,11 +74,13 @@ export interface PredictionsAgentContextInput {
|
|
|
74
74
|
AtRiskLoaded?: boolean;
|
|
75
75
|
/** Ranked at-risk row count (when loaded). */
|
|
76
76
|
AtRiskCount?: number;
|
|
77
|
+
/** True when the latest run had more predictions than the read cap, so the counts cover only the first ones. */
|
|
78
|
+
AtRiskCapped?: boolean;
|
|
77
79
|
/** Band breakdown of the at-risk rows (when loaded). */
|
|
78
80
|
HighRiskCount?: number;
|
|
79
81
|
MediumRiskCount?: number;
|
|
80
82
|
LowRiskCount?: number;
|
|
81
|
-
/**
|
|
83
|
+
/** The features the model weighted most for the selection (coefficient models only; bounded). */
|
|
82
84
|
Drivers?: string[];
|
|
83
85
|
}
|
|
84
86
|
/** Build the Predictions door context: catalog counts + bounded names, and (in workspace) the selection + at-risk breakdown. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predictive-studio-agent-context.d.ts","sourceRoot":"","sources":["../../src/PredictiveStudio/predictive-studio-agent-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,oHAAoH;AACpH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7D;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7D;AAED,iGAAiG;AACjG,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,CAS1G;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,CAE1G;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ9G;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9G;AAMD,gGAAgG;AAChG,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,mEAAmE;IACnE,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IAC9B,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,uDAAuD;IACvD,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5C,uEAAuE;IACvE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,
|
|
1
|
+
{"version":3,"file":"predictive-studio-agent-context.d.ts","sourceRoot":"","sources":["../../src/PredictiveStudio/predictive-studio-agent-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,oHAAoH;AACpH,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7D;AAED,0CAA0C;AAC1C,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7D;AAED,iGAAiG;AACjG,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,CAS1G;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,CAE1G;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ9G;AAED,oDAAoD;AACpD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9G;AAMD,gGAAgG;AAChG,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,4BAA4B;IAC3C,mEAAmE;IACnE,IAAI,EAAE,SAAS,GAAG,WAAW,CAAC;IAC9B,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,uDAAuD;IACvD,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC5C,uEAAuE;IACvE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gHAAgH;IAChH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,gIAAgI;AAChI,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,4BAA4B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8BzG;AAED,4DAA4D;AAC5D,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,4BAA4B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzG;AAMD,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACtC,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,wGAAwG;AACxG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa/F;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/F;AAMD,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACtC,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,6FAA6F;AAC7F,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAU/F;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE/F"}
|
|
@@ -94,6 +94,9 @@ export function BuildPredictionsAgentContext(input) {
|
|
|
94
94
|
context['HighRiskCount'] = input.HighRiskCount ?? 0;
|
|
95
95
|
context['MediumRiskCount'] = input.MediumRiskCount ?? 0;
|
|
96
96
|
context['LowRiskCount'] = input.LowRiskCount ?? 0;
|
|
97
|
+
if (input.AtRiskCapped) {
|
|
98
|
+
context['AtRiskCapped'] = true;
|
|
99
|
+
}
|
|
97
100
|
}
|
|
98
101
|
if (input.Drivers && input.Drivers.length > 0) {
|
|
99
102
|
context['Drivers'] = CapPSNames(input.Drivers);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"predictive-studio-agent-context.js","sourceRoot":"","sources":["../../src/PredictiveStudio/predictive-studio-agent-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure, framework-agnostic helpers for Predictive Studio's AI-agent integration across its\n * three doors — **Predictions** (business front door), **Studio** (analyst workbench), and **Models**\n * (registry + production). Each door component supplies a plain snapshot of its current state and these\n * helpers shape it into the key-value context object that flows to the async chat agent AND the realtime\n * co-agent via `NavigationService.SetAgentContext`, plus resolve an agent-supplied id/name/partial to a\n * concrete record for the doors' client tools.\n *\n * Kept Angular-free so it's unit-testable in isolation (see `src/__tests__/predictive-studio-agent-context.test.ts`).\n * The shared validation/cap helpers (`validateStringParam`, `boundNameList`) come from\n * `src/shared/agent-tool-validation.ts`; the PS-specific resolver + builders live LOCAL here (same\n * convention as every other MJ surface — e.g. Lists' `lists-agent-context.ts`).\n *\n * 🔒 SAFETY BOUNDARY: every function here is read-only and side-effect-free — it only shapes context and\n * matches strings. Predictive Studio surfaces are **read / navigate-only to the agent**: the doors expose\n * ONLY section-switch / open-prediction / review / export / open-copilot tools. Model **training,\n * promotion/publish, deletion, scoring-run, \"save scores to records\", and \"send to a list\" (which creates\n * `MJ: Lists` + `MJ: List Details` rows) are DELIBERATELY NOT exposed** — those write/irreversible actions\n * stay behind the user's own clicks and the Model Development Agent's approve-gated builder. The\n * read-only boundary is restated on each door component; this module never mutates anything.\n */\n\nimport { BoundNameList } from '../shared/agent-tool-validation';\n\n/** Upper bound on names published in any PS context list field; a companion `*Count` is surfaced when truncated. */\nexport const PS_AGENT_CONTEXT_NAME_LIST_CAP = 25;\n\n/** Cap a name list to {@link PS_AGENT_CONTEXT_NAME_LIST_CAP}. Pure; never mutates the input. */\nexport function CapPSNames(names: readonly string[]): string[] {\n return BoundNameList(names, PS_AGENT_CONTEXT_NAME_LIST_CAP);\n}\n\n/** @deprecated Use {@link CapPSNames}. */\nexport function capPSNames(names: readonly string[]): string[] {\n return CapPSNames(names);\n}\n\n/** Minimal id+name descriptor the doors hand the resolver so it can match an agent reference. */\nexport interface PSNamedRecord {\n ID: string;\n Name: string;\n}\n\n/**\n * Resolve an agent-supplied reference the way a user names things: exact ID (case-insensitive, to tolerate\n * SQL-Server-upper vs PG-lower UUID casing) → exact name (trimmed, case-insensitive) → case-insensitive\n * *contains* match on the name, but ONLY when it's unambiguous — a needle contained in several candidate\n * names returns null (silently opening the first would be silently opening the wrong one; the paired\n * {@link buildPSNotFoundError} then lists the contenders so the agent can disambiguate). Pure +\n * deterministic over the candidate list.\n */\nexport function ResolvePSRecord<T extends PSNamedRecord>(input: string, candidates: readonly T[]): T | null {\n const needle = (input ?? '').trim().toLowerCase();\n if (!needle) return null;\n const byId = candidates.find((c) => c.ID.toLowerCase() === needle);\n if (byId) return byId;\n const byName = candidates.find((c) => c.Name.trim().toLowerCase() === needle);\n if (byName) return byName;\n const contains = candidates.filter((c) => c.Name.toLowerCase().includes(needle));\n return contains.length === 1 ? contains[0] : null;\n}\n\n/** @deprecated Use {@link ResolvePSRecord}. */\nexport function resolvePSRecord<T extends PSNamedRecord>(input: string, candidates: readonly T[]): T | null {\n return ResolvePSRecord(input, candidates);\n}\n\n/**\n * Tolerant \"not found\" message so the agent can self-correct: when the input partially matches SEVERAL\n * candidates it becomes a \"did you mean…\" listing exactly those; otherwise it samples available names. Pure.\n */\nexport function BuildPSNotFoundError(input: string, candidates: readonly PSNamedRecord[], noun: string): string {\n const needle = (input ?? '').trim().toLowerCase();\n const contains = needle ? candidates.filter((c) => c.Name.toLowerCase().includes(needle)) : [];\n if (contains.length > 1) {\n return `\"${input}\" matches more than one ${noun} — did you mean: ${contains.slice(0, 6).map((c) => c.Name).join(', ')}? Use the exact name or ID.`;\n }\n const sample = candidates.slice(0, 6).map((c) => c.Name).join(', ');\n return `No ${noun} matching \"${input}\" is available. Available ${noun}s include: ${sample || '(none)'}.`;\n}\n\n/** @deprecated Use {@link BuildPSNotFoundError}. */\nexport function buildPSNotFoundError(input: string, candidates: readonly PSNamedRecord[], noun: string): string {\n return BuildPSNotFoundError(input, candidates, noun);\n}\n\n// ============================================================================\n// PREDICTIONS door context (catalog ↔ trust-gated workspace)\n// ============================================================================\n\n/** The open prediction's salient slice, published when the workspace is showing a selection. */\nexport interface SelectedPredictionSummary {\n Name: string;\n /** Trust grade (Poor/Fair/Good/Excellent). */\n TrustGrade: string;\n /** Whether the trust gate lets the user act on this prediction. */\n CanOpen: boolean;\n}\n\n/** Component-supplied snapshot for the Predictions door. */\nexport interface PredictionsAgentContextInput {\n /** catalog (the home grid) ↔ workspace (a selected prediction). */\n View: 'catalog' | 'workspace';\n /** Total published predictions in the catalog. */\n PredictionCount: number;\n /** How many clear the trust gate (openable). */\n ReadyPredictionCount: number;\n /** Names of the catalog predictions, in display order (bounded). */\n VisiblePredictionNames: string[];\n /** Whether the \"+ New prediction\" co-pilot is open. */\n ChatOpen: boolean;\n /** The open prediction (workspace view only), else null. */\n Selected?: SelectedPredictionSummary | null;\n /** Whether the at-risk list has finished loading for the selection. */\n AtRiskLoaded?: boolean;\n /** Ranked at-risk row count (when loaded). */\n AtRiskCount?: number;\n /** Band breakdown of the at-risk rows (when loaded). */\n HighRiskCount?: number;\n MediumRiskCount?: number;\n LowRiskCount?: number;\n /** Plain-language \"what's driving this\" drivers for the selection (bounded). */\n Drivers?: string[];\n}\n\n/** Build the Predictions door context: catalog counts + bounded names, and (in workspace) the selection + at-risk breakdown. */\nexport function BuildPredictionsAgentContext(input: PredictionsAgentContextInput): Record<string, unknown> {\n const context: Record<string, unknown> = {\n View: input.View,\n PredictionCount: input.PredictionCount,\n ReadyPredictionCount: input.ReadyPredictionCount,\n ChatOpen: input.ChatOpen,\n VisiblePredictionNames: CapPSNames(input.VisiblePredictionNames),\n };\n if (input.VisiblePredictionNames.length > PS_AGENT_CONTEXT_NAME_LIST_CAP) {\n context['VisiblePredictionNameCount'] = input.VisiblePredictionNames.length;\n }\n if (input.View === 'workspace' && input.Selected) {\n context['SelectedPredictionName'] = input.Selected.Name;\n context['SelectedPredictionTrust'] = input.Selected.TrustGrade;\n context['SelectedPredictionCanAct'] = input.Selected.CanOpen;\n // Only surface the at-risk breakdown once loaded — never fabricate zeros before the fetch resolves.\n if (input.AtRiskLoaded) {\n context['AtRiskCount'] = input.AtRiskCount ?? 0;\n context['HighRiskCount'] = input.HighRiskCount ?? 0;\n context['MediumRiskCount'] = input.MediumRiskCount ?? 0;\n context['LowRiskCount'] = input.LowRiskCount ?? 0;\n }\n if (input.Drivers && input.Drivers.length > 0) {\n context['Drivers'] = CapPSNames(input.Drivers);\n }\n }\n return context;\n}\n\n/** @deprecated Use {@link BuildPredictionsAgentContext}. */\nexport function buildPredictionsAgentContext(input: PredictionsAgentContextInput): Record<string, unknown> {\n return BuildPredictionsAgentContext(input);\n}\n\n// ============================================================================\n// STUDIO door context (build/run workbench)\n// ============================================================================\n\n/** Component-supplied snapshot for the Studio door. */\nexport interface StudioAgentContextInput {\n /** Active section key (home/pipelines/catalog/experiments/compare). */\n ActiveSection: string;\n /** Active section display label. */\n ActiveSectionLabel: string;\n /** Labels of the door's sections, in nav order. */\n SectionLabels: string[];\n PublishedModelCount: number;\n RunningSessionCount: number;\n PipelineCount: number;\n AlgorithmCount: number;\n ExperimentCount: number;\n TrainingRunCount: number;\n /** Whether the docked Model Dev Agent co-pilot is open. */\n ChatOpen: boolean;\n}\n\n/** Build the Studio door context: active section + section labels + the workbench's headline counts. */\nexport function BuildStudioAgentContext(input: StudioAgentContextInput): Record<string, unknown> {\n return {\n ActiveSection: input.ActiveSection,\n ActiveSectionLabel: input.ActiveSectionLabel,\n SectionLabels: CapPSNames(input.SectionLabels),\n PublishedModelCount: input.PublishedModelCount,\n RunningSessionCount: input.RunningSessionCount,\n PipelineCount: input.PipelineCount,\n AlgorithmCount: input.AlgorithmCount,\n ExperimentCount: input.ExperimentCount,\n TrainingRunCount: input.TrainingRunCount,\n ChatOpen: input.ChatOpen,\n };\n}\n\n/** @deprecated Use {@link BuildStudioAgentContext}. */\nexport function buildStudioAgentContext(input: StudioAgentContextInput): Record<string, unknown> {\n return BuildStudioAgentContext(input);\n}\n\n// ============================================================================\n// MODELS door context (registry + production)\n// ============================================================================\n\n/** Component-supplied snapshot for the Models door. */\nexport interface ModelsAgentContextInput {\n /** Active section key (registry/production). */\n ActiveSection: string;\n /** Active section display label. */\n ActiveSectionLabel: string;\n /** Labels of the door's sections, in nav order. */\n SectionLabels: string[];\n TotalModelCount: number;\n PublishedModelCount: number;\n DraftModelCount: number;\n /** Models with at least one scoring Record Process (live in production). */\n ProductionModelCount: number;\n}\n\n/** Build the Models door context: active section + section labels + the lifecycle counts. */\nexport function BuildModelsAgentContext(input: ModelsAgentContextInput): Record<string, unknown> {\n return {\n ActiveSection: input.ActiveSection,\n ActiveSectionLabel: input.ActiveSectionLabel,\n SectionLabels: CapPSNames(input.SectionLabels),\n TotalModelCount: input.TotalModelCount,\n PublishedModelCount: input.PublishedModelCount,\n DraftModelCount: input.DraftModelCount,\n ProductionModelCount: input.ProductionModelCount,\n };\n}\n\n/** @deprecated Use {@link BuildModelsAgentContext}. */\nexport function buildModelsAgentContext(input: ModelsAgentContextInput): Record<string, unknown> {\n return BuildModelsAgentContext(input);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"predictive-studio-agent-context.js","sourceRoot":"","sources":["../../src/PredictiveStudio/predictive-studio-agent-context.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview Pure, framework-agnostic helpers for Predictive Studio's AI-agent integration across its\n * three doors — **Predictions** (business front door), **Studio** (analyst workbench), and **Models**\n * (registry + production). Each door component supplies a plain snapshot of its current state and these\n * helpers shape it into the key-value context object that flows to the async chat agent AND the realtime\n * co-agent via `NavigationService.SetAgentContext`, plus resolve an agent-supplied id/name/partial to a\n * concrete record for the doors' client tools.\n *\n * Kept Angular-free so it's unit-testable in isolation (see `src/__tests__/predictive-studio-agent-context.test.ts`).\n * The shared validation/cap helpers (`validateStringParam`, `boundNameList`) come from\n * `src/shared/agent-tool-validation.ts`; the PS-specific resolver + builders live LOCAL here (same\n * convention as every other MJ surface — e.g. Lists' `lists-agent-context.ts`).\n *\n * 🔒 SAFETY BOUNDARY: every function here is read-only and side-effect-free — it only shapes context and\n * matches strings. Predictive Studio surfaces are **read / navigate-only to the agent**: the doors expose\n * ONLY section-switch / open-prediction / review / export / open-copilot tools. Model **training,\n * promotion/publish, deletion, scoring-run, \"save scores to records\", and \"send to a list\" (which creates\n * `MJ: Lists` + `MJ: List Details` rows) are DELIBERATELY NOT exposed** — those write/irreversible actions\n * stay behind the user's own clicks and the Model Development Agent's approve-gated builder. The\n * read-only boundary is restated on each door component; this module never mutates anything.\n */\n\nimport { BoundNameList } from '../shared/agent-tool-validation';\n\n/** Upper bound on names published in any PS context list field; a companion `*Count` is surfaced when truncated. */\nexport const PS_AGENT_CONTEXT_NAME_LIST_CAP = 25;\n\n/** Cap a name list to {@link PS_AGENT_CONTEXT_NAME_LIST_CAP}. Pure; never mutates the input. */\nexport function CapPSNames(names: readonly string[]): string[] {\n return BoundNameList(names, PS_AGENT_CONTEXT_NAME_LIST_CAP);\n}\n\n/** @deprecated Use {@link CapPSNames}. */\nexport function capPSNames(names: readonly string[]): string[] {\n return CapPSNames(names);\n}\n\n/** Minimal id+name descriptor the doors hand the resolver so it can match an agent reference. */\nexport interface PSNamedRecord {\n ID: string;\n Name: string;\n}\n\n/**\n * Resolve an agent-supplied reference the way a user names things: exact ID (case-insensitive, to tolerate\n * SQL-Server-upper vs PG-lower UUID casing) → exact name (trimmed, case-insensitive) → case-insensitive\n * *contains* match on the name, but ONLY when it's unambiguous — a needle contained in several candidate\n * names returns null (silently opening the first would be silently opening the wrong one; the paired\n * {@link buildPSNotFoundError} then lists the contenders so the agent can disambiguate). Pure +\n * deterministic over the candidate list.\n */\nexport function ResolvePSRecord<T extends PSNamedRecord>(input: string, candidates: readonly T[]): T | null {\n const needle = (input ?? '').trim().toLowerCase();\n if (!needle) return null;\n const byId = candidates.find((c) => c.ID.toLowerCase() === needle);\n if (byId) return byId;\n const byName = candidates.find((c) => c.Name.trim().toLowerCase() === needle);\n if (byName) return byName;\n const contains = candidates.filter((c) => c.Name.toLowerCase().includes(needle));\n return contains.length === 1 ? contains[0] : null;\n}\n\n/** @deprecated Use {@link ResolvePSRecord}. */\nexport function resolvePSRecord<T extends PSNamedRecord>(input: string, candidates: readonly T[]): T | null {\n return ResolvePSRecord(input, candidates);\n}\n\n/**\n * Tolerant \"not found\" message so the agent can self-correct: when the input partially matches SEVERAL\n * candidates it becomes a \"did you mean…\" listing exactly those; otherwise it samples available names. Pure.\n */\nexport function BuildPSNotFoundError(input: string, candidates: readonly PSNamedRecord[], noun: string): string {\n const needle = (input ?? '').trim().toLowerCase();\n const contains = needle ? candidates.filter((c) => c.Name.toLowerCase().includes(needle)) : [];\n if (contains.length > 1) {\n return `\"${input}\" matches more than one ${noun} — did you mean: ${contains.slice(0, 6).map((c) => c.Name).join(', ')}? Use the exact name or ID.`;\n }\n const sample = candidates.slice(0, 6).map((c) => c.Name).join(', ');\n return `No ${noun} matching \"${input}\" is available. Available ${noun}s include: ${sample || '(none)'}.`;\n}\n\n/** @deprecated Use {@link BuildPSNotFoundError}. */\nexport function buildPSNotFoundError(input: string, candidates: readonly PSNamedRecord[], noun: string): string {\n return BuildPSNotFoundError(input, candidates, noun);\n}\n\n// ============================================================================\n// PREDICTIONS door context (catalog ↔ trust-gated workspace)\n// ============================================================================\n\n/** The open prediction's salient slice, published when the workspace is showing a selection. */\nexport interface SelectedPredictionSummary {\n Name: string;\n /** Trust grade (Poor/Fair/Good/Excellent). */\n TrustGrade: string;\n /** Whether the trust gate lets the user act on this prediction. */\n CanOpen: boolean;\n}\n\n/** Component-supplied snapshot for the Predictions door. */\nexport interface PredictionsAgentContextInput {\n /** catalog (the home grid) ↔ workspace (a selected prediction). */\n View: 'catalog' | 'workspace';\n /** Total published predictions in the catalog. */\n PredictionCount: number;\n /** How many clear the trust gate (openable). */\n ReadyPredictionCount: number;\n /** Names of the catalog predictions, in display order (bounded). */\n VisiblePredictionNames: string[];\n /** Whether the \"+ New prediction\" co-pilot is open. */\n ChatOpen: boolean;\n /** The open prediction (workspace view only), else null. */\n Selected?: SelectedPredictionSummary | null;\n /** Whether the at-risk list has finished loading for the selection. */\n AtRiskLoaded?: boolean;\n /** Ranked at-risk row count (when loaded). */\n AtRiskCount?: number;\n /** True when the latest run had more predictions than the read cap, so the counts cover only the first ones. */\n AtRiskCapped?: boolean;\n /** Band breakdown of the at-risk rows (when loaded). */\n HighRiskCount?: number;\n MediumRiskCount?: number;\n LowRiskCount?: number;\n /** The features the model weighted most for the selection (coefficient models only; bounded). */\n Drivers?: string[];\n}\n\n/** Build the Predictions door context: catalog counts + bounded names, and (in workspace) the selection + at-risk breakdown. */\nexport function BuildPredictionsAgentContext(input: PredictionsAgentContextInput): Record<string, unknown> {\n const context: Record<string, unknown> = {\n View: input.View,\n PredictionCount: input.PredictionCount,\n ReadyPredictionCount: input.ReadyPredictionCount,\n ChatOpen: input.ChatOpen,\n VisiblePredictionNames: CapPSNames(input.VisiblePredictionNames),\n };\n if (input.VisiblePredictionNames.length > PS_AGENT_CONTEXT_NAME_LIST_CAP) {\n context['VisiblePredictionNameCount'] = input.VisiblePredictionNames.length;\n }\n if (input.View === 'workspace' && input.Selected) {\n context['SelectedPredictionName'] = input.Selected.Name;\n context['SelectedPredictionTrust'] = input.Selected.TrustGrade;\n context['SelectedPredictionCanAct'] = input.Selected.CanOpen;\n // Only surface the at-risk breakdown once loaded — never fabricate zeros before the fetch resolves.\n if (input.AtRiskLoaded) {\n context['AtRiskCount'] = input.AtRiskCount ?? 0;\n context['HighRiskCount'] = input.HighRiskCount ?? 0;\n context['MediumRiskCount'] = input.MediumRiskCount ?? 0;\n context['LowRiskCount'] = input.LowRiskCount ?? 0;\n if (input.AtRiskCapped) {\n context['AtRiskCapped'] = true;\n }\n }\n if (input.Drivers && input.Drivers.length > 0) {\n context['Drivers'] = CapPSNames(input.Drivers);\n }\n }\n return context;\n}\n\n/** @deprecated Use {@link BuildPredictionsAgentContext}. */\nexport function buildPredictionsAgentContext(input: PredictionsAgentContextInput): Record<string, unknown> {\n return BuildPredictionsAgentContext(input);\n}\n\n// ============================================================================\n// STUDIO door context (build/run workbench)\n// ============================================================================\n\n/** Component-supplied snapshot for the Studio door. */\nexport interface StudioAgentContextInput {\n /** Active section key (home/pipelines/catalog/experiments/compare). */\n ActiveSection: string;\n /** Active section display label. */\n ActiveSectionLabel: string;\n /** Labels of the door's sections, in nav order. */\n SectionLabels: string[];\n PublishedModelCount: number;\n RunningSessionCount: number;\n PipelineCount: number;\n AlgorithmCount: number;\n ExperimentCount: number;\n TrainingRunCount: number;\n /** Whether the docked Model Dev Agent co-pilot is open. */\n ChatOpen: boolean;\n}\n\n/** Build the Studio door context: active section + section labels + the workbench's headline counts. */\nexport function BuildStudioAgentContext(input: StudioAgentContextInput): Record<string, unknown> {\n return {\n ActiveSection: input.ActiveSection,\n ActiveSectionLabel: input.ActiveSectionLabel,\n SectionLabels: CapPSNames(input.SectionLabels),\n PublishedModelCount: input.PublishedModelCount,\n RunningSessionCount: input.RunningSessionCount,\n PipelineCount: input.PipelineCount,\n AlgorithmCount: input.AlgorithmCount,\n ExperimentCount: input.ExperimentCount,\n TrainingRunCount: input.TrainingRunCount,\n ChatOpen: input.ChatOpen,\n };\n}\n\n/** @deprecated Use {@link BuildStudioAgentContext}. */\nexport function buildStudioAgentContext(input: StudioAgentContextInput): Record<string, unknown> {\n return BuildStudioAgentContext(input);\n}\n\n// ============================================================================\n// MODELS door context (registry + production)\n// ============================================================================\n\n/** Component-supplied snapshot for the Models door. */\nexport interface ModelsAgentContextInput {\n /** Active section key (registry/production). */\n ActiveSection: string;\n /** Active section display label. */\n ActiveSectionLabel: string;\n /** Labels of the door's sections, in nav order. */\n SectionLabels: string[];\n TotalModelCount: number;\n PublishedModelCount: number;\n DraftModelCount: number;\n /** Models with at least one scoring Record Process (live in production). */\n ProductionModelCount: number;\n}\n\n/** Build the Models door context: active section + section labels + the lifecycle counts. */\nexport function BuildModelsAgentContext(input: ModelsAgentContextInput): Record<string, unknown> {\n return {\n ActiveSection: input.ActiveSection,\n ActiveSectionLabel: input.ActiveSectionLabel,\n SectionLabels: CapPSNames(input.SectionLabels),\n TotalModelCount: input.TotalModelCount,\n PublishedModelCount: input.PublishedModelCount,\n DraftModelCount: input.DraftModelCount,\n ProductionModelCount: input.ProductionModelCount,\n };\n}\n\n/** @deprecated Use {@link BuildModelsAgentContext}. */\nexport function buildModelsAgentContext(input: ModelsAgentContextInput): Record<string, unknown> {\n return BuildModelsAgentContext(input);\n}\n"]}
|